#*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
*#
#parse ( "common.vm" )
#
#set ( $package = "${packageModelV3}" )
#
#set ( $root = $model.getClass( $model.getRoot($version), $version ) )
#
#set ( $allClasses = [] )
#foreach ( $class in $model.allClasses )
  #if ( $class.name != "InputLocation" && $class.name != "InputSource" )
    #set ( $dummy = $allClasses.add( $class ) )
  #end
#end
#foreach ( $class in $allClasses )
  #set ( $ancestors = $Helper.ancestors( $class ) )
  #set ( $allFields = [] )
  #set ( $inheritedFields = [] )
  #foreach ( $cl in $ancestors )
    #if ( $cl != $class )
      #set ( $dummy = $inheritedFields.addAll( $cl.allFields ) )
    #end
    #set ( $dummy = $allFields.addAll( $cl.allFields ) )
  #end
  #set ( $className = "${class.name}" )
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/WrapperList.java
#parse ( "java/WrapperList.java" )
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/WrapperProperties.java
#parse ( "java/WrapperProperties.java" )
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
    #set ( $types = { } )
    #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() )
    #set ( $dummy = $imports.add( "java.io.Serializable" ) )
    #set ( $dummy = $imports.add( "java.util.AbstractList" ) )
    #set ( $dummy = $imports.add( "java.util.Collections" ) )
    #set ( $dummy = $imports.add( "java.util.HashMap" ) )
    #set ( $dummy = $imports.add( "java.util.LinkedHashMap" ) )
    #set ( $dummy = $imports.add( "java.util.List" ) )
    #set ( $dummy = $imports.add( "java.util.Map" ) )
    #set ( $dummy = $imports.add( "java.util.Set" ) )
    #set ( $dummy = $imports.add( "java.util.Objects" ) )
    #set ( $dummy = $imports.add( "java.util.stream.Collectors" ) )
    #set ( $dummy = $imports.add( "java.util.stream.Stream" ) )
    #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) )
    #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) )
    #foreach ( $field in $allFields )
      #if ( $field.type == "java.util.List" )
          #set ( $dummy = $imports.add( "java.util.ArrayList" ) )
          #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) )
      #elseif ( $field.type == "DOM" )
          #set ( $dummy = $imports.add( "org.codehaus.plexus.util.xml.Xpp3Dom" ) )
          #set ( $dummy = $types.put( $field, "Object" ) )
      #else
        #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} )
        #set ( $idx = $fieldType.lastIndexOf('.') )
        #if ( $idx > 0 )
          #set ( $dummy = $imports.add( $fieldType ) )
          #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) )
        #end
      #end
    #end
    #set ( $eq = "" )
    #set ( $hc = "" )
    #foreach ( $field in $allFields )
      #if ( $field.identifier )
        #set ( $dummy = $imports.add( "java.util.Objects" ) )
        #set ( $dummy = $identifiers.add( $field ) )
        #if ( $eq == "" )
          #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" )
        #else
          #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" )
        #end
        #if ( $hc == "" )
          #set ( $hc = "${field.name}" )
        #else
          #set ( $hc = "$hc, this.${field.name}" )
        #end
      #end
    #end
// =================== DO NOT EDIT THIS FILE ====================
//  Generated by Modello Velocity from ${template}
//  template, any modifications will be overwritten.
// ==============================================================
package ${package};

  #foreach ( $imp in $imports )
import $imp;
  #end

@Generated
public class ${class.name}
    #if ( $class.superClass )
    extends ${class.superClass}
    implements Serializable, Cloneable
    #else
    extends BaseObject
    #end
{

    public ${class.name}() {
        this(${packageModelV4}.${class.name}.newInstance());
    }

    public ${class.name}(${packageModelV4}.${class.name} delegate) {
        this(delegate, null);
    }

    public ${class.name}(${packageModelV4}.${class.name} delegate, BaseObject parent) {
        super(delegate, parent);
    }

    public ${class.name} clone(){
        return new ${class.name}(getDelegate());
    }

    #if ( $class.superClass )
    @Override
    #end
    public ${packageModelV4}.${class.name} getDelegate() {
        return (${packageModelV4}.${class.name}) super.getDelegate();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || !(o instanceof ${class.name})) {
            return false;
        }
        ${class.name} that = (${class.name}) o;
        return Objects.equals(this.delegate, that.delegate);
    }

    @Override
    public int hashCode() {
        return getDelegate().hashCode();
    }

    #if ( $class == $root )
    public String getModelEncoding() {
        return getDelegate().getModelEncoding();
    }

    #end
    #foreach ( $field in $class.getFields($version) )
      #set ( $cap = $Helper.capitalise( $field.name ) )
      #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} )
      #if ( $type == "boolean" || $type == "Boolean" )
        #set ( $pfx = "is" )
      #else
        #set ( $pfx = "get" )
      #end
      #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" )
    @Nonnull
      #end
    public ${type} ${pfx}${cap}() {
      #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
        return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>(
                    () -> getDelegate().get${cap}(), l -> update(getDelegate().with${cap}(l)),
                    d -> new ${field.to}(d, this), ${field.to}::getDelegate);
      #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" )
        return new WrapperProperties(() -> getDelegate().get${cap}(), this::set${cap});
      #elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
        return new WrapperList<String, ${field.to}>(() -> getDelegate().get${cap}(), this::set${cap}, s -> s, s -> s);
      #elseif ( $field.to )
        return getDelegate().${pfx}${cap}() != null ? new ${field.to}(getDelegate().${pfx}${cap}(), this) : null;
      #elseif ( $field.type == "DOM" )
        return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom(getDelegate().${pfx}${cap}(), this::replace) : null;
      #else
        return getDelegate().${pfx}${cap}();
      #end
    }

    public void set${cap}(${type} ${field.name}) {
      #if ($field.type == "DOM")
        if (${field.name} instanceof Xpp3Dom xpp3Dom) {
            if (!Objects.equals(xpp3Dom.getDom(), getDelegate().${pfx}${cap}())) {
                update(getDelegate().with${cap}(xpp3Dom.getDom()));
                xpp3Dom.setChildrenTracking(this::replace);
            }
        } else if (${field.name} == null) {
            if (getDelegate().${pfx}${cap}() != null) {
                update(getDelegate().with${cap}(null));
            }
        } else {
            throw new IllegalArgumentException("Expected an Xpp3Dom object but received a " + ${field.name}.getClass() + ": " + ${field.name});
        }
      #elseif( $field.type == "java.util.Properties" )
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        ${field.name}.forEach((key, value) -> {
            if (value != null) {
                map.put(key.toString(), value.toString());
            }
        });
        if (!Objects.equals(map, getDelegate().get${cap}())) {
            update(getDelegate().with${cap}(map));
        }
      #elseif ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
        if (${field.name} == null) {
            ${field.name} = Collections.emptyList();
        }
        if (!Objects.equals(${field.name}, ${pfx}${cap}())) {
            update(getDelegate().with${cap}(
                ${field.name}.stream().map(c -> c.getDelegate()).collect(Collectors.toList())));
            ${field.name}.forEach(e -> e.childrenTracking = this::replace);
        }
      #elseif ( $field.to && $field.to != "String" )
        if (!Objects.equals(${field.name}, ${pfx}${cap}())){
            if (${field.name} != null) {
                update(getDelegate().with${cap}(${field.name}.getDelegate()));
                ${field.name}.childrenTracking = this::replace;
            } else {
                update(getDelegate().with${cap}(null));
            }
        }
      #else
        if (!Objects.equals(${field.name}, ${pfx}${cap}())) {
            update(getDelegate().with${cap}(${field.name}));
        }
      #end
    }

      #if ( $field.type == "java.util.List" && $field.multiplicity == "*" )
        #set ( $v = $Helper.singular( ${field.name} ) )
        #set ( $scap = $Helper.capitalise( $v ) )
    public void add${scap}(${field.to} ${v}) {
        #if ( $field.to == "String" )
        update(getDelegate().with${cap}(
               Stream.concat(getDelegate().get${cap}().stream(), Stream.of(${v}))
                        .collect(Collectors.toList())));
        #else
        update(getDelegate().with${cap}(
               Stream.concat(getDelegate().get${cap}().stream(), Stream.of(${v}.getDelegate()))
                        .collect(Collectors.toList())));
        ${v}.childrenTracking = this::replace;
        #end
    }

    public void remove${scap}(${field.to} ${v}) {
        #if ( $field.to == "String" )
        update(getDelegate().with${cap}(
               getDelegate().get${cap}().stream()
                        .filter(e -> !Objects.equals(e, ${v}))
                        .collect(Collectors.toList())));
        #else
        update(getDelegate().with${cap}(
               getDelegate().get${cap}().stream()
                        .filter(e -> !Objects.equals(e, ${v}))
                        .collect(Collectors.toList())));
        ${v}.childrenTracking = null;
        #end
    }

      #elseif ( $field.type == "java.util.Properties" && $field.multiplicity == "*" )
        #set ( $v = $Helper.singular( ${field.name} ) )
        #set ( $scap = $Helper.capitalise( $v ) )
    public void add${scap}(String key, String value) {
        get${cap}().put(key, value);
    }

      #end
    #end
    #if ( $locationTracking )
    public InputLocation getLocation(Object key) {
        ${packageModelV4}.InputLocation loc = getDelegate().getLocation(key);
        return loc != null ? new InputLocation(loc) : null;
    }

    public void setLocation(Object key, InputLocation location) {
        update(${packageModelV4}.${class.name}.newBuilder(getDelegate(), true)
                        .location(key, location != null ? location.toApiLocation() : null).build());
    }

    public InputLocation getImportedFrom() {
        ${packageModelV4}.InputLocation loc = getDelegate().getImportedFrom();
        return loc != null ? new InputLocation(loc) : null;
    }

    public void setImportedFrom(InputLocation location) {
        update(${packageModelV4}.${class.name}.newBuilder(getDelegate(), true)
                        .importedFrom(location != null ? location.toApiLocation() : null).build());
    }

    public Set<Object> getLocationKeys() {
        return getDelegate().getLocationKeys();
    }

    #end
    protected boolean replace(Object oldDelegate, Object newDelegate) {
        if (super.replace(oldDelegate, newDelegate)) {
            return true;
        }
    #foreach ( $field in $class.getFields($version) )
      #set ( $cap = $Helper.capitalise( $field.name ) )
      #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} )
      #if ( $field.to && $field.multiplicity != "*" )
        if (oldDelegate == getDelegate().get${cap}()) {
            update(getDelegate().with${cap}((${packageModelV4}.${field.to}) newDelegate));
            return true;
        }
      #elseif ($field.type == "java.util.List" && $field.to != "String")
        if (getDelegate().get${cap}().contains(oldDelegate)) {
            List<${packageModelV4}.${field.to}> list = new ArrayList<>(getDelegate().get${cap}());
            list.replaceAll(d -> d == oldDelegate ? (${packageModelV4}.${field.to}) newDelegate : d);
            update(getDelegate().with${cap}(list));
            return true;
        }
      #elseif ( $field.type == "DOM" )
        if (getDelegate().get${cap}() == oldDelegate) {
            update(getDelegate().with${cap}((org.apache.maven.api.xml.XmlNode) newDelegate));
        }
      #end
    #end
        return false;
    }

    public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4(List<${class.name}> list) {
        return list != null ? new WrapperList<>(list, ${class.name}::getDelegate, ${class.name}::new) : null;
    }

    public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3(List<${packageModelV4}.${class.name}> list) {
        return list != null ? new WrapperList<>(list, ${class.name}::new, ${class.name}::getDelegate) : null;
    }

    #foreach ( $cs in $class.getCodeSegments($version) )
$cs.code
    #end
}
#end
