This is an automated email from the ASF dual-hosted git repository.

dkulp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new 8197803  [AVRO-2630] Part 2 - allow the JSR310 conversions to truncate 
at the appropriate value
8197803 is described below

commit 8197803dceb89d53d6f5a3e9143f46c035d6558b
Author: Daniel Kulp <[email protected]>
AuthorDate: Thu Mar 28 13:39:58 2019 -0400

    [AVRO-2630] Part 2 - allow the JSR310 conversions to truncate at the 
appropriate value
---
 .../src/main/java/org/apache/avro/Conversion.java  |  13 +
 .../apache/avro/data/Jsr310TimeConversions.java    |  20 +
 .../avro/compiler/specific/SpecificCompiler.java   |  11 +
 .../specific/templates/java/classic/record.vm      |   6 +-
 .../tools/src/test/compiler/input/fieldtest.avsc   |  10 +
 .../avro/examples/baseball/FieldTest.java          | 664 +++++++++++++++++++++
 .../apache/avro/tool/TestSpecificCompilerTool.java |  12 +
 pom.xml                                            |   1 +
 8 files changed, 734 insertions(+), 3 deletions(-)

diff --git a/lang/java/avro/src/main/java/org/apache/avro/Conversion.java 
b/lang/java/avro/src/main/java/org/apache/avro/Conversion.java
index 9e036df..b0cf701 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Conversion.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Conversion.java
@@ -61,6 +61,19 @@ public abstract class Conversion<T> {
    */
   public abstract String getLogicalTypeName();
 
+  /**
+   * Certain logical types may require adjusting the code within the "setter"
+   * methods to make sure the data that is set is properly formatted. This 
method
+   * allows teh Conversion to generate custom setter code if required.
+   * 
+   * @param varName
+   * @param valParamName
+   * @return a String for the body of the setter method
+   */
+  public String adjustAndSetValue(String varName, String valParamName) {
+    return varName + " = " + valParamName + ";";
+  }
+
   public Schema getRecommendedSchema() {
     throw new UnsupportedOperationException("No recommended schema for " + 
getLogicalTypeName());
   }
diff --git 
a/lang/java/avro/src/main/java/org/apache/avro/data/Jsr310TimeConversions.java 
b/lang/java/avro/src/main/java/org/apache/avro/data/Jsr310TimeConversions.java
index a717bbc..0f608dc 100644
--- 
a/lang/java/avro/src/main/java/org/apache/avro/data/Jsr310TimeConversions.java
+++ 
b/lang/java/avro/src/main/java/org/apache/avro/data/Jsr310TimeConversions.java
@@ -71,6 +71,11 @@ public class Jsr310TimeConversions {
     }
 
     @Override
+    public String adjustAndSetValue(String varName, String valParamName) {
+      return varName + " = " + valParamName + 
".truncatedTo(java.time.temporal.ChronoUnit.MILLIS);";
+    }
+
+    @Override
     public LocalTime fromInt(Integer millisFromMidnight, Schema schema, 
LogicalType type) {
       return 
LocalTime.ofNanoOfDay(TimeUnit.MILLISECONDS.toNanos(millisFromMidnight));
     }
@@ -98,6 +103,11 @@ public class Jsr310TimeConversions {
     }
 
     @Override
+    public String adjustAndSetValue(String varName, String valParamName) {
+      return varName + " = " + valParamName + 
".truncatedTo(java.time.temporal.ChronoUnit.MICROS);";
+    }
+
+    @Override
     public LocalTime fromLong(Long microsFromMidnight, Schema schema, 
LogicalType type) {
       return 
LocalTime.ofNanoOfDay(TimeUnit.MICROSECONDS.toNanos(microsFromMidnight));
     }
@@ -125,6 +135,11 @@ public class Jsr310TimeConversions {
     }
 
     @Override
+    public String adjustAndSetValue(String varName, String valParamName) {
+      return varName + " = " + valParamName + 
".truncatedTo(java.time.temporal.ChronoUnit.MILLIS);";
+    }
+
+    @Override
     public Instant fromLong(Long millisFromEpoch, Schema schema, LogicalType 
type) {
       return Instant.ofEpochMilli(millisFromEpoch);
     }
@@ -152,6 +167,11 @@ public class Jsr310TimeConversions {
     }
 
     @Override
+    public String adjustAndSetValue(String varName, String valParamName) {
+      return varName + " = " + valParamName + 
".truncatedTo(java.time.temporal.ChronoUnit.MICROS);";
+    }
+
+    @Override
     public Instant fromLong(Long microsFromEpoch, Schema schema, LogicalType 
type) {
       long epochSeconds = microsFromEpoch / (1_000_000);
       long nanoAdjustment = (microsFromEpoch % (1_000_000)) * 1_000;
diff --git 
a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
 
b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
index cf86c5d..730a1e9 100644
--- 
a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
+++ 
b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
@@ -820,6 +820,17 @@ public class SpecificCompiler {
   }
 
   /**
+   * Utility for template use.
+   */
+  public String generateSetterCode(Schema schema, String name, String pname) {
+    Conversion<?> conversion = 
specificData.getConversionFor(schema.getLogicalType());
+    if (conversion != null) {
+      return conversion.adjustAndSetValue("this." + name, pname);
+    }
+    return "this." + name + " = " + pname + ";";
+  }
+
+  /**
    * Utility for template use. Returns the unboxed java type for a Schema.
    *
    * @Deprecated use javaUnbox(Schema, boolean), kept for backward 
compatibiliby
diff --git 
a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
 
b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
index 23b5848..738ffac 100644
--- 
a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
+++ 
b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
@@ -152,7 +152,7 @@ static {
    */
   public ${this.mangle($schema.getName())}(#foreach($field in 
$schema.getFields())${this.javaType($field.schema())} 
${this.mangle($field.name())}#if($foreach.count < $schema.getFields().size()), 
#end#end) {
 #foreach ($field in $schema.getFields())
-    this.${this.mangle($field.name())} = ${this.mangle($field.name())};
+    ${this.generateSetterCode($field.schema(), ${this.mangle($field.name())}, 
${this.mangle($field.name())})}
 #end
   }
 #else
@@ -251,7 +251,7 @@ static {
    * @param value the value to set.
    */
   public void ${this.generateSetMethod($schema, 
$field)}(${this.javaUnbox($field.schema())} value) {
-    this.${this.mangle($field.name(), $schema.isError())} = value;
+    ${this.generateSetterCode($field.schema(), ${this.mangle($field.name(), 
$schema.isError())}, "value")}
   }
 #end
 
@@ -410,7 +410,7 @@ static {
 #if (${this.hasBuilder($field.schema())})
       this.${this.mangle($field.name(), $schema.isError())}Builder = null;
 #end
-      this.${this.mangle($field.name(), $schema.isError())} = value;
+      ${this.generateSetterCode($field.schema(), ${this.mangle($field.name(), 
$schema.isError())}, "value")}
       fieldSetFlags()[$field.pos()] = true;
       return this;
     }
diff --git a/lang/java/tools/src/test/compiler/input/fieldtest.avsc 
b/lang/java/tools/src/test/compiler/input/fieldtest.avsc
new file mode 100644
index 0000000..fad6355
--- /dev/null
+++ b/lang/java/tools/src/test/compiler/input/fieldtest.avsc
@@ -0,0 +1,10 @@
+{"type":"record", "name":"FieldTest", "namespace": 
"avro.examples.baseball","doc":"Test various field types",
+  "fields": [
+   {"name": "number", "type": "int", "doc": "The number of the player"},
+   {"name": "last_name", "type": "string"},
+   {"name": "timestamp", "type": { "type": "long", "logicalType": 
"timestamp-millis"}},
+   {"name": "timestampMicros", "type": { "type": "long", "logicalType": 
"timestamp-micros"}},
+   {"name": "timeMillis", "type": { "type": "int", "logicalType": 
"time-millis"}},
+   {"name": "timeMicros", "type": { "type": "long", "logicalType": 
"time-micros"}}
+  ]
+}
diff --git 
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
 
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
new file mode 100644
index 0000000..5187554
--- /dev/null
+++ 
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
@@ -0,0 +1,664 @@
+/**
+ * Autogenerated by Avro
+ *
+ * DO NOT EDIT DIRECTLY
+ */
+package avro.examples.baseball;
+
+import org.apache.avro.generic.GenericArray;
+import org.apache.avro.specific.SpecificData;
+import org.apache.avro.util.Utf8;
+import org.apache.avro.message.BinaryMessageEncoder;
+import org.apache.avro.message.BinaryMessageDecoder;
+import org.apache.avro.message.SchemaStore;
+
+/** Test various field types */
[email protected]
+public class FieldTest extends org.apache.avro.specific.SpecificRecordBase 
implements org.apache.avro.specific.SpecificRecord {
+  private static final long serialVersionUID = 4609235620572341636L;
+  public static final org.apache.avro.Schema SCHEMA$ = new 
org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"FieldTest\",\"namespace\":\"avro.examples.baseball\",\"doc\":\"Test
 various field 
types\",\"fields\":[{\"name\":\"number\",\"type\":\"int\",\"doc\":\"The number 
of the 
player\"},{\"name\":\"last_name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"timestamp\",\"type\":{\"type\":\"long\",\"logicalType\":\"timestamp-millis\"}},{\"na
 [...]
+  public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
+
+  private static SpecificData MODEL$ = new SpecificData();
+static {
+    MODEL$.addLogicalTypeConversion(new 
org.apache.avro.data.Jsr310TimeConversions.TimestampMillisConversion());
+    MODEL$.addLogicalTypeConversion(new 
org.apache.avro.data.Jsr310TimeConversions.TimeMillisConversion());
+  }
+
+  private static final BinaryMessageEncoder<FieldTest> ENCODER =
+      new BinaryMessageEncoder<FieldTest>(MODEL$, SCHEMA$);
+
+  private static final BinaryMessageDecoder<FieldTest> DECODER =
+      new BinaryMessageDecoder<FieldTest>(MODEL$, SCHEMA$);
+
+  /**
+   * Return the BinaryMessageEncoder instance used by this class.
+   * @return the message encoder used by this class
+   */
+  public static BinaryMessageEncoder<FieldTest> getEncoder() {
+    return ENCODER;
+  }
+
+  /**
+   * Return the BinaryMessageDecoder instance used by this class.
+   * @return the message decoder used by this class
+   */
+  public static BinaryMessageDecoder<FieldTest> getDecoder() {
+    return DECODER;
+  }
+
+  /**
+   * Create a new BinaryMessageDecoder instance for this class that uses the 
specified {@link SchemaStore}.
+   * @param resolver a {@link SchemaStore} used to find schemas by fingerprint
+   * @return a BinaryMessageDecoder instance for this class backed by the 
given SchemaStore
+   */
+  public static BinaryMessageDecoder<FieldTest> createDecoder(SchemaStore 
resolver) {
+    return new BinaryMessageDecoder<FieldTest>(MODEL$, SCHEMA$, resolver);
+  }
+
+  /**
+   * Serializes this FieldTest to a ByteBuffer.
+   * @return a buffer holding the serialized data for this instance
+   * @throws java.io.IOException if this instance could not be serialized
+   */
+  public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException {
+    return ENCODER.encode(this);
+  }
+
+  /**
+   * Deserializes a FieldTest from a ByteBuffer.
+   * @param b a byte buffer holding serialized data for an instance of this 
class
+   * @return a FieldTest instance decoded from the given buffer
+   * @throws java.io.IOException if the given bytes could not be deserialized 
into an instance of this class
+   */
+  public static FieldTest fromByteBuffer(
+      java.nio.ByteBuffer b) throws java.io.IOException {
+    return DECODER.decode(b);
+  }
+
+  /** The number of the player */
+   private int number;
+   private java.lang.String last_name;
+   private java.time.Instant timestamp;
+   private java.time.Instant timestampMicros;
+   private java.time.LocalTime timeMillis;
+   private java.time.LocalTime timeMicros;
+
+  /**
+   * 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 FieldTest() {}
+
+  /**
+   * All-args constructor.
+   * @param number The number of the player
+   * @param last_name The new value for last_name
+   * @param timestamp The new value for timestamp
+   * @param timestampMicros The new value for timestampMicros
+   * @param timeMillis The new value for timeMillis
+   * @param timeMicros The new value for timeMicros
+   */
+  public FieldTest(java.lang.Integer number, java.lang.String last_name, 
java.time.Instant timestamp, java.time.Instant timestampMicros, 
java.time.LocalTime timeMillis, java.time.LocalTime timeMicros) {
+    this.number = number;
+    this.last_name = last_name;
+    this.timestamp = 
timestamp.truncatedTo(java.time.temporal.ChronoUnit.MILLIS);
+    this.timestampMicros = 
timestampMicros.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
+    this.timeMillis = 
timeMillis.truncatedTo(java.time.temporal.ChronoUnit.MILLIS);
+    this.timeMicros = 
timeMicros.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
+  }
+
+  public org.apache.avro.specific.SpecificData getSpecificData() { return 
MODEL$; }
+  public org.apache.avro.Schema getSchema() { return SCHEMA$; }
+  // Used by DatumWriter.  Applications should not call.
+  public java.lang.Object get(int field$) {
+    switch (field$) {
+    case 0: return number;
+    case 1: return last_name;
+    case 2: return timestamp;
+    case 3: return timestampMicros;
+    case 4: return timeMillis;
+    case 5: return timeMicros;
+    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    }
+  }
+
+  private static final org.apache.avro.Conversion<?>[] conversions =
+      new org.apache.avro.Conversion<?>[] {
+      null,
+      null,
+      new 
org.apache.avro.data.Jsr310TimeConversions.TimestampMillisConversion(),
+      new 
org.apache.avro.data.Jsr310TimeConversions.TimestampMicrosConversion(),
+      new org.apache.avro.data.Jsr310TimeConversions.TimeMillisConversion(),
+      new org.apache.avro.data.Jsr310TimeConversions.TimeMicrosConversion(),
+      null
+  };
+
+  @Override
+  public org.apache.avro.Conversion<?> getConversion(int field) {
+    return conversions[field];
+  }
+
+  // Used by DatumReader.  Applications should not call.
+  @SuppressWarnings(value="unchecked")
+  public void put(int field$, java.lang.Object value$) {
+    switch (field$) {
+    case 0: number = (java.lang.Integer)value$; break;
+    case 1: last_name = (java.lang.String)value$; break;
+    case 2: timestamp = (java.time.Instant)value$; break;
+    case 3: timestampMicros = (java.time.Instant)value$; break;
+    case 4: timeMillis = (java.time.LocalTime)value$; break;
+    case 5: timeMicros = (java.time.LocalTime)value$; break;
+    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    }
+  }
+
+  /**
+   * Gets the value of the 'number' field.
+   * @return The number of the player
+   */
+  public int getNumber() {
+    return number;
+  }
+
+
+  /**
+   * Sets the value of the 'number' field.
+   * The number of the player
+   * @param value the value to set.
+   */
+  public void setNumber(int value) {
+    this.number = value;
+  }
+
+  /**
+   * Gets the value of the 'last_name' field.
+   * @return The value of the 'last_name' field.
+   */
+  public java.lang.String getLastName() {
+    return last_name;
+  }
+
+
+  /**
+   * Sets the value of the 'last_name' field.
+   * @param value the value to set.
+   */
+  public void setLastName(java.lang.String value) {
+    this.last_name = value;
+  }
+
+  /**
+   * Gets the value of the 'timestamp' field.
+   * @return The value of the 'timestamp' field.
+   */
+  public java.time.Instant getTimestamp() {
+    return timestamp;
+  }
+
+
+  /**
+   * Sets the value of the 'timestamp' field.
+   * @param value the value to set.
+   */
+  public void setTimestamp(java.time.Instant value) {
+    this.timestamp = value.truncatedTo(java.time.temporal.ChronoUnit.MILLIS);
+  }
+
+  /**
+   * Gets the value of the 'timestampMicros' field.
+   * @return The value of the 'timestampMicros' field.
+   */
+  public java.time.Instant getTimestampMicros() {
+    return timestampMicros;
+  }
+
+
+  /**
+   * Sets the value of the 'timestampMicros' field.
+   * @param value the value to set.
+   */
+  public void setTimestampMicros(java.time.Instant value) {
+    this.timestampMicros = 
value.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
+  }
+
+  /**
+   * Gets the value of the 'timeMillis' field.
+   * @return The value of the 'timeMillis' field.
+   */
+  public java.time.LocalTime getTimeMillis() {
+    return timeMillis;
+  }
+
+
+  /**
+   * Sets the value of the 'timeMillis' field.
+   * @param value the value to set.
+   */
+  public void setTimeMillis(java.time.LocalTime value) {
+    this.timeMillis = value.truncatedTo(java.time.temporal.ChronoUnit.MILLIS);
+  }
+
+  /**
+   * Gets the value of the 'timeMicros' field.
+   * @return The value of the 'timeMicros' field.
+   */
+  public java.time.LocalTime getTimeMicros() {
+    return timeMicros;
+  }
+
+
+  /**
+   * Sets the value of the 'timeMicros' field.
+   * @param value the value to set.
+   */
+  public void setTimeMicros(java.time.LocalTime value) {
+    this.timeMicros = value.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
+  }
+
+  /**
+   * Creates a new FieldTest RecordBuilder.
+   * @return A new FieldTest RecordBuilder
+   */
+  public static avro.examples.baseball.FieldTest.Builder newBuilder() {
+    return new avro.examples.baseball.FieldTest.Builder();
+  }
+
+  /**
+   * Creates a new FieldTest RecordBuilder by copying an existing Builder.
+   * @param other The existing builder to copy.
+   * @return A new FieldTest RecordBuilder
+   */
+  public static avro.examples.baseball.FieldTest.Builder 
newBuilder(avro.examples.baseball.FieldTest.Builder other) {
+    if (other == null) {
+      return new avro.examples.baseball.FieldTest.Builder();
+    } else {
+      return new avro.examples.baseball.FieldTest.Builder(other);
+    }
+  }
+
+  /**
+   * Creates a new FieldTest RecordBuilder by copying an existing FieldTest 
instance.
+   * @param other The existing instance to copy.
+   * @return A new FieldTest RecordBuilder
+   */
+  public static avro.examples.baseball.FieldTest.Builder 
newBuilder(avro.examples.baseball.FieldTest other) {
+    if (other == null) {
+      return new avro.examples.baseball.FieldTest.Builder();
+    } else {
+      return new avro.examples.baseball.FieldTest.Builder(other);
+    }
+  }
+
+  /**
+   * RecordBuilder for FieldTest instances.
+   */
+  public static class Builder extends 
org.apache.avro.specific.SpecificRecordBuilderBase<FieldTest>
+    implements org.apache.avro.data.RecordBuilder<FieldTest> {
+
+    /** The number of the player */
+    private int number;
+    private java.lang.String last_name;
+    private java.time.Instant timestamp;
+    private java.time.Instant timestampMicros;
+    private java.time.LocalTime timeMillis;
+    private java.time.LocalTime timeMicros;
+
+    /** Creates a new Builder */
+    private Builder() {
+      super(SCHEMA$);
+    }
+
+    /**
+     * Creates a Builder by copying an existing Builder.
+     * @param other The existing Builder to copy.
+     */
+    private Builder(avro.examples.baseball.FieldTest.Builder other) {
+      super(other);
+      if (isValidValue(fields()[0], other.number)) {
+        this.number = data().deepCopy(fields()[0].schema(), other.number);
+        fieldSetFlags()[0] = other.fieldSetFlags()[0];
+      }
+      if (isValidValue(fields()[1], other.last_name)) {
+        this.last_name = data().deepCopy(fields()[1].schema(), 
other.last_name);
+        fieldSetFlags()[1] = other.fieldSetFlags()[1];
+      }
+      if (isValidValue(fields()[2], other.timestamp)) {
+        this.timestamp = data().deepCopy(fields()[2].schema(), 
other.timestamp);
+        fieldSetFlags()[2] = other.fieldSetFlags()[2];
+      }
+      if (isValidValue(fields()[3], other.timestampMicros)) {
+        this.timestampMicros = data().deepCopy(fields()[3].schema(), 
other.timestampMicros);
+        fieldSetFlags()[3] = other.fieldSetFlags()[3];
+      }
+      if (isValidValue(fields()[4], other.timeMillis)) {
+        this.timeMillis = data().deepCopy(fields()[4].schema(), 
other.timeMillis);
+        fieldSetFlags()[4] = other.fieldSetFlags()[4];
+      }
+      if (isValidValue(fields()[5], other.timeMicros)) {
+        this.timeMicros = data().deepCopy(fields()[5].schema(), 
other.timeMicros);
+        fieldSetFlags()[5] = other.fieldSetFlags()[5];
+      }
+    }
+
+    /**
+     * Creates a Builder by copying an existing FieldTest instance
+     * @param other The existing instance to copy.
+     */
+    private Builder(avro.examples.baseball.FieldTest other) {
+      super(SCHEMA$);
+      if (isValidValue(fields()[0], other.number)) {
+        this.number = data().deepCopy(fields()[0].schema(), other.number);
+        fieldSetFlags()[0] = true;
+      }
+      if (isValidValue(fields()[1], other.last_name)) {
+        this.last_name = data().deepCopy(fields()[1].schema(), 
other.last_name);
+        fieldSetFlags()[1] = true;
+      }
+      if (isValidValue(fields()[2], other.timestamp)) {
+        this.timestamp = data().deepCopy(fields()[2].schema(), 
other.timestamp);
+        fieldSetFlags()[2] = true;
+      }
+      if (isValidValue(fields()[3], other.timestampMicros)) {
+        this.timestampMicros = data().deepCopy(fields()[3].schema(), 
other.timestampMicros);
+        fieldSetFlags()[3] = true;
+      }
+      if (isValidValue(fields()[4], other.timeMillis)) {
+        this.timeMillis = data().deepCopy(fields()[4].schema(), 
other.timeMillis);
+        fieldSetFlags()[4] = true;
+      }
+      if (isValidValue(fields()[5], other.timeMicros)) {
+        this.timeMicros = data().deepCopy(fields()[5].schema(), 
other.timeMicros);
+        fieldSetFlags()[5] = true;
+      }
+    }
+
+    /**
+      * Gets the value of the 'number' field.
+      * The number of the player
+      * @return The value.
+      */
+    public int getNumber() {
+      return number;
+    }
+
+
+    /**
+      * Sets the value of the 'number' field.
+      * The number of the player
+      * @param value The value of 'number'.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder setNumber(int value) {
+      validate(fields()[0], value);
+      this.number = value;
+      fieldSetFlags()[0] = true;
+      return this;
+    }
+
+    /**
+      * Checks whether the 'number' field has been set.
+      * The number of the player
+      * @return True if the 'number' field has been set, false otherwise.
+      */
+    public boolean hasNumber() {
+      return fieldSetFlags()[0];
+    }
+
+
+    /**
+      * Clears the value of the 'number' field.
+      * The number of the player
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder clearNumber() {
+      fieldSetFlags()[0] = false;
+      return this;
+    }
+
+    /**
+      * Gets the value of the 'last_name' field.
+      * @return The value.
+      */
+    public java.lang.String getLastName() {
+      return last_name;
+    }
+
+
+    /**
+      * Sets the value of the 'last_name' field.
+      * @param value The value of 'last_name'.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder 
setLastName(java.lang.String value) {
+      validate(fields()[1], value);
+      this.last_name = value;
+      fieldSetFlags()[1] = true;
+      return this;
+    }
+
+    /**
+      * Checks whether the 'last_name' field has been set.
+      * @return True if the 'last_name' field has been set, false otherwise.
+      */
+    public boolean hasLastName() {
+      return fieldSetFlags()[1];
+    }
+
+
+    /**
+      * Clears the value of the 'last_name' field.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder clearLastName() {
+      last_name = null;
+      fieldSetFlags()[1] = false;
+      return this;
+    }
+
+    /**
+      * Gets the value of the 'timestamp' field.
+      * @return The value.
+      */
+    public java.time.Instant getTimestamp() {
+      return timestamp;
+    }
+
+
+    /**
+      * Sets the value of the 'timestamp' field.
+      * @param value The value of 'timestamp'.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder 
setTimestamp(java.time.Instant value) {
+      validate(fields()[2], value);
+      this.timestamp = value.truncatedTo(java.time.temporal.ChronoUnit.MILLIS);
+      fieldSetFlags()[2] = true;
+      return this;
+    }
+
+    /**
+      * Checks whether the 'timestamp' field has been set.
+      * @return True if the 'timestamp' field has been set, false otherwise.
+      */
+    public boolean hasTimestamp() {
+      return fieldSetFlags()[2];
+    }
+
+
+    /**
+      * Clears the value of the 'timestamp' field.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder clearTimestamp() {
+      fieldSetFlags()[2] = false;
+      return this;
+    }
+
+    /**
+      * Gets the value of the 'timestampMicros' field.
+      * @return The value.
+      */
+    public java.time.Instant getTimestampMicros() {
+      return timestampMicros;
+    }
+
+
+    /**
+      * Sets the value of the 'timestampMicros' field.
+      * @param value The value of 'timestampMicros'.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder 
setTimestampMicros(java.time.Instant value) {
+      validate(fields()[3], value);
+      this.timestampMicros = 
value.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
+      fieldSetFlags()[3] = true;
+      return this;
+    }
+
+    /**
+      * Checks whether the 'timestampMicros' field has been set.
+      * @return True if the 'timestampMicros' field has been set, false 
otherwise.
+      */
+    public boolean hasTimestampMicros() {
+      return fieldSetFlags()[3];
+    }
+
+
+    /**
+      * Clears the value of the 'timestampMicros' field.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder clearTimestampMicros() {
+      fieldSetFlags()[3] = false;
+      return this;
+    }
+
+    /**
+      * Gets the value of the 'timeMillis' field.
+      * @return The value.
+      */
+    public java.time.LocalTime getTimeMillis() {
+      return timeMillis;
+    }
+
+
+    /**
+      * Sets the value of the 'timeMillis' field.
+      * @param value The value of 'timeMillis'.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder 
setTimeMillis(java.time.LocalTime value) {
+      validate(fields()[4], value);
+      this.timeMillis = 
value.truncatedTo(java.time.temporal.ChronoUnit.MILLIS);
+      fieldSetFlags()[4] = true;
+      return this;
+    }
+
+    /**
+      * Checks whether the 'timeMillis' field has been set.
+      * @return True if the 'timeMillis' field has been set, false otherwise.
+      */
+    public boolean hasTimeMillis() {
+      return fieldSetFlags()[4];
+    }
+
+
+    /**
+      * Clears the value of the 'timeMillis' field.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder clearTimeMillis() {
+      fieldSetFlags()[4] = false;
+      return this;
+    }
+
+    /**
+      * Gets the value of the 'timeMicros' field.
+      * @return The value.
+      */
+    public java.time.LocalTime getTimeMicros() {
+      return timeMicros;
+    }
+
+
+    /**
+      * Sets the value of the 'timeMicros' field.
+      * @param value The value of 'timeMicros'.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder 
setTimeMicros(java.time.LocalTime value) {
+      validate(fields()[5], value);
+      this.timeMicros = 
value.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
+      fieldSetFlags()[5] = true;
+      return this;
+    }
+
+    /**
+      * Checks whether the 'timeMicros' field has been set.
+      * @return True if the 'timeMicros' field has been set, false otherwise.
+      */
+    public boolean hasTimeMicros() {
+      return fieldSetFlags()[5];
+    }
+
+
+    /**
+      * Clears the value of the 'timeMicros' field.
+      * @return This builder.
+      */
+    public avro.examples.baseball.FieldTest.Builder clearTimeMicros() {
+      fieldSetFlags()[5] = false;
+      return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public FieldTest build() {
+      try {
+        FieldTest record = new FieldTest();
+        record.number = fieldSetFlags()[0] ? this.number : (java.lang.Integer) 
defaultValue(fields()[0]);
+        record.last_name = fieldSetFlags()[1] ? this.last_name : 
(java.lang.String) defaultValue(fields()[1]);
+        record.timestamp = fieldSetFlags()[2] ? this.timestamp : 
(java.time.Instant) defaultValue(fields()[2]);
+        record.timestampMicros = fieldSetFlags()[3] ? this.timestampMicros : 
(java.time.Instant) defaultValue(fields()[3]);
+        record.timeMillis = fieldSetFlags()[4] ? this.timeMillis : 
(java.time.LocalTime) defaultValue(fields()[4]);
+        record.timeMicros = fieldSetFlags()[5] ? this.timeMicros : 
(java.time.LocalTime) defaultValue(fields()[5]);
+        return record;
+      } catch (org.apache.avro.AvroMissingFieldException e) {
+        throw e;
+      } catch (java.lang.Exception e) {
+        throw new org.apache.avro.AvroRuntimeException(e);
+      }
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private static final org.apache.avro.io.DatumWriter<FieldTest>
+    WRITER$ = 
(org.apache.avro.io.DatumWriter<FieldTest>)MODEL$.createDatumWriter(SCHEMA$);
+
+  @Override public void writeExternal(java.io.ObjectOutput out)
+    throws java.io.IOException {
+    WRITER$.write(this, SpecificData.getEncoder(out));
+  }
+
+  @SuppressWarnings("unchecked")
+  private static final org.apache.avro.io.DatumReader<FieldTest>
+    READER$ = 
(org.apache.avro.io.DatumReader<FieldTest>)MODEL$.createDatumReader(SCHEMA$);
+
+  @Override public void readExternal(java.io.ObjectInput in)
+    throws java.io.IOException {
+    READER$.read(this, SpecificData.getDecoder(in));
+  }
+
+}
+
+
+
+
+
+
+
+
+
+
diff --git 
a/lang/java/tools/src/test/java/org/apache/avro/tool/TestSpecificCompilerTool.java
 
b/lang/java/tools/src/test/java/org/apache/avro/tool/TestSpecificCompilerTool.java
index 85aec64..cc5c38f 100644
--- 
a/lang/java/tools/src/test/java/org/apache/avro/tool/TestSpecificCompilerTool.java
+++ 
b/lang/java/tools/src/test/java/org/apache/avro/tool/TestSpecificCompilerTool.java
@@ -49,6 +49,8 @@ public class TestSpecificCompilerTool {
       "avro/examples/baseball/Position.java");
   private static final File TEST_EXPECTED_STRING_PLAYER = new 
File(TEST_EXPECTED_STRING_OUTPUT_DIR,
       "avro/examples/baseball/Player.java");
+  private static final File TEST_EXPECTED_STRING_FIELDTEST = new 
File(TEST_EXPECTED_STRING_OUTPUT_DIR,
+      "avro/examples/baseball/FieldTest.java");
 
   // where test output goes
   private static final File TEST_OUTPUT_DIR = new 
File("target/compiler/output");
@@ -60,6 +62,8 @@ public class TestSpecificCompilerTool {
       "avro/examples/baseball/Player.java");
   private static final File TEST_OUTPUT_STRING_POSITION = new 
File(TEST_OUTPUT_STRING_DIR,
       "avro/examples/baseball/Position.java");
+  private static final File TEST_OUTPUT_STRING_FIELDTEST = new 
File(TEST_OUTPUT_STRING_DIR,
+      "avro/examples/baseball/FieldTest.java");
 
   @Before
   public void setUp() {
@@ -101,6 +105,14 @@ public class TestSpecificCompilerTool {
     assertFileMatch(TEST_EXPECTED_STRING_PLAYER, TEST_OUTPUT_STRING_PLAYER);
   }
 
+  @Test
+  public void testCompileSchemasWithVariousFieldTypes() throws Exception {
+
+    doCompile(new String[] { "-encoding", "UTF-8", "-string", "schema", 
TEST_INPUT_DIR.toString() + "/fieldtest.avsc",
+        TEST_INPUT_DIR.toString() + "/fieldtest.avsc", 
TEST_OUTPUT_STRING_DIR.getPath() });
+    assertFileMatch(TEST_EXPECTED_STRING_FIELDTEST, 
TEST_OUTPUT_STRING_FIELDTEST);
+  }
+
   // Runs the actual compiler tool with the given input args
   private void doCompile(String[] args) throws Exception {
     SpecificCompilerTool tool = new SpecificCompilerTool();
diff --git a/pom.xml b/pom.xml
index 4f76d42..6e52c34 100644
--- a/pom.xml
+++ b/pom.xml
@@ -291,6 +291,7 @@
                 
<exclude>lang/java/avro/src/test/java/org/apache/avro/specific/TestRecordWithoutLogicalTypes.java</exclude>
                 
<exclude>lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java</exclude>
                 
<exclude>lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Position.java</exclude>
+                
<exclude>lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java</exclude>
                 
<exclude>lang/java/tools/src/test/compiler/output-string/Position.java</exclude>
                 
<exclude>lang/java/tools/src/test/compiler/output/Player.java</exclude>
                 
<exclude>lang/java/tools/src/test/compiler/output/Position.java</exclude>

Reply via email to