AVRO-2392: Enable Joda micros logical types supports (#533)

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 2959493..448a768 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
@@ -39,7 +39,9 @@
 import org.apache.avro.LogicalTypes;
 import org.apache.avro.data.TimeConversions.DateConversion;
 import org.apache.avro.data.TimeConversions.TimeConversion;
+import org.apache.avro.data.TimeConversions.TimeMicrosConversion;
 import org.apache.avro.data.TimeConversions.TimestampConversion;
+import org.apache.avro.data.TimeConversions.TimestampMicrosConversion;
 import org.apache.avro.specific.SpecificData;
 import org.codehaus.jackson.JsonNode;
 
@@ -97,6 +99,8 @@
     SPECIFIC.addLogicalTypeConversion(new DateConversion());
     SPECIFIC.addLogicalTypeConversion(new TimeConversion());
     SPECIFIC.addLogicalTypeConversion(new TimestampConversion());
+    SPECIFIC.addLogicalTypeConversion(new TimeMicrosConversion());
+    SPECIFIC.addLogicalTypeConversion(new TimestampMicrosConversion());
     SPECIFIC.addLogicalTypeConversion(new Conversions.DecimalConversion());
   }
 
@@ -669,8 +673,12 @@
       return "DATE_CONVERSION";
     } else if (LogicalTypes.timeMillis().equals(schema.getLogicalType())) {
       return "TIME_CONVERSION";
+    } else if (LogicalTypes.timeMicros().equals(schema.getLogicalType())) {
+      return "TIME_MICROS_CONVERSION";
     } else if (LogicalTypes.timestampMillis().equals(schema.getLogicalType())) {
       return "TIMESTAMP_CONVERSION";
+    } else if (LogicalTypes.timestampMicros().equals(schema.getLogicalType())) {
+      return "TIMESTAMP_MICROS_CONVERSION";
     } else if (LogicalTypes.Decimal.class.equals(schema.getLogicalType().getClass())) {
       return enableDecimalLogicalType ? "DECIMAL_CONVERSION" : "null";
     }
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 de7fd1c..e017808 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
@@ -163,7 +163,9 @@
 #if ($this.hasLogicalTypeField($schema))
   protected static final org.apache.avro.data.TimeConversions.DateConversion DATE_CONVERSION = new org.apache.avro.data.TimeConversions.DateConversion();
   protected static final org.apache.avro.data.TimeConversions.TimeConversion TIME_CONVERSION = new org.apache.avro.data.TimeConversions.TimeConversion();
+  protected static final org.apache.avro.data.TimeConversions.TimeMicrosConversion TIME_MICROS_CONVERSION = new org.apache.avro.data.TimeConversions.TimeMicrosConversion();
   protected static final org.apache.avro.data.TimeConversions.TimestampConversion TIMESTAMP_CONVERSION = new org.apache.avro.data.TimeConversions.TimestampConversion();
+  protected static final org.apache.avro.data.TimeConversions.TimestampMicrosConversion TIMESTAMP_MICROS_CONVERSION = new org.apache.avro.data.TimeConversions.TimestampMicrosConversion();
   protected static final org.apache.avro.Conversions.DecimalConversion DECIMAL_CONVERSION = new org.apache.avro.Conversions.DecimalConversion();
 
   private static final org.apache.avro.Conversion<?>[] conversions =
diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
index 50adb19..1f069ab 100644
--- a/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
+++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
@@ -417,6 +417,7 @@
     Schema floatSchema = Schema.create(Schema.Type.FLOAT);
     Schema doubleSchema = Schema.create(Schema.Type.DOUBLE);
     Schema boolSchema = Schema.create(Schema.Type.BOOLEAN);
+
     Assert.assertEquals("Should use int for Type.INT",
         "int", compiler.javaUnbox(intSchema));
     Assert.assertEquals("Should use long for Type.LONG",
@@ -432,8 +433,12 @@
         .addToSchema(Schema.create(Schema.Type.INT));
     Schema timeSchema = LogicalTypes.timeMillis()
         .addToSchema(Schema.create(Schema.Type.INT));
+    Schema timeMicroSchema = LogicalTypes.timeMicros()
+        .addToSchema(Schema.create(Schema.Type.LONG));
     Schema timestampSchema = LogicalTypes.timestampMillis()
         .addToSchema(Schema.create(Schema.Type.LONG));
+    Schema timestampMicrosSchema = LogicalTypes.timestampMicros()
+        .addToSchema(Schema.create(Schema.Type.LONG));
     // Date/time types should always use upper level java classes, even though
     // their underlying representations are primitive types
     Assert.assertEquals("Should use Joda LocalDate for date type",
@@ -442,7 +447,10 @@
         "org.joda.time.LocalTime", compiler.javaUnbox(timeSchema));
     Assert.assertEquals("Should use Joda DateTime for timestamp-millis type",
         "org.joda.time.DateTime", compiler.javaUnbox(timestampSchema));
-
+    Assert.assertEquals("Should use Joda DateTime for timestamp-millis type",
+        "org.joda.time.LocalTime", compiler.javaUnbox(timeMicroSchema));
+    Assert.assertEquals("Should use Joda DateTime for timestamp-millis type",
+        "org.joda.time.DateTime", compiler.javaUnbox(timestampMicrosSchema));
   }
 
   @Test
@@ -522,8 +530,12 @@
         .addToSchema(Schema.create(Schema.Type.INT));
     Schema timeSchema = LogicalTypes.timeMillis()
         .addToSchema(Schema.create(Schema.Type.INT));
+    Schema timeMicroSchema = LogicalTypes.timeMicros()
+        .addToSchema(Schema.create(Schema.Type.LONG));
     Schema timestampSchema = LogicalTypes.timestampMillis()
         .addToSchema(Schema.create(Schema.Type.LONG));
+    Schema timestampMicrosSchema = LogicalTypes.timestampMicros()
+        .addToSchema(Schema.create(Schema.Type.LONG));
     Schema decimalSchema = LogicalTypes.decimal(9,2)
         .addToSchema(Schema.create(Schema.Type.BYTES));
     Schema uuidSchema = LogicalTypes.uuid()
@@ -533,12 +545,17 @@
         "DATE_CONVERSION", compiler.conversionInstance(dateSchema));
     Assert.assertEquals("Should use TIME_CONVERSION for time type",
         "TIME_CONVERSION", compiler.conversionInstance(timeSchema));
+    Assert.assertEquals("Should use TIME_MICROS_CONVERSION for time type",
+        "TIME_MICROS_CONVERSION", compiler.conversionInstance(timeMicroSchema));
     Assert.assertEquals("Should use TIMESTAMP_CONVERSION for date type",
         "TIMESTAMP_CONVERSION", compiler.conversionInstance(timestampSchema));
+    Assert.assertEquals("Should use TIMESTAMP_MICROS_CONVERSION for date type",
+        "TIMESTAMP_MICROS_CONVERSION", compiler.conversionInstance(timestampMicrosSchema));
     Assert.assertEquals("Should use null for decimal if the flag is off",
         "null", compiler.conversionInstance(decimalSchema));
     Assert.assertEquals("Should use null for decimal if the flag is off",
         "null", compiler.conversionInstance(uuidSchema));
+
   }
 
 
@@ -551,8 +568,12 @@
         .addToSchema(Schema.create(Schema.Type.INT));
     Schema timeSchema = LogicalTypes.timeMillis()
         .addToSchema(Schema.create(Schema.Type.INT));
+    Schema timeMicroSchema = LogicalTypes.timeMicros()
+        .addToSchema(Schema.create(Schema.Type.LONG));
     Schema timestampSchema = LogicalTypes.timestampMillis()
         .addToSchema(Schema.create(Schema.Type.LONG));
+    Schema timestampMicrosSchema = LogicalTypes.timestampMicros()
+        .addToSchema(Schema.create(Schema.Type.LONG));
     Schema decimalSchema = LogicalTypes.decimal(9,2)
         .addToSchema(Schema.create(Schema.Type.BYTES));
     Schema uuidSchema = LogicalTypes.uuid()
@@ -562,8 +583,12 @@
         "DATE_CONVERSION", compiler.conversionInstance(dateSchema));
     Assert.assertEquals("Should use TIME_CONVERSION for time type",
         "TIME_CONVERSION", compiler.conversionInstance(timeSchema));
+    Assert.assertEquals("Should use TIME_MICROS_CONVERSION for time type",
+        "TIME_MICROS_CONVERSION", compiler.conversionInstance(timeMicroSchema));
     Assert.assertEquals("Should use TIMESTAMP_CONVERSION for date type",
         "TIMESTAMP_CONVERSION", compiler.conversionInstance(timestampSchema));
+    Assert.assertEquals("Should use TIMESTAMP_MICROS_CONVERSION for date type",
+        "TIMESTAMP_MICROS_CONVERSION", compiler.conversionInstance(timestampMicrosSchema));
     Assert.assertEquals("Should use null for decimal if the flag is off",
         "DECIMAL_CONVERSION", compiler.conversionInstance(decimalSchema));
     Assert.assertEquals("Should use null for decimal if the flag is off",
diff --git a/lang/java/compiler/src/test/resources/logical_types_with_multiple_fields.avsc b/lang/java/compiler/src/test/resources/logical_types_with_multiple_fields.avsc
index 7a05111..a878631 100644
--- a/lang/java/compiler/src/test/resources/logical_types_with_multiple_fields.avsc
+++ b/lang/java/compiler/src/test/resources/logical_types_with_multiple_fields.avsc
@@ -19,6 +19,13 @@
       }
     },
     {
+      "name": "timeMicros",
+      "type": {
+        "type": "long",
+        "logicalType": "timestamp-micros"
+      }
+    },
+    {
       "name": "requestId",
       "type": [
         "null",