##
## 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.
##
#if ($schema.getNamespace())
package $schema.getNamespace();  
#end
@SuppressWarnings("all")
#if ($schema.getDoc())
/** $schema.getDoc() */
#end
#foreach ($annotation in $this.javaAnnotations($schema))
@$annotation
#end
@org.apache.avro.specific.AvroGenerated
public class ${this.mangle($schema.getName())}#if ($schema.isError()) extends org.apache.avro.specific.SpecificExceptionBase#else extends org.apache.avro.specific.SpecificRecordBase#end implements org.apache.avro.specific.SpecificRecord {
  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse(${this.javaSplit($schema.toString())});
  public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
#foreach ($field in $schema.getFields())
#if ($field.doc())
  /** $field.doc() */
#end
#foreach ($annotation in $this.javaAnnotations($field))
  @$annotation
#end
  #if (${this.deprecatedFields()})@Deprecated#end #if (${this.publicFields()})public#elseif (${this.privateFields()})private#end ${this.javaUnbox($field.schema())} ${this.mangle($field.name(), $schema.isError())};
#end
#if ($schema.isError())

  public ${this.mangle($schema.getName())}() {
    super();
  }
  
  public ${this.mangle($schema.getName())}(Object value) {
    super(value);
  }

  public ${this.mangle($schema.getName())}(Throwable cause) {
    super(cause);
  }

  public ${this.mangle($schema.getName())}(Object value, Throwable cause) {
    super(value, cause);
  }
  
#else
#if ($schema.getFields().size() > 0)  

  /**
   * Default constructor.  Note that this does not initialize fields
   * to their default values from the schema.  If that is desired then
   * one should use <code>newBuilder()</code>. 
   */
  public ${this.mangle($schema.getName())}() {}

  /**
   * All-args constructor.
   */
  public ${this.mangle($schema.getName())}(#foreach($field in $schema.getFields())${this.javaType($field.schema())} ${this.mangle($field.name())}#if($velocityCount < $schema.getFields().size()), #end#end) {
#foreach ($field in $schema.getFields())
    this.${this.mangle($field.name())} = ${this.mangle($field.name())};
#end
  }
#end

#end
  public org.apache.avro.Schema getSchema() { return SCHEMA$; }
  // Used by DatumWriter.  Applications should not call. 
  public java.lang.Object get(int field$) {
    switch (field$) {
#set ($i = 0)
#foreach ($field in $schema.getFields())
    case $i: return ${this.mangle($field.name(), $schema.isError())};
#set ($i = $i + 1)
#end
    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
    }
  }
  // Used by DatumReader.  Applications should not call. 
  @SuppressWarnings(value="unchecked")
  public void put(int field$, java.lang.Object value$) {
    switch (field$) {
#set ($i = 0)
#foreach ($field in $schema.getFields())
    case $i: ${this.mangle($field.name(), $schema.isError())} = (${this.javaType($field.schema())})value$; break;
#set ($i = $i + 1)
#end
    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
    }
  }

#foreach ($field in $schema.getFields())
  /**
   * Gets the value of the '${this.mangle($field.name(), $schema.isError())}' field.
#if ($field.doc())   * $field.doc()#end
   */
  public ${this.javaType($field.schema())} ${this.generateGetMethod($schema, $field)}() {
    return ${this.mangle($field.name(), $schema.isError())};
  }

#if ($this.createSetters)
  /**
   * Sets the value of the '${this.mangle($field.name(), $schema.isError())}' field.
#if ($field.doc())   * $field.doc()#end
   * @param value the value to set.
   */
  public void ${this.generateSetMethod($schema, $field)}(${this.javaType($field.schema())} value) {
    this.${this.mangle($field.name(), $schema.isError())} = value;
  }
#end

#end
  /** Creates a new ${this.mangle($schema.getName())} RecordBuilder */
  public static #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder newBuilder() {
    return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder();
  }
  
  /** Creates a new ${this.mangle($schema.getName())} RecordBuilder by copying an existing Builder */
  public static #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder newBuilder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder other) {
    return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder(other);
  }
  
  /** Creates a new ${this.mangle($schema.getName())} RecordBuilder by copying an existing $this.mangle($schema.getName()) instance */
  public static #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder newBuilder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())} other) {
    return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder(other);
  }
  
  /**
   * RecordBuilder for ${this.mangle($schema.getName())} instances.
   */
  public static class Builder extends#if ($schema.isError()) org.apache.avro.specific.SpecificErrorBuilderBase<${this.mangle($schema.getName())}>#else org.apache.avro.specific.SpecificRecordBuilderBase<${this.mangle($schema.getName())}>#end

    implements#if ($schema.isError()) org.apache.avro.data.ErrorBuilder<${this.mangle($schema.getName())}>#else org.apache.avro.data.RecordBuilder<${this.mangle($schema.getName())}>#end {

#foreach ($field in $schema.getFields())
    private ${this.javaUnbox($field.schema())} ${this.mangle($field.name(), $schema.isError())};
#end

    /** Creates a new Builder */
    private Builder() {
      super(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.SCHEMA$);
    }
    
    /** Creates a Builder by copying an existing Builder */
    private Builder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder other) {
      super(other);
#foreach ($field in $schema.getFields())
      if (isValidValue(fields()[$field.pos()], other.${this.mangle($field.name(), $schema.isError())})) {
        this.${this.mangle($field.name(), $schema.isError())} = data().deepCopy(fields()[$field.pos()].schema(), other.${this.mangle($field.name(), $schema.isError())});
        fieldSetFlags()[$field.pos()] = true;
      }
#end
    }
    
    /** Creates a Builder by copying an existing $this.mangle($schema.getName()) instance */
    private Builder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())} other) {
      #if ($schema.isError())super(other)#else
      super(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.SCHEMA$)#end;
#foreach ($field in $schema.getFields())
      if (isValidValue(fields()[$field.pos()], other.${this.mangle($field.name(), $schema.isError())})) {
        this.${this.mangle($field.name(), $schema.isError())} = data().deepCopy(fields()[$field.pos()].schema(), other.${this.mangle($field.name(), $schema.isError())});
        fieldSetFlags()[$field.pos()] = true;
      }
#end
    }
#if ($schema.isError())

    @Override
    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder setValue(Object value) {
      super.setValue(value);
      return this;
    }
    
    @Override
    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder clearValue() {
      super.clearValue();
      return this;
    }

    @Override
    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder setCause(Throwable cause) {
      super.setCause(cause);
      return this;
    }
    
    @Override
    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder clearCause() {
      super.clearCause();
      return this;
    }
#end

#foreach ($field in $schema.getFields())
    /** Gets the value of the '${this.mangle($field.name(), $schema.isError())}' field */
    public ${this.javaType($field.schema())} ${this.generateGetMethod($schema, $field)}() {
      return ${this.mangle($field.name(), $schema.isError())};
    }
    
    /** Sets the value of the '${this.mangle($field.name(), $schema.isError())}' field */
    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder ${this.generateSetMethod($schema, $field)}(${this.javaUnbox($field.schema())} value) {
      validate(fields()[$field.pos()], value);
      this.${this.mangle($field.name(), $schema.isError())} = value;
      fieldSetFlags()[$field.pos()] = true;
      return this; 
    }
    
    /** Checks whether the '${this.mangle($field.name(), $schema.isError())}' field has been set */
    public boolean ${this.generateHasMethod($schema, $field)}() {
      return fieldSetFlags()[$field.pos()];
    }
    
    /** Clears the value of the '${this.mangle($field.name(), $schema.isError())}' field */
    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder ${this.generateClearMethod($schema, $field)}() {
#if (${this.isUnboxedJavaTypeNullable($field.schema())})
      ${this.mangle($field.name(), $schema.isError())} = null;
#end
      fieldSetFlags()[$field.pos()] = false;
      return this;
    }

#end
    @Override
    public ${this.mangle($schema.getName())} build() {
      try {
        ${this.mangle($schema.getName())} record = new ${this.mangle($schema.getName())}(#if ($schema.isError())getValue(), getCause()#end);
#foreach ($field in $schema.getFields())
        record.${this.mangle($field.name(), $schema.isError())} = fieldSetFlags()[$field.pos()] ? this.${this.mangle($field.name(), $schema.isError())} : (${this.javaType($field.schema())}) defaultValue(fields()[$field.pos()]);
#end
        return record;
      } catch (Exception e) {
        throw new org.apache.avro.AvroRuntimeException(e);
      }
    }
  }
}
