aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp6
-rw-r--r--build/Android.bp4
-rw-r--r--build/xsdc.go94
-rw-r--r--src/com/android/xsdc/CodeWriter.java21
-rw-r--r--src/com/android/xsdc/Main.java85
-rw-r--r--src/com/android/xsdc/XmlSchema.java27
-rw-r--r--src/com/android/xsdc/XsdHandler.java19
-rw-r--r--src/com/android/xsdc/cpp/CppCodeGenerator.java660
-rw-r--r--src/com/android/xsdc/cpp/CppComplexType.java5
-rw-r--r--src/com/android/xsdc/cpp/CppSimpleType.java61
-rw-r--r--src/com/android/xsdc/cpp/CppType.java2
-rw-r--r--src/com/android/xsdc/cpp/Utils.java20
-rw-r--r--src/com/android/xsdc/java/JavaCodeGenerator.java349
-rw-r--r--src/com/android/xsdc/java/JavaComplexType.java10
-rw-r--r--src/com/android/xsdc/java/JavaSimpleType.java36
-rw-r--r--src/com/android/xsdc/java/JavaType.java4
-rw-r--r--src/com/android/xsdc/java/Utils.java3
-rw-r--r--src/com/android/xsdc/tag/XsdAttribute.java8
-rw-r--r--tests/Android.bp86
-rw-r--r--tests/main.cpp207
-rw-r--r--tests/resources/attr_group_simple.xml2
-rw-r--r--tests/resources/attr_group_simple/Android.bp6
-rw-r--r--tests/resources/attr_group_simple/api/current.txt8
-rw-r--r--tests/resources/attr_group_simple/attr_group_simple.xsd6
-rw-r--r--tests/resources/enum_type/Android.bp9
-rw-r--r--tests/resources/enum_type/api/current.txt532
-rw-r--r--tests/resources/enum_type/api/last_current.txt0
-rw-r--r--tests/resources/enum_type/api/last_removed.txt0
-rw-r--r--tests/resources/enum_type/api/removed.txt1
-rw-r--r--tests/resources/enum_type/attr_enumtype.xsd743
-rw-r--r--tests/resources/group.xml8
-rw-r--r--tests/resources/group/Android.bp6
-rw-r--r--tests/resources/group/address.xsd8
-rw-r--r--tests/resources/group/api/current.txt6
-rw-r--r--tests/resources/group/group.xsd7
-rw-r--r--tests/resources/group2.xml1
-rw-r--r--tests/resources/nested_type/Android.bp6
-rw-r--r--tests/resources/nested_type/api/current.txt6
-rw-r--r--tests/resources/predefined_types.xml2
-rw-r--r--tests/resources/predefined_types/Android.bp6
-rw-r--r--tests/resources/predefined_types/api/current.txt16
-rw-r--r--tests/resources/purchase_simple/Android.bp6
-rw-r--r--tests/resources/purchase_simple/api/current.txt6
-rw-r--r--tests/resources/reference/Android.bp7
-rw-r--r--tests/resources/reference/api/current.txt18
-rw-r--r--tests/resources/simple_complex_content.xml2
-rw-r--r--tests/resources/simple_complex_content/Android.bp7
-rw-r--r--tests/resources/simple_complex_content/api/current.txt22
-rw-r--r--tests/resources/simple_type/Android.bp23
-rw-r--r--tests/resources/simple_type/api/current.txt14
-rw-r--r--tests/resources/simple_type/simple_type.xsd3
-rw-r--r--tests/simple_type.cpp52
-rw-r--r--tests/simple_type_enumsonly.cpp28
-rw-r--r--tests/src/com/android/xsdc/tests/TestCompilationResult.java58
-rw-r--r--tests/src/com/android/xsdc/tests/TestHelper.java150
-rw-r--r--tests/src/com/android/xsdc/tests/XmlParserTest.java465
-rw-r--r--tests/tests.cpp282
-rw-r--r--tests/xmltest.h29
-rw-r--r--utils/Android.bp24
-rw-r--r--utils/include/xsdc/XsdcSupport.h56
60 files changed, 3357 insertions, 981 deletions
diff --git a/Android.bp b/Android.bp
index fa7618a..e731a13 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,3 +1,7 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_binary_host {
name: "xsdc",
srcs: ["src/**/*.java"],
@@ -5,4 +9,4 @@ java_binary_host {
"commons-cli-1.2",
],
manifest: "MANIFEST.MF"
-} \ No newline at end of file
+}
diff --git a/build/Android.bp b/build/Android.bp
index befa978..446cd8f 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
bootstrap_go_package {
name: "xsdc-soong-rules",
pkgPath: "android/soong/xsdc",
diff --git a/build/xsdc.go b/build/xsdc.go
index 0546ec4..3a09d71 100644
--- a/build/xsdc.go
+++ b/build/xsdc.go
@@ -39,19 +39,19 @@ var (
xsdc = pctx.HostBinToolVariable("xsdcCmd", "xsdc")
xsdcJavaRule = pctx.StaticRule("xsdcJavaRule", blueprint.RuleParams{
Command: `rm -rf "${out}.temp" && mkdir -p "${out}.temp" && ` +
- `${xsdcCmd} $in -p $pkgName -o ${out}.temp -j && ` +
+ `${xsdcCmd} $in -p $pkgName -o ${out}.temp -j $args && ` +
`${config.SoongZipCmd} -jar -o ${out} -C ${out}.temp -D ${out}.temp && ` +
`rm -rf ${out}.temp`,
CommandDeps: []string{"${xsdcCmd}", "${config.SoongZipCmd}"},
Description: "xsdc Java ${in} => ${out}",
- }, "pkgName")
+ }, "pkgName", "args")
xsdcCppRule = pctx.StaticRule("xsdcCppRule", blueprint.RuleParams{
Command: `rm -rf "${outDir}" && ` +
- `${xsdcCmd} $in -p $pkgName -o ${outDir} -c`,
+ `${xsdcCmd} $in -p $pkgName -o ${outDir} -c $args`,
CommandDeps: []string{"${xsdcCmd}", "${config.SoongZipCmd}"},
Description: "xsdc C++ ${in} => ${out}",
- }, "pkgName", "outDir")
+ }, "pkgName", "outDir", "args")
xsdConfigRule = pctx.StaticRule("xsdConfigRule", blueprint.RuleParams{
Command: "cp -f ${in} ${output}",
@@ -63,6 +63,23 @@ type xsdConfigProperties struct {
Srcs []string
Package_name *string
Api_dir *string
+ Gen_writer *bool
+ Nullability *bool
+
+ // Whether has{element or atrribute} methods are set to public.
+ // It is not applied to C++, because these methods are always
+ // generated to public for C++.
+ Gen_has *bool
+ // Only generate code for enum converters. Applies to C++ only.
+ // This is useful for memory footprint reduction since it avoids
+ // depending on libxml2.
+ Enums_only *bool
+ // Only generate complementary code for XML parser. Applies to C++ only.
+ // The code being generated depends on the enum converters module.
+ Parser_only *bool
+ // Whether getter name of boolean element or attribute is getX or isX.
+ // Default value is false. If the property is true, getter name is isX.
+ Boolean_getter *bool
}
type xsdConfig struct {
@@ -72,13 +89,13 @@ type xsdConfig struct {
genOutputDir android.Path
genOutputs_j android.WritablePath
- genOutputs_c android.WritablePath
- genOutputs_h android.WritablePath
+ genOutputs_c android.WritablePaths
+ genOutputs_h android.WritablePaths
docsPath android.Path
xsdConfigPath android.OptionalPath
- genOutputs android.Paths
+ genOutputs android.Paths
}
var _ android.SourceFileProducer = (*xsdConfig)(nil)
@@ -105,7 +122,7 @@ type DroidstubsProperties struct {
}
func (module *xsdConfig) GeneratedSourceFiles() android.Paths {
- return android.Paths{module.genOutputs_c}
+ return module.genOutputs_c.Paths()
}
func (module *xsdConfig) Srcs() android.Paths {
@@ -113,7 +130,7 @@ func (module *xsdConfig) Srcs() android.Paths {
}
func (module *xsdConfig) GeneratedDeps() android.Paths {
- return android.Paths{module.genOutputs_h}
+ return module.genOutputs_h.Paths()
}
func (module *xsdConfig) GeneratedHeaderDirs() android.Paths {
@@ -159,6 +176,31 @@ func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext)
pkgName := *module.properties.Package_name
filenameStem := strings.Replace(pkgName, ".", "_", -1)
+ args := ""
+ if proptools.Bool(module.properties.Gen_writer) {
+ args = "-w"
+ }
+
+ if proptools.Bool(module.properties.Nullability) {
+ args = args + " -n "
+ }
+
+ if proptools.Bool(module.properties.Gen_has) {
+ args = args + " -g "
+ }
+
+ if proptools.Bool(module.properties.Enums_only) {
+ args = args + " -e "
+ }
+
+ if proptools.Bool(module.properties.Parser_only) {
+ args = args + " -x "
+ }
+
+ if proptools.Bool(module.properties.Boolean_getter) {
+ args = args + " -b "
+ }
+
module.genOutputs_j = android.PathForModuleGen(ctx, "java", filenameStem+"_xsdcgen.srcjar")
ctx.Build(pctx, android.BuildParams{
@@ -169,23 +211,41 @@ func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext)
Output: module.genOutputs_j,
Args: map[string]string{
"pkgName": pkgName,
+ "args": args,
},
})
- module.genOutputs_c = android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp")
- module.genOutputs_h = android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h")
+ if proptools.Bool(module.properties.Enums_only) {
+ module.genOutputs_c = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", filenameStem+"_enums.cpp")}
+ module.genOutputs_h = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+"_enums.h")}
+ } else if proptools.Bool(module.properties.Parser_only) {
+ module.genOutputs_c = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp")}
+ module.genOutputs_h = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h")}
+ } else {
+ module.genOutputs_c = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp"),
+ android.PathForModuleGen(ctx, "cpp", filenameStem+"_enums.cpp")}
+ module.genOutputs_h = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h"),
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+"_enums.h")}
+ }
module.genOutputDir = android.PathForModuleGen(ctx, "cpp", "include")
ctx.Build(pctx, android.BuildParams{
- Rule: xsdcCppRule,
- Description: "xsdc " + xsdFile.String(),
- Input: xsdFile,
- Implicit: module.docsPath,
- Output: module.genOutputs_c,
- ImplicitOutput: module.genOutputs_h,
+ Rule: xsdcCppRule,
+ Description: "xsdc " + xsdFile.String(),
+ Input: xsdFile,
+ Implicit: module.docsPath,
+ Outputs: module.genOutputs_c,
+ ImplicitOutputs: module.genOutputs_h,
Args: map[string]string{
"pkgName": pkgName,
"outDir": android.PathForModuleGen(ctx, "cpp").String(),
+ "args": args,
},
})
module.xsdConfigPath = android.ExistentPathForSource(ctx, xsdFile.String())
diff --git a/src/com/android/xsdc/CodeWriter.java b/src/com/android/xsdc/CodeWriter.java
index 1ffe801..489ccdc 100644
--- a/src/com/android/xsdc/CodeWriter.java
+++ b/src/com/android/xsdc/CodeWriter.java
@@ -24,6 +24,10 @@ public class CodeWriter implements Closeable {
private int indent;
private boolean startLine;
+ public CodeWriter() {
+ this(null);
+ }
+
public CodeWriter(PrintWriter printWriter) {
out = printWriter;
indent = 0;
@@ -33,13 +37,15 @@ public class CodeWriter implements Closeable {
private void printIndent() {
assert startLine;
for (int i = 0; i < indent; ++i) {
- out.print(" ");
+ printImpl(" ");
}
startLine = false;
}
public void println() {
- out.println();
+ if (out != null) {
+ out.println();
+ }
startLine = true;
}
@@ -58,13 +64,12 @@ public class CodeWriter implements Closeable {
if (startLine && !line.isEmpty()) {
printIndent();
}
- out.print(line);
+ printImpl(line);
if (line.endsWith("{")) {
++indent;
}
if (i + 1 < lines.length) {
- out.println();
- startLine = true;
+ println();
}
}
}
@@ -79,4 +84,10 @@ public class CodeWriter implements Closeable {
out.close();
}
}
+
+ private void printImpl(String code) {
+ if (out != null) {
+ out.print(code);
+ }
+ }
}
diff --git a/src/com/android/xsdc/Main.java b/src/com/android/xsdc/Main.java
index b8f6dd3..0358f08 100644
--- a/src/com/android/xsdc/Main.java
+++ b/src/com/android/xsdc/Main.java
@@ -29,7 +29,9 @@ import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
@@ -60,6 +62,44 @@ public class Main {
.hasArgs(0)
.withDescription("Generate Cpp code.")
.create("c"));
+ options.addOption(OptionBuilder
+ .withLongOpt("writer")
+ .hasArgs(0)
+ .withDescription("Generate Writer code.")
+ .create("w"));
+ options.addOption(OptionBuilder
+ .withLongOpt("nullability")
+ .hasArgs(0)
+ .withDescription("Add @NonNull or @Nullable annotation to generated java code.")
+ .create("n"));
+ options.addOption(OptionBuilder
+ .withLongOpt("genHas")
+ .hasArgs(0)
+ .withDescription("Generate public hasX() method")
+ .create("g"));
+ options.addOption(OptionBuilder
+ .withLongOpt("booleanGetter")
+ .hasArgs(0)
+ .withDescription("Generate isX() for boolean element or attribute.")
+ .create("b"));
+ Option genEnumsOnly = OptionBuilder
+ .withLongOpt("genEnumsOnly")
+ .hasArgs(0)
+ .withDescription("Only generate enum converters in Cpp code.")
+ .create("e");
+ options.addOption(genEnumsOnly);
+ Option genParserOnly = OptionBuilder
+ .withLongOpt("genParserOnly")
+ .hasArgs(0)
+ .withDescription("Only generate XML parser in Cpp code.")
+ .create("x");
+ options.addOption(genParserOnly);
+ // "Only generate enums" and "Only generate parser" options are mutually exclusive.
+ OptionGroup genOnlyGroup = new OptionGroup();
+ genOnlyGroup.setRequired(false);
+ genOnlyGroup.addOption(genEnumsOnly);
+ genOnlyGroup.addOption(genParserOnly);
+ options.addOptionGroup(genOnlyGroup);
CommandLineParser CommandParser = new GnuParser();
CommandLine cmd;
@@ -75,9 +115,15 @@ public class Main {
String[] xsdFile = cmd.getArgs();
String packageName = cmd.getOptionValue('p', null);
String outDir = cmd.getOptionValue('o', null);
+ boolean writer = cmd.hasOption('w');
+ boolean nullability = cmd.hasOption('n');
+ boolean genHas = cmd.hasOption('g');
+ boolean enumsOnly = cmd.hasOption('e');
+ boolean parserOnly = cmd.hasOption('x');
+ boolean booleanGetter = cmd.hasOption('b');
if (xsdFile.length != 1 || packageName == null) {
- System.err.println("Error: no xsd files or pacakge name");
+ System.err.println("Error: no xsd files or package name");
help(options);
}
@@ -85,31 +131,46 @@ public class Main {
outDir = ".";
}
- XmlSchema xmlSchema;
- try (FileInputStream in = new FileInputStream(xsdFile[0])) {
- SAXParserFactory factory = SAXParserFactory.newInstance();
- factory.setNamespaceAware(true);
- SAXParser parser = factory.newSAXParser();
- XsdHandler xsdHandler = new XsdHandler();
- parser.parse(in, xsdHandler);
- xmlSchema = xsdHandler.getSchema();
- }
+ XmlSchema xmlSchema = parse(xsdFile[0]);
if (cmd.hasOption('j')) {
File packageDir = new File(Paths.get(outDir, packageName.replace(".", "/")).toString());
packageDir.mkdirs();
FileSystem fs = new FileSystem(packageDir);
- JavaCodeGenerator javaCodeGenerator = new JavaCodeGenerator(xmlSchema, packageName);
+ JavaCodeGenerator javaCodeGenerator =
+ new JavaCodeGenerator(xmlSchema, packageName, writer, nullability, genHas,
+ booleanGetter);
javaCodeGenerator.print(fs);
} else if (cmd.hasOption('c')) {
File includeDir = new File(Paths.get(outDir, "include").toString());
includeDir.mkdirs();
FileSystem fs = new FileSystem(new File(outDir));
- CppCodeGenerator cppCodeGenerator = new CppCodeGenerator(xmlSchema, packageName);
+ int generators = enumsOnly ? CppCodeGenerator.GENERATE_ENUMS :
+ (parserOnly ? CppCodeGenerator.GENERATE_PARSER :
+ CppCodeGenerator.GENERATE_ENUMS | CppCodeGenerator.GENERATE_PARSER);
+ CppCodeGenerator cppCodeGenerator =
+ new CppCodeGenerator(xmlSchema, packageName, writer, generators, booleanGetter);
cppCodeGenerator.print(fs);
}
}
+ private static XmlSchema parse(String xsdFile) throws Exception {
+ XmlSchema xmlSchema;
+ try (FileInputStream in = new FileInputStream(xsdFile)) {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ SAXParser parser = factory.newSAXParser();
+ XsdHandler xsdHandler = new XsdHandler();
+ parser.parse(in, xsdHandler);
+ xmlSchema = xsdHandler.getSchema();
+ }
+ for (String file : xmlSchema.getIncludeList()) {
+ XmlSchema temp = parse(Paths.get(xsdFile).resolveSibling(file).toString());
+ xmlSchema.include(temp);
+ }
+ return xmlSchema;
+ }
+
private static void help(Options options) {
new HelpFormatter().printHelp(
"xsdc path/to/xsd_file.xsd","", options, null, true);
diff --git a/src/com/android/xsdc/XmlSchema.java b/src/com/android/xsdc/XmlSchema.java
index a941791..4bfa3fd 100644
--- a/src/com/android/xsdc/XmlSchema.java
+++ b/src/com/android/xsdc/XmlSchema.java
@@ -19,6 +19,7 @@ package com.android.xsdc;
import com.android.xsdc.tag.*;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
public class XmlSchema {
@@ -27,16 +28,18 @@ public class XmlSchema {
final private Map<String, XsdAttribute> attributeMap;
final private Map<String, XsdAttributeGroup> attributeGroupMap;
final private Map<String, XsdGroup> groupMap;
+ final private List<String> includeList;
XmlSchema(Map<String, XsdElement> elementMap, Map<String, XsdType> typeMap,
Map<String, XsdAttribute> attributeMap,
Map<String, XsdAttributeGroup> attributeGroupMap,
- Map<String, XsdGroup> groupMap) {
- this.elementMap = Collections.unmodifiableMap(elementMap);
- this.typeMap = Collections.unmodifiableMap(typeMap);
- this.attributeMap = Collections.unmodifiableMap(attributeMap);
- this.attributeGroupMap = Collections.unmodifiableMap(attributeGroupMap);
- this.groupMap = Collections.unmodifiableMap(groupMap);
+ Map<String, XsdGroup> groupMap, List<String> includeList) {
+ this.elementMap = elementMap;
+ this.typeMap = typeMap;
+ this.attributeMap = attributeMap;
+ this.attributeGroupMap = attributeGroupMap;
+ this.groupMap = groupMap;
+ this.includeList = includeList;
}
public Map<String, XsdElement> getElementMap() {
@@ -58,4 +61,16 @@ public class XmlSchema {
public Map<String, XsdGroup> getGroupMap() {
return groupMap;
}
+
+ public List<String> getIncludeList() {
+ return includeList;
+ }
+
+ public void include(XmlSchema schema) {
+ elementMap.putAll(schema.getElementMap());
+ typeMap.putAll(schema.getTypeMap());
+ attributeMap.putAll(schema.getAttributeMap());
+ attributeGroupMap.putAll(schema.getAttributeGroupMap());
+ groupMap.putAll(schema.getGroupMap());
+ }
}
diff --git a/src/com/android/xsdc/XsdHandler.java b/src/com/android/xsdc/XsdHandler.java
index a2cc57c..f6a9492 100644
--- a/src/com/android/xsdc/XsdHandler.java
+++ b/src/com/android/xsdc/XsdHandler.java
@@ -60,6 +60,7 @@ public class XsdHandler extends DefaultHandler {
private boolean documentationFlag;
private boolean enumerationFlag;
private List<XsdTag> enumTags;
+ private List<String> includeList;
public XsdHandler() {
stateStack = new Stack<>();
@@ -67,6 +68,7 @@ public class XsdHandler extends DefaultHandler {
documentationFlag = false;
enumerationFlag = false;
enumTags = new ArrayList<>();
+ includeList = new ArrayList<>();
}
public XmlSchema getSchema() {
@@ -226,6 +228,9 @@ public class XsdHandler extends DefaultHandler {
// They are using when validating xml files via xsd file.
// So they are ignored.
break;
+ case "include":
+ addInclude(state);
+ break;
default:
throw new XsdParserException(String.format("unsupported tag : %s", state.name));
}
@@ -259,7 +264,7 @@ public class XsdHandler extends DefaultHandler {
}
}
- return new XmlSchema(elementMap, typeMap, attrMap, attrGroupMap, groupMap);
+ return new XmlSchema(elementMap, typeMap, attrMap, attrGroupMap, groupMap, includeList);
}
private XsdElement makeElement(State state) throws XsdParserException {
@@ -311,6 +316,11 @@ public class XsdHandler extends DefaultHandler {
if (use != null && use.equals("prohibited")) return null;
+ boolean required = false;
+ if (use != null && use.equals("required")) {
+ required = true;
+ }
+
XsdType type = null;
if (typename != null) {
type = new XsdType(null, typename);
@@ -322,7 +332,7 @@ public class XsdHandler extends DefaultHandler {
}
}
- return setDeprecatedAndFinal(new XsdAttribute(name, ref, type), state.deprecated,
+ return setDeprecatedAndFinal(new XsdAttribute(name, ref, type, required), state.deprecated,
state.finalValue, state.nullability);
}
@@ -658,6 +668,11 @@ public class XsdHandler extends DefaultHandler {
state.finalValue, state.nullability);
}
+ private void addInclude(State state) throws XsdParserException {
+ String fileName = state.attributeMap.get("schemaLocation");
+ includeList.add(fileName);
+ }
+
private boolean isDeprecated(Map<String, String> attributeMap,List<XsdTag> tags,
boolean deprecated) throws XsdParserException {
String name = attributeMap.get("name");
diff --git a/src/com/android/xsdc/cpp/CppCodeGenerator.java b/src/com/android/xsdc/cpp/CppCodeGenerator.java
index f7ef86b..3f4b844 100644
--- a/src/com/android/xsdc/cpp/CppCodeGenerator.java
+++ b/src/com/android/xsdc/cpp/CppCodeGenerator.java
@@ -34,17 +34,30 @@ import java.util.Set;
import javax.xml.namespace.QName;
public class CppCodeGenerator {
+ public static final int GENERATE_ENUMS = 1 << 0;
+ public static final int GENERATE_PARSER = 1 << 1;
+
private XmlSchema xmlSchema;
private String pkgName;
private Map<String, CppSimpleType> cppSimpleTypeMap;
- private CodeWriter cppFile;
- private CodeWriter headerFile;
+ private CodeWriter enumsCppFile;
+ private CodeWriter enumsHeaderFile;
+ private CodeWriter parserCppFile;
+ private CodeWriter parserHeaderFile;
private boolean hasAttr;
+ private boolean writer;
+ private int generators;
+ private boolean booleanGetter;
- public CppCodeGenerator(XmlSchema xmlSchema, String pkgName)
- throws CppCodeGeneratorException {
+ private static final String UNKNOWN_ENUM = "UNKNOWN";
+
+ public CppCodeGenerator(XmlSchema xmlSchema, String pkgName, boolean writer, int generators,
+ boolean booleanGetter) throws CppCodeGeneratorException {
this.xmlSchema = xmlSchema;
this.pkgName = pkgName;
+ this.writer = writer;
+ this.generators = generators;
+ this.booleanGetter = booleanGetter;
// class naming validation
{
@@ -91,28 +104,76 @@ public class CppCodeGenerator {
public void print(FileSystem fs)
throws CppCodeGeneratorException, IOException {
- // cpp file, headr file init
- String cppFileName = pkgName.replace(".", "_") + ".cpp";
- String hFileName = pkgName.replace(".", "_") + ".h";
- cppFile = new CodeWriter(fs.getPrintWriter(cppFileName));
- headerFile = new CodeWriter(fs.getPrintWriter("include/" + hFileName));
-
- String headerMacro = hFileName.toUpperCase().replace(".", "_");
- headerFile.printf("#ifndef %s\n", headerMacro);
- headerFile.printf("#define %s\n\n", headerMacro);
- headerFile.printf("#include <libxml/parser.h>\n");
- headerFile.printf("#include <libxml/xinclude.h>\n\n");
- headerFile.printf("#include <map>\n");
- headerFile.printf("#include <optional>\n");
- headerFile.printf("#include <string>\n");
- headerFile.printf("#include <vector>\n\n");
-
- cppFile.printf("#define LOG_TAG \"%s\"\n\n", pkgName);
- cppFile.printf("#include <android/log.h>\n");
- cppFile.printf("#include <android-base/strings.h>\n\n");
- cppFile.printf("#include <libxml/parser.h>\n");
- cppFile.printf("#include <libxml/xinclude.h>\n\n");
- cppFile.printf("#include \"%s\"\n\n", hFileName);
+ // cpp file, header file init
+ String fileNameStem = pkgName.replace('.', '_');
+ String enumsCppFileName = fileNameStem + "_enums.cpp";
+ String enumsHeaderFileName = fileNameStem + "_enums.h";
+ String parserCppFileName = fileNameStem + ".cpp";
+ String parserHeaderFileName = fileNameStem + ".h";
+ if ((this.generators & GENERATE_ENUMS) == GENERATE_ENUMS) {
+ enumsCppFile = new CodeWriter(fs.getPrintWriter(enumsCppFileName));
+ enumsHeaderFile = new CodeWriter(fs.getPrintWriter("include/" + enumsHeaderFileName));
+ } else {
+ enumsCppFile = new CodeWriter();
+ enumsHeaderFile = new CodeWriter();
+ }
+ if ((this.generators & GENERATE_PARSER) == GENERATE_PARSER) {
+ parserCppFile = new CodeWriter(fs.getPrintWriter(parserCppFileName));
+ parserHeaderFile = new CodeWriter(fs.getPrintWriter("include/" + parserHeaderFileName));
+ } else {
+ parserCppFile = new CodeWriter();
+ parserHeaderFile = new CodeWriter();
+ }
+
+ boolean hasEnums = false;
+ for (XsdType type : xmlSchema.getTypeMap().values()) {
+ if (type instanceof XsdRestriction &&
+ ((XsdRestriction)type).getEnums() != null) {
+ hasEnums = true;
+ break;
+ }
+ }
+
+ String enumsHeaderMacro = enumsHeaderFileName.toUpperCase().replace('.', '_');
+ String parserHeaderMacro = parserHeaderFileName.toUpperCase().replace('.', '_');
+ enumsHeaderFile.printf("#ifndef %s\n", enumsHeaderMacro);
+ enumsHeaderFile.printf("#define %s\n", enumsHeaderMacro);
+ enumsHeaderFile.printf("\n");
+ enumsHeaderFile.printf("#include <array>\n");
+ enumsHeaderFile.printf("#include <string>\n");
+ enumsHeaderFile.printf("\n");
+ parserHeaderFile.printf("#ifndef %s\n", parserHeaderMacro);
+ parserHeaderFile.printf("#define %s\n", parserHeaderMacro);
+ parserHeaderFile.printf("\n");
+ parserHeaderFile.printf("#include <array>\n");
+ parserHeaderFile.printf("#include <map>\n");
+ parserHeaderFile.printf("#include <optional>\n");
+ parserHeaderFile.printf("#include <string>\n");
+ parserHeaderFile.printf("#include <vector>\n");
+ if (writer) {
+ parserHeaderFile.printf("#include <iostream>\n");
+ }
+ parserHeaderFile.printf("\n");
+ parserHeaderFile.printf("#if __has_include(<libxml/parser.h>)\n");
+ parserHeaderFile.printf("#include <libxml/parser.h>\n");
+ parserHeaderFile.printf("#include <libxml/xinclude.h>\n");
+ parserHeaderFile.printf("#else\n");
+ parserHeaderFile.printf("#error Require libxml2 library. ");
+ parserHeaderFile.printf("Please add libxml2 to shared_libs or static_libs\n");
+ parserHeaderFile.printf("#endif\n");
+ if (hasEnums) {
+ enumsHeaderFile.printf("#include <xsdc/XsdcSupport.h>\n");
+ enumsHeaderFile.printf("\n");
+ }
+ parserHeaderFile.printf("\n");
+ parserHeaderFile.printf("#include \"%s\"\n", enumsHeaderFileName);
+ parserHeaderFile.printf("\n");
+
+ enumsCppFile.printf("#include <map>\n");
+ enumsCppFile.printf("\n");
+ enumsCppFile.printf("#include \"%s\"\n\n", enumsHeaderFileName);
+ parserCppFile.printf("#define LOG_TAG \"%s\"\n", pkgName);
+ parserCppFile.printf("#include \"%s\"\n\n", parserHeaderFileName);
List<String> namespace = new java.util.ArrayList<>();
for (String token : pkgName.split("\\.")) {
@@ -123,25 +184,33 @@ public class CppCodeGenerator {
token = "_" + token;
}
namespace.add(token);
- headerFile.printf("namespace %s {\n", token);
- cppFile.printf("namespace %s {\n", token);
+ enumsHeaderFile.printf("namespace %s {\n", token);
+ enumsCppFile.printf("namespace %s {\n", token);
+ parserHeaderFile.printf("namespace %s {\n", token);
+ parserCppFile.printf("namespace %s {\n", token);
}
printPrototype();
printXmlParser();
+ if (writer) {
+ printXmlWriter();
+ }
for (XsdType type : xmlSchema.getTypeMap().values()) {
- if (type instanceof XsdComplexType) {
- String name = Utils.toClassName(type.getName());
- XsdComplexType complexType = (XsdComplexType) type;
- printClass(name, "", complexType);
- } else if (type instanceof XsdRestriction &&
+ if (type instanceof XsdRestriction &&
((XsdRestriction)type).getEnums() != null) {
String name = Utils.toClassName(type.getName());
XsdRestriction restrictionType = (XsdRestriction) type;
printEnum(name, restrictionType);
}
}
+ for (XsdType type : xmlSchema.getTypeMap().values()) {
+ if (type instanceof XsdComplexType) {
+ String name = Utils.toClassName(type.getName());
+ XsdComplexType complexType = (XsdComplexType) type;
+ printClass(name, "", complexType);
+ }
+ }
for (XsdElement element : xmlSchema.getElementMap().values()) {
XsdType type = element.getType();
if (type.getRef() == null && type instanceof XsdComplexType) {
@@ -153,52 +222,97 @@ public class CppCodeGenerator {
Collections.reverse(namespace);
for (String token : namespace) {
- headerFile.printf("} // %s\n", token);
- cppFile.printf("} // %s\n", token);
+ enumsHeaderFile.printf("} // %s\n", token);
+ enumsCppFile.printf("} // %s\n", token);
+ parserHeaderFile.printf("} // %s\n", token);
+ parserCppFile.printf("} // %s\n", token);
+ }
+
+ if (hasEnums) {
+ enumsHeaderFile.printf("\n//\n// global type declarations for package\n//\n\n");
+ enumsHeaderFile.printf("namespace android {\nnamespace details {\n");
+ Collections.reverse(namespace);
+ for (XsdType type : xmlSchema.getTypeMap().values()) {
+ if (type instanceof XsdRestriction &&
+ ((XsdRestriction)type).getEnums() != null) {
+ String name = Utils.toClassName(type.getName());
+ XsdRestriction restrictionType = (XsdRestriction) type;
+ printEnumValues(namespace, name, restrictionType);
+ }
+ }
+ enumsHeaderFile.printf("} // namespace details\n} // namespace android\n\n");
}
- headerFile.printf("#endif // %s\n", headerMacro);
- cppFile.close();
- headerFile.close();
+ parserHeaderFile.printf("#endif // %s\n", parserHeaderMacro);
+ enumsHeaderFile.printf("#endif // %s\n", enumsHeaderMacro);
+ parserCppFile.close();
+ parserHeaderFile.close();
+ enumsCppFile.close();
+ enumsHeaderFile.close();
}
private void printEnum(String name, XsdRestriction restrictionType)
throws CppCodeGeneratorException {
- headerFile.printf("enum class %s {\n", name);
- cppFile.printf("const std::map<std::string, %s> %sString {\n", name, name);
+ enumsHeaderFile.printf("enum class %s {\n", name);
+ enumsCppFile.printf("const std::map<std::string, %s> %sString {\n", name, name);
List<XsdEnumeration> enums = restrictionType.getEnums();
+ enumsHeaderFile.printf("%s = %d,\n", UNKNOWN_ENUM, -1);
for (XsdEnumeration tag : enums) {
String value = tag.getValue();
- if ("".equals(value)) {
- value = "EMPTY";
- }
- headerFile.printf("%s,\n", Utils.toEnumName(value));
- cppFile.printf("{ \"%s\", %s::%s },\n", tag.getValue(), name,
+ enumsHeaderFile.printf("%s,\n", Utils.toEnumName(value));
+ enumsCppFile.printf("{ \"%s\", %s::%s },\n", tag.getValue(), name,
Utils.toEnumName(value));
}
- headerFile.printf("UNKNOWN\n};\n\n");
- cppFile.printf("};\n\n");
-
- cppFile.printf("static %s stringTo%s(std::string value) {\n"
- + "auto enumValue = %sString.find(value);\n"
- + "return enumValue == %sString.end() ? %s::UNKNOWN : enumValue->second;\n"
- + "}\n\n", name, name, name, name, name);
+ enumsHeaderFile.printf("};\n");
+ enumsCppFile.printf("};\n\n");
+
+ enumsHeaderFile.printf("%s stringTo%s(const std::string& value);\n",
+ name, name);
+ enumsCppFile.printf("%s stringTo%s(const std::string& value) {\n"
+ + "auto enumValue = %sString.find(value);\n"
+ + "return enumValue != %sString.end() ? enumValue->second : %s::%s;\n"
+ + "}\n\n", name, name, name, name, name, UNKNOWN_ENUM);
+
+ enumsHeaderFile.printf("std::string toString(%s o);\n\n", name);
+ enumsCppFile.printf("std::string toString(%s o) {\n", name);
+ enumsCppFile.printf("switch (o) {\n");
+ for (XsdEnumeration tag : enums) {
+ String value = tag.getValue();
+ enumsCppFile.printf("case %s::%s: return \"%s\";\n",
+ name, Utils.toEnumName(value), tag.getValue());
+ }
+ enumsCppFile.printf("default: return std::to_string(static_cast<int>(o));\n}\n");
+ enumsCppFile.printf("}\n\n");
}
+ private void printEnumValues(List<String> namespace, String name,
+ XsdRestriction restrictionType) throws CppCodeGeneratorException {
+ List<XsdEnumeration> enums = restrictionType.getEnums();
+ String absoluteNamespace = "::" + String.join("::", namespace);
+ enumsHeaderFile.printf("template<> inline constexpr std::array<%s::%s, %d> "
+ + "xsdc_enum_values<%s::%s> = {\n",
+ absoluteNamespace, name, enums.size(), absoluteNamespace, name);
+ for (XsdEnumeration tag : enums) {
+ String value = tag.getValue();
+ enumsHeaderFile.printf("%s::%s::%s,\n",
+ absoluteNamespace, name, Utils.toEnumName(value));
+ }
+ enumsHeaderFile.printf("};\n");
+ }
private void printPrototype() throws CppCodeGeneratorException {
for (XsdType type : xmlSchema.getTypeMap().values()) {
if (type instanceof XsdComplexType) {
String name = Utils.toClassName(type.getName());
- headerFile.printf("class %s;\n", name);
+ parserHeaderFile.printf("class %s;\n", name);
}
}
for (XsdElement element : xmlSchema.getElementMap().values()) {
XsdType type = element.getType();
if (type.getRef() == null && type instanceof XsdComplexType) {
String name = Utils.toClassName(element.getName());
- headerFile.printf("class %s;\n", name);
+ parserHeaderFile.printf("class %s;\n", name);
}
}
}
@@ -212,12 +326,12 @@ public class CppCodeGenerator {
CppSimpleType valueType = (complexType instanceof XsdSimpleContent) ?
getValueType((XsdSimpleContent) complexType, false) : null;
- headerFile.printf("class %s ", name);
+ parserHeaderFile.printf("class %s ", name);
if (baseName != null) {
- headerFile.printf(": public %s {\n", baseName);
+ parserHeaderFile.printf(": public %s {\n", baseName);
} else {
- headerFile.println("{");
+ parserHeaderFile.println("{");
}
// parse types for elements and attributes
@@ -232,11 +346,11 @@ public class CppCodeGenerator {
if (element.getRef() == null && element.getType().getRef() == null
&& element.getType() instanceof XsdComplexType) {
// print inner class for anonymous types
- headerFile.printf("public:\n");
+ parserHeaderFile.printf("public:\n");
String innerName = Utils.toClassName(getElementName(element));
XsdComplexType innerType = (XsdComplexType) element.getType();
printClass(innerName, nameScope + name + "::", innerType);
- headerFile.println();
+ parserHeaderFile.println();
cppType = new CppComplexType(nameScope + name + "::"+ innerName);
} else {
cppType = parseType(elementValue.getType(), getElementName(elementValue));
@@ -257,53 +371,66 @@ public class CppCodeGenerator {
// print member variables
- headerFile.printf("private:\n");
+ parserHeaderFile.printf("private:\n");
for (int i = 0; i < elementTypes.size(); ++i) {
CppType type = elementTypes.get(i);
XsdElement element = elements.get(i);
XsdElement elementValue = resolveElement(element);
- String typeName = element.isMultiple() || type instanceof CppComplexType ?
- String.format("std::vector<%s>", type.getName()) : type.getName();
- headerFile.printf("%s %s;\n", typeName,
+ String typeName = Utils.elementTypeName(type.getName(),
+ element.isMultiple() || type instanceof CppComplexType);
+ parserHeaderFile.printf("const %s %s_;\n", typeName,
Utils.toVariableName(getElementName(elementValue)));
}
for (int i = 0; i < attributeTypes.size(); ++i) {
CppType type = attributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(attributes.get(i));
- headerFile.printf("%s %s;\n", type.getName(),
- Utils.toVariableName(attribute.getName()));
+ String variableName = Utils.toVariableName(attribute.getName());
+ if (attribute.isRequired()) {
+ parserHeaderFile.printf("const %s %s_;\n", type.getName(), variableName);
+ } else {
+ parserHeaderFile.printf("const std::optional<%s> %s_;\n",
+ type.getName(), variableName);
+ }
}
if (valueType != null) {
- headerFile.printf("%s value;\n", valueType.getName());
+ parserHeaderFile.printf("const std::optional<%s> _value;\n", valueType.getName());
}
- // print getters and setters
+ parserHeaderFile.printf("public:\n");
+ String constructorArgs = printConstructor(name, nameScope, complexType, elements,
+ attributes, baseName);
- headerFile.printf("public:\n");
+ // print getters and setters
for (int i = 0; i < elementTypes.size(); ++i) {
CppType type = elementTypes.get(i);
XsdElement element = elements.get(i);
XsdElement elementValue = resolveElement(element);
- printGetterAndSetter(nameScope + name, type,
+ printGetter(nameScope + name, type,
Utils.toVariableName(getElementName(elementValue)),
type instanceof CppComplexType ? true : element.isMultiple(),
- type instanceof CppComplexType ? false : ((CppSimpleType)type).isList());
+ type instanceof CppComplexType ? false : ((CppSimpleType)type).isList(),
+ false);
}
for (int i = 0; i < attributeTypes.size(); ++i) {
CppType type = attributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(attributes.get(i));
- printGetterAndSetter(nameScope + name, type,
- Utils.toVariableName(attribute.getName()), false, false);
+ printGetter(nameScope + name, type, Utils.toVariableName(attribute.getName()),
+ false, false, attribute.isRequired());
}
if (valueType != null) {
- printGetterAndSetter(nameScope + name, valueType, "value", false, false);
+ printGetter(nameScope + name, valueType, "value", false, false, false);
+ }
+
+ printParser(name, nameScope, complexType, constructorArgs);
+
+ if (writer) {
+ printWriter(name, nameScope, complexType);
}
- printParser(name, nameScope, complexType);
- headerFile.println("};\n");
+ parserHeaderFile.println("};\n");
}
- private void printParser(String name, String nameScope, XsdComplexType complexType)
+ private void printParser(String name, String nameScope, XsdComplexType complexType, String args)
throws CppCodeGeneratorException {
CppSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ?
getValueType((XsdSimpleContent) complexType, true) : null;
@@ -325,118 +452,321 @@ public class CppCodeGenerator {
}
String fullName = nameScope + name;
- headerFile.printf("static %s read(xmlNode *root);\n", fullName, Utils.lowerize(name));
- cppFile.printf("\n%s %s::read(xmlNode *root) {\n", fullName, fullName);
+ parserHeaderFile.printf("static %s read(xmlNode *root);\n", fullName, Utils.lowerize(name));
+ parserCppFile.printf("\n%s %s::read(xmlNode *root) {\n", fullName, fullName);
- cppFile.printf("%s instance;\n std::string raw;\n", fullName, fullName);
+ parserCppFile.print("std::string raw;\n");
for (int i = 0; i < allAttributes.size(); ++i) {
- CppType type = allAttributeTypes.get(i);
+ CppSimpleType type = allAttributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
- cppFile.printf("raw = getXmlAttribute(root, \"%s\");\n", attribute.getName());
- cppFile.printf("if (raw != \"\") {\n");
- cppFile.print(type.getParsingExpression());
- cppFile.printf("instance.set%s(value);\n}\n", Utils.capitalize(variableName));
+ parserCppFile.printf("raw = getXmlAttribute(root, \"%s\");\n", attribute.getName());
+ if (attribute.isRequired()) {
+ if (type.isEnum()) {
+ parserCppFile.printf("%s %s = %s::%s;\n",
+ type.getName(), variableName, type.getName(), UNKNOWN_ENUM);
+ } else {
+ parserCppFile.printf("%s %s{};\n", type.getName(), variableName);
+ }
+ } else {
+ parserCppFile.printf("std::optional<%s> %s = std::nullopt;\n", type.getName(),
+ variableName);
+ }
+ parserCppFile.printf("if (raw != \"\") {\n");
+ parserCppFile.print(type.getParsingExpression());
+ parserCppFile.printf("%s = value;\n}\n", variableName);
}
if (baseValueType != null) {
- cppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString("
+ parserCppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString("
+ "root->doc, root->xmlChildrenNode, 1));\n"
+ "if (xmlValue != nullptr) {\n"
+ "raw = reinterpret_cast<const char*>(xmlValue.get());\n");
- cppFile.print(baseValueType.getParsingExpression());
- cppFile.printf("instance.setValue(value);\n");
- cppFile.printf("}\n");
+ parserCppFile.print(baseValueType.getParsingExpression());
+ parserCppFile.printf("instance.setValue(value);\n");
+ parserCppFile.printf("}\n");
} else if (!allElements.isEmpty()) {
- cppFile.print("for (xmlNode *child = root->xmlChildrenNode; child != nullptr;"
+ for (int i = 0; i < allElements.size(); ++i) {
+ CppType type = allElementTypes.get(i);
+ XsdElement element = allElements.get(i);
+ XsdElement elementValue = resolveElement(element);
+ String variableName = Utils.toVariableName(getElementName(elementValue));
+ parserCppFile.printf("%s %s;\n", Utils.elementTypeName(type.getName(),
+ element.isMultiple() || type instanceof CppComplexType), variableName);
+ }
+ parserCppFile.print("for (xmlNode *child = root->xmlChildrenNode; child != nullptr;"
+ " child = child->next) {\n");
for (int i = 0; i < allElements.size(); ++i) {
CppType type = allElementTypes.get(i);
XsdElement element = allElements.get(i);
XsdElement elementValue = resolveElement(element);
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());
+
+ if (i != 0) parserCppFile.printf("} else ");
+ parserCppFile.print("if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>");
+ parserCppFile.printf("(\"%s\"))) {\n", elementValue.getName());
if (type instanceof CppSimpleType) {
- cppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString(");
- cppFile.printf("child->doc, child->xmlChildrenNode, 1));\n");
- cppFile.printf("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n");
- cppFile.printf("raw = reinterpret_cast<const char*>(xmlValue.get());\n}\n");
+ parserCppFile.print("auto xmlValue = make_xmlUnique(xmlNodeListGetString(");
+ parserCppFile.print("child->doc, child->xmlChildrenNode, 1));\n");
+ parserCppFile.print("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n");
+ parserCppFile.print("raw = reinterpret_cast<const char*>(xmlValue.get());\n}");
+ parserCppFile.print("\n");
}
- cppFile.print(type.getParsingExpression());
+ parserCppFile.print(type.getParsingExpression());
if (element.isMultiple() || type instanceof CppComplexType) {
- cppFile.printf("instance.get%s().push_back(std::move(value));\n",
- Utils.capitalize(variableName));
+ parserCppFile.printf("%s.push_back(std::move(value));\n", variableName);
} else {
- cppFile.printf("instance.set%s(value);\n", Utils.capitalize(variableName));
+ parserCppFile.printf("%s = std::move(value);\n", variableName);
}
}
- cppFile.printf("}\n}\n");
+ parserCppFile.printf("}\n}\n");
}
- cppFile.printf("return instance;\n"
- + "}\n");
+ parserCppFile.printf("%s instance%s;\n",
+ fullName, args.length() > 0 ? "(" + args + ")" : "");
+ parserCppFile.print("return instance;\n}\n");
}
- private void printGetterAndSetter(String name, CppType type, String variableName,
- boolean isMultiple, boolean isMultipleType) {
- String typeName = isMultiple ? String.format("std::vector<%s>", type.getName())
- : type.getName();
+ private void printWriter(String name, String nameScope, XsdComplexType complexType)
+ throws CppCodeGeneratorException {
+ CppSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ?
+ getValueType((XsdSimpleContent) complexType, true) : null;
+ List<XsdElement> allElements = new ArrayList<>();
+ List<XsdAttribute> allAttributes = new ArrayList<>();
+ stackComponents(complexType, allElements, allAttributes);
- headerFile.printf("%s& get%s();\n", typeName, Utils.capitalize(variableName));
+ // parse types for elements and attributes
+ List<CppType> allElementTypes = new ArrayList<>();
+ for (XsdElement element : allElements) {
+ XsdElement elementValue = resolveElement(element);
+ CppType cppType = parseType(elementValue.getType(), elementValue.getName());
+ allElementTypes.add(cppType);
+ }
+ List<CppSimpleType> allAttributeTypes = new ArrayList<>();
+ for (XsdAttribute attribute : allAttributes) {
+ XsdType type = resolveAttribute(attribute).getType();
+ allAttributeTypes.add(parseSimpleType(type, false));
+ }
+
+ String fullName = nameScope + name;
+ parserHeaderFile.printf("void write(std::ostream& out, const std::string& name) const;\n");
+ parserCppFile.printf(
+ "\nvoid %s::write(std::ostream& out, const std::string& name) const {\n",
+ fullName);
+
+ parserCppFile.printf("out << printIndent() << \"<\" << name;\n");
+ for (int i = 0; i < allAttributes.size(); ++i) {
+ CppType type = allAttributeTypes.get(i);
+ XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
+ String variableName = Utils.toVariableName(attribute.getName());
+ parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
+ parserCppFile.printf("out << \" %s=\\\"\";\n", attribute.getName());
+ parserCppFile.print(type.getWritingExpression(String.format("%s%s()",
+ getterName(type.getName()), Utils.capitalize(variableName)),
+ attribute.getName()));
+ parserCppFile.printf("out << \"\\\"\";\n}\n");
+ }
+ parserCppFile.print("out << \">\" << std::endl;\n");
+ parserCppFile.print("++indentIndex;\n");
+
+ if (!allElements.isEmpty()) {
+ for (int i = 0; i < allElements.size(); ++i) {
+ CppType type = allElementTypes.get(i);
+ XsdElement element = allElements.get(i);
+ XsdElement elementValue = resolveElement(element);
+ String elementName = getElementName(elementValue);
+ String variableName = Utils.toVariableName(elementName);
+
+ if (type instanceof CppComplexType || element.isMultiple()) {
+ parserCppFile.printf("for (auto& value : get%s()) {\n",
+ Utils.capitalize(variableName));
+ if (type instanceof CppSimpleType) {
+ parserCppFile.printf("out << printIndent() << \"<%s>\";\n",
+ elementValue.getName());
+ }
+ parserCppFile.printf(
+ type.getWritingExpression("value", elementValue.getName()));
+ if (type instanceof CppSimpleType) {
+ parserCppFile.printf("out << \"</%s>\" << std::endl;\n",
+ elementValue.getName());
+ }
+ parserCppFile.printf("}\n");
+ } else {
+ parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
+ if (type instanceof CppSimpleType) {
+ parserCppFile.printf("out << printIndent() << \"<%s>\";\n",
+ elementValue.getName());
+ }
+ parserCppFile.print(type.getWritingExpression(String.format("%s%s()",
+ getterName(type.getName()), Utils.capitalize(variableName)),
+ elementValue.getName()));
+ if (type instanceof CppSimpleType) {
+ parserCppFile.printf("out << \"</%s>\" << std::endl;\n",
+ elementValue.getName());
+ }
+ parserCppFile.print("}\n");
+ }
+ }
+ }
+ parserCppFile.print("--indentIndex;\n");
+ parserCppFile.printf("out << printIndent() << \"</\" << name << \">\" << std::endl;\n");
+ parserCppFile.printf("}\n");
+ }
- cppFile.println();
- cppFile.printf("%s& %s::get%s() {\n"
- + "return %s;\n}\n",
- typeName, name, Utils.capitalize(variableName), variableName);
+ private void printGetter(String name, CppType type, String variableName,
+ boolean isMultiple, boolean isMultipleType, boolean isRequired) {
+ String typeName = isMultiple ? String.format("std::vector<%s>",
+ type.getName()) : type.getName();
+
+ parserHeaderFile.printf("const %s& %s%s() const;\n", typeName, getterName(typeName),
+ Utils.capitalize(variableName));
+
+ parserCppFile.println();
+ parserCppFile.printf("const %s& %s::%s%s() const {\n"
+ + "return %s;\n}\n\n",
+ typeName, name, getterName(typeName), Utils.capitalize(variableName),
+ isMultiple || isRequired ?
+ variableName + "_" : String.format("%s_.value()", variableName));
+
+ parserHeaderFile.printf("bool has%s() const;\n", Utils.capitalize(variableName));
+ parserCppFile.printf("bool %s::has%s() const {\n", name, Utils.capitalize(variableName));
+ if (isMultiple) {
+ parserCppFile.printf("return !(%s_.empty());\n}\n", variableName);
+ } else if (isRequired){
+ parserCppFile.print("return true;\n}\n");
+ } else {
+ parserCppFile.printf("return %s_.has_value();\n}\n", variableName);
+ }
if (isMultiple || isMultipleType) {
String elementTypeName = type instanceof CppComplexType ? type.getName() :
((CppSimpleType)type).getTypeName();
if (elementTypeName.equals("bool")) {
- headerFile.printf("%s getFirst%s();\n",
+ parserHeaderFile.printf("%s getFirst%s() const;\n",
elementTypeName, Utils.capitalize(variableName));
- cppFile.println();
- cppFile.printf("%s %s::getFirst%s() {\n"
- + "if (%s.empty()) {\n"
+ parserCppFile.println();
+ parserCppFile.printf("%s %s::getFirst%s() const {\n"
+ + "if (%s_%sempty()) {\n"
+ "return false;\n"
+ "}\n"
- + "return %s[0];\n"
+ + "return %s;\n"
+ "}\n",
elementTypeName, name, Utils.capitalize(variableName), variableName,
- variableName);
+ isMultiple ? "." : "->",
+ isMultiple ? String.format("%s_[0]", variableName) :
+ String.format("%s_.value()[0]", variableName));
} else {
- headerFile.printf("%s* getFirst%s();\n",
+ parserHeaderFile.printf("const %s* getFirst%s() const;\n",
elementTypeName, Utils.capitalize(variableName));
- cppFile.println();
- cppFile.printf("%s* %s::getFirst%s() {\n"
- + "if (%s.empty()) {\n"
+ parserCppFile.println();
+ parserCppFile.printf("const %s* %s::getFirst%s() const {\n"
+ + "if (%s_%sempty()) {\n"
+ "return nullptr;\n"
+ "}\n"
- + "return &%s[0];\n"
+ + "return &%s;\n"
+ "}\n",
elementTypeName, name, Utils.capitalize(variableName), variableName,
- variableName);
+ isMultiple ? "." : "->",
+ isMultiple ? String.format("%s_[0]", variableName) :
+ String.format("%s_.value()[0]", variableName));
+ }
+ }
+ }
+
+ private String printConstructor(String name, String nameScope, XsdComplexType complexType,
+ List<XsdElement> elements, List<XsdAttribute> attributes, String baseName)
+ throws CppCodeGeneratorException {
+ String fullName = nameScope + name;
+ StringBuilder constructorArgs = new StringBuilder();
+ StringBuilder parentArgs = new StringBuilder();
+ StringBuilder constructor = new StringBuilder();
+ StringBuilder args = new StringBuilder();
+
+ List<XsdElement> allElements = new ArrayList<>();
+ List<XsdAttribute> allAttributes = new ArrayList<>();
+ stackComponents(complexType, allElements, allAttributes);
+
+ List<CppType> allElementTypes = new ArrayList<>();
+ for (XsdElement element : allElements) {
+ XsdElement elementValue = resolveElement(element);
+ CppType type = parseType(elementValue.getType(), elementValue.getName());
+ String variableName = Utils.toVariableName(getElementName(elementValue));
+ constructorArgs.append(String.format(", %s %s", Utils.elementTypeName(type.getName(),
+ element.isMultiple() || type instanceof CppComplexType), variableName));
+ args.append(String.format(", %s", variableName));
+ boolean isMultipleType;
+ if (type instanceof CppComplexType) {
+ isMultipleType = true;
+ } else if (((CppSimpleType)type).isList()) {
+ isMultipleType = true;
+ } else {
+ isMultipleType = false;
+ }
+
+ if (elements.contains(element)) {
+ constructor.append(String.format(", %s_(%s)", variableName,
+ Utils.toAssignmentName(type.getName(), variableName, isMultipleType)));
+ } else {
+ parentArgs.append(String.format(", %s", variableName));
+ }
+ }
+ List<CppSimpleType> allAttributeTypes = new ArrayList<>();
+ for (XsdAttribute attribute : allAttributes) {
+ CppType type = parseSimpleType(resolveAttribute(attribute).getType(), false);
+ String variableName = Utils.toVariableName(resolveAttribute(attribute).getName());
+ if (attribute.isRequired()) {
+ constructorArgs.append(String.format(", %s %s", type.getName(), variableName));
+ } else {
+ constructorArgs.append(String.format(", std::optional<%s> %s", type.getName(),
+ variableName));
+ }
+ args.append(String.format(", %s", variableName));
+ boolean isMultipleType = ((CppSimpleType)type).isList() ? true : false;
+ if (attributes.contains(attribute)) {
+ constructor.append(String.format(", %s_(%s)", variableName,
+ Utils.toAssignmentName(type.getName(), variableName, isMultipleType)));
+ } else {
+ parentArgs.append(String.format(", %s", variableName));
}
}
- if (isMultiple) return;
- headerFile.printf("void set%s(%s);\n", Utils.capitalize(variableName), typeName);
- cppFile.println();
- cppFile.printf("void %s::set%s(%s %s) {\n"
- + "this->%s = std::move(%s);\n"
- + "}\n",
- name, Utils.capitalize(variableName), typeName, variableName,
- variableName, variableName);
+ String constructorArgsString = constructorArgs.toString();
+ String constructorString = constructor.toString();
+ if (constructorArgsString.length() > 0) {
+ constructorArgsString = constructorArgsString.substring(2);
+ }
+
+ boolean useExplicit =
+ !(constructorArgsString.isEmpty() || constructorArgsString.contains(","));
+ if (useExplicit) {
+ parserHeaderFile.printf("explicit %s(%s);\n", name, constructorArgsString);
+ } else {
+ parserHeaderFile.printf("%s(%s);\n", name, constructorArgsString);
+ }
+ parserCppFile.printf("\n%s::%s(%s) : ", fullName, name, constructorArgsString);
+
+ String parentArgsString = parentArgs.toString();
+ if (parentArgsString.length() > 0) {
+ parentArgsString = parentArgsString.substring(2);
+ parserCppFile.printf("%s(%s)", baseName, parentArgsString);
+ } else {
+ constructorString = constructorString.substring(2);
+ }
+ parserCppFile.printf("%s {\n}\n", constructorString);
+
+ String argsString = args.toString();
+ if (argsString.length() > 0) {
+ argsString = argsString.substring(2);
+ }
+ return argsString;
}
private void printXmlParser() throws CppCodeGeneratorException {
- cppFile.printf("template <class T>\n"
+ parserCppFile.printf("template <class T>\n"
+ "constexpr void (*xmlDeleter)(T* t);\n"
+ "template <>\nconstexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;\n"
+ "template <>\nauto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };\n\n"
@@ -447,7 +777,7 @@ public class CppCodeGenerator {
+ "}\n\n");
if (hasAttr) {
- cppFile.printf("static std::string getXmlAttribute"
+ parserCppFile.printf("static std::string getXmlAttribute"
+ "(const xmlNode *cur, const char *attribute) {\n"
+ "auto xmlValue = make_xmlUnique(xmlGetProp(cur, "
+ "reinterpret_cast<const xmlChar*>(attribute)));\n"
@@ -469,16 +799,19 @@ public class CppCodeGenerator {
String typeName = cppType instanceof CppSimpleType ? cppType.getName() :
Utils.toClassName(cppType.getName());
- headerFile.printf("std::optional<%s> read%s(const char* configFile);\n\n",
+ parserHeaderFile.printf("std::optional<%s> read%s(const char* configFile);\n\n",
typeName, isMultiRootElement ? Utils.capitalize(typeName) : "");
- cppFile.printf("std::optional<%s> read%s(const char* configFile) {\n",
+ parserCppFile.printf("std::optional<%s> read%s(const char* configFile) {\n",
typeName, isMultiRootElement ? Utils.capitalize(typeName) : "");
- cppFile.printf("auto doc = make_xmlUnique(xmlParseFile(configFile));\n"
+ parserCppFile.printf("auto doc = make_xmlUnique(xmlParseFile(configFile));\n"
+ "if (doc == nullptr) {\n"
+ "return std::nullopt;\n"
+ "}\n"
+ "xmlNodePtr child = xmlDocGetRootElement(doc.get());\n"
- + "if (child == NULL) {\n"
+ + "if (child == nullptr) {\n"
+ + "return std::nullopt;\n"
+ + "}\n"
+ + "if (xmlXIncludeProcess(doc.get()) < 0) {\n"
+ "return std::nullopt;\n"
+ "}\n\n"
+ "if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>"
@@ -486,15 +819,41 @@ public class CppCodeGenerator {
elementName);
if (cppType instanceof CppSimpleType) {
- cppFile.printf("%s value = getXmlAttribute(child, \"%s\");\n",
+ parserCppFile.printf("%s value = getXmlAttribute(child, \"%s\");\n",
elementName, elementName);
} else {
- cppFile.printf(cppType.getParsingExpression());
+ parserCppFile.printf(cppType.getParsingExpression());
}
- cppFile.printf("return value;\n}\n");
- cppFile.printf("return std::nullopt;\n");
- cppFile.printf("}\n\n");
+ parserCppFile.printf("return value;\n}\n");
+ parserCppFile.printf("return std::nullopt;\n");
+ parserCppFile.printf("}\n\n");
+ }
+ }
+
+ private void printXmlWriter() throws CppCodeGeneratorException {
+ for (XsdElement element : xmlSchema.getElementMap().values()) {
+ CppType cppType = parseType(element.getType(), element.getName());
+ String elementName = element.getName();
+ String VariableName = Utils.toVariableName(elementName);
+ String typeName = cppType instanceof CppSimpleType ? cppType.getName() :
+ Utils.toClassName(cppType.getName());
+ parserHeaderFile.printf("void write(std::ostream& out, %s& %s);\n\n",
+ typeName, VariableName);
+ parserCppFile.printf("void write(std::ostream& out, %s& %s) {\n",
+ typeName, VariableName);
+
+ parserCppFile.print(
+ "out << \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\";\n");
+ parserCppFile.printf("%s.write(out, \"%s\");\n", VariableName, elementName);
+ parserCppFile.printf("}\n\n");
}
+
+ parserCppFile.print("static int indentIndex = 0;\n"
+ + "std::string printIndent() {\n"
+ + "std::string s = \"\";\n"
+ + "for (int index = 0; index < indentIndex; ++index) {\n"
+ + "s += \" \";\n"
+ + "}\nreturn s;\n}\n\n");
}
private String getElementName(XsdElement element) {
@@ -506,6 +865,13 @@ public class CppCodeGenerator {
return element.getName();
}
+ private String getterName(String type) {
+ if (type.equals("bool") && booleanGetter) {
+ return "is";
+ }
+ return "get";
+ }
+
private void stackComponents(XsdComplexType complexType, List<XsdElement> elements,
List<XsdAttribute> attributes) throws CppCodeGeneratorException {
if (complexType.getBase() != null) {
@@ -641,7 +1007,7 @@ public class CppCodeGenerator {
XsdRestriction restriction = (XsdRestriction) simpleType;
if (restriction.getEnums() != null) {
String name = Utils.toClassName(restriction.getName());
- return new CppSimpleType(name, "stringTo" + name + "(%s)", false);
+ return new CppSimpleType(name, "stringTo" + name + "(%s)", false, true);
}
return parseSimpleType(restriction.getBase(), traverse);
} else if (simpleType instanceof XsdUnion) {
@@ -764,11 +1130,11 @@ public class CppCodeGenerator {
case "nonNegativeInteger":
case "positiveInteger":
case "nonPositiveInteger":
- return new CppSimpleType("long long", "std::stoll(%s)", false);
+ return new CppSimpleType("int64_t", "std::stoll(%s)", false);
case "unsignedLong":
- return new CppSimpleType("unsigned long long", "std::stoull(%s)", false);
+ return new CppSimpleType("uint64_t", "std::stoull(%s)", false);
case "long":
- return new CppSimpleType("long long", "std::stoll(%s)", false);
+ return new CppSimpleType("int64_t", "std::stoll(%s)", false);
case "unsignedInt":
return new CppSimpleType("unsigned int",
"static_cast<unsigned int>(stoul(%s))", false);
diff --git a/src/com/android/xsdc/cpp/CppComplexType.java b/src/com/android/xsdc/cpp/CppComplexType.java
index 2c9d397..64d735d 100644
--- a/src/com/android/xsdc/cpp/CppComplexType.java
+++ b/src/com/android/xsdc/cpp/CppComplexType.java
@@ -32,4 +32,9 @@ class CppComplexType implements CppType {
public String getParsingExpression() {
return String.format("%s value = %s::read(child);\n", name, name);
}
+
+ @Override
+ public String getWritingExpression(String getValue, String name) {
+ return String.format("%s.write(out, \"%s\");\n", getValue, name);
+ }
}
diff --git a/src/com/android/xsdc/cpp/CppSimpleType.java b/src/com/android/xsdc/cpp/CppSimpleType.java
index f59aec5..282855f 100644
--- a/src/com/android/xsdc/cpp/CppSimpleType.java
+++ b/src/com/android/xsdc/cpp/CppSimpleType.java
@@ -21,18 +21,28 @@ class CppSimpleType implements CppType {
final private String fullName;
final private String rawParsingExpression;
final private boolean list;
+ final private boolean isEnum;
- CppSimpleType(String name, String rawParsingExpression, boolean list) {
+ CppSimpleType(String name, String rawParsingExpression, boolean list, boolean isEnum) {
this.rawParsingExpression = rawParsingExpression;
this.list = list;
this.name = name;
this.fullName = list ? String.format("std::vector<%s>", name) : name;
+ this.isEnum = isEnum;
+ }
+
+ CppSimpleType(String name, String rawParsingExpression, boolean list) {
+ this(name, rawParsingExpression, list, false);
}
boolean isList() {
return list;
}
+ boolean isEnum() {
+ return isEnum;
+ }
+
CppSimpleType newListType() throws CppCodeGeneratorException {
if (list) throw new CppCodeGeneratorException("list of list is not supported");
return new CppSimpleType(name, rawParsingExpression, true);
@@ -53,15 +63,56 @@ class CppSimpleType implements CppType {
if (list) {
expression.append(
String.format("%s value;\n", getName()));
- expression.append("for (auto& token : android::base::Split(raw, \" \")) {\n");
- expression.append(String.format("value.push_back(std::move(%s));\n",
- String.format(rawParsingExpression, "token")));
+ expression.append(String.format("{\nint base = 0;\n"
+ + "int found;\n"
+ + "while(true) {\n"
+ + "found = raw.find_first_of(\" \", base);\n"
+ + "value.push_back(%s);\n"
+ + "if (found == raw.npos) break;\n"
+ + "base = found + 1;\n"
+ + "}\n",
+ String.format(rawParsingExpression, "raw.substr(base, found - base)")));
expression.append("}\n");
} else {
expression.append(
- String.format("%s value = %s;\n", getName(),
+ String.format("%s %svalue = %s;\n", getName(),
+ this.name.equals("std::string") ? "&" : "",
String.format(rawParsingExpression, "raw")));
}
return expression.toString();
}
+
+ @Override
+ public String getWritingExpression(String getValue, String name) {
+ StringBuilder expression = new StringBuilder();
+ if (list) {
+ expression.append("{\nint count = 0;\n");
+ expression.append(String.format("for (const auto& v : %s) {\n", getValue));
+ String value;
+ if (isEnum) {
+ value = String.format("%sToString(v)", this.name);
+ } else if (this.name.equals("char") || this.name.equals("unsigned char")) {
+ value = "(int)v";
+ } else if (this.name.equals("bool")) {
+ value = "(v ? \"true\" : \"false\")";
+ } else {
+ value = "v";
+ }
+ expression.append("if (count != 0) {\n"
+ + "out << \" \";\n}\n"
+ + "++count;\n");
+ expression.append(String.format("out << %s;\n}\n}\n", value));
+ } else {
+ if (isEnum) {
+ expression.append(String.format("out << toString(%s);\n", getValue));
+ } else if (this.name.equals("char") || this.name.equals("unsigned char")) {
+ expression.append(String.format("out << (int)%s;\n", getValue));
+ } else if (this.name.equals("bool")) {
+ expression.append(String.format("out << (%s ? \"true\" : \"false\");\n", getValue));
+ } else {
+ expression.append(String.format("out << %s;\n", getValue));
+ }
+ }
+ return expression.toString();
+ }
}
diff --git a/src/com/android/xsdc/cpp/CppType.java b/src/com/android/xsdc/cpp/CppType.java
index 097d663..05d4da9 100644
--- a/src/com/android/xsdc/cpp/CppType.java
+++ b/src/com/android/xsdc/cpp/CppType.java
@@ -20,4 +20,6 @@ interface CppType {
String getName();
String getParsingExpression();
+
+ public String getWritingExpression(String getValue, String name);
}
diff --git a/src/com/android/xsdc/cpp/Utils.java b/src/com/android/xsdc/cpp/Utils.java
index c612fc6..d54a9aa 100644
--- a/src/com/android/xsdc/cpp/Utils.java
+++ b/src/com/android/xsdc/cpp/Utils.java
@@ -75,6 +75,9 @@ class Utils {
}
static String toEnumName(String name) throws CppCodeGeneratorException {
+ if ("".equals(name)) {
+ name = "EMPTY";
+ }
String trimmed = name.replace(".", "_").replaceAll("[^A-Za-z0-9_]", "");
if (trimmed.isEmpty()) {
throw new CppCodeGeneratorException(
@@ -83,4 +86,21 @@ class Utils {
String enumName = Character.isDigit(trimmed.charAt(0)) ? "_" + trimmed : trimmed;
return (keywordSet.contains(enumName)) ? "_" + enumName : enumName;
}
+
+ static String toAssignmentName(String typeName, String variableName, boolean isMultipleType) {
+ if (isMultipleType || typeName.equals("std::string")) {
+ return String.format("std::move(%s)", variableName);
+ }
+ return variableName;
+ }
+
+ static String elementTypeName(String name, boolean isMultipleType) {
+ String res;
+ if (isMultipleType) {
+ res = "std::vector<" + name + ">";
+ } else {
+ res = "std::optional<" + name + ">";
+ }
+ return res;
+ }
}
diff --git a/src/com/android/xsdc/java/JavaCodeGenerator.java b/src/com/android/xsdc/java/JavaCodeGenerator.java
index 23ce51d..0025896 100644
--- a/src/com/android/xsdc/java/JavaCodeGenerator.java
+++ b/src/com/android/xsdc/java/JavaCodeGenerator.java
@@ -36,11 +36,22 @@ public class JavaCodeGenerator {
private XmlSchema xmlSchema;
private String packageName;
private Map<String, JavaSimpleType> javaSimpleTypeMap;
-
- public JavaCodeGenerator(XmlSchema xmlSchema, String packageName)
+ private boolean writer;
+ private boolean showNullability;
+ private boolean generateHasMethod;
+ private boolean useHexBinary;
+ private boolean booleanGetter;
+
+ public JavaCodeGenerator(XmlSchema xmlSchema, String packageName, boolean writer,
+ boolean showNullability, boolean generateHasMethod, boolean booleanGetter)
throws JavaCodeGeneratorException {
this.xmlSchema = xmlSchema;
this.packageName = packageName;
+ this.writer = writer;
+ this.showNullability = showNullability;
+ this.generateHasMethod = generateHasMethod;
+ this.booleanGetter = booleanGetter;
+ useHexBinary = false;
// class naming validation
{
@@ -113,6 +124,16 @@ public class JavaCodeGenerator {
try (CodeWriter out = new CodeWriter(fs.getPrintWriter("XmlParser.java"))) {
printXmlParser(out);
}
+ if (writer) {
+ try (CodeWriter out = new CodeWriter(fs.getPrintWriter("XmlWriter.java"))) {
+ printXmlWriter(out);
+ }
+ }
+ if (useHexBinary) {
+ try (CodeWriter out = new CodeWriter(fs.getPrintWriter("HexBinaryHelper.java"))) {
+ printHexBinaryHelper(out);
+ }
+ }
}
private void printEnumClass(CodeWriter out, String name, XsdRestriction restrictionType)
@@ -128,19 +149,33 @@ public class JavaCodeGenerator {
out.printf("@java.lang.Deprecated\n");
}
String value = tag.getValue();
- if ("".equals(value)) {
- value = "EMPTY";
- }
- out.printf("\n%s(\"%s\"),", Utils.toEnumName(value), tag.getValue());
+ out.printf("\n%s(\"%s\"),", Utils.toEnumName(value), value);
}
out.printf(";\n\n");
out.printf("private final String rawName;\n\n");
- out.printf("%s(String rawName) {\n"
+ out.printf("%s(%sString rawName) {\n"
+ "this.rawName = rawName;\n"
- + "}\n\n", name);
- out.printf("public String getRawName() {\n"
+ + "}\n\n", name, getDefaultNullability(Nullability.NON_NULL));
+ out.printf("public %sString getRawName() {\n"
+ "return rawName;\n"
- + "}\n");
+ + "}\n\n", getDefaultNullability(Nullability.NON_NULL));
+
+ out.printf("static %s%s fromString(%sString rawString) {\n"
+ + "for (%s _f : values()) {\n"
+ + "if (_f.getRawName().equals(rawString)) {\n"
+ + "return _f;\n"
+ + "}\n"
+ + "}\n"
+ + "throw new IllegalArgumentException(rawString);\n"
+ + "}\n\n", getDefaultNullability(Nullability.NULLABLE), name,
+ getDefaultNullability(Nullability.NON_NULL), name);
+
+ if (writer) {
+ out.printf("@Override\n"
+ + "public %sString toString() {\n"
+ + "return rawName;\n"
+ + "}\n", getDefaultNullability(Nullability.NON_NULL));
+ }
out.println("}");
}
@@ -209,7 +244,7 @@ public class JavaCodeGenerator {
XsdElement element = elements.get(i);
XsdElement elementValue = resolveElement(element);
String typeName = element.isMultiple() ? String.format("java.util.List<%s>",
- type.getNullableName()) : type.getName();
+ type.getNullableName()) : type.getNullableName();
out.printf("%sprivate %s %s;\n", getNullabilityString(element.getNullability()),
typeName, Utils.toVariableName(getElementName(elementValue)));
}
@@ -217,7 +252,7 @@ public class JavaCodeGenerator {
JavaType type = attributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(attributes.get(i));
out.printf("%sprivate %s %s;\n", getNullabilityString(attribute.getNullability()),
- type.getName(), Utils.toVariableName(attribute.getName()));
+ type.getNullableName(), Utils.toVariableName(attribute.getName()));
}
if (valueType != null) {
out.printf("private %s value;\n", valueType.getName());
@@ -243,6 +278,9 @@ public class JavaCodeGenerator {
out.println();
printParser(out, nameScope + name, complexType);
+ if (writer) {
+ printWriter(out, name, complexType);
+ }
out.println("}");
}
@@ -268,9 +306,11 @@ public class JavaCodeGenerator {
allAttributeTypes.add(parseSimpleType(type, false));
}
- out.printf("static %s read(org.xmlpull.v1.XmlPullParser parser) " +
+ out.printf("static %s%s read(%sorg.xmlpull.v1.XmlPullParser parser) " +
"throws org.xmlpull.v1.XmlPullParserException, java.io.IOException, " +
- "javax.xml.datatype.DatatypeConfigurationException {\n", name);
+ "javax.xml.datatype.DatatypeConfigurationException {\n",
+ getDefaultNullability(Nullability.NON_NULL), name,
+ getDefaultNullability(Nullability.NON_NULL));
out.printf("%s instance = new %s();\n"
+ "String raw = null;\n", name, name);
@@ -332,6 +372,87 @@ public class JavaCodeGenerator {
+ "}\n");
}
+ private void printWriter(CodeWriter out, String name, XsdComplexType complexType)
+ throws JavaCodeGeneratorException {
+ JavaSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ?
+ getValueType((XsdSimpleContent) complexType, true) : null;
+ List<XsdElement> allElements = new ArrayList<>();
+ List<XsdAttribute> allAttributes = new ArrayList<>();
+ stackComponents(complexType, allElements, allAttributes);
+
+ // parse types for elements and attributes
+ List<JavaType> allElementTypes = new ArrayList<>();
+ for (XsdElement element : allElements) {
+ XsdElement elementValue = resolveElement(element);
+ JavaType javaType = parseType(elementValue.getType(), elementValue.getName());
+ allElementTypes.add(javaType);
+ }
+ List<JavaSimpleType> allAttributeTypes = new ArrayList<>();
+ for (XsdAttribute attribute : allAttributes) {
+ XsdType type = resolveAttribute(attribute).getType();
+ allAttributeTypes.add(parseSimpleType(type, false));
+ }
+
+ out.printf("\nvoid write(%sXmlWriter out, %sString name) " +
+ "throws java.io.IOException {\n", getDefaultNullability(Nullability.NON_NULL),
+ getDefaultNullability(Nullability.NON_NULL));
+
+ out.print("out.print(\"<\" + name);\n");
+ for (int i = 0; i < allAttributes.size(); ++i) {
+ JavaType type = allAttributeTypes.get(i);
+ boolean isList = allAttributeTypes.get(i).isList();
+ XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
+ String variableName = Utils.toVariableName(attribute.getName());
+ out.printf("if (has%s()) {\n", Utils.capitalize(variableName));
+ out.printf("out.print(\" %s=\\\"\");\n", attribute.getName());
+ out.print(type.getWritingExpression(String.format("%s%s()",
+ getterName(type.getName()), Utils.capitalize(variableName)),
+ attribute.getName()));
+ out.printf("out.print(\"\\\"\");\n}\n");
+ }
+ out.printf("out.print(\">\\n\");\n");
+
+ if (!allElements.isEmpty()) {
+ out.printf("out.increaseIndent();\n");
+ for (int i = 0; i < allElements.size(); ++i) {
+ JavaType type = allElementTypes.get(i);
+ XsdElement element = allElements.get(i);
+ XsdElement elementValue = resolveElement(element);
+ String elementName = getElementName(elementValue);
+ String variableName = Utils.toVariableName(elementName);
+
+ if (element.isMultiple()) {
+ out.printf("for (%s value : get%s()) {\n", type.getName(),
+ Utils.capitalize(variableName));
+ if (type instanceof JavaSimpleType) {
+ out.printf("out.print(\"<%s>\");\n", elementValue.getName());
+ }
+ out.print(type.getWritingExpression("value", elementValue.getName()));
+ if (type instanceof JavaSimpleType) {
+ out.printf("out.print(\"</%s>\\n\");\n", elementValue.getName());
+ }
+ out.print("}\n");
+ } else {
+ out.printf("if (has%s()) {\n", Utils.capitalize(variableName));
+ if (type instanceof JavaSimpleType) {
+ out.printf("out.print(\"<%s>\");\n", elementValue.getName());
+ }
+ out.print(type.getWritingExpression(String.format("%s%s()",
+ getterName(type.getName()), Utils.capitalize(variableName)),
+ elementValue.getName()));
+ if (type instanceof JavaSimpleType) {
+ out.printf("out.print(\"</%s>\\n\");\n", elementValue.getName());
+ }
+ out.printf("}\n");
+ }
+
+ }
+ out.printf("out.decreaseIndent();\n");
+ }
+ out.print("out.print(\"</\" + name + \">\\n\");\n");
+ out.print("}\n");
+ }
+
private void printGetterAndSetter(CodeWriter out, JavaType type, String variableName,
boolean isMultiple, XsdTag tag) {
String typeName = isMultiple ? String.format("java.util.List<%s>", type.getNullableName())
@@ -343,18 +464,33 @@ public class JavaCodeGenerator {
if (deprecated) {
out.printf("@java.lang.Deprecated\n");
}
- out.printf("public%s %s%s get%s() {\n", getFinalString(finalValue),
- getNullabilityString(nullability), typeName, Utils.capitalize(variableName));
- if (isMultiple) {
+ out.printf("public%s %s%s %s%s() {\n", getFinalString(finalValue),
+ getNullabilityString(nullability), typeName, getterName(typeName),
+ Utils.capitalize(variableName));
+ if ((type instanceof JavaSimpleType && ((JavaSimpleType)type).isList()) || isMultiple) {
out.printf("if (%s == null) {\n"
+ "%s = new java.util.ArrayList<>();\n"
+ "}\n", variableName, variableName);
+ } else if (type.isPrimitiveType()) {
+ out.printf("if (%s == null) {\n", variableName);
+ if (typeName.equals("boolean")) {
+ out.printf("return false;\n}\n", variableName);
+ } else {
+ out.printf("return (%s)0;\n}\n", typeName);
+ }
}
out.printf("return %s;\n"
+ "}\n", variableName);
if (isMultiple) return;
out.println();
+ out.printf("%sboolean has%s() {\n"
+ + "if (%s == null) {\n"
+ + "return false;\n"
+ + "}\n"
+ + "return true;\n}\n\n",
+ generateHasMethod ? "public " : "",
+ Utils.capitalize(variableName), variableName);
if (deprecated) {
out.printf("@java.lang.Deprecated\n");
}
@@ -374,7 +510,7 @@ public class JavaCodeGenerator {
boolean isMultiRootElement = xmlSchema.getElementMap().values().size() > 1;
for (XsdElement element : xmlSchema.getElementMap().values()) {
JavaType javaType = parseType(element.getType(), element.getName());
- out.printf("public static %s read%s(java.io.InputStream in)"
+ out.printf("public static %s%s read%s(%sjava.io.InputStream in)"
+ " throws org.xmlpull.v1.XmlPullParserException, java.io.IOException, "
+ "javax.xml.datatype.DatatypeConfigurationException {\n"
+ "org.xmlpull.v1.XmlPullParser parser = org.xmlpull.v1.XmlPullParserFactory"
@@ -384,8 +520,9 @@ public class JavaCodeGenerator {
+ "parser.setInput(in, null);\n"
+ "parser.nextTag();\n"
+ "String tagName = parser.getName();\n"
- + "String raw = null;\n", javaType.getName(),
- isMultiRootElement ? Utils.capitalize(javaType.getName()) : "");
+ + "String raw = null;\n", getDefaultNullability(Nullability.NULLABLE),
+ javaType.getName(), isMultiRootElement ? Utils.capitalize(javaType.getName()) : "",
+ getDefaultNullability(Nullability.NON_NULL));
out.printf("if (tagName.equals(\"%s\")) {\n", element.getName());
if (javaType instanceof JavaSimpleType) {
out.print("raw = XmlParser.readText(parser);\n");
@@ -398,8 +535,8 @@ public class JavaCodeGenerator {
out.println();
}
- out.print(
- "public static java.lang.String readText(org.xmlpull.v1.XmlPullParser parser)"
+ out.printf(
+ "public static %sjava.lang.String readText(%sorg.xmlpull.v1.XmlPullParser parser)"
+ " throws org.xmlpull.v1.XmlPullParserException, java.io.IOException {\n"
+ "String result = \"\";\n"
+ "if (parser.next() == org.xmlpull.v1.XmlPullParser.TEXT) {\n"
@@ -407,11 +544,12 @@ public class JavaCodeGenerator {
+ " parser.nextTag();\n"
+ "}\n"
+ "return result;\n"
- + "}\n");
+ + "}\n", getDefaultNullability(Nullability.NULLABLE),
+ getDefaultNullability(Nullability.NON_NULL));
out.println();
- out.print(
- "public static void skip(org.xmlpull.v1.XmlPullParser parser)"
+ out.printf(
+ "public static void skip(%sorg.xmlpull.v1.XmlPullParser parser)"
+ " throws org.xmlpull.v1.XmlPullParserException, java.io.IOException {\n"
+ "if (parser.getEventType() != org.xmlpull.v1.XmlPullParser.START_TAG) {\n"
+ " throw new IllegalStateException();\n"
@@ -427,11 +565,106 @@ public class JavaCodeGenerator {
+ " break;\n"
+ " }\n"
+ "}\n"
- + "}\n");
+ + "}\n", getDefaultNullability(Nullability.NON_NULL));
out.println("}");
}
+ private void printXmlWriter(CodeWriter out) throws JavaCodeGeneratorException {
+ out.printf("package %s;\n", packageName);
+ out.println();
+ out.println("public class XmlWriter implements java.io.Closeable {");
+
+ out.printf("private java.io.PrintWriter out;\n"
+ + "private StringBuilder outBuffer;\n"
+ + "private int indent;\n"
+ + "private boolean startLine;\n\n"
+ + "public XmlWriter(%sjava.io.PrintWriter printWriter) {\n"
+ + " out = printWriter;\n"
+ + " outBuffer = new StringBuilder();\n"
+ + " indent = 0;\n"
+ + " startLine = true;\n"
+ + "}\n\n"
+ + "private void printIndent() {\n"
+ + " assert startLine;\n"
+ + " for (int i = 0; i < indent; ++i) {\n"
+ + " outBuffer.append(\" \");\n"
+ + " }\n"
+ + " startLine = false;\n"
+ + "}\n\n"
+ + "void print(String code) {\n"
+ + " String[] lines = code.split(\"\\n\", -1);\n"
+ + " for (int i = 0; i < lines.length; ++i) {\n"
+ + " if (startLine && !lines[i].isEmpty()) {\n"
+ + " printIndent();\n"
+ + " }\n"
+ + " outBuffer.append(lines[i]);\n"
+ + " if (i + 1 < lines.length) {\n"
+ + " outBuffer.append(\"\\n\");\n"
+ + " startLine = true;\n"
+ + " }\n"
+ + " }\n"
+ + "}\n\n"
+ + "void increaseIndent() {\n"
+ + " ++indent;\n}\n\n"
+ + "void decreaseIndent() {\n"
+ + " --indent;\n"
+ + "}\n\n"
+ + "void printXml() {\n"
+ + " out.print(outBuffer.toString());\n"
+ + "}\n\n"
+ + "@Override\n"
+ + "public void close() {\n"
+ + " if (out != null) {\n"
+ + " out.close();\n"
+ + " }\n"
+ + "}\n\n", getDefaultNullability(Nullability.NON_NULL));
+
+
+ for (XsdElement element : xmlSchema.getElementMap().values()) {
+ JavaType javaType = parseType(element.getType(), element.getName());
+ String elementName = element.getName();
+ String VariableName = Utils.toVariableName(elementName);
+ String typeName = javaType instanceof JavaSimpleType ? javaType.getName() :
+ Utils.toClassName(javaType.getName());
+ out.printf("public static void write(%sXmlWriter out, %s%s %s) "
+ + "throws java.io.IOException {", getDefaultNullability(Nullability.NON_NULL),
+ getDefaultNullability(Nullability.NON_NULL), typeName, VariableName);
+ out.print("\nout.print(\"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\");\n");
+ out.printf("if (%s != null) {\n", VariableName);
+ out.printf("%s.write(out, \"%s\");\n}\n", VariableName, elementName);
+ out.print("out.printXml();\n}\n\n");
+ }
+ out.printf("}\n");
+ }
+
+ private void printHexBinaryHelper(CodeWriter out) throws JavaCodeGeneratorException {
+ out.printf("package %s;\n", packageName);
+ out.println();
+ out.println("public class HexBinaryHelper {");
+ out.print("public static byte[] hexStringToByteArray(String hexString) {\n"
+ + "if (hexString.length() % 2 != 0) {\n"
+ + "throw new IllegalArgumentException(\"length must be multiple of 2\");\n"
+ + "}\n"
+ + "byte[] outputBytes = new byte[hexString.length() / 2];\n"
+ + "for (int i = 0; i < hexString.length(); i += 2) {\n"
+ + "char c1 = hexString.charAt(i);\n"
+ + "char c2 = hexString.charAt(i + 1);\n"
+ + "outputBytes[i / 2] = (byte) ((Character.digit(c1, 16) << 4)"
+ + " + Character.digit(c2, 16));\n"
+ + "}\n"
+ + "return outputBytes;"
+ + "}\n\n"
+ + "public static String byteArrayToHexString(byte[] b) {\n"
+ + "StringBuffer s = new StringBuffer();\n"
+ + "for (int i = 0; i < b.length; i++) {\n"
+ + "s.append(Integer.toHexString(0x100 + (b[i] & 0xff)).substring(1));\n"
+ + "}\n"
+ + "return s.toString();\n"
+ + "}\n"
+ + "}\n");
+ }
+
private String getElementName(XsdElement element) {
if (element instanceof XsdChoice) {
return element.getName() + "_optional";
@@ -448,15 +681,31 @@ public class JavaCodeGenerator {
return "";
}
+ private String getDefaultNullability(Nullability nullability) {
+ if (showNullability) {
+ return getNullabilityString(nullability);
+ }
+ return "";
+ }
+
private String getNullabilityString(Nullability nullability) {
if (nullability == Nullability.NON_NULL) {
return "@android.annotation.NonNull ";
} else if (nullability == Nullability.NULLABLE) {
return "@android.annotation.Nullable ";
+ } else if (showNullability) {
+ return "@android.annotation.Nullable ";
}
return "";
}
+ private String getterName(String type) {
+ if (type.equals("boolean") && booleanGetter) {
+ return "is";
+ }
+ return "get";
+ }
+
private void stackComponents(XsdComplexType complexType, List<XsdElement> elements,
List<XsdAttribute> attributes) throws JavaCodeGeneratorException {
if (complexType.getBase() != null) {
@@ -591,8 +840,8 @@ public class JavaCodeGenerator {
XsdRestriction restriction = (XsdRestriction) simpleType;
if (restriction.getEnums() != null) {
String name = Utils.toClassName(restriction.getName());
- return new JavaSimpleType(name, name + ".valueOf(%s.replace(\".\", \"_\")."
- + "replaceAll(\"[^A-Za-z0-9_]\", \"\"))", false);
+ return new JavaSimpleType(name, name, name + ".fromString(%s)", "%s.toString()",
+ false);
}
return parseSimpleType(restriction.getBase(), traverse);
} else if (simpleType instanceof XsdUnion) {
@@ -658,7 +907,7 @@ public class JavaCodeGenerator {
throw new JavaCodeGeneratorException(String.format("not a simple type : %s", name));
}
- private static JavaSimpleType predefinedType(String name) throws JavaCodeGeneratorException {
+ private JavaSimpleType predefinedType(String name) throws JavaCodeGeneratorException {
switch (name) {
case "string":
case "token":
@@ -688,51 +937,61 @@ public class JavaCodeGenerator {
case "gMonthDay":
case "gYearMonth":
return new JavaSimpleType("javax.xml.datatype.XMLGregorianCalendar",
+ "javax.xml.datatype.XMLGregorianCalendar",
"javax.xml.datatype.DatatypeFactory.newInstance()"
+ ".newXMLGregorianCalendar(%s)",
- false);
+ "%s.toString()", false);
case "duration":
return new JavaSimpleType("javax.xml.datatype.Duration",
- "javax.xml.datatype.DatatypeFactory.newInstance().newDuration(%s)", false);
+ "javax.xml.datatype.Duration",
+ "javax.xml.datatype.DatatypeFactory.newInstance().newDuration(%s)",
+ "%s.toString()", false);
case "decimal":
- return new JavaSimpleType("java.math.BigDecimal", "new java.math.BigDecimal(%s)",
- false);
+ return new JavaSimpleType("java.math.BigDecimal", "java.math.BigDecimal",
+ "new java.math.BigDecimal(%s)", "%s.toString()", false);
case "integer":
case "negativeInteger":
case "nonNegativeInteger":
case "positiveInteger":
case "nonPositiveInteger":
case "unsignedLong":
- return new JavaSimpleType("java.math.BigInteger", "new java.math.BigInteger(%s)",
- false);
+ return new JavaSimpleType("java.math.BigInteger", "java.math.BigInteger",
+ "new java.math.BigInteger(%s)", "%s.toString()", false);
case "long":
case "unsignedInt":
- return new JavaSimpleType("long", "java.lang.Long", "Long.parseLong(%s)", false);
+ return new JavaSimpleType("long", "java.lang.Long", "Long.parseLong(%s)",
+ "Long.toString(%s)", false);
case "int":
case "unsignedShort":
return new JavaSimpleType("int", "java.lang.Integer", "Integer.parseInt(%s)",
- false);
+ "Integer.toString(%s)", false);
case "short":
case "unsignedByte":
return new JavaSimpleType("short", "java.lang.Short", "Short.parseShort(%s)",
- false);
+ "Short.toString(%s)", false);
case "byte":
- return new JavaSimpleType("byte", "java.lang.Byte", "Byte.parseByte(%s)", false);
+ return new JavaSimpleType("byte", "java.lang.Byte", "Byte.parseByte(%s)",
+ "Byte.toString(%s)",false);
case "boolean":
return new JavaSimpleType("boolean", "java.lang.Boolean",
- "Boolean.parseBoolean(%s)", false);
+ "Boolean.parseBoolean(%s)", "Boolean.toString(%s)", false);
case "double":
return new JavaSimpleType("double", "java.lang.Double", "Double.parseDouble(%s)",
- false);
+ "Double.toString(%s)", false);
case "float":
return new JavaSimpleType("float", "java.lang.Float", "Float.parseFloat(%s)",
- false);
+ "Float.toString(%s)", false);
case "base64Binary":
- return new JavaSimpleType("byte[]", "java.util.Base64.getDecoder().decode(%s)",
+ return new JavaSimpleType("byte[]", "byte[]",
+ "java.util.Base64.getDecoder().decode(%s)",
+ "java.util.Base64.getEncoder().encodeToString(%s)",
false);
case "hexBinary":
- return new JavaSimpleType("java.math.BigInteger",
- "new java.math.BigInteger(%s, 16)", false);
+ useHexBinary = true;
+ return new JavaSimpleType("byte[]", "byte[]",
+ "HexBinaryHelper.hexStringToByteArray(%s)",
+ "HexBinaryHelper.byteArrayToHexString(%s)",
+ false);
}
throw new JavaCodeGeneratorException("unknown xsd predefined type : " + name);
}
diff --git a/src/com/android/xsdc/java/JavaComplexType.java b/src/com/android/xsdc/java/JavaComplexType.java
index c0c694a..1a66794 100644
--- a/src/com/android/xsdc/java/JavaComplexType.java
+++ b/src/com/android/xsdc/java/JavaComplexType.java
@@ -24,6 +24,11 @@ class JavaComplexType implements JavaType {
}
@Override
+ public boolean isPrimitiveType() {
+ return false;
+ }
+
+ @Override
public String getName() {
return name;
}
@@ -37,4 +42,9 @@ class JavaComplexType implements JavaType {
public String getParsingExpression() {
return String.format("%s value = %s.read(parser);\n", name, name);
}
+
+ @Override
+ public String getWritingExpression(String getValue, String name) {
+ return String.format("%s.write(out, \"%s\");\n", getValue, name);
+ }
}
diff --git a/src/com/android/xsdc/java/JavaSimpleType.java b/src/com/android/xsdc/java/JavaSimpleType.java
index 4aac0d1..5c73466 100644
--- a/src/com/android/xsdc/java/JavaSimpleType.java
+++ b/src/com/android/xsdc/java/JavaSimpleType.java
@@ -20,19 +20,26 @@ class JavaSimpleType implements JavaType {
final private String name;
final private String nullableName;
final private String rawParsingExpression;
+ final private String rawWritingExpression;
final private boolean list;
final private String fullName;
final private String nullableFullName;
- JavaSimpleType(String name, String nullableName, String rawParsingExpression, boolean list) {
+ JavaSimpleType(String name, String nullableName, String rawParsingExpression,
+ String rawWritingExpression, boolean list) {
this.name = name;
this.nullableName = nullableName;
this.rawParsingExpression = rawParsingExpression;
+ this.rawWritingExpression = rawWritingExpression;
this.list = list;
fullName = list ? String.format("java.util.List<%s>", nullableName) : name;
nullableFullName = list ? String.format("java.util.List<%s>", nullableName) : nullableName;
}
+ JavaSimpleType(String name, String nullableName, String rawParsingExpression, boolean list) {
+ this(name, nullableName, rawParsingExpression, "%s", list);
+ }
+
JavaSimpleType(String name, String rawParsingExpression, boolean list) {
this(name, name, rawParsingExpression, list);
}
@@ -43,7 +50,8 @@ class JavaSimpleType implements JavaType {
JavaSimpleType newListType() throws JavaCodeGeneratorException {
if (list) throw new JavaCodeGeneratorException("list of list is not supported");
- return new JavaSimpleType(name, nullableName, rawParsingExpression, true);
+ return new JavaSimpleType(name, nullableName, rawParsingExpression, rawWritingExpression,
+ true);
}
@Override
@@ -52,6 +60,11 @@ class JavaSimpleType implements JavaType {
}
@Override
+ public boolean isPrimitiveType() {
+ return !fullName.equals(nullableName);
+ }
+
+ @Override
public String getNullableName() {
return nullableFullName;
}
@@ -73,4 +86,23 @@ class JavaSimpleType implements JavaType {
}
return expression.toString();
}
+
+ @Override
+ public String getWritingExpression(String getValue, String name) {
+ StringBuilder expression = new StringBuilder();
+ if (list) {
+ expression.append("{\nint count = 0;\n");
+ expression.append(String.format("for (%s v : %s) {\n", this.name, getValue));
+ expression.append("if (count != 0) {\n"
+ + "out.print(\" \");\n}\n"
+ + "++count;\n");
+ expression.append(String.format("out.print(%s);\n}\n",
+ String.format(rawWritingExpression, "v")));
+ expression.append("}\n");
+ } else {
+ expression.append(String.format("out.print(%s);\n",
+ String.format(rawWritingExpression, getValue)));
+ }
+ return expression.toString();
+ }
}
diff --git a/src/com/android/xsdc/java/JavaType.java b/src/com/android/xsdc/java/JavaType.java
index a0de172..8605f5d 100644
--- a/src/com/android/xsdc/java/JavaType.java
+++ b/src/com/android/xsdc/java/JavaType.java
@@ -24,4 +24,8 @@ interface JavaType {
String getNullableName();
String getParsingExpression();
+
+ String getWritingExpression(String getValue, String name);
+
+ boolean isPrimitiveType();
}
diff --git a/src/com/android/xsdc/java/Utils.java b/src/com/android/xsdc/java/Utils.java
index 4d825e9..5a7a92a 100644
--- a/src/com/android/xsdc/java/Utils.java
+++ b/src/com/android/xsdc/java/Utils.java
@@ -72,6 +72,9 @@ class Utils {
}
static String toEnumName(String name) throws JavaCodeGeneratorException {
+ if ("".equals(name)) {
+ name = "EMPTY";
+ }
String trimmed = name.replace(".", "_").replaceAll("[^A-Za-z0-9_]", "");
if (trimmed.isEmpty()) {
throw new JavaCodeGeneratorException(
diff --git a/src/com/android/xsdc/tag/XsdAttribute.java b/src/com/android/xsdc/tag/XsdAttribute.java
index d940ed4..0c46eb0 100644
--- a/src/com/android/xsdc/tag/XsdAttribute.java
+++ b/src/com/android/xsdc/tag/XsdAttribute.java
@@ -22,8 +22,9 @@ import javax.xml.namespace.QName;
public class XsdAttribute extends XsdTag {
final private XsdType type;
+ final private boolean required;
- public XsdAttribute(String name, QName ref, XsdType type)
+ public XsdAttribute(String name, QName ref, XsdType type, boolean required)
throws XsdParserException {
super(name, ref);
if (name == null && ref == null) {
@@ -33,9 +34,14 @@ public class XsdAttribute extends XsdTag {
throw new XsdParserException("type definition should exist");
}
this.type = type;
+ this.required = required;
}
public XsdType getType() {
return type;
}
+
+ public boolean isRequired() {
+ return required;
+ }
}
diff --git a/tests/Android.bp b/tests/Android.bp
index afd6150..ab44220 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1,21 +1,47 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
java_test_host {
name: "xsdc-java-tests",
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java",
+ ":xsdc_attr_group_simple_tests",
+ ":xsdc_attr_enumtype_tests",
+ ":xsdc_group_tests",
+ ":xsdc_nested_type_tests",
+ ":xsdc_predefined_types_tests",
+ ":xsdc_purchase_simple_tests",
+ ":xsdc_reference_tests",
+ ":xsdc_simple_complex_content_tests",
+ ":xsdc_simple_type_tests",
+ ],
+ test_options: {
+ unit_test: true,
+ },
static_libs: [
"junit",
"xsdc",
+ "stub-annotations",
+ "kxml2-2.3.0",
],
- java_resource_dirs: ["resources"]
+ java_resource_dirs: ["resources"],
+ test_suites: ["general-tests"],
}
cc_test_host {
name: "xsdc-cpp-tests",
srcs: [
+ "simple_type.cpp",
+ "tests.cpp",
"main.cpp",
],
+ test_options: {
+ unit_test: true,
+ },
generated_sources: [
"xsdc_attr_group_simple_tests",
+ "xsdc_attr_enumtype_tests",
"xsdc_group_tests",
"xsdc_nested_type_tests",
"xsdc_predefined_types_tests",
@@ -26,6 +52,7 @@ cc_test_host {
],
generated_headers: [
"xsdc_attr_group_simple_tests",
+ "xsdc_attr_enumtype_tests",
"xsdc_group_tests",
"xsdc_nested_type_tests",
"xsdc_predefined_types_tests",
@@ -34,9 +61,64 @@ cc_test_host {
"xsdc_simple_complex_content_tests",
"xsdc_simple_type_tests",
],
+ header_libs: ["libxsdc-utils"],
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+ data: ["resources/*.xml"],
+ test_suites: ["general-tests"],
+}
+
+// These tests verify that enums-only and parser-only
+// modules can be combined later.
+cc_test_host {
+ name: "xsdc-cpp-tests-split",
+ srcs: [
+ "simple_type.cpp",
+ "main.cpp",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+ generated_sources: [
+ "xsdc_simple_type_tests_enums",
+ "xsdc_simple_type_tests_parser",
+ ],
+ generated_headers: [
+ "xsdc_simple_type_tests_enums",
+ "xsdc_simple_type_tests_parser",
+ ],
+ header_libs: ["libxsdc-utils"],
shared_libs: [
"libbase",
"libxml2",
],
data: ["resources/*.xml"],
+ test_suites: ["general-tests"],
+}
+
+// These tests verify that enums-only module can be used on
+// its own and it does not depend on libxml2.
+cc_test_host {
+ name: "xsdc-cpp-tests-enums",
+ srcs: [
+ "simple_type_enumsonly.cpp",
+ "main.cpp",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+ generated_sources: [
+ "xsdc_simple_type_tests_enums",
+ ],
+ generated_headers: [
+ "xsdc_simple_type_tests_enums",
+ ],
+ header_libs: ["libxsdc-utils"],
+ shared_libs: [
+ "libbase",
+ ],
+ data: ["resources/*.xml"],
+ test_suites: ["general-tests"],
}
diff --git a/tests/main.cpp b/tests/main.cpp
index fa9d82c..5e91e2d 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -14,212 +14,7 @@
* limitations under the License.
*/
-#include <iostream>
-#include <string>
#include <gtest/gtest.h>
-#include "nested_type.h"
-#include "purchase_simple.h"
-#include "simple_complex_content.h"
-
-#include "predefined_types.h"
-#include "reference.h"
-#include "simple_type.h"
-#include "attr_group_simple.h"
-#include "group.h"
-
-using namespace std;
-
-class XmlTest : public ::testing::Test {
-public:
- virtual void SetUp() override {
- }
- virtual void TearDown() override {
- }
-};
-
-TEST_F(XmlTest, Simpletype) {
- using namespace simple::type;
- string file_name = "resources/simple_type.xml";
- SimpleTypes simple = *readSimpleTypes(file_name.c_str());
-
- for (int i = 0; i < simple.getListInt().size(); ++i) {
- EXPECT_EQ(simple.getListInt()[i], i + 1);
- }
- EXPECT_EQ(*simple.getFirstUnionTest(), "100");
- EXPECT_EQ(simple.getYesOrNo()[0], EnumType::YES);
- EXPECT_EQ(simple.getYesOrNo()[1], EnumType::EMPTY);
-}
-
-TEST_F(XmlTest, Predefinedtypes) {
- using namespace predefined::types;
- Types type = *read("resources/predefined_types.xml");
-
- StringTypes stringTypes = *type.getFirstStringTypes();
- DateTypes dateTypes = *type.getFirstDateTypes();
- NumericTypes numericTypes = *type.getFirstNumericTypes();
- MiscTypes miscTypes = *type.getFirstMiscTypes();
- ListPrimitiveTypes listPrimitiveTypes = *type.getFirstListPrimitiveTypes();
-
- EXPECT_EQ(stringTypes.getString(), "abcd");
- EXPECT_EQ(stringTypes.getToken(), "abcd");
- EXPECT_EQ(stringTypes.getNormalizedString(), "abcd");
- EXPECT_EQ(stringTypes.getLanguage(), "abcd");
- EXPECT_EQ(stringTypes.getEntity(), "abcd");
- EXPECT_EQ(stringTypes.getEntities()[0], "a");
- EXPECT_EQ(stringTypes.getEntities()[1], "b");
- EXPECT_EQ(stringTypes.getEntities()[2], "c");
- EXPECT_EQ(stringTypes.getEntities()[3], "d");
- EXPECT_EQ(stringTypes.getId(), "abcd");
- EXPECT_EQ(stringTypes.getName(), "abcd");
- EXPECT_EQ(stringTypes.getNcname(), "abcd");
- EXPECT_EQ(stringTypes.getNmtoken(), "abcd");
- EXPECT_EQ(stringTypes.getNmtokens()[0], "a");
- EXPECT_EQ(stringTypes.getNmtokens()[1], "b");
- EXPECT_EQ(stringTypes.getNmtokens()[2], "c");
- EXPECT_EQ(stringTypes.getNmtokens()[3], "d");
-
-
- EXPECT_EQ(dateTypes.getDate(), "2018-06-18");
- EXPECT_EQ(dateTypes.getDateTime(), "2018-06-18T21:32:52");
- EXPECT_EQ(dateTypes.getDuration(), "P3M");
- EXPECT_EQ(dateTypes.getGDay(), "---18");
- EXPECT_EQ(dateTypes.getGMonth(), "--06");
- EXPECT_EQ(dateTypes.getGMonthDay(), "--06-18");
- EXPECT_EQ(dateTypes.getGYear(), "2018");
- EXPECT_EQ(dateTypes.getGYearMonth(), "2018-06");
- EXPECT_EQ(dateTypes.getTime(), "21:32:52");
-
- EXPECT_EQ(numericTypes.getDecimal(), 1234.57);
- EXPECT_EQ(numericTypes.getInteger(), 1234567890123456789);
- EXPECT_EQ(numericTypes.get_long(), 9223372036854775807);
- EXPECT_EQ(numericTypes.get_int(), 2147483647);
- EXPECT_EQ(numericTypes.get_short(), 32767);
- EXPECT_EQ((int)numericTypes.getByte(), 127);
- EXPECT_EQ(numericTypes.getNegativeInteger(), -1234);
- EXPECT_EQ(numericTypes.getNonNegativeInteger(), 1234);
- EXPECT_EQ(numericTypes.getPositiveInteger(), 1234);
- EXPECT_EQ(numericTypes.getNonPositiveInteger(), -1234);
- EXPECT_EQ(numericTypes.getUnsignedLong(), 1234);
- EXPECT_EQ(numericTypes.getUnsignedInt(), 1234);
- EXPECT_EQ(numericTypes.getUnsignedShort(), 1234);
- EXPECT_EQ((int)(numericTypes.getUnsignedByte()), 255);
-
- EXPECT_EQ(miscTypes.get_double(), 1234.57);
- EXPECT_EQ(miscTypes.getAnyURI(), "https://www.google.com");
- EXPECT_EQ(miscTypes.getBase64Binary(), "Z29vZ2xl");
- EXPECT_TRUE(miscTypes.getBoolean());
- EXPECT_EQ(miscTypes.getHexBinary(), "516a75cb56d7e7");
- EXPECT_EQ(miscTypes.getQName(), "abcd");
- EXPECT_EQ(miscTypes.getIDREF(), "abcd");
- EXPECT_EQ(miscTypes.getIDREFS()[0], "abcd");
- EXPECT_EQ(miscTypes.getIDREFS()[1], "abcd");
- EXPECT_EQ(miscTypes.getAnyType(), "abcd");
-
- EXPECT_EQ(listPrimitiveTypes.getListInt()[0], -2147483648);
- EXPECT_EQ(listPrimitiveTypes.getListInt()[1], 2147483647);
- EXPECT_EQ(listPrimitiveTypes.getListShort()[0], -32768);
- EXPECT_EQ(listPrimitiveTypes.getListShort()[1], 32767);
- EXPECT_EQ((int)listPrimitiveTypes.getListByte()[0], -128);
- EXPECT_EQ((int)listPrimitiveTypes.getListByte()[1], 127);
- EXPECT_EQ(listPrimitiveTypes.getListDouble()[0], 1234.56);
- EXPECT_EQ(listPrimitiveTypes.getListDouble()[1], 5678.12);
- EXPECT_TRUE(listPrimitiveTypes.getListBoolean()[0]);
- EXPECT_FALSE(listPrimitiveTypes.getListBoolean()[1]);
-
-}
-
-TEST_F(XmlTest, Nestedtype) {
- using namespace nested::type;
- Employee employee = *read("resources/nested_type.xml");
-
- Employee::Address address = *employee.getFirstAddress();
- Employee::Address::Extra extra = *address.getFirstExtra();
-
- EXPECT_EQ((int)employee.getId(), 1);
- EXPECT_EQ(employee.getName(), "Peter");
- EXPECT_EQ(address.getCountry(), "US");
- EXPECT_EQ(address.getState(), "Mountain View");
- EXPECT_EQ(address.getZip(), 3342);
- EXPECT_EQ(extra.getLine1(), "Donga 303-111");
- EXPECT_EQ(extra.getLine2(), "Good Street");
-}
-
-TEST_F(XmlTest, Purchasesimple) {
- using namespace purchase::simple;
- PurchaseOrderType orderType = *read("resources/purchase_simple.xml");
-
- EXPECT_EQ(orderType.getOrderDate(), "1900-01-01");
-
- EXPECT_EQ(orderType.getShipTo()[0].getName(), "name1");
- EXPECT_EQ(orderType.getShipTo()[0].getStreet(), "street1");
- EXPECT_EQ(orderType.getShipTo()[0].getCity(), "city1");
- EXPECT_EQ(orderType.getShipTo()[0].getState(), "state1");
- EXPECT_EQ(orderType.getShipTo()[0].getZip(), 1);
- EXPECT_EQ(orderType.getShipTo()[0].getCountry(), "US");
- EXPECT_EQ(orderType.getShipTo()[1].getName(), "name2");
- EXPECT_EQ(orderType.getShipTo()[1].getStreet(), "street2");
- EXPECT_EQ(orderType.getShipTo()[1].getCity(), "city2");
- EXPECT_EQ(orderType.getShipTo()[1].getState(), "state2");
- EXPECT_EQ(orderType.getShipTo()[1].getZip(), -7922816251426433759);
- EXPECT_EQ(orderType.getShipTo()[1].getCountry(), "US");
-
- EXPECT_EQ(orderType.getBillTo()[0].getName(), "billName");
- EXPECT_EQ(orderType.getBillTo()[0].getStreet(), "billStreet");
- EXPECT_EQ(orderType.getBillTo()[0].getCity(), "billCity");
- EXPECT_EQ(orderType.getBillTo()[0].getState(), "billState");
- EXPECT_EQ(orderType.getBillTo()[0].getZip(), 1);
- EXPECT_EQ(orderType.getBillTo()[0].getCountry(), "US");
-}
-
-TEST_F(XmlTest, Reference) {
- using namespace reference;
- Class _class = *read("resources/reference.xml");
-
- EXPECT_EQ(_class.getStudent()[0], "Sam");
- EXPECT_EQ(_class.getStudent()[1], "Paul");
- EXPECT_EQ(_class.getStudent()[2], "Peter");
-}
-
-TEST_F(XmlTest, Simplecomplexcontent) {
- using namespace simple::complex::content;
- Person person = *readPerson("resources/simple_complex_content.xml");
- USAddressP uSAddressP = *person.getFirstUSAddressP();
- KRAddress kRAddress = *person.getFirstKRAddress();
- SubAddress subAddress = *person.getFirstSubAddress();
-
- EXPECT_EQ(person.getName(), "Petr");
-
- EXPECT_EQ(uSAddressP.getName(), "404");
- EXPECT_EQ(uSAddressP.getStreet(), "street fighter");
- EXPECT_EQ(uSAddressP.getCity(), "New York");
- EXPECT_EQ(uSAddressP.getState(), "Washington");
- EXPECT_EQ(uSAddressP.getZipcode(), 323232318329852);
-
- EXPECT_EQ(kRAddress.getName(), "Donga Studio");
- EXPECT_EQ(kRAddress.getStreet(), "Nokdu Street");
- EXPECT_EQ(kRAddress.getCity(), "Seoul");
-
- EXPECT_EQ(subAddress.getChoice1_optional(), "Temp");
-}
-
-TEST_F(XmlTest, Attrgroupsimple) {
- using namespace attr::group::simple;
- Student student = *read("resources/attr_group_simple.xml");
-
- EXPECT_EQ(student.getName(), "Jun");
- EXPECT_EQ(student.getCity(), "Mountain View");
- EXPECT_EQ(student.getState(), "CA");
- EXPECT_EQ(student.getRoad(), "Street 101");
-}
-
-TEST_F(XmlTest, Group) {
- using namespace group;
- Student student = *read("resources/group.xml");
-
- EXPECT_EQ(student.getCity(), "Mountain View");
- EXPECT_EQ(student.getState(), "CA");
- EXPECT_EQ(student.getRoad(), "Street 101");
-}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
diff --git a/tests/resources/attr_group_simple.xml b/tests/resources/attr_group_simple.xml
index fb3bfc8..0a14222 100644
--- a/tests/resources/attr_group_simple.xml
+++ b/tests/resources/attr_group_simple.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-<Student State="CA" city="Mountain View" road="Street 101">
+<Student State="CA" city="Mountain View" road="Street 101" list="1 2 3">
<Name>Jun</Name>
</Student>
diff --git a/tests/resources/attr_group_simple/Android.bp b/tests/resources/attr_group_simple/Android.bp
index fe62b55..ef3136d 100644
--- a/tests/resources/attr_group_simple/Android.bp
+++ b/tests/resources/attr_group_simple/Android.bp
@@ -1,7 +1,11 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_attr_group_simple_tests",
srcs: ["attr_group_simple.xsd"],
package_name: "attr.group.simple",
+ gen_writer: true,
}
-
diff --git a/tests/resources/attr_group_simple/api/current.txt b/tests/resources/attr_group_simple/api/current.txt
index 20aefda..9203633 100644
--- a/tests/resources/attr_group_simple/api/current.txt
+++ b/tests/resources/attr_group_simple/api/current.txt
@@ -4,10 +4,12 @@ package attr.group.simple {
public class Student {
ctor public Student();
method public String getCity();
+ method public java.util.List<java.lang.Integer> getList();
method public String getName();
method public String getRoad();
method public String getState();
method public void setCity(String);
+ method public void setList(java.util.List<java.lang.Integer>);
method public void setName(String);
method public void setRoad(String);
method public void setState(String);
@@ -20,5 +22,11 @@ package attr.group.simple {
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(java.io.PrintWriter);
+ method public void close();
+ method public static void write(attr.group.simple.XmlWriter, attr.group.simple.Student) throws java.io.IOException;
+ }
+
}
diff --git a/tests/resources/attr_group_simple/attr_group_simple.xsd b/tests/resources/attr_group_simple/attr_group_simple.xsd
index 7f94e31..0853848 100644
--- a/tests/resources/attr_group_simple/attr_group_simple.xsd
+++ b/tests/resources/attr_group_simple/attr_group_simple.xsd
@@ -1,18 +1,22 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="attr_group_simple" elementFormDefault="qualified">
<xs:attributeGroup name="address">
<xs:attribute name="State" type="xs:string"/>
- <xs:attribute name="city" type="xs:string"/>
+ <xs:attribute name="city" type="xs:string" use="required"/>
</xs:attributeGroup>
<xs:attributeGroup name="homeAddress">
<xs:attributeGroup ref="address"/>
<xs:attribute name="road" type="xs:string"/>
</xs:attributeGroup>
+ <xs:simpleType name="listInt">
+ <xs:list itemType="xs:int" />
+ </xs:simpleType>
<xs:element name="Student">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
</xs:sequence>
<xs:attributeGroup ref="homeAddress"/>
+ <xs:attribute name="list" type="listInt" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
diff --git a/tests/resources/enum_type/Android.bp b/tests/resources/enum_type/Android.bp
new file mode 100644
index 0000000..979ae6d
--- /dev/null
+++ b/tests/resources/enum_type/Android.bp
@@ -0,0 +1,9 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+xsd_config {
+ name: "xsdc_attr_enumtype_tests",
+ srcs: ["attr_enumtype.xsd"],
+ package_name: "attr.enumtype",
+}
diff --git a/tests/resources/enum_type/api/current.txt b/tests/resources/enum_type/api/current.txt
new file mode 100644
index 0000000..263deed
--- /dev/null
+++ b/tests/resources/enum_type/api/current.txt
@@ -0,0 +1,532 @@
+// Signature format: 2.0
+package attr.enumtype {
+
+ public class AttachedDevices {
+ ctor public AttachedDevices();
+ method public java.util.List<java.lang.String> getItem();
+ }
+
+ public enum AudioChannelMask {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_1;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_10;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_11;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_12;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_13;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_14;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_15;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_16;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_17;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_18;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_19;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_2;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_20;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_21;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_22;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_23;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_24;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_3;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_4;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_5;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_6;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_7;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_8;
+ enum_constant public static final attr.enumtype.AudioChannelMask INDEX_MASK_9;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_2POINT0POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_2POINT1POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_3POINT0POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_3POINT1POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_5POINT1;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_6;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_FRONT_BACK;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_MONO;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_STEREO;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_VOICE_CALL_MONO;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_VOICE_DNLINK_MONO;
+ enum_constant public static final attr.enumtype.AudioChannelMask IN_VOICE_UPLINK_MONO;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_2POINT0POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_2POINT1;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_2POINT1POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_3POINT0POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_3POINT1POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_5POINT1;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_5POINT1POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_5POINT1POINT4;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_6POINT1;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_7POINT1;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_7POINT1POINT2;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_7POINT1POINT4;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_HAPTIC_AB;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_MONO;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_MONO_HAPTIC_A;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_MONO_HAPTIC_AB;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_PENTA;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_QUAD;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_QUAD_BACK;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_QUAD_SIDE;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_STEREO;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_STEREO_HAPTIC_A;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_STEREO_HAPTIC_AB;
+ enum_constant public static final attr.enumtype.AudioChannelMask OUT_SURROUND;
+ }
+
+ public enum AudioContentType {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.AudioContentType AUDIO_CONTENT_TYPE_MOVIE;
+ enum_constant public static final attr.enumtype.AudioContentType AUDIO_CONTENT_TYPE_MUSIC;
+ enum_constant public static final attr.enumtype.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION;
+ enum_constant public static final attr.enumtype.AudioContentType AUDIO_CONTENT_TYPE_SPEECH;
+ enum_constant public static final attr.enumtype.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN;
+ }
+
+ public enum AudioDevice {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_AMBIENT;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_AUX_DIGITAL;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_BACK_MIC;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_BUILTIN_MIC;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_BUS;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_COMMUNICATION;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_DEFAULT;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_ECHO_REFERENCE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_FM_TUNER;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_HDMI;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_IP;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_LINE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_LOOPBACK;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_PROXY;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_SPDIF;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_STUB;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_TELEPHONY_RX;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_TV_TUNER;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_USB_ACCESSORY;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_USB_DEVICE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_USB_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_VOICE_CALL;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_IN_WIRED_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_NONE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_AUX_LINE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_BUS;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_DEFAULT;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_EARPIECE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_ECHO_CANCELLER;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_FM;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_HDMI;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_HDMI_ARC;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_IP;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_LINE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_PROXY;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_SPDIF;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_SPEAKER;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_STUB;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_TELEPHONY_TX;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_USB_DEVICE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_USB_HEADSET;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ enum_constant public static final attr.enumtype.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ }
+
+ public enum AudioFormat {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADIF;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_ELD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_ERLC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V1;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V2;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_LC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_LD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_LTP;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_MAIN;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_SCALABLE;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_SSR;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ADTS_XHE;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ELD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_ERLC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_HE_V1;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_HE_V2;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_LATM;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V1;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V2;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_LATM_LC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_LC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_LD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_LTP;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_MAIN;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_SCALABLE;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_SSR;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AAC_XHE;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AC3;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AC4;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_ALAC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AMR_NB;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AMR_WB;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_AMR_WB_PLUS;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_APE;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_APTX;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_APTX_HD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_APTX_TWSP;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_CELT;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_DSD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_DTS;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_DTS_HD;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_EVRC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_EVRCB;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_EVRCNW;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_EVRCWB;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_E_AC3;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_E_AC3_JOC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_FLAC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_HE_AAC_V1;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_HE_AAC_V2;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_IEC61937;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_LDAC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_LHDC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_LHDC_LL;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_MAT_1_0;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_MAT_2_0;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_MAT_2_1;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_MP2;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_MP3;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_OPUS;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_PCM_16_BIT;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_PCM_32_BIT;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_PCM_8_24_BIT;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_PCM_8_BIT;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_PCM_FLOAT;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_QCELP;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_SBC;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_VORBIS;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_WMA;
+ enum_constant public static final attr.enumtype.AudioFormat AUDIO_FORMAT_WMA_PRO;
+ }
+
+ public class AudioPolicyConfiguration {
+ ctor public AudioPolicyConfiguration();
+ method public attr.enumtype.GlobalConfiguration getGlobalConfiguration();
+ method public java.util.List<attr.enumtype.Modules> getModules();
+ method public attr.enumtype.SurroundSound getSurroundSound();
+ method public attr.enumtype.Version getVersion();
+ method public java.util.List<attr.enumtype.Volumes> getVolumes();
+ method public void setGlobalConfiguration(attr.enumtype.GlobalConfiguration);
+ method public void setSurroundSound(attr.enumtype.SurroundSound);
+ method public void setVersion(attr.enumtype.Version);
+ }
+
+ public enum AudioSource {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_CAMCORDER;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_DEFAULT;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_ECHO_REFERENCE;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_FM_TUNER;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_HOTWORD;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_MIC;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_REMOTE_SUBMIX;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_UNPROCESSED;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_VOICE_CALL;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_VOICE_COMMUNICATION;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_VOICE_DOWNLINK;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_VOICE_PERFORMANCE;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_VOICE_RECOGNITION;
+ enum_constant public static final attr.enumtype.AudioSource AUDIO_SOURCE_VOICE_UPLINK;
+ }
+
+ public enum AudioStreamType {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_ACCESSIBILITY;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_ALARM;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_ASSISTANT;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_BLUETOOTH_SCO;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_DEFAULT;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_DTMF;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_ENFORCED_AUDIBLE;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_MUSIC;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_NOTIFICATION;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_PATCH;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_REROUTING;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_RING;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_SYSTEM;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_TTS;
+ enum_constant public static final attr.enumtype.AudioStreamType AUDIO_STREAM_VOICE_CALL;
+ }
+
+ public enum AudioUsage {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_ALARM;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_ANNOUNCEMENT;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_ASSISTANT;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_CALL_ASSISTANT;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_EMERGENCY;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_GAME;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_MEDIA;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_NOTIFICATION;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_SAFETY;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_UNKNOWN;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_VEHICLE_STATUS;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_VIRTUAL_SOURCE;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION;
+ enum_constant public static final attr.enumtype.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ }
+
+ public enum DeviceCategory {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.DeviceCategory DEVICE_CATEGORY_EARPIECE;
+ enum_constant public static final attr.enumtype.DeviceCategory DEVICE_CATEGORY_EXT_MEDIA;
+ enum_constant public static final attr.enumtype.DeviceCategory DEVICE_CATEGORY_HEADSET;
+ enum_constant public static final attr.enumtype.DeviceCategory DEVICE_CATEGORY_HEARING_AID;
+ enum_constant public static final attr.enumtype.DeviceCategory DEVICE_CATEGORY_SPEAKER;
+ }
+
+ public class DevicePorts {
+ ctor public DevicePorts();
+ method public java.util.List<attr.enumtype.DevicePorts.DevicePort> getDevicePort();
+ }
+
+ public static class DevicePorts.DevicePort {
+ ctor public DevicePorts.DevicePort();
+ method public String getAddress();
+ method public java.util.List<attr.enumtype.AudioFormat> getEncodedFormats();
+ method public attr.enumtype.Gains getGains();
+ method public java.util.List<attr.enumtype.Profile> getProfile();
+ method public attr.enumtype.Role getRole();
+ method public String getTagName();
+ method public String getType();
+ method public boolean get_default();
+ method public void setAddress(String);
+ method public void setEncodedFormats(java.util.List<attr.enumtype.AudioFormat>);
+ method public void setGains(attr.enumtype.Gains);
+ method public void setRole(attr.enumtype.Role);
+ method public void setTagName(String);
+ method public void setType(String);
+ method public void set_default(boolean);
+ }
+
+ public enum EngineSuffix {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.EngineSuffix _default;
+ enum_constant public static final attr.enumtype.EngineSuffix configurable;
+ }
+
+ public enum GainMode {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.GainMode AUDIO_GAIN_MODE_CHANNELS;
+ enum_constant public static final attr.enumtype.GainMode AUDIO_GAIN_MODE_JOINT;
+ enum_constant public static final attr.enumtype.GainMode AUDIO_GAIN_MODE_RAMP;
+ }
+
+ public class Gains {
+ ctor public Gains();
+ method public java.util.List<attr.enumtype.Gains.Gain> getGain();
+ }
+
+ public static class Gains.Gain {
+ ctor public Gains.Gain();
+ method public String getChannel_mask();
+ method public int getDefaultValueMB();
+ method public int getMaxRampMs();
+ method public int getMaxValueMB();
+ method public int getMinRampMs();
+ method public int getMinValueMB();
+ method public attr.enumtype.GainMode getMode();
+ method public String getName();
+ method public int getStepValueMB();
+ method public boolean getUseForVolume();
+ method public void setChannel_mask(String);
+ method public void setDefaultValueMB(int);
+ method public void setMaxRampMs(int);
+ method public void setMaxValueMB(int);
+ method public void setMinRampMs(int);
+ method public void setMinValueMB(int);
+ method public void setMode(attr.enumtype.GainMode);
+ method public void setName(String);
+ method public void setStepValueMB(int);
+ method public void setUseForVolume(boolean);
+ }
+
+ public class GlobalConfiguration {
+ ctor public GlobalConfiguration();
+ method public boolean getCall_screen_mode_supported();
+ method public attr.enumtype.EngineSuffix getEngine_library();
+ method public boolean getSpeaker_drc_enabled();
+ method public void setCall_screen_mode_supported(boolean);
+ method public void setEngine_library(attr.enumtype.EngineSuffix);
+ method public void setSpeaker_drc_enabled(boolean);
+ }
+
+ public enum HalVersion {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.HalVersion _2_0;
+ enum_constant public static final attr.enumtype.HalVersion _3_0;
+ }
+
+ public class MixPorts {
+ ctor public MixPorts();
+ method public java.util.List<attr.enumtype.MixPorts.MixPort> getMixPort();
+ }
+
+ public static class MixPorts.MixPort {
+ ctor public MixPorts.MixPort();
+ method public String getFlags();
+ method public attr.enumtype.Gains getGains();
+ method public long getMaxActiveCount();
+ method public long getMaxOpenCount();
+ method public String getName();
+ method public java.util.List<attr.enumtype.AudioUsage> getPreferredUsage();
+ method public java.util.List<attr.enumtype.Profile> getProfile();
+ method public attr.enumtype.Role getRole();
+ method public void setFlags(String);
+ method public void setGains(attr.enumtype.Gains);
+ method public void setMaxActiveCount(long);
+ method public void setMaxOpenCount(long);
+ method public void setName(String);
+ method public void setPreferredUsage(java.util.List<attr.enumtype.AudioUsage>);
+ method public void setRole(attr.enumtype.Role);
+ }
+
+ public enum MixType {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.MixType mix;
+ enum_constant public static final attr.enumtype.MixType mux;
+ }
+
+ public class Modules {
+ ctor public Modules();
+ method public java.util.List<attr.enumtype.Modules.Module> getModule();
+ }
+
+ public static class Modules.Module {
+ ctor public Modules.Module();
+ method public attr.enumtype.AttachedDevices getAttachedDevices();
+ method public String getDefaultOutputDevice();
+ method public attr.enumtype.DevicePorts getDevicePorts();
+ method public attr.enumtype.HalVersion getHalVersion();
+ method public attr.enumtype.MixPorts getMixPorts();
+ method public String getName();
+ method public attr.enumtype.Routes getRoutes();
+ method public void setAttachedDevices(attr.enumtype.AttachedDevices);
+ method public void setDefaultOutputDevice(String);
+ method public void setDevicePorts(attr.enumtype.DevicePorts);
+ method public void setHalVersion(attr.enumtype.HalVersion);
+ method public void setMixPorts(attr.enumtype.MixPorts);
+ method public void setName(String);
+ method public void setRoutes(attr.enumtype.Routes);
+ }
+
+ public class Profile {
+ ctor public Profile();
+ method public String getChannelMasks();
+ method public String getFormat();
+ method public String getName();
+ method public String getSamplingRates();
+ method public void setChannelMasks(String);
+ method public void setFormat(String);
+ method public void setName(String);
+ method public void setSamplingRates(String);
+ }
+
+ public class Reference {
+ ctor public Reference();
+ method public String getName();
+ method public java.util.List<java.lang.String> getPoint();
+ method public void setName(String);
+ }
+
+ public enum Role {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.Role sink;
+ enum_constant public static final attr.enumtype.Role source;
+ }
+
+ public class Routes {
+ ctor public Routes();
+ method public java.util.List<attr.enumtype.Routes.Route> getRoute();
+ }
+
+ public static class Routes.Route {
+ ctor public Routes.Route();
+ method public String getSink();
+ method public String getSources();
+ method public attr.enumtype.MixType getType();
+ method public void setSink(String);
+ method public void setSources(String);
+ method public void setType(attr.enumtype.MixType);
+ }
+
+ public class SurroundFormats {
+ ctor public SurroundFormats();
+ method public java.util.List<attr.enumtype.SurroundFormats.Format> getFormat();
+ }
+
+ public static class SurroundFormats.Format {
+ ctor public SurroundFormats.Format();
+ method public attr.enumtype.AudioFormat getName();
+ method public java.util.List<attr.enumtype.AudioFormat> getSubformats();
+ method public void setName(attr.enumtype.AudioFormat);
+ method public void setSubformats(java.util.List<attr.enumtype.AudioFormat>);
+ }
+
+ public class SurroundSound {
+ ctor public SurroundSound();
+ method public attr.enumtype.SurroundFormats getFormats();
+ method public void setFormats(attr.enumtype.SurroundFormats);
+ }
+
+ public enum Version {
+ method public String getRawName();
+ enum_constant public static final attr.enumtype.Version _1_0;
+ }
+
+ public class Volume {
+ ctor public Volume();
+ method public attr.enumtype.DeviceCategory getDeviceCategory();
+ method public java.util.List<java.lang.String> getPoint();
+ method public String getRef();
+ method public attr.enumtype.AudioStreamType getStream();
+ method public void setDeviceCategory(attr.enumtype.DeviceCategory);
+ method public void setRef(String);
+ method public void setStream(attr.enumtype.AudioStreamType);
+ }
+
+ public class Volumes {
+ ctor public Volumes();
+ method public java.util.List<attr.enumtype.Reference> getReference();
+ method public java.util.List<attr.enumtype.Volume> getVolume();
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method public static attr.enumtype.AudioPolicyConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/tests/resources/enum_type/api/last_current.txt b/tests/resources/enum_type/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/enum_type/api/last_current.txt
diff --git a/tests/resources/enum_type/api/last_removed.txt b/tests/resources/enum_type/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/enum_type/api/last_removed.txt
diff --git a/tests/resources/enum_type/api/removed.txt b/tests/resources/enum_type/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/tests/resources/enum_type/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/tests/resources/enum_type/attr_enumtype.xsd b/tests/resources/enum_type/attr_enumtype.xsd
new file mode 100644
index 0000000..65223b1
--- /dev/null
+++ b/tests/resources/enum_type/attr_enumtype.xsd
@@ -0,0 +1,743 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema version="2.0"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <!-- List the config versions supported by audio policy. -->
+ <xs:simpleType name="version">
+ <xs:restriction base="xs:decimal">
+ <xs:enumeration value="1.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="halVersion">
+ <xs:restriction base="xs:decimal">
+ <!-- List of HAL versions supported by the framework. -->
+ <xs:enumeration value="2.0"/>
+ <xs:enumeration value="3.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="audioPolicyConfiguration">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="globalConfiguration" type="globalConfiguration"/>
+ <xs:element name="modules" type="modules" maxOccurs="unbounded"/>
+ <xs:element name="volumes" type="volumes" maxOccurs="unbounded"/>
+ <xs:element name="surroundSound" type="surroundSound" minOccurs="0" />
+ </xs:sequence>
+ <xs:attribute name="version" type="version"/>
+ </xs:complexType>
+ <xs:key name="moduleNameKey">
+ <xs:selector xpath="modules/module"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:unique name="volumeTargetUniqueness">
+ <xs:selector xpath="volumes/volume"/>
+ <xs:field xpath="@stream"/>
+ <xs:field xpath="@deviceCategory"/>
+ </xs:unique>
+ <xs:key name="volumeCurveNameKey">
+ <xs:selector xpath="volumes/reference"/>
+ <xs:field xpath="@name"/>
+ </xs:key>
+ <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+ <xs:selector xpath="volumes/volume"/>
+ <xs:field xpath="@ref"/>
+ </xs:keyref>
+ </xs:element>
+ <xs:complexType name="globalConfiguration">
+ <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
+ <xs:attribute name="call_screen_mode_supported" type="xs:boolean" use="optional"/>
+ <xs:attribute name="engine_library" type="engineSuffix" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="modules">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ There should be one section per audio HW module present on the platform.
+ Each <module/> contains two mandatory tags: “halVersion” and “name”.
+ The module "name" is the same as in previous .conf file.
+ Each module must contain the following sections:
+ - <devicePorts/>: a list of device descriptors for all
+ input and output devices accessible via this module.
+ This contains both permanently attached devices and removable devices.
+ - <mixPorts/>: listing all output and input streams exposed by the audio HAL
+ - <routes/>: list of possible connections between input
+ and output devices or between stream and devices.
+ A <route/> is defined by a set of 3 attributes:
+ -"type": mux|mix means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via this route
+ - <attachedDevices/>: permanently attached devices.
+ The attachedDevices section is a list of devices names.
+ Their names correspond to device names defined in "devicePorts" section.
+ - <defaultOutputDevice/> is the device to be used when no policy rule applies
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="module" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="attachedDevices" type="attachedDevices" minOccurs="0">
+ <xs:unique name="attachedDevicesUniqueness">
+ <xs:selector xpath="item"/>
+ <xs:field xpath="."/>
+ </xs:unique>
+ </xs:element>
+ <xs:element name="defaultOutputDevice" type="xs:token" minOccurs="0"/>
+ <xs:element name="mixPorts" type="mixPorts" minOccurs="0"/>
+ <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
+ <xs:element name="routes" type="routes" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="halVersion" type="halVersion" use="required"/>
+ </xs:complexType>
+ <xs:unique name="mixPortNameUniqueness">
+ <xs:selector xpath="mixPorts/mixPort"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ <xs:key name="devicePortNameKey">
+ <xs:selector xpath="devicePorts/devicePort"/>
+ <xs:field xpath="@tagName"/>
+ </xs:key>
+ <xs:unique name="devicePortUniqueness">
+ <xs:selector xpath="devicePorts/devicePort"/>
+ <xs:field xpath="@type"/>
+ <xs:field xpath="@address"/>
+ </xs:unique>
+ <xs:keyref name="defaultOutputDeviceRef" refer="devicePortNameKey">
+ <xs:selector xpath="defaultOutputDevice"/>
+ <xs:field xpath="."/>
+ </xs:keyref>
+ <xs:keyref name="attachedDeviceRef" refer="devicePortNameKey">
+ <xs:selector xpath="attachedDevices/item"/>
+ <xs:field xpath="."/>
+ </xs:keyref>
+ <!-- The following 3 constraints try to make sure each sink port
+ is reference in one an only one route. -->
+ <xs:key name="routeSinkKey">
+ <!-- predicate [@type='sink'] does not work in xsd 1.0 -->
+ <xs:selector xpath="devicePorts/devicePort|mixPorts/mixPort"/>
+ <xs:field xpath="@tagName|@name"/>
+ </xs:key>
+ <xs:keyref name="routeSinkRef" refer="routeSinkKey">
+ <xs:selector xpath="routes/route"/>
+ <xs:field xpath="@sink"/>
+ </xs:keyref>
+ <xs:unique name="routeUniqueness">
+ <xs:selector xpath="routes/route"/>
+ <xs:field xpath="@sink"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="attachedDevices">
+ <xs:sequence>
+ <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- TODO: separate values by space for better xsd validations. -->
+ <xs:simpleType name="audioInOutFlags">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ "|" separated list of audio_output_flags_t or audio_input_flags_t.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="|[_A-Z]+(\|[_A-Z]+)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="role">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="sink"/>
+ <xs:enumeration value="source"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="mixPorts">
+ <xs:sequence>
+ <xs:element name="mixPort" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="gains" type="gains" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ <xs:attribute name="role" type="role" use="required"/>
+ <xs:attribute name="flags" type="audioInOutFlags"/>
+ <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
+ <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
+ <xs:attribute name="preferredUsage" type="audioUsageList">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ When choosing the mixPort of an audio track, the audioPolicy
+ first considers the mixPorts with a preferredUsage including
+ the track AudioUsage preferred .
+ If non support the track format, the other mixPorts are considered.
+ Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
+ the audio of all apps playing with a MEDIA usage.
+ It may receive audio from ALARM if there are no audio compatible
+ <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ <xs:unique name="mixPortProfileUniqueness">
+ <xs:selector xpath="profile"/>
+ <xs:field xpath="format"/>
+ <xs:field xpath="samplingRate"/>
+ <xs:field xpath="channelMasks"/>
+ </xs:unique>
+ <xs:unique name="mixPortGainUniqueness">
+ <xs:selector xpath="gains/gain"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="audioDevice">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_DEVICE_NONE"/>
+
+ <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_HEARING_AID"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_ECHO_CANCELLER"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+ <xs:enumeration value="AUDIO_DEVICE_OUT_STUB"/>
+
+ <!-- Due to the xml format, IN types can not be a separated from OUT types -->
+ <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_ARC"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+ <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="vendorExtension">
+ <!-- Vendor extension names must be prefixed by "VX_" to distinguish them from AOSP values.
+ Vendor are encouraged to namespace their module names to avoid conflicts.
+ Example for an hypothetical Google virtual reality device:
+ <devicePort tagName="VR" type="VX_GOOGLE_VR" role="sink">
+ -->
+ <xs:restriction base="xs:string">
+ <xs:pattern value="VX_[_a-zA-Z0-9]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="extendableAudioDevice">
+ <xs:union memberTypes="audioDevice vendorExtension"/>
+ </xs:simpleType>
+ <xs:simpleType name="audioFormat">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
+ <xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_8_24_BIT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_FLOAT"/>
+ <xs:enumeration value="AUDIO_FORMAT_PCM_24_BIT_PACKED"/>
+ <xs:enumeration value="AUDIO_FORMAT_MP3"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_NB"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_WB"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_MAIN"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_SSR"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LTP"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_SCALABLE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ERLC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ELD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_MAIN"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SSR"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LTP"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SCALABLE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ERLC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ELD"/>
+ <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS_HD"/>
+ <xs:enumeration value="AUDIO_FORMAT_IEC61937"/>
+ <xs:enumeration value="AUDIO_FORMAT_DOLBY_TRUEHD"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRC"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCB"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCWB"/>
+ <xs:enumeration value="AUDIO_FORMAT_EVRCNW"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADIF"/>
+ <xs:enumeration value="AUDIO_FORMAT_WMA"/>
+ <xs:enumeration value="AUDIO_FORMAT_WMA_PRO"/>
+ <xs:enumeration value="AUDIO_FORMAT_AMR_WB_PLUS"/>
+ <xs:enumeration value="AUDIO_FORMAT_MP2"/>
+ <xs:enumeration value="AUDIO_FORMAT_QCELP"/>
+ <xs:enumeration value="AUDIO_FORMAT_DSD"/>
+ <xs:enumeration value="AUDIO_FORMAT_FLAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_ALAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_APE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS"/>
+ <xs:enumeration value="AUDIO_FORMAT_SBC"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+ <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
+ <xs:enumeration value="AUDIO_FORMAT_E_AC3_JOC"/>
+ <xs:enumeration value="AUDIO_FORMAT_MAT_1_0"/>
+ <xs:enumeration value="AUDIO_FORMAT_MAT_2_0"/>
+ <xs:enumeration value="AUDIO_FORMAT_MAT_2_1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_XHE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_XHE"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_LC"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_HE_V1"/>
+ <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_HE_V2"/>
+ <xs:enumeration value="AUDIO_FORMAT_CELT"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_ADAPTIVE"/>
+ <xs:enumeration value="AUDIO_FORMAT_LHDC"/>
+ <xs:enumeration value="AUDIO_FORMAT_LHDC_LL"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_TWSP"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="extendableAudioFormat">
+ <xs:union memberTypes="audioFormat vendorExtension"/>
+ </xs:simpleType>
+ <xs:simpleType name="audioUsage">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio usage specifies the intention cased the sound to be played.
+ Please consult frameworks/base/media/java/android/media/AudioAttributes.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
+ <xs:enumeration value="AUDIO_USAGE_MEDIA" />
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+ <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+ <xs:enumeration value="AUDIO_USAGE_ALARM" />
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+ <xs:enumeration value="AUDIO_USAGE_GAME" />
+ <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
+ <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
+ <xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT" />
+ <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
+ <xs:enumeration value="AUDIO_USAGE_SAFETY" />
+ <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioUsageList">
+ <xs:list itemType="audioUsage"/>
+ </xs:simpleType>
+ <xs:simpleType name="audioContentType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio content type expresses the general category of the content.
+ Please consult frameworks/base/media/java/android/media/AudioAttributes.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_UNKNOWN"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+ <xs:simpleType name="samplingRates">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]+(,[0-9]+)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioChannelMask">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio channel mask specifies presence of particular channels.
+ There are two representations:
+ - representation position (traditional discrete channel specification,
+ e.g. "left", "right");
+ - indexed (this is similar to "tracks" in audio mixing, channels
+ are represented using numbers).
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="OUT_MONO"/>
+ <xs:enumeration value="OUT_STEREO"/>
+ <xs:enumeration value="OUT_2POINT1"/>
+ <xs:enumeration value="OUT_2POINT0POINT2"/>
+ <xs:enumeration value="OUT_2POINT1POINT2"/>
+ <xs:enumeration value="OUT_3POINT0POINT2"/>
+ <xs:enumeration value="OUT_3POINT1POINT2"/>
+ <xs:enumeration value="OUT_QUAD"/>
+ <xs:enumeration value="OUT_QUAD_BACK"/>
+ <xs:enumeration value="OUT_QUAD_SIDE"/>
+ <xs:enumeration value="OUT_SURROUND"/>
+ <xs:enumeration value="OUT_PENTA"/>
+ <xs:enumeration value="OUT_5POINT1"/>
+ <xs:enumeration value="OUT_5POINT1POINT2"/>
+ <xs:enumeration value="OUT_5POINT1POINT4"/>
+ <xs:enumeration value="OUT_6POINT1"/>
+ <xs:enumeration value="OUT_7POINT1"/>
+ <xs:enumeration value="OUT_7POINT1POINT2"/>
+ <xs:enumeration value="OUT_7POINT1POINT4"/>
+ <xs:enumeration value="OUT_MONO_HAPTIC_A"/>
+ <xs:enumeration value="OUT_STEREO_HAPTIC_A"/>
+ <xs:enumeration value="OUT_HAPTIC_AB"/>
+ <xs:enumeration value="OUT_MONO_HAPTIC_AB"/>
+ <xs:enumeration value="OUT_STEREO_HAPTIC_AB"/>
+ <xs:enumeration value="IN_MONO"/>
+ <xs:enumeration value="IN_STEREO"/>
+ <xs:enumeration value="IN_FRONT_BACK"/>
+ <xs:enumeration value="IN_6"/>
+ <xs:enumeration value="IN_2POINT0POINT2"/>
+ <xs:enumeration value="IN_2POINT1POINT2"/>
+ <xs:enumeration value="IN_3POINT0POINT2"/>
+ <xs:enumeration value="IN_3POINT1POINT2"/>
+ <xs:enumeration value="IN_5POINT1"/>
+ <xs:enumeration value="IN_VOICE_UPLINK_MONO"/>
+ <xs:enumeration value="IN_VOICE_DNLINK_MONO"/>
+ <xs:enumeration value="IN_VOICE_CALL_MONO"/>
+ <xs:enumeration value="INDEX_MASK_1"/>
+ <xs:enumeration value="INDEX_MASK_2"/>
+ <xs:enumeration value="INDEX_MASK_3"/>
+ <xs:enumeration value="INDEX_MASK_4"/>
+ <xs:enumeration value="INDEX_MASK_5"/>
+ <xs:enumeration value="INDEX_MASK_6"/>
+ <xs:enumeration value="INDEX_MASK_7"/>
+ <xs:enumeration value="INDEX_MASK_8"/>
+ <xs:enumeration value="INDEX_MASK_9"/>
+ <xs:enumeration value="INDEX_MASK_10"/>
+ <xs:enumeration value="INDEX_MASK_11"/>
+ <xs:enumeration value="INDEX_MASK_12"/>
+ <xs:enumeration value="INDEX_MASK_13"/>
+ <xs:enumeration value="INDEX_MASK_14"/>
+ <xs:enumeration value="INDEX_MASK_15"/>
+ <xs:enumeration value="INDEX_MASK_16"/>
+ <xs:enumeration value="INDEX_MASK_17"/>
+ <xs:enumeration value="INDEX_MASK_18"/>
+ <xs:enumeration value="INDEX_MASK_19"/>
+ <xs:enumeration value="INDEX_MASK_20"/>
+ <xs:enumeration value="INDEX_MASK_21"/>
+ <xs:enumeration value="INDEX_MASK_22"/>
+ <xs:enumeration value="INDEX_MASK_23"/>
+ <xs:enumeration value="INDEX_MASK_24"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+ <xs:simpleType name="channelMask">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Comma (",") separated list of channel flags
+ from audio_channel_mask_t.
+ </xs:documentation>
+ </xs:annotation>
+ <!-- Need to use audioChannelMask -->
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[_A-Z][_A-Z0-9]*(,[_A-Z][_A-Z0-9]*)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="profile">
+ <xs:attribute name="name" type="xs:token" use="optional"/>
+ <xs:attribute name="format" type="extendableAudioFormat" use="optional"/>
+ <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+ <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
+ </xs:complexType>
+ <xs:simpleType name="gainMode">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_GAIN_MODE_JOINT"/>
+ <xs:enumeration value="AUDIO_GAIN_MODE_CHANNELS"/>
+ <xs:enumeration value="AUDIO_GAIN_MODE_RAMP"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="gains">
+ <xs:sequence>
+ <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ <xs:attribute name="mode" type="gainMode" use="required"/>
+ <xs:attribute name="channel_mask" type="channelMask" use="optional"/>
+ <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="maxValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="defaultValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
+ <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
+ <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+ <xs:attribute name="useForVolume" type="xs:boolean" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="devicePorts">
+ <xs:sequence>
+ <xs:element name="devicePort" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="gains" type="gains" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="tagName" type="xs:token" use="required"/>
+ <xs:attribute name="type" type="extendableAudioDevice" use="required"/>
+ <xs:attribute name="role" type="role" use="required"/>
+ <xs:attribute name="address" type="xs:string" use="optional" default=""/>
+ <!-- Note that XSD 1.0 can not check that a type only has one default. -->
+ <xs:attribute name="default" type="xs:boolean" use="optional">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ The default device will be used if multiple have the same type
+ and no explicit route request exists for a specific device of
+ that type.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="encodedFormats" type="audioFormatsList" use="optional"
+ default="" />
+ </xs:complexType>
+ <xs:unique name="devicePortProfileUniqueness">
+ <xs:selector xpath="profile"/>
+ <xs:field xpath="format"/>
+ <xs:field xpath="samplingRate"/>
+ <xs:field xpath="channelMasks"/>
+ </xs:unique>
+ <xs:unique name="devicePortGainUniqueness">
+ <xs:selector xpath="gains/gain"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="mixType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="mix"/>
+ <xs:enumeration value="mux"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="routes">
+ <xs:sequence>
+ <xs:element name="route" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ List all available sources for a given sink.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="type" type="mixType" use="required"/>
+ <xs:attribute name="sink" type="xs:string" use="required"/>
+ <xs:attribute name="sources" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="volumes">
+ <xs:sequence>
+ <xs:element name="volume" type="volume" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="reference" type="reference" minOccurs="0" maxOccurs="unbounded">
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <!-- TODO: Always require a ref for better xsd validations.
+ Currently a volume could have no points nor ref
+ as it can not be forbidden by xsd 1.0.-->
+ <xs:simpleType name="volumePoint">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Comma separated pair of number.
+ The fist one is the framework level (between 0 and 100).
+ The second one is the volume to send to the HAL.
+ The framework will interpolate volumes not specified.
+ Their MUST be at least 2 points specified.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioStreamType">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Audio stream type describing the intended use case of a stream.
+ Please consult frameworks/base/media/java/android/media/AudioSystem.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <!-- Do we need DEFAULT? -->
+ <xs:enumeration value="AUDIO_STREAM_DEFAULT"/>
+ <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+ <xs:enumeration value="AUDIO_STREAM_RING"/>
+ <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+ <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+ <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+ <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+ <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+ <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+ <xs:enumeration value="AUDIO_STREAM_TTS"/>
+ <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+ <xs:enumeration value="AUDIO_STREAM_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_STREAM_REROUTING"/>
+ <xs:enumeration value="AUDIO_STREAM_PATCH"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="audioSource">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ An audio source defines both a default physical source of audio
+ signal and a recording configuration.
+ Please consult frameworks/base/media/java/android/media/MediaRecorder.java
+ for the description of each value.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <!-- Do we need DEFAULT? -->
+ <xs:enumeration value="AUDIO_SOURCE_DEFAULT"/>
+ <xs:enumeration value="AUDIO_SOURCE_MIC"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_UPLINK"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_DOWNLINK"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_CALL"/>
+ <xs:enumeration value="AUDIO_SOURCE_CAMCORDER"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_RECOGNITION"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_COMMUNICATION"/>
+ <xs:enumeration value="AUDIO_SOURCE_REMOTE_SUBMIX"/>
+ <xs:enumeration value="AUDIO_SOURCE_UNPROCESSED"/>
+ <xs:enumeration value="AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+ <xs:enumeration value="AUDIO_SOURCE_ECHO_REFERENCE"/>
+ <xs:enumeration value="AUDIO_SOURCE_FM_TUNER"/>
+ <xs:enumeration value="AUDIO_SOURCE_HOTWORD"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <!-- Enum values of device_category from Volume.h. -->
+ <xs:simpleType name="deviceCategory">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+ <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+ <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+ <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+ <xs:enumeration value="DEVICE_CATEGORY_HEARING_AID"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="volume">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Volume section defines a volume curve for a given use case and device category.
+ It contains a list of points of this curve expressing the attenuation in Millibels
+ for a given volume index from 0 to 100.
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-9600</point>
+ <point>100,0</point>
+ </volume>
+
+ It may also reference a reference/@name to avoid duplicating curves.
+ <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+ ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+ <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+ <point>0,-9600</point>
+ <point>100,0</point>
+ </reference>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="stream" type="audioStreamType"/>
+ <xs:attribute name="deviceCategory" type="deviceCategory"/>
+ <xs:attribute name="ref" type="xs:token" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="reference">
+ <xs:sequence>
+ <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:token" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="surroundSound">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Surround Sound section provides configuration related to handling of
+ multi-channel formats.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="formats" type="surroundFormats"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="audioFormatsList">
+ <xs:list itemType="audioFormat" />
+ </xs:simpleType>
+ <xs:complexType name="surroundFormats">
+ <xs:sequence>
+ <xs:element name="format" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="audioFormat" use="required"/>
+ <xs:attribute name="subformats" type="audioFormatsList" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="engineSuffix">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="configurable"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
diff --git a/tests/resources/group.xml b/tests/resources/group.xml
index 9a51ab6..6e9f45d 100644
--- a/tests/resources/group.xml
+++ b/tests/resources/group.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<Student>
- <State>CA</State>
- <city>Mountain View</city>
- <road>Street 101</road>
+<Student version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <State>CA</State>
+ <city>Mountain View</city>
+ <xi:include href="group2.xml"/>
</Student>
diff --git a/tests/resources/group/Android.bp b/tests/resources/group/Android.bp
index 21e7242..6560ffd 100644
--- a/tests/resources/group/Android.bp
+++ b/tests/resources/group/Android.bp
@@ -1,7 +1,11 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_group_tests",
srcs: ["group.xsd"],
package_name: "group",
+ gen_writer: true,
}
-
diff --git a/tests/resources/group/address.xsd b/tests/resources/group/address.xsd
new file mode 100644
index 0000000..6fc075c
--- /dev/null
+++ b/tests/resources/group/address.xsd
@@ -0,0 +1,8 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="attr_group_simple" elementFormDefault="qualified">
+ <xs:group name="address1">
+ <xs:sequence>
+ <xs:element name="State" type="xs:string"/>
+ <xs:element name="city" type="xs:string"/>
+ </xs:sequence>
+ </xs:group>
+</xs:schema>
diff --git a/tests/resources/group/api/current.txt b/tests/resources/group/api/current.txt
index c79d293..4a0c206 100644
--- a/tests/resources/group/api/current.txt
+++ b/tests/resources/group/api/current.txt
@@ -18,5 +18,11 @@ package group {
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(java.io.PrintWriter);
+ method public void close();
+ method public static void write(group.XmlWriter, group.Student) throws java.io.IOException;
+ }
+
}
diff --git a/tests/resources/group/group.xsd b/tests/resources/group/group.xsd
index 2bef1a3..3e96834 100644
--- a/tests/resources/group/group.xsd
+++ b/tests/resources/group/group.xsd
@@ -1,10 +1,5 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="attr_group_simple" elementFormDefault="qualified">
- <xs:group name="address1">
- <xs:sequence>
- <xs:element name="State" type="xs:string"/>
- <xs:element name="city" type="xs:string"/>
- </xs:sequence>
- </xs:group>
+ <xs:include schemaLocation="address.xsd" />
<xs:group name="address2" ref="address1">
<xs:sequence>
<xs:element name="road" type="xs:string"/>
diff --git a/tests/resources/group2.xml b/tests/resources/group2.xml
new file mode 100644
index 0000000..c7bc0d3
--- /dev/null
+++ b/tests/resources/group2.xml
@@ -0,0 +1 @@
+<road>Street 101</road>
diff --git a/tests/resources/nested_type/Android.bp b/tests/resources/nested_type/Android.bp
index b228879..15140fb 100644
--- a/tests/resources/nested_type/Android.bp
+++ b/tests/resources/nested_type/Android.bp
@@ -1,7 +1,11 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_nested_type_tests",
srcs: ["nested_type.xsd"],
package_name: "nested.type",
+ gen_writer: true,
}
-
diff --git a/tests/resources/nested_type/api/current.txt b/tests/resources/nested_type/api/current.txt
index a655437..cd75080 100644
--- a/tests/resources/nested_type/api/current.txt
+++ b/tests/resources/nested_type/api/current.txt
@@ -49,5 +49,11 @@ package nested.type {
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(java.io.PrintWriter);
+ method public void close();
+ method public static void write(nested.type.XmlWriter, nested.type.Employee) throws java.io.IOException;
+ }
+
}
diff --git a/tests/resources/predefined_types.xml b/tests/resources/predefined_types.xml
index 7c4cf1b..9c24542 100644
--- a/tests/resources/predefined_types.xml
+++ b/tests/resources/predefined_types.xml
@@ -46,7 +46,7 @@
<anyURI>https://www.google.com</anyURI>
<base64Binary>Z29vZ2xl</base64Binary>
<boolean>true</boolean>
- <hexBinary>516a75cb56d7e7</hexBinary>
+ <hexBinary>016a75cb56d7e7</hexBinary>
<QName>abcd</QName>
<IDREF>abcd</IDREF>
<IDREFS>abcd abcd</IDREFS>
diff --git a/tests/resources/predefined_types/Android.bp b/tests/resources/predefined_types/Android.bp
index 8501f1a..05f2ae0 100644
--- a/tests/resources/predefined_types/Android.bp
+++ b/tests/resources/predefined_types/Android.bp
@@ -1,7 +1,11 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_predefined_types_tests",
srcs: ["predefined_types.xsd"],
package_name: "predefined.types",
+ gen_writer: true,
}
-
diff --git a/tests/resources/predefined_types/api/current.txt b/tests/resources/predefined_types/api/current.txt
index 5b7f393..e7141d3 100644
--- a/tests/resources/predefined_types/api/current.txt
+++ b/tests/resources/predefined_types/api/current.txt
@@ -23,6 +23,12 @@ package predefined.types {
method public void setTime(javax.xml.datatype.XMLGregorianCalendar);
}
+ public class HexBinaryHelper {
+ ctor public HexBinaryHelper();
+ method public static String byteArrayToHexString(byte[]);
+ method public static byte[] hexStringToByteArray(String);
+ }
+
public class ListPrimitiveTypes {
ctor public ListPrimitiveTypes();
method public java.util.List<java.lang.Boolean> getListBoolean();
@@ -46,7 +52,7 @@ package predefined.types {
method public String getAnyType();
method public String getAnyURI();
method public byte[] getBase64Binary();
- method public java.math.BigInteger getHexBinary();
+ method public byte[] getHexBinary();
method public String getIDREF();
method public java.util.List<java.lang.String> getIDREFS();
method public String getQName();
@@ -56,7 +62,7 @@ package predefined.types {
method public void setAnyType(String);
method public void setAnyURI(String);
method public void setBase64Binary(byte[]);
- method public void setHexBinary(java.math.BigInteger);
+ method public void setHexBinary(byte[]);
method public void setIDREF(String);
method public void setIDREFS(java.util.List<java.lang.String>);
method public void setQName(String);
@@ -144,5 +150,11 @@ package predefined.types {
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(java.io.PrintWriter);
+ method public void close();
+ method public static void write(predefined.types.XmlWriter, predefined.types.Types) throws java.io.IOException;
+ }
+
}
diff --git a/tests/resources/purchase_simple/Android.bp b/tests/resources/purchase_simple/Android.bp
index a607e25..0773cb8 100644
--- a/tests/resources/purchase_simple/Android.bp
+++ b/tests/resources/purchase_simple/Android.bp
@@ -1,7 +1,11 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_purchase_simple_tests",
srcs: ["purchase_simple.xsd"],
package_name: "purchase.simple",
+ gen_writer: true,
}
-
diff --git a/tests/resources/purchase_simple/api/current.txt b/tests/resources/purchase_simple/api/current.txt
index c7a455e..eb138a8 100644
--- a/tests/resources/purchase_simple/api/current.txt
+++ b/tests/resources/purchase_simple/api/current.txt
@@ -33,5 +33,11 @@ package purchase.simple {
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(java.io.PrintWriter);
+ method public void close();
+ method public static void write(purchase.simple.XmlWriter, purchase.simple.PurchaseOrderType) throws java.io.IOException;
+ }
+
}
diff --git a/tests/resources/reference/Android.bp b/tests/resources/reference/Android.bp
index 842b236..b0e7bca 100644
--- a/tests/resources/reference/Android.bp
+++ b/tests/resources/reference/Android.bp
@@ -1,7 +1,12 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_reference_tests",
srcs: ["reference.xsd"],
package_name: "reference",
+ gen_writer: true,
+ nullability: true,
}
-
diff --git a/tests/resources/reference/api/current.txt b/tests/resources/reference/api/current.txt
index 1ef6ee5..e33fb20 100644
--- a/tests/resources/reference/api/current.txt
+++ b/tests/resources/reference/api/current.txt
@@ -3,16 +3,22 @@ package reference {
public class Class {
ctor public Class();
- method public String getName();
- method public java.util.List<java.lang.String> getStudent();
- method public void setName(String);
+ method @Nullable public String getName();
+ method @Nullable public java.util.List<java.lang.String> getStudent();
+ method public void setName(@Nullable String);
}
public class XmlParser {
ctor public XmlParser();
- method public static reference.Class read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method @Nullable public static reference.Class read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(@NonNull java.io.PrintWriter);
+ method public void close();
+ method public static void write(@NonNull reference.XmlWriter, @NonNull reference.Class) throws java.io.IOException;
}
}
diff --git a/tests/resources/simple_complex_content.xml b/tests/resources/simple_complex_content.xml
index 06c590f..2f18161 100644
--- a/tests/resources/simple_complex_content.xml
+++ b/tests/resources/simple_complex_content.xml
@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<person>
<name>Petr</name>
- <shoeSize sizing="Korea">265</shoeSize>
- <generalPrice currency="dollar">1234.56</generalPrice>
<USAddressP>
<name>404</name>
<street>street fighter</street>
diff --git a/tests/resources/simple_complex_content/Android.bp b/tests/resources/simple_complex_content/Android.bp
index 34c5300..00502cb 100644
--- a/tests/resources/simple_complex_content/Android.bp
+++ b/tests/resources/simple_complex_content/Android.bp
@@ -1,7 +1,12 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_simple_complex_content_tests",
srcs: ["simple_complex_content.xsd"],
package_name: "simple.complex.content",
+ gen_writer: true,
+ gen_has: true,
}
-
diff --git a/tests/resources/simple_complex_content/api/current.txt b/tests/resources/simple_complex_content/api/current.txt
index 8ca1793..043fb50 100644
--- a/tests/resources/simple_complex_content/api/current.txt
+++ b/tests/resources/simple_complex_content/api/current.txt
@@ -6,6 +6,9 @@ package simple.complex.content {
method @Deprecated public String getCity();
method @Deprecated public final String getName();
method @Deprecated public String getStreet();
+ method @Deprecated public boolean hasCity();
+ method @Deprecated public boolean hasName();
+ method @Deprecated public boolean hasStreet();
method @Deprecated public void setCity(String);
method @Deprecated public final void setName(String);
method @Deprecated public void setStreet(String);
@@ -21,6 +24,10 @@ package simple.complex.content {
method public String getName();
method public simple.complex.content.SubAddress getSubAddress();
method public simple.complex.content.USAddressP getUSAddressP();
+ method public boolean hasKRAddress();
+ method public boolean hasName();
+ method public boolean hasSubAddress();
+ method public boolean hasUSAddressP();
method public void setKRAddress(simple.complex.content.KRAddress);
method public void setName(String);
method public void setSubAddress(simple.complex.content.SubAddress);
@@ -33,6 +40,10 @@ package simple.complex.content {
method public String getName();
method @NonNull public simple.complex.content.SubAddress getSubAddress();
method public simple.complex.content.USAddressP getUSAddressP();
+ method public boolean hasKRAddress();
+ method public boolean hasName();
+ method public boolean hasSubAddress();
+ method public boolean hasUSAddressP();
method public void setKRAddress(simple.complex.content.KRAddress);
method public void setName(String);
method public void setSubAddress(@NonNull simple.complex.content.SubAddress);
@@ -43,6 +54,8 @@ package simple.complex.content {
ctor public SubAddress();
method @Nullable public final String getChoice1_optional();
method @NonNull public final String getChoice2_optional();
+ method public boolean hasChoice1_optional();
+ method public boolean hasChoice2_optional();
method public final void setChoice1_optional(@Nullable String);
method public final void setChoice2_optional(@NonNull String);
}
@@ -51,6 +64,8 @@ package simple.complex.content {
ctor public USAddressP();
method public String getState();
method public java.math.BigInteger getZipcode();
+ method public boolean hasState();
+ method public boolean hasZipcode();
method public void setState(String);
method public void setZipcode(java.math.BigInteger);
}
@@ -63,5 +78,12 @@ package simple.complex.content {
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(java.io.PrintWriter);
+ method public void close();
+ method public static void write(simple.complex.content.XmlWriter, simple.complex.content.Person) throws java.io.IOException;
+ method public static void write(simple.complex.content.XmlWriter, simple.complex.content.Person2) throws java.io.IOException;
+ }
+
}
diff --git a/tests/resources/simple_type/Android.bp b/tests/resources/simple_type/Android.bp
index fba259f..b4be8d4 100644
--- a/tests/resources/simple_type/Android.bp
+++ b/tests/resources/simple_type/Android.bp
@@ -1,7 +1,30 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
xsd_config {
name: "xsdc_simple_type_tests",
srcs: ["simple_type.xsd"],
package_name: "simple.type",
+ gen_writer: true,
+ boolean_getter: true,
}
+xsd_config {
+ name: "xsdc_simple_type_tests_enums",
+ srcs: ["simple_type.xsd"],
+ package_name: "simple.type",
+ enums_only: true,
+ gen_writer: true,
+ boolean_getter: true,
+}
+
+xsd_config {
+ name: "xsdc_simple_type_tests_parser",
+ srcs: ["simple_type.xsd"],
+ package_name: "simple.type",
+ parser_only: true,
+ gen_writer: true,
+ boolean_getter: true,
+}
diff --git a/tests/resources/simple_type/api/current.txt b/tests/resources/simple_type/api/current.txt
index e61f1fa..0b163a5 100644
--- a/tests/resources/simple_type/api/current.txt
+++ b/tests/resources/simple_type/api/current.txt
@@ -20,6 +20,12 @@ package simple.type {
method public java.util.List<java.lang.Integer> getListInt();
method public java.util.List<java.lang.String> getUnionTest();
method public java.util.List<simple.type.EnumType> getYesOrNo();
+ method public boolean isExample1();
+ method public boolean isExample2();
+ method public boolean isExample3();
+ method public void setExample1(boolean);
+ method public void setExample2(boolean);
+ method public void setExample3(boolean);
method public void setListInt(java.util.List<java.lang.Integer>);
method public void setUnionTest(java.util.List<java.lang.String>);
}
@@ -43,5 +49,13 @@ package simple.type {
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
+ public class XmlWriter implements java.io.Closeable {
+ ctor public XmlWriter(java.io.PrintWriter);
+ method public void close();
+ method public static void write(simple.type.XmlWriter, simple.type.SimpleTypes) throws java.io.IOException;
+ method public static void write(simple.type.XmlWriter, simple.type.MultiChoice) throws java.io.IOException;
+ method public static void write(simple.type.XmlWriter, simple.type.SingleChoice) throws java.io.IOException;
+ }
+
}
diff --git a/tests/resources/simple_type/simple_type.xsd b/tests/resources/simple_type/simple_type.xsd
index 23a46b4..481c476 100644
--- a/tests/resources/simple_type/simple_type.xsd
+++ b/tests/resources/simple_type/simple_type.xsd
@@ -31,7 +31,10 @@
<xs:element name="listInt" type="restrictedInts"/>
<xs:element name="union-test" type="unionOfListAndInteger"/>
<xs:element name="yesOrNo" type="enumType" maxOccurs="2"/>
+ <xs:element name="example1" type="xs:boolean"/>
+ <xs:element name="example2" type="xs:boolean"/>
</xs:sequence>
+ <xs:attribute name="example3" type="xs:boolean"/>
</xs:complexType>
</xs:element>
<xs:element name="multi-choice">
diff --git a/tests/simple_type.cpp b/tests/simple_type.cpp
new file mode 100644
index 0000000..5162c6d
--- /dev/null
+++ b/tests/simple_type.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <android-base/macros.h>
+
+#include "simple_type.h"
+#include "xmltest.h"
+
+using namespace std;
+
+TEST_F(XmlTest, Simpletype) {
+ using namespace simple::type;
+ for (const auto v : android::xsdc_enum_range<EnumType>()) {
+ EXPECT_NE(v, EnumType::UNKNOWN);
+ EXPECT_EQ(stringToEnumType(toString(v)), v);
+ }
+
+ string file_name = Resource("simple_type.xml");
+ SimpleTypes simple = *readSimpleTypes(file_name.c_str());
+
+ for (int i = 0; i < simple.getListInt().size(); ++i) {
+ EXPECT_EQ(simple.getListInt()[i], i + 1);
+ }
+ EXPECT_EQ(*simple.getFirstUnionTest(), "100");
+ EXPECT_EQ(simple.getYesOrNo()[0], EnumType::YES);
+ EXPECT_EQ(simple.getYesOrNo()[1], EnumType::EMPTY);
+ ofstream out("old_simple_type.xml");
+ write(out, simple);
+ SimpleTypes simple2 = *readSimpleTypes("old_simple_type.xml");
+ for (int i = 0; i < simple.getListInt().size(); ++i) {
+ EXPECT_EQ(simple.getListInt()[i], simple2.getListInt()[i]);
+ }
+ EXPECT_EQ(*simple.getFirstUnionTest(), *simple2.getFirstUnionTest());
+ EXPECT_EQ(simple.getYesOrNo()[0], simple2.getYesOrNo()[0]);
+ EXPECT_EQ(simple.getYesOrNo()[1], simple2.getYesOrNo()[1]);
+}
diff --git a/tests/simple_type_enumsonly.cpp b/tests/simple_type_enumsonly.cpp
new file mode 100644
index 0000000..b083a6c
--- /dev/null
+++ b/tests/simple_type_enumsonly.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <android-base/macros.h>
+
+#include "simple_type_enums.h"
+#include "xmltest.h"
+
+TEST_F(XmlTest, SimpletypeEnumsOnly) {
+ using namespace simple::type;
+ for (const auto v : android::xsdc_enum_range<EnumType>()) {
+ EXPECT_NE(v, EnumType::UNKNOWN);
+ EXPECT_EQ(stringToEnumType(toString(v)), v);
+ }
+}
diff --git a/tests/src/com/android/xsdc/tests/TestCompilationResult.java b/tests/src/com/android/xsdc/tests/TestCompilationResult.java
deleted file mode 100644
index 840fc37..0000000
--- a/tests/src/com/android/xsdc/tests/TestCompilationResult.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.tests;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-class TestCompilationResult {
- private static class ByteArrayClassLoader extends ClassLoader {
- private Map<String, byte[]> codeMap;
-
- ByteArrayClassLoader(List<TestHelper.InMemoryJavaClassObject> objects) {
- super();
- codeMap = new HashMap<>();
- for (TestHelper.InMemoryJavaClassObject object : objects) {
- codeMap.put(object.getClassName(), object.getBytes());
- }
- }
-
- @Override
- protected Class findClass(String name) throws ClassNotFoundException {
- byte[] code = codeMap.get(name);
- return defineClass(name, code, 0, code.length);
- }
- }
-
- private Map<String, Class<?>> classes;
-
- TestCompilationResult(List<TestHelper.InMemoryJavaClassObject> objects)
- throws ClassNotFoundException {
- ByteArrayClassLoader loader = new ByteArrayClassLoader(objects);
- classes = new HashMap<>();
-
- for (TestHelper.InMemoryJavaClassObject object : objects) {
- Class<?> cls = loader.loadClass(object.getClassName());
- classes.put(object.getClassName(), cls);
- }
- }
-
- Class<?> loadClass(String name) {
- return classes.get(TestHelper.packageName + "." + name);
- }
-}
diff --git a/tests/src/com/android/xsdc/tests/TestHelper.java b/tests/src/com/android/xsdc/tests/TestHelper.java
deleted file mode 100644
index c801dc8..0000000
--- a/tests/src/com/android/xsdc/tests/TestHelper.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.tests;
-
-import com.android.xsdc.FileSystem;
-import com.android.xsdc.XmlSchema;
-import com.android.xsdc.XsdHandler;
-import com.android.xsdc.java.JavaCodeGenerator;
-
-import javax.tools.*;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import java.io.*;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import static org.junit.Assert.fail;
-
-class TestHelper {
- static class InMemoryJavaFileObject extends SimpleJavaFileObject {
- private final String contents;
-
- InMemoryJavaFileObject(String className, String contents) {
- super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension),
- Kind.SOURCE);
- this.contents = contents;
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return contents;
- }
- }
-
- static class InMemoryJavaClassObject extends SimpleJavaFileObject {
- private ByteArrayOutputStream baos;
- private String name;
-
- InMemoryJavaClassObject(String name, Kind kind) {
- super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind);
- baos = new ByteArrayOutputStream();
- this.name = name;
- }
-
- byte[] getBytes() {
- return baos.toByteArray();
- }
-
- @Override
- public OutputStream openOutputStream() {
- return baos;
- }
-
- String getClassName() {
- return name;
- }
- }
-
- static class InMemoryClassManager extends ForwardingJavaFileManager<JavaFileManager> {
- private List<InMemoryJavaClassObject> classObjects;
-
- InMemoryClassManager(JavaFileManager fileManager) {
- super(fileManager);
- classObjects = new ArrayList<>();
- }
-
- @Override
- public JavaFileObject getJavaFileForOutput(Location location, String name,
- JavaFileObject.Kind kind, FileObject sibling) {
- InMemoryJavaClassObject object = new InMemoryJavaClassObject(name, kind);
- classObjects.add(object);
- return object;
- }
-
- List<InMemoryJavaClassObject> getAllClasses() {
- return classObjects;
- }
- }
-
- final static String packageName = "test";
-
- static TestCompilationResult parseXsdAndCompile(InputStream in) throws Exception {
- SAXParserFactory factory = SAXParserFactory.newInstance();
- factory.setNamespaceAware(true);
- SAXParser parser = factory.newSAXParser();
- XsdHandler xsdHandler = new XsdHandler();
- parser.parse(in, xsdHandler);
- XmlSchema xmlSchema = xsdHandler.getSchema();
- Map<String, StringBuffer> fileOutputMap = new HashMap<>();
- FileSystem fs = new FileSystem(fileOutputMap);
- JavaCodeGenerator javaCodeGenerator = new JavaCodeGenerator(xmlSchema, packageName);
- javaCodeGenerator.print(fs);
- List<JavaFileObject> javaFileObjects = new ArrayList<>();
- for (Map.Entry<String, StringBuffer> entry : fileOutputMap.entrySet()) {
- String className = entry.getKey().split("\\.")[0];
- javaFileObjects.add(
- new InMemoryJavaFileObject(className, entry.getValue().toString()));
- }
- return new TestCompilationResult(compile(javaFileObjects));
- }
-
- private static List<InMemoryJavaClassObject> compile(List<JavaFileObject> javaFileObjects)
- throws IOException {
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
- List<InMemoryJavaClassObject> ret = null;
-
- try (InMemoryClassManager fileManager = new InMemoryClassManager(
- compiler.getStandardFileManager(diagnostics, null, null))) {
- JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics,
- null, null, javaFileObjects);
- boolean success = task.call();
-
- if (!success) {
- StringBuilder log = new StringBuilder();
- log.append("Compilation failed!\n\n");
- for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
- log.append("Code: ").append(diagnostic.getCode()).append("\n");
- log.append("Kind: " + diagnostic.getKind() + "\n");
- log.append("Line: " + diagnostic.getLineNumber() + "\n");
- log.append("Column: " + diagnostic.getColumnNumber() + "\n");
- log.append("Source: " + diagnostic.getSource() + "\n");
- log.append("Message: " + diagnostic.getMessage(Locale.getDefault()) + "\n");
- }
- fail(log.toString());
- }
- ret = fileManager.getAllClasses();
- }
- return ret;
- }
-} \ No newline at end of file
diff --git a/tests/src/com/android/xsdc/tests/XmlParserTest.java b/tests/src/com/android/xsdc/tests/XmlParserTest.java
index 0e42f67..f3b5eaf 100644
--- a/tests/src/com/android/xsdc/tests/XmlParserTest.java
+++ b/tests/src/com/android/xsdc/tests/XmlParserTest.java
@@ -33,361 +33,242 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
+
public class XmlParserTest {
@Test
public void testPurchaseSimple() throws Exception {
- TestCompilationResult result;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "purchase_simple/purchase_simple.xsd")) {
- result = TestHelper.parseXsdAndCompile(in);
- }
-
- Class<?> xmlParser = result.loadClass("XmlParser");
- Class<?> purchaseOrderType = result.loadClass("PurchaseOrderType");
- Class<?> usAddress = result.loadClass("USAddress");
-
- Object instance;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
+ purchase.simple.PurchaseOrderType orderType;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
"purchase_simple.xml")) {
- instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in);
+ orderType = purchase.simple.XmlParser.read(str);
}
- Object billTo = purchaseOrderType.getMethod("getBillTo").invoke(instance);
- List shipToList = (List) purchaseOrderType.getMethod("getShipTo").invoke(instance);
-
- String name = (String) usAddress.getMethod("getName").invoke(billTo);
- BigInteger zip = (BigInteger) usAddress.getMethod("getZip").invoke(billTo);
- String street = (String) usAddress.getMethod("getStreet").invoke(shipToList.get(0));
- BigInteger largeZip = (BigInteger) usAddress.getMethod("getZip").invoke(shipToList.get(1));
- XMLGregorianCalendar orderDate = (XMLGregorianCalendar) purchaseOrderType.getMethod(
- "getOrderDate").invoke(instance);
-
- assertThat(name, is("billName"));
- assertThat(zip, is(new BigInteger("1")));
- assertThat(street, is("street1"));
- assertThat(largeZip, is(new BigInteger("-7922816251426433759")));
- assertThat(orderDate,
+
+ assertThat(orderType.getOrderDate(),
is(javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar(
- "1900-01-01")));
+ "1900-01-01")));
+ assertThat(orderType.getBillTo().getName(), is("billName"));
+ assertThat(orderType.getBillTo().getZip(), is(new BigInteger("1")));
+ assertThat(orderType.getShipTo().get(0).getStreet(), is("street1"));
+ assertThat(orderType.getShipTo().get(1).getZip(),
+ is(new BigInteger("-7922816251426433759")));
+
+ String actualStr, expectedStr;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "purchase_simple.xml")) {
+ expectedStr = new String(str.readAllBytes());
+ }
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ try(purchase.simple.XmlWriter writer =
+ new purchase.simple.XmlWriter(new PrintWriter(baos))) {
+ purchase.simple.XmlWriter.write(writer, orderType);
+ }
+ actualStr = new String(baos.toByteArray());
+ }
+
+ assertThat(new String(actualStr), is(expectedStr));
}
@Test
public void testNestedType() throws Exception {
- TestCompilationResult result;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "nested_type/nested_type.xsd")) {
- result = TestHelper.parseXsdAndCompile(in);
- }
-
- Class<?> xmlParser = result.loadClass("XmlParser");
- Class<?> employee = result.loadClass("Employee");
- Class<?> address = result.loadClass("Employee$Address");
- Class<?> extra = result.loadClass("Employee$Address$Extra");
-
- Object instance;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
+ nested.type.Employee employee;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
"nested_type.xml")) {
- instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in);
+ employee = nested.type.XmlParser.read(str);
}
- String name = (String) employee.getMethod("getName").invoke(instance);
- Object addressInstance = employee.getMethod("getAddress").invoke(instance);
- String country = (String) address.getMethod("getCountry").invoke(addressInstance);
- Object extraInstance = address.getMethod("getExtra").invoke(addressInstance);
- String line2 = (String) extra.getMethod("getLine2").invoke(extraInstance);
-
- assertThat(name, is("Peter"));
- assertThat(country, is("US"));
- assertThat(line2, is("Good Street"));
+ assertThat(employee.getName(), is("Peter"));
+ assertThat(employee.getAddress().getCountry(), is("US"));
+ assertThat(employee.getAddress().getExtra().getLine2(), is("Good Street"));
}
@Test
public void testSimpleComplexContent() throws Exception {
- TestCompilationResult result;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "simple_complex_content/simple_complex_content.xsd")) {
- result = TestHelper.parseXsdAndCompile(in);
- }
-
- Class<?> xmlParser = result.loadClass("XmlParser");
- Class<?> person = result.loadClass("Person");
- Class<?> usAddress = result.loadClass("USAddressP");
- Class<?> krAddress = result.loadClass("KRAddress");
-
- Object instance;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
+ simple.complex.content.Person person;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
"simple_complex_content.xml")) {
- instance = xmlParser.getMethod("readPerson", InputStream.class).invoke(null, in);
+ person = simple.complex.content.XmlParser.readPerson(str);
}
- String name = (String) person.getMethod("getName").invoke(instance);
-
- Object usAddressInstance = person.getMethod("getUSAddressP").invoke(instance);
- String usStreet = (String) usAddress.getMethod("getStreet").invoke(usAddressInstance);
- BigInteger usZipcode = (BigInteger) usAddress.getMethod("getZipcode").invoke(
- usAddressInstance);
+ assertThat(person.getName(), is("Petr"));
+ assertThat(person.getUSAddressP().getStreet(), is("street fighter"));
+ assertThat(person.getUSAddressP().getZipcode(), is(new BigInteger("323232318329852")));
+ assertThat(person.getKRAddress().getStreet(), is("Nokdu Street"));
- Object krAddressInstance = person.getMethod("getKRAddress").invoke(instance);
- String krStreet = (String) krAddress.getMethod("getStreet").invoke(krAddressInstance);
+ String actualStr, expectedStr;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "simple_complex_content.xml")) {
+ expectedStr = new String(str.readAllBytes());
+ }
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ try(simple.complex.content.XmlWriter writer =
+ new simple.complex.content.XmlWriter(new PrintWriter(baos))) {
+ simple.complex.content.XmlWriter.write(writer, person);
+ }
+ actualStr = new String(baos.toByteArray());
+ }
- assertThat(name, is("Petr"));
- assertThat(usStreet, is("street fighter"));
- assertThat(usZipcode, is(new BigInteger("323232318329852")));
- assertThat(krStreet, is("Nokdu Street"));
+ assertThat(new String(actualStr), is(expectedStr));
}
@Test
public void testPredefinedTypes() throws Exception {
- TestCompilationResult result;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "predefined_types/predefined_types.xsd")) {
- result = TestHelper.parseXsdAndCompile(in);
- }
-
- Class<?> xmlParser = result.loadClass("XmlParser");
- Class<?> types = result.loadClass("Types");
- Class<?> stringTypes = result.loadClass("StringTypes");
- Class<?> dateTypes = result.loadClass("DateTypes");
- Class<?> numericTypes = result.loadClass("NumericTypes");
- Class<?> miscTypes = result.loadClass("MiscTypes");
- Class<?> listPrimitiveTypes = result.loadClass("ListPrimitiveTypes");
+ predefined.types.Types type;
- Object instance;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
"predefined_types.xml")) {
- instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in);
+ type = predefined.types.XmlParser.read(str);
}
{
- Object stringTypesInstance = types.getMethod("getStringTypes").invoke(instance);
- String string = (String) stringTypes.getMethod("getString").invoke(stringTypesInstance);
- String token = (String) stringTypes.getMethod("getToken").invoke(stringTypesInstance);
- String normalizedString = (String) stringTypes.getMethod("getNormalizedString").invoke(
- stringTypesInstance);
- String language = (String) stringTypes.getMethod("getLanguage").invoke(
- stringTypesInstance);
- String entity = (String) stringTypes.getMethod("getEntity").invoke(stringTypesInstance);
- List entities = (List) stringTypes.getMethod("getEntities").invoke(stringTypesInstance);
- String id = (String) stringTypes.getMethod("getId").invoke(stringTypesInstance);
- String name = (String) stringTypes.getMethod("getName").invoke(stringTypesInstance);
- String ncName = (String) stringTypes.getMethod("getNcname").invoke(stringTypesInstance);
- String nmToken = (String) stringTypes.getMethod("getNmtoken").invoke(
- stringTypesInstance);
- List nmTokens = (List) stringTypes.getMethod("getNmtokens").invoke(stringTypesInstance);
-
- assertThat(string, is("abcd"));
- assertThat(token, is("abcd"));
- assertThat(normalizedString, is("abcd"));
- assertThat(language, is("abcd"));
- assertThat(entity, is("abcd"));
- assertThat(entities, is(Arrays.asList("a", "b", "c", "d")));
- assertThat(id, is("abcd"));
- assertThat(name, is("abcd"));
- assertThat(ncName, is("abcd"));
- assertThat(nmToken, is("abcd"));
- assertThat(nmTokens, is(Arrays.asList("a", "b", "c", "d")));
+ predefined.types.StringTypes stringTypes = type.getStringTypes();
+
+ assertThat(stringTypes.getString(), is("abcd"));
+ assertThat(stringTypes.getToken(), is("abcd"));
+ assertThat(stringTypes.getNormalizedString(), is("abcd"));
+ assertThat(stringTypes.getLanguage(), is("abcd"));
+ assertThat(stringTypes.getEntity(), is("abcd"));
+ assertThat(stringTypes.getEntities(), is(Arrays.asList("a", "b", "c", "d")));
+ assertThat(stringTypes.getId(), is("abcd"));
+ assertThat(stringTypes.getName(), is("abcd"));
+ assertThat(stringTypes.getNcname(), is("abcd"));
+ assertThat(stringTypes.getNmtoken(), is("abcd"));
+ assertThat(stringTypes.getNmtokens(), is(Arrays.asList("a", "b", "c", "d")));
}
{
- Object dateTypesInstance = types.getMethod("getDateTypes").invoke(instance);
- XMLGregorianCalendar date = (XMLGregorianCalendar) dateTypes.getMethod(
- "getDate").invoke(dateTypesInstance);
- XMLGregorianCalendar dateTime = (XMLGregorianCalendar) dateTypes.getMethod(
- "getDateTime").invoke(dateTypesInstance);
- Duration duration = (Duration) dateTypes.getMethod("getDuration").invoke(
- dateTypesInstance);
- XMLGregorianCalendar gDay = (XMLGregorianCalendar) dateTypes.getMethod(
- "getGDay").invoke(dateTypesInstance);
- XMLGregorianCalendar gMonth = (XMLGregorianCalendar) dateTypes.getMethod(
- "getGMonth").invoke(dateTypesInstance);
- XMLGregorianCalendar gMonthDay = (XMLGregorianCalendar) dateTypes.getMethod(
- "getGMonthDay").invoke(dateTypesInstance);
- XMLGregorianCalendar gYear = (XMLGregorianCalendar) dateTypes.getMethod(
- "getGYear").invoke(dateTypesInstance);
- XMLGregorianCalendar gYearMonth = (XMLGregorianCalendar) dateTypes.getMethod(
- "getGYearMonth").invoke(dateTypesInstance);
- XMLGregorianCalendar time = (XMLGregorianCalendar) dateTypes.getMethod(
- "getTime").invoke(dateTypesInstance);
-
+ predefined.types.DateTypes dateTypes = type.getDateTypes();
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
- assertThat(date, is(datatypeFactory.newXMLGregorianCalendar("2018-06-18")));
- assertThat(dateTime,
+
+ assertThat(dateTypes.getDate(),
+ is(datatypeFactory.newXMLGregorianCalendar("2018-06-18")));
+ assertThat(dateTypes.getDateTime(),
is(datatypeFactory.newXMLGregorianCalendar("2018-06-18T21:32:52")));
- assertThat(duration, is(datatypeFactory.newDuration("P3M")));
- assertThat(gDay, is(datatypeFactory.newXMLGregorianCalendar("---18")));
- assertThat(gMonth, is(datatypeFactory.newXMLGregorianCalendar("--06")));
- assertThat(gMonthDay, is(datatypeFactory.newXMLGregorianCalendar("--06-18")));
- assertThat(gYear, is(datatypeFactory.newXMLGregorianCalendar("2018")));
- assertThat(gYearMonth, is(datatypeFactory.newXMLGregorianCalendar("2018-06")));
- assertThat(time, is(datatypeFactory.newXMLGregorianCalendar("21:32:52")));
+ assertThat(dateTypes.getDuration(), is(datatypeFactory.newDuration("P3M")));
+ assertThat(dateTypes.getGDay(), is(datatypeFactory.newXMLGregorianCalendar("---18")));
+ assertThat(dateTypes.getGMonth(), is(datatypeFactory.newXMLGregorianCalendar("--06")));
+ assertThat(dateTypes.getGMonthDay(),
+ is(datatypeFactory.newXMLGregorianCalendar("--06-18")));
+ assertThat(dateTypes.getGYear(), is(datatypeFactory.newXMLGregorianCalendar("2018")));
+ assertThat(dateTypes.getGYearMonth(),
+ is(datatypeFactory.newXMLGregorianCalendar("2018-06")));
+ assertThat(dateTypes.getTime(),
+ is(datatypeFactory.newXMLGregorianCalendar("21:32:52")));
}
-
{
- Object numericTypesInstance = types.getMethod("getNumericTypes").invoke(instance);
- BigDecimal decimal = (BigDecimal) numericTypes.getMethod("getDecimal").invoke(
- numericTypesInstance);
- BigInteger integer = (BigInteger) numericTypes.getMethod("getInteger").invoke(
- numericTypesInstance);
- long _long = (long) numericTypes.getMethod("get_long").invoke(numericTypesInstance);
- int _int = (int) numericTypes.getMethod("get_int").invoke(numericTypesInstance);
- short _short = (short) numericTypes.getMethod("get_short").invoke(numericTypesInstance);
- byte _byte = (byte) numericTypes.getMethod("get_byte").invoke(numericTypesInstance);
- BigInteger negativeInteger = (BigInteger) numericTypes.getMethod(
- "getNegativeInteger").invoke(numericTypesInstance);
- BigInteger nonNegativeInteger = (BigInteger) numericTypes.getMethod(
- "getNonNegativeInteger").invoke(numericTypesInstance);
- BigInteger positiveInteger = (BigInteger) numericTypes.getMethod(
- "getPositiveInteger").invoke(numericTypesInstance);
- BigInteger nonPositiveInteger = (BigInteger) numericTypes.getMethod(
- "getNonPositiveInteger").invoke(numericTypesInstance);
- BigInteger unsignedLong = (BigInteger) numericTypes.getMethod("getUnsignedLong").invoke(
- numericTypesInstance);
- long unsignedInt = (long) numericTypes.getMethod("getUnsignedInt").invoke(
- numericTypesInstance);
- int unsignedShort = (int) numericTypes.getMethod("getUnsignedShort").invoke(
- numericTypesInstance);
- short unsignedByte = (short) numericTypes.getMethod("getUnsignedByte").invoke(
- numericTypesInstance);
-
- assertThat(decimal, is(new BigDecimal("1234.57")));
- assertThat(integer, is(new BigInteger("1234567890123456789")));
- assertThat(_long, is(9223372036854775807L));
- assertThat(_int, is(2147483647));
- assertThat(_short, is((short) 32767));
- assertThat(_byte, is((byte) 127));
- assertThat(negativeInteger, is(new BigInteger("-1234")));
- assertThat(nonNegativeInteger, is(new BigInteger("1234")));
- assertThat(positiveInteger, is(new BigInteger("1234")));
- assertThat(nonPositiveInteger, is(new BigInteger("-1234")));
- assertThat(unsignedLong, is(new BigInteger("1234")));
- assertThat(unsignedInt, is(1234L));
- assertThat(unsignedShort, is(1234));
- assertThat(unsignedByte, is((short) 255));
+ predefined.types.NumericTypes numericTypes = type.getNumericTypes();
+
+ assertThat(numericTypes.getDecimal(), is(new BigDecimal("1234.57")));
+ assertThat(numericTypes.getInteger(), is(new BigInteger("1234567890123456789")));
+ assertThat(numericTypes.get_long(), is(9223372036854775807L));
+ assertThat(numericTypes.get_int(), is(2147483647));
+ assertThat(numericTypes.get_short(), is((short) 32767));
+ assertThat(numericTypes.get_byte(), is((byte) 127));
+ assertThat(numericTypes.getNegativeInteger(), is(new BigInteger("-1234")));
+ assertThat(numericTypes.getNonNegativeInteger(), is(new BigInteger("1234")));
+ assertThat(numericTypes.getPositiveInteger(), is(new BigInteger("1234")));
+ assertThat(numericTypes.getNonPositiveInteger(), is(new BigInteger("-1234")));
+ assertThat(numericTypes.getUnsignedLong(), is(new BigInteger("1234")));
+ assertThat(numericTypes.getUnsignedInt(), is(1234L));
+ assertThat(numericTypes.getUnsignedShort(), is(1234));
+ assertThat(numericTypes.getUnsignedByte(), is((short) 255));
}
{
- Object miscTypesInstance = types.getMethod("getMiscTypes").invoke(instance);
- double _double = (double) miscTypes.getMethod("get_double").invoke(miscTypesInstance);
- float _float = (float) miscTypes.getMethod("get_float").invoke(miscTypesInstance);
- String anyURI = (String) miscTypes.getMethod("getAnyURI").invoke(miscTypesInstance);
- byte[] base64Binary = (byte[]) miscTypes.getMethod("getBase64Binary").invoke(
- miscTypesInstance);
- boolean _boolean = (boolean) miscTypes.getMethod("get_boolean").invoke(
- miscTypesInstance);
- BigInteger hexBinary = (BigInteger) miscTypes.getMethod("getHexBinary").invoke(
- miscTypesInstance);
- String qName = (String) miscTypes.getMethod("getQName").invoke(miscTypesInstance);
- String iDREF = (String) miscTypes.getMethod("getIDREF").invoke(miscTypesInstance);
- List iDREFS = (List) miscTypes.getMethod("getIDREFS").invoke(miscTypesInstance);
- String anyType = (String) miscTypes.getMethod("getAnyType").invoke(miscTypesInstance);
-
- assertThat(_double, is(1234.57));
- assertThat(_float, is(123.4f));
- assertThat(anyURI, is("https://www.google.com"));
- assertThat(base64Binary, is(Base64.getDecoder().decode("Z29vZ2xl")));
- assertThat(_boolean, is(true));
- assertThat(hexBinary, is(new BigInteger("516a75cb56d7e7", 16)));
- assertThat(qName, is("abcd"));
- assertThat(iDREF, is("abcd"));
- assertThat(iDREFS, is(Arrays.asList("abcd", "abcd")));
- assertThat(anyType, is("abcd"));
+ predefined.types.MiscTypes miscTypes = type.getMiscTypes();
+
+ assertThat(miscTypes.get_double(), is(1234.57));
+ assertThat(miscTypes.getAnyURI(), is("https://www.google.com"));
+ assertThat(miscTypes.getBase64Binary(), is(Base64.getDecoder().decode("Z29vZ2xl")));
+ assertThat(miscTypes.get_boolean(), is(true));
+ assertThat(miscTypes.getHexBinary(),
+ is(predefined.types.HexBinaryHelper.hexStringToByteArray("016a75cb56d7e7")));
+ assertThat(miscTypes.getQName(), is("abcd"));
+ assertThat(miscTypes.getIDREF(), is("abcd"));
+ assertThat(miscTypes.getIDREFS(), is(Arrays.asList("abcd", "abcd")));
+ assertThat(miscTypes.getAnyType(), is("abcd"));
}
{
- Object listPrimitiveTypesInstance = types.getMethod("getListPrimitiveTypes").invoke(
- instance);
- List listLong = (List) listPrimitiveTypes.getMethod("getListLong").invoke(
- listPrimitiveTypesInstance);
- List listInt = (List) listPrimitiveTypes.getMethod("getListInt").invoke(
- listPrimitiveTypesInstance);
- List listShort = (List) listPrimitiveTypes.getMethod("getListShort").invoke(
- listPrimitiveTypesInstance);
- List listByte = (List) listPrimitiveTypes.getMethod("getListByte").invoke(
- listPrimitiveTypesInstance);
- List listDouble = (List) listPrimitiveTypes.getMethod("getListDouble").invoke(
- listPrimitiveTypesInstance);
- List listFloat = (List) listPrimitiveTypes.getMethod("getListFloat").invoke(
- listPrimitiveTypesInstance);
- List listBoolean = (List) listPrimitiveTypes.getMethod("getListBoolean").invoke(
- listPrimitiveTypesInstance);
-
- assertThat(listLong, is(Arrays.asList(-9223372036854775808L, 9223372036854775807L)));
- assertThat(listInt, is(Arrays.asList(-2147483648, 2147483647)));
- assertThat(listShort, is(Arrays.asList((short) -32768, (short) 32767)));
- assertThat(listByte, is(Arrays.asList((byte) -128, (byte) 127)));
- assertThat(listDouble, is(Arrays.asList(1234.56, 5678.12)));
- assertThat(listFloat, is(Arrays.asList(123.4f, 456.1f)));
- assertThat(listBoolean, is(Arrays.asList(true, false)));
+ predefined.types.ListPrimitiveTypes listPrimitiveTypes =
+ type.getListPrimitiveTypes();
+
+ assertThat(listPrimitiveTypes.getListLong(),
+ is(Arrays.asList(-9223372036854775808L, 9223372036854775807L)));
+ assertThat(listPrimitiveTypes.getListInt(),
+ is(Arrays.asList(-2147483648, 2147483647)));
+ assertThat(listPrimitiveTypes.getListShort(),
+ is(Arrays.asList((short) -32768, (short) 32767)));
+ assertThat(listPrimitiveTypes.getListByte(),
+ is(Arrays.asList((byte) -128, (byte) 127)));
+ assertThat(listPrimitiveTypes.getListDouble(), is(Arrays.asList(1234.56, 5678.12)));
+ assertThat(listPrimitiveTypes.getListFloat(), is(Arrays.asList(123.4f, 456.1f)));
+ assertThat(listPrimitiveTypes.getListBoolean(), is(Arrays.asList(true, false)));
}
- }
- @Test
- public void testSimpleType() throws Exception {
- TestCompilationResult result;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "simple_type/simple_type.xsd")) {
- result = TestHelper.parseXsdAndCompile(in);
+ String actualStr, expectedStr;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "predefined_types.xml")) {
+ expectedStr = new String(str.readAllBytes());
}
-
- Class<?> xmlParser = result.loadClass("XmlParser");
- Class<?> simpleTypes = result.loadClass("SimpleTypes");
-
- Object instance;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "simple_type.xml")) {
- instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in);
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ try(predefined.types.XmlWriter writer =
+ new predefined.types.XmlWriter(new PrintWriter(baos))) {
+ predefined.types.XmlWriter.write(writer, type);
+ }
+ actualStr = new String(baos.toByteArray());
}
- List listInt = (List) simpleTypes.getMethod("getListInt").invoke(instance);
- List uniontest = (List) simpleTypes.getMethod("getUnionTest").invoke(instance);
-
- assertThat(listInt, is(Arrays.asList(1, 2, 3, 4, 5)));
- assertThat(uniontest, is(Arrays.asList("100")));
+ assertThat(new String(actualStr), is(expectedStr));
}
@Test
- public void testReference() throws Exception {
- TestCompilationResult result;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "reference/reference.xsd")) {
- result = TestHelper.parseXsdAndCompile(in);
+ public void testSimpleType() throws Exception {
+ simple.type.SimpleTypes simples;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "simple_type.xml")) {
+ simples = simple.type.XmlParser.readSimpleTypes(str);
}
- Class<?> xmlParser = result.loadClass("XmlParser");
- Class<?> cls = result.loadClass("Class");
+ assertThat(simples.getListInt(), is(Arrays.asList(1, 2, 3, 4, 5)));
+ assertThat(simples.getUnionTest(), is(Arrays.asList("100")));
- Object instance;
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "reference.xml")) {
- instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in);
+ String actualStr, expectedStr;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "simple_type.xml")) {
+ expectedStr = new String(str.readAllBytes());
+ }
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ try(simple.type.XmlWriter writer = new simple.type.XmlWriter(new PrintWriter(baos))) {
+ simple.type.XmlWriter.write(writer, simples);
+ }
+ actualStr = new String(baos.toByteArray());
}
- List student = (List) cls.getMethod("getStudent").invoke(instance);
-
- assertThat(student, is(Arrays.asList("Sam", "Paul", "Peter")));
+ assertThat(new String(actualStr), is(expectedStr));
}
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
@Test
- public void testUnsupportedTag() throws Exception {
- thrown.expect(SAXException.class);
- thrown.expectMessage("unsupported tag : import");
-
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "unsupported_tag.xsd")) {
- TestHelper.parseXsdAndCompile(in);
+ public void testReference() throws Exception {
+ reference.Class _class;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "reference.xml")) {
+ _class = reference.XmlParser.read(str);
}
- }
- @Test
- public void testUnsupportedAttribute() throws Exception {
- thrown.expect(SAXException.class);
- thrown.expectMessage("substitution group of an element is not supported.");
+ assertThat(_class.getStudent(), is(Arrays.asList("Sam", "Paul", "Peter")));
- try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
- "unsupported_attribute.xsd")) {
- TestHelper.parseXsdAndCompile(in);
+ String actualStr, expectedStr;
+ try (InputStream str = this.getClass().getClassLoader().getResourceAsStream(
+ "reference.xml")) {
+ expectedStr = new String(str.readAllBytes());
}
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ try(reference.XmlWriter writer = new reference.XmlWriter(new PrintWriter(baos))) {
+ reference.XmlWriter.write(writer, _class);
+ }
+ actualStr = new String(baos.toByteArray());
+ }
+
+ assertThat(new String(actualStr), is(expectedStr));
}
}
diff --git a/tests/tests.cpp b/tests/tests.cpp
new file mode 100644
index 0000000..c143f4e
--- /dev/null
+++ b/tests/tests.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <optional>
+
+#include <android-base/macros.h>
+#include <gtest/gtest.h>
+#include "nested_type.h"
+#include "purchase_simple.h"
+#include "simple_complex_content.h"
+
+#include "predefined_types.h"
+#include "reference.h"
+#include "attr_group_simple.h"
+#include "group.h"
+#include "xmltest.h"
+
+using namespace std;
+
+TEST_F(XmlTest, Predefinedtypes) {
+ using namespace predefined::types;
+ Types type = *read(Resource("predefined_types.xml").c_str());
+
+ StringTypes stringTypes = *type.getFirstStringTypes();
+ DateTypes dateTypes = *type.getFirstDateTypes();
+ NumericTypes numericTypes = *type.getFirstNumericTypes();
+ MiscTypes miscTypes = *type.getFirstMiscTypes();
+ ListPrimitiveTypes listPrimitiveTypes = *type.getFirstListPrimitiveTypes();
+
+ EXPECT_EQ(stringTypes.getString(), "abcd");
+ EXPECT_EQ(stringTypes.getToken(), "abcd");
+ EXPECT_EQ(stringTypes.getNormalizedString(), "abcd");
+ EXPECT_EQ(stringTypes.getLanguage(), "abcd");
+ EXPECT_EQ(stringTypes.getEntity(), "abcd");
+ EXPECT_EQ(stringTypes.getEntities()[0], "a");
+ EXPECT_EQ(stringTypes.getEntities()[1], "b");
+ EXPECT_EQ(stringTypes.getEntities()[2], "c");
+ EXPECT_EQ(stringTypes.getEntities()[3], "d");
+ EXPECT_EQ(stringTypes.getId(), "abcd");
+ EXPECT_EQ(stringTypes.getName(), "abcd");
+ EXPECT_EQ(stringTypes.getNcname(), "abcd");
+ EXPECT_EQ(stringTypes.getNmtoken(), "abcd");
+ EXPECT_EQ(stringTypes.getNmtokens()[0], "a");
+ EXPECT_EQ(stringTypes.getNmtokens()[1], "b");
+ EXPECT_EQ(stringTypes.getNmtokens()[2], "c");
+ EXPECT_EQ(stringTypes.getNmtokens()[3], "d");
+
+
+ EXPECT_EQ(dateTypes.getDate(), "2018-06-18");
+ EXPECT_EQ(dateTypes.getDateTime(), "2018-06-18T21:32:52");
+ EXPECT_EQ(dateTypes.getDuration(), "P3M");
+ EXPECT_EQ(dateTypes.getGDay(), "---18");
+ EXPECT_EQ(dateTypes.getGMonth(), "--06");
+ EXPECT_EQ(dateTypes.getGMonthDay(), "--06-18");
+ EXPECT_EQ(dateTypes.getGYear(), "2018");
+ EXPECT_EQ(dateTypes.getGYearMonth(), "2018-06");
+ EXPECT_EQ(dateTypes.getTime(), "21:32:52");
+
+ EXPECT_EQ(numericTypes.getDecimal(), 1234.57);
+ EXPECT_EQ(numericTypes.getInteger(), 1234567890123456789);
+ EXPECT_EQ(numericTypes.get_long(), 9223372036854775807);
+ EXPECT_EQ(numericTypes.get_int(), 2147483647);
+ EXPECT_EQ(numericTypes.get_short(), 32767);
+ EXPECT_EQ((int)numericTypes.getByte(), 127);
+ EXPECT_EQ(numericTypes.getNegativeInteger(), -1234);
+ EXPECT_EQ(numericTypes.getNonNegativeInteger(), 1234);
+ EXPECT_EQ(numericTypes.getPositiveInteger(), 1234);
+ EXPECT_EQ(numericTypes.getNonPositiveInteger(), -1234);
+ EXPECT_EQ(numericTypes.getUnsignedLong(), 1234);
+ EXPECT_EQ(numericTypes.getUnsignedInt(), 1234);
+ EXPECT_EQ(numericTypes.getUnsignedShort(), 1234);
+ EXPECT_EQ((int)(numericTypes.getUnsignedByte()), 255);
+
+ EXPECT_EQ(miscTypes.get_double(), 1234.57);
+ EXPECT_EQ(miscTypes.getAnyURI(), "https://www.google.com");
+ EXPECT_EQ(miscTypes.getBase64Binary(), "Z29vZ2xl");
+ EXPECT_TRUE(miscTypes.getBoolean());
+ EXPECT_EQ(miscTypes.getHexBinary(), "016a75cb56d7e7");
+ EXPECT_EQ(miscTypes.getQName(), "abcd");
+ EXPECT_EQ(miscTypes.getIDREF(), "abcd");
+ EXPECT_EQ(miscTypes.getIDREFS()[0], "abcd");
+ EXPECT_EQ(miscTypes.getIDREFS()[1], "abcd");
+ EXPECT_EQ(miscTypes.getAnyType(), "abcd");
+
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[0], -2147483648);
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[1], 2147483647);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[0], -32768);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[1], 32767);
+ EXPECT_EQ((int)listPrimitiveTypes.getListByte()[0], -128);
+ EXPECT_EQ((int)listPrimitiveTypes.getListByte()[1], 127);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[0], 1234.56);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[1], 5678.12);
+ EXPECT_TRUE(listPrimitiveTypes.getListBoolean()[0]);
+ EXPECT_FALSE(listPrimitiveTypes.getListBoolean()[1]);
+
+ ofstream out("old_predefined_types.xml");
+ write(out, type);
+ Types type2 = *read("old_predefined_types.xml");
+
+ NumericTypes numericTypes2 = *type.getFirstNumericTypes();
+ ListPrimitiveTypes listPrimitiveTypes2 = *type.getFirstListPrimitiveTypes();
+
+ EXPECT_EQ(numericTypes.getDecimal(), numericTypes2.getDecimal());
+ EXPECT_EQ(numericTypes.getInteger(), numericTypes2.getInteger());
+ EXPECT_EQ(numericTypes.get_long(), numericTypes2.get_long());
+ EXPECT_EQ(numericTypes.get_int(), numericTypes2.get_int());
+ EXPECT_EQ(numericTypes.get_short(), numericTypes2.get_short());
+ EXPECT_EQ(numericTypes.getByte(), numericTypes2.getByte());
+ EXPECT_EQ(numericTypes.getNegativeInteger(), numericTypes2.getNegativeInteger());
+ EXPECT_EQ(numericTypes.getNonNegativeInteger(), numericTypes2.getNonNegativeInteger());
+ EXPECT_EQ(numericTypes.getPositiveInteger(), numericTypes2.getPositiveInteger());
+ EXPECT_EQ(numericTypes.getNonPositiveInteger(), numericTypes2.getNonPositiveInteger());
+ EXPECT_EQ(numericTypes.getUnsignedLong(), numericTypes2.getUnsignedLong());
+ EXPECT_EQ(numericTypes.getUnsignedInt(), numericTypes2.getUnsignedInt());
+ EXPECT_EQ(numericTypes.getUnsignedShort(), numericTypes2.getUnsignedShort());
+ EXPECT_EQ((numericTypes.getUnsignedByte()), numericTypes2.getUnsignedByte());
+
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[0], listPrimitiveTypes2.getListInt()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[1], listPrimitiveTypes2.getListInt()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[0], listPrimitiveTypes2.getListShort()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[1], listPrimitiveTypes2.getListShort()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListByte()[0], listPrimitiveTypes2.getListByte()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListByte()[1], listPrimitiveTypes2.getListByte()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[0], listPrimitiveTypes2.getListDouble()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[1], listPrimitiveTypes2.getListDouble()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListBoolean()[0], listPrimitiveTypes2.getListBoolean()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListBoolean()[1], listPrimitiveTypes2.getListBoolean()[1]);
+}
+
+TEST_F(XmlTest, Nestedtype) {
+ using namespace nested::type;
+ Employee employee = *read(Resource("nested_type.xml").c_str());
+
+ Employee::Address address = *employee.getFirstAddress();
+ Employee::Address::Extra extra = *address.getFirstExtra();
+
+ EXPECT_EQ((int)employee.getId(), 1);
+ EXPECT_EQ(employee.getName(), "Peter");
+ EXPECT_EQ(address.getCountry(), "US");
+ EXPECT_EQ(address.getState(), "Mountain View");
+ EXPECT_EQ(address.getZip(), 3342);
+ EXPECT_EQ(extra.getLine1(), "Donga 303-111");
+ EXPECT_EQ(extra.getLine2(), "Good Street");
+
+ ofstream out("old_nested_type.xml");
+ write(out, employee);
+}
+
+TEST_F(XmlTest, Purchasesimple) {
+ using namespace purchase::simple;
+ PurchaseOrderType orderType = *read(Resource("purchase_simple.xml").c_str());
+
+ EXPECT_EQ(orderType.getOrderDate(), "1900-01-01");
+
+ EXPECT_EQ(orderType.getShipTo()[0].getName(), "name1");
+ EXPECT_EQ(orderType.getShipTo()[0].getStreet(), "street1");
+ EXPECT_EQ(orderType.getShipTo()[0].getCity(), "city1");
+ EXPECT_EQ(orderType.getShipTo()[0].getState(), "state1");
+ EXPECT_EQ(orderType.getShipTo()[0].getZip(), 1);
+ EXPECT_EQ(orderType.getShipTo()[0].getCountry(), "US");
+ EXPECT_EQ(orderType.getShipTo()[1].getName(), "name2");
+ EXPECT_EQ(orderType.getShipTo()[1].getStreet(), "street2");
+ EXPECT_EQ(orderType.getShipTo()[1].getCity(), "city2");
+ EXPECT_EQ(orderType.getShipTo()[1].getState(), "state2");
+ EXPECT_EQ(orderType.getShipTo()[1].getZip(), -7922816251426433759);
+ EXPECT_EQ(orderType.getShipTo()[1].getCountry(), "US");
+
+ EXPECT_EQ(orderType.getBillTo()[0].getName(), "billName");
+ EXPECT_EQ(orderType.getBillTo()[0].getStreet(), "billStreet");
+ EXPECT_EQ(orderType.getBillTo()[0].getCity(), "billCity");
+ EXPECT_EQ(orderType.getBillTo()[0].getState(), "billState");
+ EXPECT_EQ(orderType.getBillTo()[0].getZip(), 1);
+ EXPECT_EQ(orderType.getBillTo()[0].getCountry(), "US");
+
+ ofstream out("old_purchase_simple.xml");
+ write(out, orderType);
+
+ PurchaseOrderType orderType2 = *read("old_purchase_simple.xml");
+
+ EXPECT_EQ(orderType.getOrderDate(), orderType2.getOrderDate());
+
+ EXPECT_EQ(orderType.getShipTo()[0].getName(), orderType2.getShipTo()[0].getName());
+ EXPECT_EQ(orderType.getShipTo()[0].getStreet(), orderType2.getShipTo()[0].getStreet());
+ EXPECT_EQ(orderType.getShipTo()[0].getCity(), orderType2.getShipTo()[0].getCity());
+ EXPECT_EQ(orderType.getShipTo()[0].getState(), orderType2.getShipTo()[0].getState());
+ EXPECT_EQ(orderType.getShipTo()[0].getZip(), orderType2.getShipTo()[0].getZip());
+ EXPECT_EQ(orderType.getShipTo()[0].getCountry(), orderType2.getShipTo()[0].getCountry());
+ EXPECT_EQ(orderType.getShipTo()[1].getName(), orderType2.getShipTo()[1].getName());
+ EXPECT_EQ(orderType.getShipTo()[1].getStreet(), orderType2.getShipTo()[1].getStreet());
+ EXPECT_EQ(orderType.getShipTo()[1].getCity(), orderType2.getShipTo()[1].getCity());
+ EXPECT_EQ(orderType.getShipTo()[1].getState(), orderType2.getShipTo()[1].getState());
+ EXPECT_EQ(orderType.getShipTo()[1].getZip(), orderType2.getShipTo()[1].getZip());
+ EXPECT_EQ(orderType.getShipTo()[1].getCountry(), orderType2.getShipTo()[1].getCountry());
+
+ EXPECT_EQ(orderType.getBillTo()[0].getName(), orderType2.getBillTo()[0].getName());
+ EXPECT_EQ(orderType.getBillTo()[0].getStreet(), orderType2.getBillTo()[0].getStreet());
+ EXPECT_EQ(orderType.getBillTo()[0].getCity(), orderType2.getBillTo()[0].getCity());
+ EXPECT_EQ(orderType.getBillTo()[0].getState(), orderType2.getBillTo()[0].getState());
+ EXPECT_EQ(orderType.getBillTo()[0].getZip(), orderType2.getBillTo()[0].getZip());
+ EXPECT_EQ(orderType.getBillTo()[0].getCountry(), orderType2.getBillTo()[0].getCountry());
+}
+
+TEST_F(XmlTest, Reference) {
+ using namespace reference;
+ Class _class = *read(Resource("reference.xml").c_str());
+
+ EXPECT_EQ(_class.getStudent()[0], "Sam");
+ EXPECT_EQ(_class.getStudent()[1], "Paul");
+ EXPECT_EQ(_class.getStudent()[2], "Peter");
+
+ ofstream out("old_reference.xml");
+ write(out, _class);
+}
+
+TEST_F(XmlTest, Simplecomplexcontent) {
+ using namespace simple::complex::content;
+ Person person = *readPerson(Resource("simple_complex_content.xml").c_str());
+ USAddressP uSAddressP = *person.getFirstUSAddressP();
+ KRAddress kRAddress = *person.getFirstKRAddress();
+ SubAddress subAddress = *person.getFirstSubAddress();
+
+ EXPECT_EQ(person.getName(), "Petr");
+
+ EXPECT_EQ(uSAddressP.getName(), "404");
+ EXPECT_EQ(uSAddressP.getStreet(), "street fighter");
+ EXPECT_EQ(uSAddressP.getCity(), "New York");
+ EXPECT_EQ(uSAddressP.getState(), "Washington");
+ EXPECT_EQ(uSAddressP.getZipcode(), 323232318329852);
+
+ EXPECT_EQ(kRAddress.getName(), "Donga Studio");
+ EXPECT_EQ(kRAddress.getStreet(), "Nokdu Street");
+ EXPECT_EQ(kRAddress.getCity(), "Seoul");
+
+ EXPECT_EQ(subAddress.getChoice1_optional(), "Temp");
+
+ ofstream out("old_simple_complex_content.xml");
+ write(out, person);
+}
+
+TEST_F(XmlTest, Attrgroupsimple) {
+ using namespace attr::group::simple;
+ Student student = *read(Resource("attr_group_simple.xml").c_str());
+
+ EXPECT_EQ(student.getName(), "Jun");
+ EXPECT_EQ(student.getCity(), "Mountain View");
+ EXPECT_EQ(student.getState(), "CA");
+ EXPECT_EQ(student.getRoad(), "Street 101");
+ EXPECT_EQ(student.getList()[0], 1);
+ EXPECT_EQ(student.getList()[1], 2);
+ EXPECT_EQ(student.getList()[2], 3);
+
+ ofstream out("old_attr_group_simple.xml");
+ write(out, student);
+}
+
+TEST_F(XmlTest, Group) {
+ using namespace group;
+ Student student = *read(Resource("group.xml").c_str());
+
+ EXPECT_EQ(student.getCity(), "Mountain View");
+ EXPECT_EQ(student.getState(), "CA");
+ EXPECT_EQ(student.getRoad(), "Street 101");
+
+ ofstream out("old_group.xml");
+ write(out, student);
+}
diff --git a/tests/xmltest.h b/tests/xmltest.h
new file mode 100644
index 0000000..b645b98
--- /dev/null
+++ b/tests/xmltest.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+
+class XmlTest : public ::testing::Test {
+public:
+ std::string Resource(const std::string& filename) {
+ return ::android::base::GetExecutableDirectory() + "/resources/" + filename;
+ }
+};
diff --git a/utils/Android.bp b/utils/Android.bp
new file mode 100644
index 0000000..5204bbc
--- /dev/null
+++ b/utils/Android.bp
@@ -0,0 +1,24 @@
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library_headers {
+ name: "libxsdc-utils",
+ export_include_dirs: ["include"],
+ host_supported: true,
+ vendor_available: true,
+}
diff --git a/utils/include/xsdc/XsdcSupport.h b/utils/include/xsdc/XsdcSupport.h
new file mode 100644
index 0000000..fe0d31c
--- /dev/null
+++ b/utils/include/xsdc/XsdcSupport.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef ANDROID_XSDC_SUPPORT_H
+#define ANDROID_XSDC_SUPPORT_H
+
+#include <iterator>
+#include <type_traits>
+
+namespace android {
+
+namespace details {
+// Never instantiated. Used as a placeholder for template variables.
+template <typename T>
+struct xsdc_invalid_type;
+
+// XSDC generates specializations of this for enums. See xsdc_enum_range.
+template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
+constexpr xsdc_invalid_type<T> xsdc_enum_values;
+} // namespace details
+
+/**
+ * Every XSDC generated enum supports this function.
+ * E.x.: for (const auto v : xsdc_enum_range<Enum>()) { ... }
+ */
+template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
+struct xsdc_enum_range {
+ // Container-like associated type.
+ using value_type = T;
+
+ constexpr auto begin() const { return std::begin(details::xsdc_enum_values<T>); }
+ constexpr auto cbegin() const { return begin(); }
+ constexpr auto rbegin() const { return std::rbegin(details::xsdc_enum_values<T>); }
+ constexpr auto crbegin() const { return rbegin(); }
+ constexpr auto end() const { return std::end(details::xsdc_enum_values<T>); }
+ constexpr auto cend() const { return end(); }
+ constexpr auto rend() const { return std::rend(details::xsdc_enum_values<T>); }
+ constexpr auto crend() const { return rend(); }
+};
+
+} // namespace android
+
+#endif // ANDROID_XSDC_SUPPORT_H