From 54d6f3cc377867c80b646cd7778bd5d5477c9ba8 Mon Sep 17 00:00:00 2001 From: Tomas Rehak Date: Wed, 4 Jan 2017 22:01:26 +0100 Subject: [PATCH] Simplified integration of custom logical types --- .../logical/AbstractLogicalTypeContainer.java | 21 ++++++++ .../avro/logical/LogicalTypeContainer.java | 35 ++++++++++++ .../compiler/specific/SpecificCompiler.java | 4 ++ .../org/apache/avro/compiler/idl/TestIdl.java | 2 +- .../java/org/apache/avro/mojo/SchemaMojo.java | 54 +++++++++++++++---- 5 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 lang/java/avro/src/main/java/org/apache/avro/logical/AbstractLogicalTypeContainer.java create mode 100644 lang/java/avro/src/main/java/org/apache/avro/logical/LogicalTypeContainer.java diff --git a/lang/java/avro/src/main/java/org/apache/avro/logical/AbstractLogicalTypeContainer.java b/lang/java/avro/src/main/java/org/apache/avro/logical/AbstractLogicalTypeContainer.java new file mode 100644 index 00000000000..e0201e07454 --- /dev/null +++ b/lang/java/avro/src/main/java/org/apache/avro/logical/AbstractLogicalTypeContainer.java @@ -0,0 +1,21 @@ +package org.apache.avro.logical; + +import org.apache.avro.LogicalTypes; +import org.apache.avro.generic.GenericData; + +/** + * Abstract container for LogicalType support + */ +public abstract class AbstractLogicalTypeContainer implements LogicalTypeContainer { + + /** + * Performs integration with Avro ecosystem + */ + public void register() { + LogicalTypes.LogicalTypeFactory factory = this.getFactory(); + LogicalTypes.register(getTypeName(), factory); + GenericData.get().addLogicalTypeConversion(getConversion()); + } + + +} diff --git a/lang/java/avro/src/main/java/org/apache/avro/logical/LogicalTypeContainer.java b/lang/java/avro/src/main/java/org/apache/avro/logical/LogicalTypeContainer.java new file mode 100644 index 00000000000..527a91c8567 --- /dev/null +++ b/lang/java/avro/src/main/java/org/apache/avro/logical/LogicalTypeContainer.java @@ -0,0 +1,35 @@ +package org.apache.avro.logical; + +import org.apache.avro.Conversion; +import org.apache.avro.LogicalTypes; + +/** + * Container for LogicalType support + */ +public interface LogicalTypeContainer { + + /** + * Return logical type factory + * + * @return + */ + LogicalTypes.LogicalTypeFactory getFactory(); + + /** + * Return Conversion for logical type + * + * @return + */ + Conversion getConversion(); + + /** + * Get type name + */ + String getTypeName(); + + /** + * Performs integration with Avro ecosystem + */ + void register(); + +} 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 295949313d1..685532a461b 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 @@ -826,6 +826,10 @@ public static boolean hasBuilder(Schema schema) { } } + public static void addLogicalTypeConversion(Conversion conversion) { + SPECIFIC.addLogicalTypeConversion(conversion); + } + /** * Generates the name of a field Builder accessor method. * @param schema the schema in which the field is defined. diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java index 52403a220a3..c0a48b05cda 100644 --- a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java +++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java @@ -152,7 +152,7 @@ public String testName() { public void run() throws Exception { String output = generate(); String slurped = slurp(expectedOut); - assertEquals(slurped.trim(), output.replace("\r", "").trim()); + assertEquals(slurped.trim(), output.replace("\\r", "").trim()); } public void write() throws Exception { diff --git a/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/SchemaMojo.java b/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/SchemaMojo.java index 9a849207f33..00f23deb457 100644 --- a/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/SchemaMojo.java +++ b/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/SchemaMojo.java @@ -6,9 +6,9 @@ * 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 - * + *

+ * 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. @@ -18,14 +18,15 @@ package org.apache.avro.mojo; +import org.apache.avro.Schema; +import org.apache.avro.compiler.specific.SpecificCompiler; import org.apache.avro.generic.GenericData.StringType; +import org.apache.avro.logical.LogicalTypeContainer; +import org.apache.maven.plugin.MojoExecutionException; import java.io.File; import java.io.IOException; -import org.apache.avro.Schema; -import org.apache.avro.compiler.specific.SpecificCompiler; - /** * Generate Java classes from Avro schema files (.avsc) * @@ -38,16 +39,16 @@ public class SchemaMojo extends AbstractAvroMojo { * A parser used to parse all schema files. Using a common parser will * facilitate the import of external schemas. */ - private Schema.Parser schemaParser = new Schema.Parser(); + private Schema.Parser schemaParser = new Schema.Parser(); - /** + /** * A set of Ant-like inclusion patterns used to select files from the source * directory for processing. By default, the pattern * **/*.avsc is used to select grammar files. * * @parameter */ - private String[] includes = new String[] { "**/*.avsc" }; + private String[] includes = new String[]{"**/*.avsc"}; /** * A set of Ant-like inclusion patterns used to select files from the source @@ -56,8 +57,22 @@ public class SchemaMojo extends AbstractAvroMojo { * * @parameter */ - private String[] testIncludes = new String[] { "**/*.avsc" }; + private String[] testIncludes = new String[]{"**/*.avsc"}; + /** + * A set of custom LogicalTypeContainers fully qualified class names to be used for code generation in maven plugin; + * expecting public constructors with no parameters + * + * @parameter + */ + private String[] logicalTypeContainers = new String[]{}; + + /** + * @param filename + * @param sourceDirectory + * @param outputDirectory + * @throws IOException + */ @Override protected void doCompile(String filename, File sourceDirectory, File outputDirectory) throws IOException { File src = new File(sourceDirectory, filename); @@ -83,6 +98,25 @@ protected void doCompile(String filename, File sourceDirectory, File outputDirec compiler.compileToDestination(src, outputDirectory); } + @Override + public void execute() throws MojoExecutionException { + registerContainers(); + super.execute(); + } + + private void registerContainers() { + try { + for (String logicalTypeContainer : logicalTypeContainers) { + LogicalTypeContainer container = (LogicalTypeContainer) Class.forName(logicalTypeContainer).newInstance(); + SpecificCompiler.addLogicalTypeConversion(container.getConversion()); + container.register(); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + @Override protected String[] getIncludes() { return includes;