#*
  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.List" ) )
    #set ( $dummy = $imports.add( "java.util.Map" ) )
    #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) {
            if (!Objects.equals(((Xpp3Dom) ${field.name}).getDom(), getDelegate().${pfx}${cap}())) {
                update(getDelegate().with${cap}(((Xpp3Dom) ${field.name}).getDom()));
                ((Xpp3Dom) ${field.name}).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" )
        Map<String, String> map = ${field.name}.entrySet().stream()
                .collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().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.toApiLocation()).build());
    }

    #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
