/** * 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. */ package org.apache.avro.xml; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.xml.transform.stream.StreamSource; import org.apache.avro.Schema; import org.apache.avro.xml.AvroSchemaGenerator; import org.apache.avro.xml.Utils; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaCollection; import org.apache.ws.commons.schema.XmlSchemaElement; import org.apache.ws.commons.schema.walker.XmlSchemaWalker; import org.junit.Test; /** * Verifies the {@link AvroSchemaGenerator} generates the expected * {@link Schema} for <code>src/test/resources/test_schema.xsd</code>. */ public class TestAvroSchemaGenerator { @Test public void testSchema() throws Exception { File file = UtilsForTests.buildFile("src", "test", "resources", "test_schema.xsd"); ArrayList<File> schemaFiles = new ArrayList<File>(1); schemaFiles.add(file); Schema schema = createSchemaOf(file, "root"); UtilsForTests.assertEquivalent(getExpectedTestSchema(), schema); } @Test public void testComplexSchema() throws Exception { File file = UtilsForTests.buildFile( "src", "test", "resources", "complex_schema.xsd"); Schema schema = createSchemaOf(file, "root"); UtilsForTests.assertEquivalent(getExpectedComplexSchema(), schema); } private static Schema createSchemaOf(File file, String rootName) throws Exception { ArrayList<File> schemaFiles = new ArrayList<File>(1); schemaFiles.add(file); XmlSchemaCollection collection = null; FileReader fileReader = null; AvroSchemaGenerator visitor = new AvroSchemaGenerator(null, null, schemaFiles); try { fileReader = new FileReader(file); collection = new XmlSchemaCollection(); collection.read(new StreamSource(fileReader, file.getAbsolutePath())); } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } XmlSchemaElement elem = getElementOf(collection, rootName); XmlSchemaWalker walker = new XmlSchemaWalker(collection, visitor); walker.setUserRecognizedTypes( Utils.getAvroRecognizedTypes() ); walker.walk(elem); Schema schema = visitor.getSchema(); visitor.clear(); walker.clear(); return schema; } private static XmlSchemaElement getElementOf( XmlSchemaCollection collection, String name) { XmlSchemaElement elem = null; for (XmlSchema schema : collection.getXmlSchemas()) { elem = schema.getElementByName(name); if (elem != null) { break; } } return elem; } private static Schema getExpectedTestSchema() { final String namespace = "org.apache.avro.avrotest"; Schema optionalStringSchema = getOptionalStringSchema(); List<Schema> optionalStringArrayTypes = new ArrayList<Schema>(2); optionalStringArrayTypes.add( Schema.createArray(Schema.create(Schema.Type.STRING))); optionalStringArrayTypes.add( Schema.create(Schema.Type.NULL) ); Schema optionalStringArraySchema = Schema.createUnion(optionalStringArrayTypes); Schema optionalDoubleSchema = getOptionalDoubleSchema(); List<Schema> optionalLongTypes = new ArrayList<Schema>(2); optionalLongTypes.add( Schema.create(Schema.Type.LONG) ); optionalLongTypes.add( Schema.create(Schema.Type.NULL) ); Schema optionalLongSchema = Schema.createUnion(optionalLongTypes); Schema optionalIntSchema = getOptionalIntSchema(); Schema optionalBooleanSchema = getOptionalBooleanSchema(); Schema optionalBinarySchema = getOptionalBinarySchema(); Schema optionalDurationSchema = getOptionalDurationSchema(); List<Schema> optionalFloatTypes = new ArrayList<Schema>(2); optionalFloatTypes.add( Schema.create(Schema.Type.FLOAT) ); optionalFloatTypes.add( Schema.create(Schema.Type.NULL) ); Schema optionalFloatSchema = Schema.createUnion(optionalFloatTypes); List<Schema> optionalQNameTypes = new ArrayList<Schema>(2); optionalQNameTypes.add( getQNameSchema() ); optionalQNameTypes.add(Schema.create(Schema.Type.NULL)); Schema optionalQNameSchema = Schema.createUnion(optionalQNameTypes); List<Schema.Field> rootFields = new ArrayList<Schema.Field>(); rootFields.add( new Schema.Field("anySimpleType", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("duration", optionalDurationSchema, null, null) ); rootFields.add( new Schema.Field("dateTime", optionalLongSchema, null, null) ); rootFields.add( new Schema.Field("date", optionalIntSchema, null, null) ); rootFields.add( new Schema.Field("time", optionalIntSchema, null, null) ); rootFields.add( new Schema.Field("gYearMonth", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("gYear", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("gMonthDay", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("gDay", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("gMonth", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("anyURI", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("qname", optionalQNameSchema, null, null) ); rootFields.add( new Schema.Field("string", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("token", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("language", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("nmtoken", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("name", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("ncName", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("id", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("idref", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("entity", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field("nmtokens", optionalStringArraySchema, null, null)); rootFields.add( new Schema.Field("idrefs", optionalStringArraySchema, null, null)); rootFields.add( new Schema.Field("entities", optionalStringArraySchema, null, null)); rootFields.add( new Schema.Field("integer", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field("negativeInteger", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field("positiveInteger", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field("unsignedLong", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field("long", optionalLongSchema, null, null)); rootFields.add( new Schema.Field("unsignedInt", optionalLongSchema, null, null)); rootFields.add( new Schema.Field("int", optionalIntSchema, null, null)); rootFields.add( new Schema.Field("short", optionalIntSchema, null, null)); rootFields.add( new Schema.Field("byte", optionalIntSchema, null, null)); rootFields.add( new Schema.Field("unsignedShort", optionalIntSchema, null, null)); rootFields.add( new Schema.Field("unsignedByte", optionalIntSchema, null, null)); rootFields.add( new Schema.Field("boolean", optionalBooleanSchema, null, null)); rootFields.add( new Schema.Field("base64Binary", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field("hexBinary", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field("decimal", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field("float", optionalFloatSchema, null, null)); rootFields.add( new Schema.Field("double", optionalDoubleSchema, null, null)); rootFields.add( new Schema.Field( "normalizedString", optionalStringSchema, null, null) ); rootFields.add( new Schema.Field( "nonPositiveInteger", optionalBinarySchema, null, null)); rootFields.add( new Schema.Field( "nonNegativeInteger", optionalBinarySchema, null, null)); ArrayList<String> nonNullPrimitiveEnumSymbols = new ArrayList<String>(); nonNullPrimitiveEnumSymbols.add("boolean"); nonNullPrimitiveEnumSymbols.add("int"); nonNullPrimitiveEnumSymbols.add("long"); nonNullPrimitiveEnumSymbols.add("float"); nonNullPrimitiveEnumSymbols.add("double"); nonNullPrimitiveEnumSymbols.add("decimal"); nonNullPrimitiveEnumSymbols.add("bytes"); nonNullPrimitiveEnumSymbols.add("string"); Schema nonNullPrimitiveEnumSchema = Schema.createEnum( "nonNullPrimitive", "Enumeration of symbols in " + "{http://avro.apache.org/AvroTest}nonNullPrimitive", namespace + ".enums", nonNullPrimitiveEnumSymbols); Schema.Field nonNullPrimitiveEnumField = new Schema.Field( "nonNullPrimitive", nonNullPrimitiveEnumSchema, "Simple type {http://www.w3.org/2001/XMLSchema}anyType", null); Schema nonNullPrimitiveRecord = Schema.createRecord( "nonNullPrimitive", null, namespace, false); List<Schema.Field> nonNullPrimitiveFields = new ArrayList<Schema.Field>(); nonNullPrimitiveFields.add(nonNullPrimitiveEnumField); nonNullPrimitiveRecord.setFields(nonNullPrimitiveFields); ArrayList<String> primitiveEnumSymbols = (ArrayList<String>) nonNullPrimitiveEnumSymbols.clone(); primitiveEnumSymbols.add("null"); Schema primitiveEnumSchema = Schema.createEnum( "primitive", "Enumeration of symbols in " + "{http://avro.apache.org/AvroTest}primitive", namespace + ".enums", primitiveEnumSymbols); Schema.Field primitiveEnumField = new Schema.Field( "primitive", primitiveEnumSchema, "Simple type {http://www.w3.org/2001/XMLSchema}anyType", null); Schema primitiveRecord = Schema.createRecord( "primitive", null, namespace, false); ArrayList<Schema.Field> primitiveFields = new ArrayList<Schema.Field>(1); primitiveFields.add(primitiveEnumField); primitiveRecord.setFields(primitiveFields); Schema recordSchema = Schema.createRecord("record", null, namespace, false); Schema mapRecordSchema = Schema.createRecord("map", null, namespace, false); Schema mapSchema = Schema.createMap(mapRecordSchema); Schema listSchema = Schema.createRecord("list", null, namespace, false); List<Schema> listChildren = new ArrayList<Schema>(); listChildren.add(recordSchema); listChildren.add(mapSchema); listChildren.add(primitiveRecord); Schema listChildSchema = Schema.createArray(Schema.createUnion(listChildren)); List<Schema.Field> listFields = new ArrayList<Schema.Field>(); listFields.add( new Schema.Field( "list", listChildSchema, "Children of {http://avro.apache.org/AvroTest}list", null)); listFields.add( new Schema.Field("size", optionalBinarySchema, null, null)); listSchema.setFields(listFields); Schema tupleSchema = Schema.createRecord("tuple", null, namespace, false); List<Schema> tupleChildren = new ArrayList<Schema>(); tupleChildren.add(primitiveRecord); tupleChildren.add(nonNullPrimitiveRecord); tupleChildren.add(recordSchema); tupleChildren.add(mapSchema); tupleChildren.add(listSchema); Schema tupleChildSchema = Schema.createArray(Schema.createUnion(tupleChildren)); List<Schema.Field> tupleChildrenFields = new ArrayList<Schema.Field>(); tupleChildrenFields.add( new Schema.Field( "tuple", tupleChildSchema, "Children of {http://avro.apache.org/AvroTest}tuple", null)); tupleSchema.setFields(tupleChildrenFields); List<Schema> recordChildSchemas = new ArrayList<Schema>(); recordChildSchemas.add(primitiveRecord); recordChildSchemas.add(nonNullPrimitiveRecord); recordChildSchemas.add(recordSchema); recordChildSchemas.add(listSchema); recordChildSchemas.add(tupleSchema); recordChildSchemas.add(mapSchema); Schema recordChildSchema = Schema.createArray(Schema.createUnion(recordChildSchemas)); ArrayList<Schema.Field> recordFields = new ArrayList<Schema.Field>(); recordFields.add( new Schema.Field( "record", recordChildSchema, "Children of {http://avro.apache.org/AvroTest}record", null)); recordSchema.setFields(recordFields); List<Schema> mapChildSchemas = new ArrayList<Schema>(); mapChildSchemas.add(primitiveRecord); mapChildSchemas.add(nonNullPrimitiveRecord); mapChildSchemas.add(recordSchema); mapChildSchemas.add(listSchema); mapChildSchemas.add(tupleSchema); mapChildSchemas.add(mapSchema); Schema mapChildSchema = Schema.createArray(Schema.createUnion(mapChildSchemas)); List<Schema.Field> mapFields = new ArrayList<Schema.Field>(); mapFields.add( new Schema.Field( "id", Schema.create(Schema.Type.STRING), null, null)); mapFields.add( new Schema.Field( "map", mapChildSchema, "Children of {http://avro.apache.org/AvroTest}map", null)); mapRecordSchema.setFields(mapFields); Schema rootChildSchema = Schema.createArray(Schema.createUnion(mapChildSchemas)); rootFields.add( new Schema.Field( "root", rootChildSchema, "Children of {http://avro.apache.org/AvroTest}root", null) ); Schema rootSchema = Schema.createRecord("root", null, namespace, false); rootSchema.setFields(rootFields); return rootSchema; } private static Schema getExpectedComplexSchema() { final String namespace = "avro.complex_schema"; Schema firstMapValue = Schema.createRecord("value", null, namespace, false); // simpleRestriction List<Schema.Field> simpleRestrictionFields = new ArrayList<Schema.Field>(); simpleRestrictionFields.add( new Schema.Field( "default", Schema.create(Schema.Type.STRING), null, null)); simpleRestrictionFields.add( new Schema.Field( "fixed", Schema.create(Schema.Type.INT), null, null)); List<Schema> simpleRestrictionTypes = new ArrayList<Schema>(2); simpleRestrictionTypes.add( Schema.create(Schema.Type.BOOLEAN) ); simpleRestrictionTypes.add( Schema.create(Schema.Type.BYTES) ); simpleRestrictionFields.add( new Schema.Field( "simpleRestriction", Schema.createUnion(simpleRestrictionTypes), "Simple type null", null)); Schema simpleRestrictionSchema = Schema.createRecord("simpleRestriction", null, namespace, false); simpleRestrictionSchema.setFields(simpleRestrictionFields); // simpleExtension List<Schema.Field> simpleExtensionFields = new ArrayList<Schema.Field>(); simpleExtensionFields.add( new Schema.Field( "default", Schema.create(Schema.Type.STRING), null, null)); simpleExtensionFields.add( new Schema.Field( "fixed", Schema.create(Schema.Type.INT), null, null)); List<Schema> simpleExtensionTypes = new ArrayList<Schema>(); simpleExtensionTypes.add( Schema.create(Schema.Type.BOOLEAN) ); simpleExtensionTypes.add( Schema.create(Schema.Type.BYTES) ); simpleExtensionFields.add( new Schema.Field( "simpleExtension", Schema.createUnion(simpleExtensionTypes), "Simple type null", null)); Schema simpleExtensionSchema = Schema.createRecord("simpleExtension", null, namespace, false); simpleExtensionSchema.setFields(simpleExtensionFields); // anyAndFriends List<Schema.Field> anyAndFriendsFields = new ArrayList<Schema.Field>(); anyAndFriendsFields.add( new Schema.Field( "anyAndFriends", Schema.create(Schema.Type.STRING), "Simple type null", null)); Schema anyAndFriendsSchema = Schema.createRecord("anyAndFriends", null, namespace, false); anyAndFriendsSchema.setFields(anyAndFriendsFields); // prohibit and children List<Schema.Field> fixedSchemaFields = new ArrayList<Schema.Field>(); fixedSchemaFields.add( new Schema.Field( "fixed", Schema.create(Schema.Type.BYTES), "Simple type {http://www.w3.org/2001/XMLSchema}decimal", null)); Schema fixedSchema = Schema.createRecord("fixed", null, namespace, false); fixedSchema.setFields(fixedSchemaFields); List<Schema.Field> prohibitFields = new ArrayList<Schema.Field>(); prohibitFields.add( new Schema.Field( "prohibit", Schema.createArray( Schema.createUnion( Collections.singletonList(fixedSchema))), "Children of {urn:avro:complex_schema}prohibit", null)); Schema prohibitSchema = Schema.createRecord("prohibit", null, namespace, false); prohibitSchema.setFields(prohibitFields); // allTheThings and children List<Schema.Field> firstMapValueFields = new ArrayList<Schema.Field>(); firstMapValueFields.add( new Schema.Field( "value", getOptionalBinarySchema(), "Simple type {http://www.w3.org/2001/XMLSchema}decimal", null)); firstMapValue.setFields(firstMapValueFields); List<Schema> firstMapChildren = new ArrayList<Schema>(); firstMapChildren.add(firstMapValue); List<Schema.Field> firstMapFields = new ArrayList<Schema.Field>(); firstMapFields.add( new Schema.Field( "firstMap", Schema.createArray(Schema.createUnion(firstMapChildren)), "Children of {urn:avro:complex_schema}firstMap", null)); firstMapFields.add( new Schema.Field("id", Schema.create(Schema.Type.STRING), null, null)); Schema firstMapRecord = Schema.createRecord( "firstMap", null, namespace, false); firstMapRecord.setFields(firstMapFields); List<Schema.Field> secondMapFields = new ArrayList<Schema.Field>(); secondMapFields.add( new Schema.Field("id", Schema.create(Schema.Type.STRING), null, null)); secondMapFields.add( new Schema.Field( "value", Schema.create(Schema.Type.STRING), null, null)); secondMapFields.add( new Schema.Field( "secondMap", Schema.create(Schema.Type.NULL), "This element contains no attributes and no children.", null)); Schema secondMapRecord = Schema.createRecord("secondMap", null, namespace, false); secondMapRecord.setFields(secondMapFields); List<Schema> unionOfMaps = new ArrayList<Schema>(); unionOfMaps.add(firstMapRecord); unionOfMaps.add(secondMapRecord); Schema mapUnionOfMaps = Schema.createMap( Schema.createUnion(unionOfMaps) ); List<Schema.Field> allTheThingsFields = new ArrayList<Schema.Field>(); allTheThingsFields.add( new Schema.Field( "id", Schema.create(Schema.Type.STRING), null, null)); allTheThingsFields.add( new Schema.Field( "truth", Schema.create(Schema.Type.BOOLEAN), null, null)); List<Schema> listOfNumbersTypes = new ArrayList<Schema>(2); listOfNumbersTypes.add( Schema.create(Schema.Type.INT) ); listOfNumbersTypes.add( Schema.create(Schema.Type.BYTES) ); Schema listOfNumbersSchema = Schema.createArray(Schema.createUnion(listOfNumbersTypes)); allTheThingsFields.add( new Schema.Field( "listOfNumbers", listOfNumbersSchema, null, null)); allTheThingsFields.add( new Schema.Field( "allTheThings", Schema.createArray( Schema.createUnion( Collections.singletonList(mapUnionOfMaps))), "Children of {urn:avro:complex_schema}allTheThings", null)); Schema allTheThingsRecord = Schema.createRecord("allTheThings", null, namespace, false); allTheThingsRecord.setFields(allTheThingsFields); Schema allTheThingsSchema = Schema.createMap(allTheThingsRecord); // Backtrack and children List<String> avroEnumSymbols = new ArrayList<String>(6); avroEnumSymbols.add("avro"); avroEnumSymbols.add("json"); avroEnumSymbols.add("xml"); avroEnumSymbols.add("thrift"); avroEnumSymbols.add("rest_li"); avroEnumSymbols.add("protobuf"); Schema avroEnumSchema = Schema.createEnum( "avroEnum", "Enumeration of symbols in {urn:avro:complex_schema}avroEnum", namespace + ".enums", avroEnumSymbols); Schema avroEnumRecord = Schema.createRecord( "avroEnum", null, namespace, false); ArrayList<Schema.Field> avroEnumFields = new ArrayList<Schema.Field>(); avroEnumFields.add( new Schema.Field( "avroEnum", avroEnumSchema, "Simple type {http://www.w3.org/2001/XMLSchema}anyType", null)); avroEnumRecord.setFields(avroEnumFields); Schema xmlEnumRecord = Schema.createRecord("xmlEnum", null, namespace, false); List<Schema.Field> xmlEnumFields = new ArrayList<Schema.Field>(); xmlEnumFields.add( new Schema.Field( "xmlEnum", Schema.create(Schema.Type.STRING), "Simple type {http://www.w3.org/2001/XMLSchema}anyType", null)); xmlEnumRecord.setFields(xmlEnumFields); Schema unsignedLongList = Schema.createRecord("unsignedLongList", null, namespace, false); List<Schema.Field> unsignedLongListFields = new ArrayList<Schema.Field>(); unsignedLongListFields.add( new Schema.Field( "unsignedLongList", Schema.createArray(Schema.create(Schema.Type.BYTES)), "Simple type null", null)); unsignedLongList.setFields(unsignedLongListFields); Schema listOfUnion = Schema.createRecord("listOfUnion", null, namespace, false); List<Schema> listOfUnionTypes = new ArrayList<Schema>(); listOfUnionTypes.add( Schema.create(Schema.Type.BYTES) ); listOfUnionTypes.add( Schema.create(Schema.Type.BOOLEAN) ); listOfUnionTypes.add( Schema.create(Schema.Type.INT) ); listOfUnionTypes.add( Schema.create(Schema.Type.STRING) ); List<Schema.Field> listOfUnionFields = new ArrayList<Schema.Field>(); listOfUnionFields.add( new Schema.Field( "listOfUnion", Schema.createArray( Schema.createUnion(listOfUnionTypes) ), "Simple type null", null)); listOfUnion.setFields(listOfUnionFields); List<Schema.Field> qNameFields = new ArrayList<Schema.Field>(); qNameFields.add( new Schema.Field( "qName", getQNameSchema(), "Simple type {http://www.w3.org/2001/XMLSchema}QName", null)); Schema qNameSchema = Schema.createRecord("qName", null, namespace, false); qNameSchema.setFields(qNameFields); Schema backtrackSchema = Schema.createRecord( "backtrack", " This forces backtracking through the different schema options. " + "Consider the following elements: <backtrack> " + "<qName>avro:qName</qName> <avroEnum>avro</avroEnum> " + "<xmlEnum>rest.li</xmlEnum> <xmlEnum>xml</xmlEnum> " + "<unsignedLongList>18446744073709551615 1844674407370955 " + "12579</unsignedLongList> <listOfUnion>true 18446744073709551616" + " false -2147483648 -1234.567 avro</listOfUnion> </backtrack> " + "The first four elements in the list can match either the first " + "choice group or the second sequence group, and by default the " + "first branch will be taken. It is not until the last child " + "element, <listOfUnion>, is reached, that it becomes clear the " + "choice group should not be followed. ", namespace, false); List<Schema> backtrackChildren = new ArrayList<Schema>(); backtrackChildren.add(qNameSchema); backtrackChildren.add(avroEnumRecord); backtrackChildren.add(xmlEnumRecord); backtrackChildren.add(unsignedLongList); backtrackChildren.add(listOfUnion); List<Schema.Field> backtrackFields = new ArrayList<Schema.Field>(); backtrackFields.add( new Schema.Field( "backtrack", Schema.createArray(Schema.createUnion(backtrackChildren)), "Children of {urn:avro:complex_schema}backtrack", null) ); backtrackSchema.setFields(backtrackFields); // complexExtension List<Schema.Field> complexExtensionFields = new ArrayList<Schema.Field>(); complexExtensionFields.add( new Schema.Field("optional", getOptionalStringSchema(), null, null)); complexExtensionFields.add( new Schema.Field( "defaulted", Schema.create(Schema.Type.STRING), null, null)); List<Schema> complexExtensionChildren = new ArrayList<Schema>(3); complexExtensionChildren.add(unsignedLongList); complexExtensionChildren.add(listOfUnion); complexExtensionChildren.add(fixedSchema); complexExtensionFields.add( new Schema.Field( "complexExtension", Schema.createArray(Schema.createUnion(complexExtensionChildren)), "Children of {urn:avro:complex_schema}complexExtension", null)); Schema complexExtensionSchema = Schema.createRecord("complexExtension", null, namespace, false); complexExtensionSchema.setFields(complexExtensionFields); // mixedType List<Schema> mixedTypeTypes = new ArrayList<Schema>(); mixedTypeTypes.add( Schema.create(Schema.Type.STRING) ); mixedTypeTypes.add(listOfUnion); mixedTypeTypes.add(unsignedLongList); List<Schema.Field> mixedTypeFields = new ArrayList<Schema.Field>(); mixedTypeFields.add( new Schema.Field( "mixedType", Schema.createArray(Schema.createUnion(mixedTypeTypes)), "Children of {urn:avro:complex_schema}mixedType", null)); Schema mixedTypeSchema = Schema.createRecord("mixedType", null, namespace, false); mixedTypeSchema.setFields(mixedTypeFields); // realRoot Schema realRootSchema = Schema.createRecord("realRoot", null, namespace, false); List<Schema.Field> realRootSchemaFields = new ArrayList<Schema.Field>(); realRootSchemaFields.add( new Schema.Field( "month", Schema.create(Schema.Type.STRING), null, null)); realRootSchemaFields.add( new Schema.Field( "year", Schema.create(Schema.Type.STRING), null, null)); realRootSchemaFields.add( new Schema.Field( "day", Schema.create(Schema.Type.STRING), null, null)); List<Schema> realRootChildren = new ArrayList<Schema>(); realRootChildren.add(backtrackSchema); realRootChildren.add(allTheThingsSchema); realRootChildren.add(prohibitSchema); realRootChildren.add(anyAndFriendsSchema); realRootChildren.add(simpleExtensionSchema); realRootChildren.add(simpleRestrictionSchema); realRootChildren.add(complexExtensionSchema); realRootChildren.add(mixedTypeSchema); realRootSchemaFields.add( new Schema.Field( "realRoot", Schema.createArray(Schema.createUnion(realRootChildren)), "Children of {urn:avro:complex_schema}realRoot", null)); realRootSchema.setFields(realRootSchemaFields); return Schema.createUnion( Collections.singletonList(realRootSchema)); } private static Schema getOptionalStringSchema() { List<Schema> optionalStringTypes = new ArrayList<Schema>(2); optionalStringTypes.add( Schema.create(Schema.Type.STRING) ); optionalStringTypes.add( Schema.create(Schema.Type.NULL) ); return Schema.createUnion(optionalStringTypes); } private static Schema getQNameSchema() { Schema qNameSchema = Schema.createRecord( "qName", "Qualified Name", "org.w3.www._2001.xmlschema", false); List<Schema.Field> qNameFields = new ArrayList<Schema.Field>(2); qNameFields.add( new Schema.Field( "namespace", Schema.create(Schema.Type.STRING), "The namespace of this qualified name.", null)); qNameFields.add( new Schema.Field( "localPart", Schema.create(Schema.Type.STRING), "The local part of this qualified name.", null)); qNameSchema.setFields(qNameFields); return qNameSchema; } private static Schema getOptionalDoubleSchema() { List<Schema> optionalDoubleTypes = new ArrayList<Schema>(2); optionalDoubleTypes.add( Schema.create(Schema.Type.DOUBLE) ); optionalDoubleTypes.add( Schema.create(Schema.Type.NULL) ); return Schema.createUnion(optionalDoubleTypes); } private static Schema getOptionalBooleanSchema() { List<Schema> optionalBooleanTypes = new ArrayList<Schema>(2); optionalBooleanTypes.add( Schema.create(Schema.Type.BOOLEAN) ); optionalBooleanTypes.add( Schema.create(Schema.Type.NULL) ); return Schema.createUnion(optionalBooleanTypes); } private static Schema getOptionalIntSchema() { List<Schema> optionalIntTypes = new ArrayList<Schema>(2); optionalIntTypes.add( Schema.create(Schema.Type.INT) ); optionalIntTypes.add( Schema.create(Schema.Type.NULL) ); return Schema.createUnion(optionalIntTypes); } private static Schema getOptionalBinarySchema() { List<Schema> optionalBinaryTypes = new ArrayList<Schema>(2); optionalBinaryTypes.add( Schema.create(Schema.Type.BYTES) ); optionalBinaryTypes.add( Schema.create(Schema.Type.NULL) ); return Schema.createUnion(optionalBinaryTypes); } private static Schema getOptionalDurationSchema() { List<Schema> optionalDurationTypes = new ArrayList<Schema>(2); optionalDurationTypes.add( Schema.createArray(Schema.create(Schema.Type.INT))); optionalDurationTypes.add(Schema.create(Schema.Type.NULL)); return Schema.createUnion(optionalDurationTypes); } }