diff --git a/schema2proto-lib/src/main/java/no/entur/schema2proto/generateproto/SchemaParser.java b/schema2proto-lib/src/main/java/no/entur/schema2proto/generateproto/SchemaParser.java index 340d7eb2..54e62757 100644 --- a/schema2proto-lib/src/main/java/no/entur/schema2proto/generateproto/SchemaParser.java +++ b/schema2proto-lib/src/main/java/no/entur/schema2proto/generateproto/SchemaParser.java @@ -84,6 +84,7 @@ import com.sun.xml.xsom.XSSimpleType; import com.sun.xml.xsom.XSTerm; import com.sun.xml.xsom.XSType; +import com.sun.xml.xsom.XSUnionSimpleType; import com.sun.xml.xsom.impl.ElementDecl; import com.sun.xml.xsom.parser.XSOMParser; import com.sun.xml.xsom.util.DomAnnotationParserFactory; @@ -246,12 +247,65 @@ private String processSimpleType(XSSimpleType xs, String elementName) { } else if (xs.isList()) { nestingLevel--; return processSimpleType(xs.asList().getItemType(), null); + } else if (isEnumUnion(xs)) { + createEnumFromUnion(typeName, xs.asUnion()); } nestingLevel--; return typeName; } + private boolean isNonEnumUnion(XSSimpleType xs) { + return xs.isUnion() && !isEnumUnion(xs); + } + + private boolean isEnumUnion(XSSimpleType xs) { + if (!xs.isUnion()) { + return false; + } + XSUnionSimpleType unionType = xs.asUnion(); + boolean allMembersAreEnums = true; + + for (int i = 0; i < unionType.getMemberSize(); i++) { + XSSimpleType member = unionType.getMember(i); + if (!member.isRestriction() || member.getFacet(XSFacet.FACET_ENUMERATION) == null) { + allMembersAreEnums = false; + break; + } + } + return allMembersAreEnums; + } + + private void createEnumFromUnion(String typeName, XSUnionSimpleType unionType) { + Type protoType = getType(unionType.getTargetNamespace(), typeName); + if (protoType == null) { + Location location = getLocation(unionType); + List constants = new ArrayList<>(); + int counter = 1; + Set addedValues = new HashSet<>(); + + for (int i = 0; i < unionType.getMemberSize(); i++) { + XSRestrictionSimpleType member = unionType.getMember(i).asRestriction(); + for (XSFacet facet : member.getDeclaredFacets()) { + String enumValue = facet.getValue().value; + if (addedValues.add(enumValue)) { + String doc = resolveDocumentationAnnotation(facet, false); + List optionElements = new ArrayList<>(); + constants.add(new EnumConstant(location, enumValue, counter++, doc, new Options(Options.ENUM_VALUE_OPTIONS, optionElements))); + } + } + } + + List enumOptionElements = new ArrayList<>(); + Options enumOptions = new Options(Options.ENUM_OPTIONS, enumOptionElements); + String doc = resolveDocumentationAnnotation(unionType, false); + + ProtoType definedProtoType = ProtoType.get(typeName); + EnumType enumType = new EnumType(definedProtoType, location, doc, typeName, constants, new ArrayList<>(), enumOptions); + addType(unionType.getTargetNamespace(), enumType); + } + } + private void addField(MessageType message, Field newField) { addField(message, null, newField); } @@ -502,8 +556,8 @@ public String findFieldType(XSType type) { XSListSimpleType asList = type.asSimpleType().asList(); XSSimpleType itemType = asList.getItemType(); typeName = itemType.getName(); - } else if (type.asSimpleType().isUnion()) { - typeName = DEFAULT_PROTO_PRIMITIVE; // Union always resolves to string + } else if (isNonEnumUnion(type.asSimpleType())) { + typeName = DEFAULT_PROTO_PRIMITIVE; // Non enum union always resolves to string } else { typeName = type.asSimpleType().getBaseType().getName(); } @@ -711,7 +765,7 @@ private MessageType processComplexType(XSComplexType complexType, String element } String name; - if (xsSimpleType.isUnion()) { + if (isNonEnumUnion(xsSimpleType)) { name = DEFAULT_PROTO_PRIMITIVE; } else { name = xsSimpleType.getName(); @@ -840,7 +894,7 @@ private void processAttribute(MessageType messageType, Set processedXmlO XSAttributeDecl decl = attr.getDecl(); XSSimpleType type = decl.getType(); - if (type.getPrimitiveType() != null || type.isList() || type.isUnion()) { + if (type.getPrimitiveType() != null || type.isList() || isNonEnumUnion(type)) { String fieldName = decl.getName(); String doc = resolveDocumentationAnnotation(decl, false); int tag = messageType.getNextFieldNum(); diff --git a/schema2proto-lib/src/test/java/no/entur/schema2proto/generateproto/SchemaParserTest.java b/schema2proto-lib/src/test/java/no/entur/schema2proto/generateproto/SchemaParserTest.java index b4b517fa..71faccb8 100644 --- a/schema2proto-lib/src/test/java/no/entur/schema2proto/generateproto/SchemaParserTest.java +++ b/schema2proto-lib/src/test/java/no/entur/schema2proto/generateproto/SchemaParserTest.java @@ -179,6 +179,12 @@ public void testUnion() throws IOException { compareExpectedAndGenerated(expectedRootFolder, "default/union.proto", generatedRootFolder, "default/default.proto"); } + @Test + public void testUnionOfEnums() throws IOException { + generateProtobufNoOptions("basic/union-of-enums.xsd"); + compareExpectedAndGenerated(expectedRootFolder, "default/union-of-enums.proto", generatedRootFolder, "default/default.proto"); + } + // @Test public void testValidationRules() throws IOException { generateProtobufNoOptions("basic/validationrules.xsd"); diff --git a/schema2proto-lib/src/test/resources/expectedproto/basic/default/union-of-enums.proto b/schema2proto-lib/src/test/resources/expectedproto/basic/default/union-of-enums.proto new file mode 100644 index 00000000..a4ee2caa --- /dev/null +++ b/schema2proto-lib/src/test/resources/expectedproto/basic/default/union-of-enums.proto @@ -0,0 +1,26 @@ +// default.proto at 0:0 +syntax = "proto3"; +package default; + +enum Enum1 { + // Default + ENUM1_UNSPECIFIED = 0; + ENUM1_E_1_VAL_1 = 1; + ENUM1_E_1_VAL_2 = 2; +} + +enum Enum2 { + // Default + ENUM2_UNSPECIFIED = 0; + ENUM2_E_2_VAL_1 = 1; + ENUM2_E_2_VAL_2 = 2; +} + +enum UnionEnumeration { + // Default + UNION_ENUMERATION_UNSPECIFIED = 0; + UNION_ENUMERATION_E_1_VAL_1 = 1; + UNION_ENUMERATION_E_1_VAL_2 = 2; + UNION_ENUMERATION_E_2_VAL_1 = 3; + UNION_ENUMERATION_E_2_VAL_2 = 4; +} diff --git a/schema2proto-lib/src/test/resources/xsd/basic/union-of-enums.xsd b/schema2proto-lib/src/test/resources/xsd/basic/union-of-enums.xsd new file mode 100644 index 00000000..ad859be6 --- /dev/null +++ b/schema2proto-lib/src/test/resources/xsd/basic/union-of-enums.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + +