/**
* {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}}
*/{{#description}}
    @ApiModel(description = "{{{description}}}"){{/description}}
{{#jackson}}
    @JsonPropertyOrder({
    {{#vars}}
        {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
    {{/vars}}
    })
    @JsonTypeName("{{name}}")
{{/jackson}}
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{
{{#serializableModel}}
    private static final long serialVersionUID = 1L;

{{/serializableModel}}
{{#vars}}
    {{#isEnum}}
        {{^isContainer}}
            {{>modelInnerEnum}}
        {{/isContainer}}
        {{#isContainer}}
            {{#mostInnerItems}}
                {{>modelInnerEnum}}
            {{/mostInnerItems}}
        {{/isContainer}}
    {{/isEnum}}
    {{#gson}}
        public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
    {{/gson}}
    {{#jackson}}
        public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
    {{/jackson}}
    {{#withXml}}
        {{#isXmlAttribute}}
            @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
        {{/isXmlAttribute}}
        {{^isXmlAttribute}}
            {{^isContainer}}
                @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
            {{/isContainer}}
            {{#isContainer}}
                // Is a container wrapped={{isXmlWrapped}}
                {{#items}}
                    // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}}
                    // items.example={{example}} items.type={{dataType}}
                    @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
                {{/items}}
                {{#isXmlWrapped}}
                    @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
                {{/isXmlWrapped}}
            {{/isContainer}}
        {{/isXmlAttribute}}
    {{/withXml}}
    {{#gson}}
        @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}})
    {{/gson}}
    {{#vendorExtensions.x-is-jackson-optional-nullable}}
        {{#isContainer}}
            private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
        {{/isContainer}}
        {{^isContainer}}
            private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
        {{/isContainer}}
    {{/vendorExtensions.x-is-jackson-optional-nullable}}
    {{^vendorExtensions.x-is-jackson-optional-nullable}}
        {{#isContainer}}
            private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}};
        {{/isContainer}}
        {{^isContainer}}
            {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
        {{/isContainer}}
    {{/vendorExtensions.x-is-jackson-optional-nullable}}

{{/vars}}
{{#parcelableModel}}
    public {{classname}}() {
    {{#parent}}
        super();
    {{/parent}}
    {{#gson}}
        {{#discriminator}}
            this.{{{discriminatorName}}} = this.getClass().getSimpleName();
        {{/discriminator}}
    {{/gson}}
    }
{{/parcelableModel}}
{{^parcelableModel}}
    {{#gson}}
        {{#discriminator}}
            public {{classname}}() {
            this.{{{discriminatorName}}} = this.getClass().getSimpleName();
            }
        {{/discriminator}}
    {{/gson}}
{{/parcelableModel}}
{{#vars}}

        public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
        {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}}
        {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}}
        return this;
        }
        {{#isArray}}

            public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
            {{#vendorExtensions.x-is-jackson-optional-nullable}}
                if (this.{{name}} == null || !this.{{name}}.isPresent()) {
                this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}});
                }
                try {
                this.{{name}}.get().add({{name}}Item);
                } catch (java.util.NoSuchElementException e) {
                // this can never happen, as we make sure above that the value is present
                }
                return this;
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
            {{^vendorExtensions.x-is-jackson-optional-nullable}}
                {{^required}}
                    if (this.{{name}} == null) {
                    this.{{name}} = {{{defaultValue}}};
                    }
                {{/required}}
                this.{{name}}.add({{name}}Item);
                return this;
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
            }
        {{/isArray}}
        {{#isMap}}

            public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
            {{#vendorExtensions.x-is-jackson-optional-nullable}}
                if (this.{{name}} == null || !this.{{name}}.isPresent()) {
                this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}});
                }
                try {
                this.{{name}}.get().put(key, {{name}}Item);
                } catch (java.util.NoSuchElementException e) {
                // this can never happen, as we make sure above that the value is present
                }
                return this;
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
            {{^vendorExtensions.x-is-jackson-optional-nullable}}
                {{^required}}
                    if (this.{{name}} == null) {
                    this.{{name}} = {{{defaultValue}}};
                    }
                {{/required}}
                this.{{name}}.put(key, {{name}}Item);
                return this;
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
            }
        {{/isMap}}

    /**
    {{#description}}
        * {{description}}
    {{/description}}
    {{^description}}
        * Get {{name}}
    {{/description}}
    {{#minimum}}
        * minimum: {{minimum}}
    {{/minimum}}
    {{#maximum}}
        * maximum: {{maximum}}
    {{/maximum}}
    * @return {{name}}
    **/
    {{#required}}
        {{#isNullable}}
            @javax.annotation.Nullable
        {{/isNullable}}
    {{/required}}
    {{^required}}
        @javax.annotation.Nullable
    {{/required}}
    {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}  @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
    {{#vendorExtensions.x-extra-annotation}}
        {{{vendorExtensions.x-extra-annotation}}}
    {{/vendorExtensions.x-extra-annotation}}
    {{#vendorExtensions.x-is-jackson-optional-nullable}}
    {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}
        @JsonIgnore
    {{/vendorExtensions.x-is-jackson-optional-nullable}}
    {{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}}
    public {{{datatypeWithEnum}}} {{#isBoolean}}is{{nameInCamelCase}}{{/isBoolean}}{{^isBoolean}}{{getter}}{{/isBoolean}}() {
    {{#vendorExtensions.x-is-jackson-optional-nullable}}
        return {{name}}.orElse(null);
    {{/vendorExtensions.x-is-jackson-optional-nullable}}
    {{^vendorExtensions.x-is-jackson-optional-nullable}}
        return {{name}};
    {{/vendorExtensions.x-is-jackson-optional-nullable}}
    }

    {{#vendorExtensions.x-is-jackson-optional-nullable}}
        {{> jackson_annotations}}
        public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() {
        return {{name}};
        }
    {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}}
        @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
        public void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) {
        {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}}
        this.{{name}} = {{name}};
        }
    {{/vendorExtensions.x-is-jackson-optional-nullable}}

    public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
    {{#vendorExtensions.x-is-jackson-optional-nullable}}
        this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
    {{/vendorExtensions.x-is-jackson-optional-nullable}}
    {{^vendorExtensions.x-is-jackson-optional-nullable}}
        this.{{name}} = {{name}};
    {{/vendorExtensions.x-is-jackson-optional-nullable}}
    }

{{/vars}}

{{^supportJava6}}
    @Override
    public boolean equals(Object o) {
    {{#useReflectionEqualsHashCode}}
        return EqualsBuilder.reflectionEquals(this, o, false, null, true);
    {{/useReflectionEqualsHashCode}}
    {{^useReflectionEqualsHashCode}}
        if (this == o) {
        return true;
        }
        if (o == null || getClass() != o.getClass()) {
        return false;
        }{{#hasVars}}
            {{classname}} {{classVarName}} = ({{classname}}) o;
            return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
            {{/-last}}{{/vars}}{{#parent}} &&
            super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
            return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
    {{/useReflectionEqualsHashCode}}
    }

    @Override
    public int hashCode() {
    {{#useReflectionEqualsHashCode}}
        return HashCodeBuilder.reflectionHashCode(this);
    {{/useReflectionEqualsHashCode}}
    {{^useReflectionEqualsHashCode}}
        return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}});
    {{/useReflectionEqualsHashCode}}
    }

{{/supportJava6}}
{{#supportJava6}}
    @Override
    public boolean equals(Object o) {
    if (this == o) {
    return true;
    }
    if (o == null || getClass() != o.getClass()) {
    return false;
    }{{#hasVars}}
        {{classname}} {{classVarName}} = ({{classname}}) o;
        return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
        {{/-last}}{{/vars}}{{#parent}} &&
        super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
        return true;{{/hasVars}}
    }

    @Override
    public int hashCode() {
    return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}});
    }

{{/supportJava6}}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class {{classname}} {\n");
{{#parent}}
    sb.append("    ").append(toIndentedString(super.toString())).append("\n");
{{/parent}}
{{#vars}}
    sb.append("    {{name}}: ").append(toIndentedString({{name}})).append("\n");
{{/vars}}
sb.append("}");
return sb.toString();
}

/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n    ");
}

{{#parcelableModel}}

    public void writeToParcel(Parcel out, int flags) {
    {{#model}}
        {{#isArray}}
            out.writeList(this);
        {{/isArray}}
        {{^isArray}}
            {{#parent}}
                super.writeToParcel(out, flags);
            {{/parent}}
            {{#vars}}
                out.writeValue({{name}});
            {{/vars}}
        {{/isArray}}
    {{/model}}
    }

    {{classname}}(Parcel in) {
    {{#isArray}}
        in.readTypedList(this, {{arrayModelType}}.CREATOR);
    {{/isArray}}
    {{^isArray}}
        {{#parent}}
            super(in);
        {{/parent}}
        {{#vars}}
            {{#isPrimitiveType}}
                {{name}} = ({{{datatypeWithEnum}}})in.readValue(null);
            {{/isPrimitiveType}}
            {{^isPrimitiveType}}
                {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader());
            {{/isPrimitiveType}}
        {{/vars}}
    {{/isArray}}
    }

    public int describeContents() {
    return 0;
    }

    public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() {
    public {{classname}} createFromParcel(Parcel in) {
    {{#model}}
        {{#isArray}}
            {{classname}} result = new {{classname}}();
            result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader()));
            return result;
        {{/isArray}}
        {{^isArray}}
            return new {{classname}}(in);
        {{/isArray}}
    {{/model}}
    }
    public {{classname}}[] newArray(int size) {
    return new {{classname}}[size];
    }
    };
{{/parcelableModel}}
}
