Support "choice" tag
The "choice" tag is added for paring. This tag is similar to a
"sequence" tag.
The difference between the two tags are that "choice" tag allow the
maxOccurs and minOccurs and add the suffix to name as "_optional",
because to distinguish it from the sequence tag.
Test: m -j && atest xsdc-cpp-tests
Bug: 80453829
Change-Id: I73df54ff655208f99aeea242d915a1a4e9f506f2
diff --git a/src/com/android/xsdc/XsdHandler.java b/src/com/android/xsdc/XsdHandler.java
index 6589c1c..6494c1c 100644
--- a/src/com/android/xsdc/XsdHandler.java
+++ b/src/com/android/xsdc/XsdHandler.java
@@ -169,6 +169,9 @@
case "sequence":
stateStack.peek().tags.addAll(makeSequence(state.attributeMap, state.tags));
break;
+ case "choice":
+ stateStack.peek().tags.addAll(makeChoice(state.attributeMap, state.tags));
+ break;
case "enumeration":
stateStack.peek().tags.add(makeEnumeration(state.attributeMap));
enumerationFlag = true;
@@ -495,6 +498,20 @@
return elements;
}
+ private static List<XsdElement> makeChoice(Map<String, String> attributeMap,
+ List<XsdTag> tags) throws XsdParserException {
+ List<XsdElement> elements = new ArrayList<>();
+ for (XsdTag tag : tags) {
+ if (tag == null) continue;
+ if (tag instanceof XsdElement) {
+ XsdElement element = (XsdElement)tag;
+ elements.add(new XsdChoice(element.getName(), element.getRef(), element.getType(),
+ element.isMultiple()));
+ }
+ }
+ return elements;
+ }
+
private XsdEnumeration makeEnumeration(Map<String, String> attributeMap)
throws XsdParserException {
String value = attributeMap.get("value");
diff --git a/src/com/android/xsdc/cpp/CppCodeGenerator.java b/src/com/android/xsdc/cpp/CppCodeGenerator.java
index df4e2f8..121ac48 100644
--- a/src/com/android/xsdc/cpp/CppCodeGenerator.java
+++ b/src/com/android/xsdc/cpp/CppCodeGenerator.java
@@ -215,13 +215,13 @@
&& element.getType() instanceof XsdComplexType) {
// print inner class for anonymous types
headerFile.printf("public:\n");
- String innerName = Utils.toClassName(element.getName());
+ String innerName = Utils.toClassName(getElementName(element));
XsdComplexType innerType = (XsdComplexType) element.getType();
printClass(innerName, nameScope + name + "::", innerType);
headerFile.println();
cppType = new CppComplexType(nameScope + name + "::"+ innerName);
} else {
- cppType = parseType(elementValue.getType(), elementValue.getName());
+ cppType = parseType(elementValue.getType(), getElementName(elementValue));
}
elementTypes.add(cppType);
}
@@ -241,7 +241,8 @@
//String typeName = String.format("std::vector<%s>", type.getName());
String typeName = element.isMultiple() || type instanceof CppComplexType ?
String.format("std::vector<%s>", type.getName()) : type.getName();
- headerFile.printf("%s %s;\n", typeName, Utils.toVariableName(elementValue.getName()));
+ headerFile.printf("%s %s;\n", typeName,
+ Utils.toVariableName(getElementName(elementValue)));
}
for (int i = 0; i < attributeTypes.size(); ++i) {
CppType type = attributeTypes.get(i);
@@ -261,8 +262,8 @@
XsdElement element = complexType.getElements().get(i);
XsdElement elementValue = resolveElement(element);
printGetterAndSetter(nameScope + name, type,
- Utils.toVariableName(elementValue.getName()), type instanceof CppComplexType ?
- true : element.isMultiple());
+ Utils.toVariableName(getElementName(elementValue)),
+ type instanceof CppComplexType ? true : element.isMultiple());
}
for (int i = 0; i < attributeTypes.size(); ++i) {
CppType type = attributeTypes.get(i);
@@ -331,7 +332,7 @@
CppType type = allElementTypes.get(i);
XsdElement element = allElements.get(i);
XsdElement elementValue = resolveElement(element);
- String variableName = Utils.toVariableName(elementValue.getName());
+ String variableName = Utils.toVariableName(getElementName(elementValue));
if (i != 0) cppFile.printf("} else ");
cppFile.printf("if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>");
cppFile.printf("(\"%s\"))) {\n", elementValue.getName());
@@ -444,6 +445,13 @@
cppFile.printf("}\n\n");
}
+ private String getElementName(XsdElement element) {
+ if (element instanceof XsdChoice) {
+ return element.getName() + "_optional";
+ }
+ return element.getName();
+ }
+
private void stackComponents(XsdComplexType complexType, List<XsdElement> elements,
List<XsdAttribute> attributes) throws CppCodeGeneratorException {
if (complexType.getBase() != null) {
diff --git a/src/com/android/xsdc/java/JavaCodeGenerator.java b/src/com/android/xsdc/java/JavaCodeGenerator.java
index a4b36b0..63e2a66 100644
--- a/src/com/android/xsdc/java/JavaCodeGenerator.java
+++ b/src/com/android/xsdc/java/JavaCodeGenerator.java
@@ -162,14 +162,14 @@
if (element.getRef() == null && element.getType().getRef() == null
&& element.getType() instanceof XsdComplexType) {
// print inner class for anonymous types
- String innerName = Utils.toClassName(element.getName());
+ String innerName = Utils.toClassName(getElementName(element));
XsdComplexType innerType = (XsdComplexType) element.getType();
String innerNameScope = nameScope + name + ".";
printClass(out, innerName, innerType, innerNameScope);
out.println();
javaType = new JavaComplexType(innerNameScope + innerName);
} else {
- javaType = parseType(elementValue.getType(), elementValue.getName());
+ javaType = parseType(elementValue.getType(), getElementName(elementValue));
}
elementTypes.add(javaType);
}
@@ -186,7 +186,8 @@
XsdElement elementValue = resolveElement(element);
String typeName = element.isMultiple() ? String.format("java.util.List<%s>",
type.getNullableName()) : type.getName();
- out.printf("private %s %s;\n", typeName, Utils.toVariableName(elementValue.getName()));
+ out.printf("private %s %s;\n", typeName,
+ Utils.toVariableName(getElementName(elementValue)));
}
for (int i = 0; i < attributeTypes.size(); ++i) {
JavaType type = attributeTypes.get(i);
@@ -203,7 +204,7 @@
JavaType type = elementTypes.get(i);
XsdElement element = complexType.getElements().get(i);
XsdElement elementValue = resolveElement(element);
- printGetterAndSetter(out, type, Utils.toVariableName(elementValue.getName()),
+ printGetterAndSetter(out, type, Utils.toVariableName(getElementName(elementValue)),
element.isMultiple());
}
for (int i = 0; i < attributeTypes.size(); ++i) {
@@ -274,7 +275,7 @@
JavaType type = allElementTypes.get(i);
XsdElement element = allElements.get(i);
XsdElement elementValue = resolveElement(element);
- String variableName = Utils.toVariableName(elementValue.getName());
+ String variableName = Utils.toVariableName(getElementName(elementValue));
out.printf("if (tagName.equals(\"%s\")) {\n", elementValue.getName());
if (type instanceof JavaSimpleType) {
out.print("raw = XmlParser.readText(parser);\n");
@@ -387,6 +388,13 @@
out.println("}");
}
+ private String getElementName(XsdElement element) {
+ if (element instanceof XsdChoice) {
+ return element.getName() + "_optional";
+ }
+ return element.getName();
+ }
+
private void stackComponents(XsdComplexType complexType, List<XsdElement> elements,
List<XsdAttribute> attributes) throws JavaCodeGeneratorException {
if (complexType.getBase() != null) {
diff --git a/src/com/android/xsdc/tag/XsdChoice.java b/src/com/android/xsdc/tag/XsdChoice.java
new file mode 100644
index 0000000..223bb44
--- /dev/null
+++ b/src/com/android/xsdc/tag/XsdChoice.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed 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 com.android.xsdc.tag;
+
+import com.android.xsdc.XsdParserException;
+
+import javax.xml.namespace.QName;
+
+public class XsdChoice extends XsdElement {
+ public XsdChoice(String name, QName ref, XsdType type, boolean multiple)
+ throws XsdParserException {
+ super(name, ref, type, multiple);
+ }
+}
diff --git a/tests/main.cpp b/tests/main.cpp
index f3f302b..cd07467 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -182,6 +182,7 @@
Person person = read("resources/simple_complex_content.xml")[0];
USAddressP uSAddressP = person.getUSAddressP()[0];
KRAddress kRAddress = person.getKRAddress()[0];
+ SubAddress subAddress = person.getSubAddress()[0];
EXPECT_EQ(person.getName(), "Petr");
@@ -194,6 +195,8 @@
EXPECT_EQ(kRAddress.getName(), "Donga Studio");
EXPECT_EQ(kRAddress.getStreet(), "Nokdu Street");
EXPECT_EQ(kRAddress.getCity(), "Seoul");
+
+ EXPECT_EQ(subAddress.getChoice1_optional(), "Temp");
}
int main(int argc, char **argv) {
diff --git a/tests/resources/simple_complex_content.xml b/tests/resources/simple_complex_content.xml
index 505dd35..06c590f 100644
--- a/tests/resources/simple_complex_content.xml
+++ b/tests/resources/simple_complex_content.xml
@@ -15,4 +15,7 @@
<street>Nokdu Street</street>
<city>Seoul</city>
</KRAddress>
+ <subAddress>
+ <choice1>Temp</choice1>
+ </subAddress>
</person>
diff --git a/tests/resources/simple_complex_content/api/current.txt b/tests/resources/simple_complex_content/api/current.txt
index 5681c5b..d987dbc 100644
--- a/tests/resources/simple_complex_content/api/current.txt
+++ b/tests/resources/simple_complex_content/api/current.txt
@@ -18,12 +18,22 @@
ctor public Person();
method public simple.complex.content.KRAddress getKRAddress();
method public java.lang.String getName();
+ method public simple.complex.content.SubAddress getSubAddress();
method public simple.complex.content.USAddressP getUSAddressP();
method public void setKRAddress(simple.complex.content.KRAddress);
method public void setName(java.lang.String);
+ method public void setSubAddress(simple.complex.content.SubAddress);
method public void setUSAddressP(simple.complex.content.USAddressP);
}
+ public class SubAddress {
+ ctor public SubAddress();
+ method public java.lang.String getChoice1_optional();
+ method public java.lang.String getChoice2_optional();
+ method public void setChoice1_optional(java.lang.String);
+ method public void setChoice2_optional(java.lang.String);
+ }
+
public class USAddressP extends simple.complex.content.Address {
ctor public USAddressP();
method public java.lang.String getState();
diff --git a/tests/resources/simple_complex_content/simple_complex_content.xsd b/tests/resources/simple_complex_content/simple_complex_content.xsd
index 34ac508..e6be1eb 100644
--- a/tests/resources/simple_complex_content/simple_complex_content.xsd
+++ b/tests/resources/simple_complex_content/simple_complex_content.xsd
@@ -27,12 +27,19 @@
</xs:restriction>
</xs:complexContent>
</xs:complexType>
+ <xs:complexType name="subAddress">
+ <xs:choice>
+ <xs:element name="choice1" type="xs:string"/>
+ <xs:element name="choice2" type="xs:string"/>
+ </xs:choice>
+ </xs:complexType>
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="USAddressP" type="USAddressP"/>
<xs:element name="KRAddress" type="KRAddress"/>
+ <xs:element name="subAddress" type="subAddress"/>
</xs:sequence>
</xs:complexType>
</xs:element>