diff options
author | Gunhyeong Kim <gunhyeong@google.com> | 2018-08-08 11:07:46 +0900 |
---|---|---|
committer | Gunhyeong Kim <gunhyeong@google.com> | 2018-08-08 13:21:41 +0900 |
commit | e3863e41eb54a957049afe18f90be185af9cfed5 (patch) | |
tree | f5f1ff7b5cf48170645445df65fd4a754854b7f2 /tests/src | |
parent | f3843118bd5831bc9ab04035238dfa42e8e10978 (diff) | |
download | xsdc-e3863e41eb54a957049afe18f90be185af9cfed5.tar.gz |
parse .xsd file as API
This program generates Java code for a .xsd file.
If you execute 'm -j xsdc', then 'xsdc.jar' file will be created.
You can use this .jar file like this:
$ java -jar xsdc.jar $xsd_file_path $package_name $directory_name
Then it generates Java code under $directory_name.
Bug: 80453829
Test: If you want to execute unit test, execute 'm -j xsdc-tests'.
It will generate xsdc-tests.jar, and you can use it by
$ java -cp xsdc-tests.jar org.junit.runner.JUnitCore
com.android.xsdc.tests.XmlParserTest
Change-Id: Ica6432e4fc6497f8a14619fd34227702e53bfa57
Diffstat (limited to 'tests/src')
-rw-r--r-- | tests/src/com/android/xsdc/tests/TestCompilationResult.java | 41 | ||||
-rw-r--r-- | tests/src/com/android/xsdc/tests/TestHelper.java | 122 | ||||
-rw-r--r-- | tests/src/com/android/xsdc/tests/XmlParserTest.java | 271 |
3 files changed, 434 insertions, 0 deletions
diff --git a/tests/src/com/android/xsdc/tests/TestCompilationResult.java b/tests/src/com/android/xsdc/tests/TestCompilationResult.java new file mode 100644 index 0000000..b63792c --- /dev/null +++ b/tests/src/com/android/xsdc/tests/TestCompilationResult.java @@ -0,0 +1,41 @@ +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 new file mode 100644 index 0000000..4a67b93 --- /dev/null +++ b/tests/src/com/android/xsdc/tests/TestHelper.java @@ -0,0 +1,122 @@ +package com.android.xsdc.tests; + +import com.android.xsdc.XmlSchema; +import com.android.xsdc.XsdParser; +import com.android.xsdc.XsdParserException; +import com.android.xsdc.descriptor.ClassDescriptor; +import com.android.xsdc.descriptor.SchemaDescriptor; +import org.xmlpull.v1.XmlPullParserException; + +import javax.tools.*; +import java.io.*; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +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 IOException, XmlPullParserException, XsdParserException, ClassNotFoundException { + XmlSchema schema = XsdParser.parse(in); + List<JavaFileObject> javaFileObjects = new ArrayList<>(); + SchemaDescriptor schemaDescriptor = schema.explain(); + for (ClassDescriptor descriptor : schemaDescriptor.getClassDescriptorMap().values()) { + StringWriter codeOutput = new StringWriter(); + descriptor.print(packageName, new PrintWriter(codeOutput)); + javaFileObjects.add(new InMemoryJavaFileObject(descriptor.getName(), codeOutput.toString())); + } + StringWriter codeOutput = new StringWriter(); + schemaDescriptor.printXmlParser(packageName, new PrintWriter(codeOutput)); + javaFileObjects.add(new InMemoryJavaFileObject("XmlParser", codeOutput.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 new file mode 100644 index 0000000..34ba029 --- /dev/null +++ b/tests/src/com/android/xsdc/tests/XmlParserTest.java @@ -0,0 +1,271 @@ +package com.android.xsdc.tests; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +import org.junit.Test; + +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; +import java.io.*; +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.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.xml")) { + instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in); + } + 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("-79228162514264337593543950335"))); + assertThat(orderDate, is(javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar("1900-01-01"))); + } + + @Test + public void testNestedType() throws Exception { + TestCompilationResult result; + try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("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.xml")) { + instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in); + } + + 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")); + } + + @Test + public void testSimpleComplexContent() throws Exception { + TestCompilationResult result; + try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("simple_complex_content.xsd")) { + result = TestHelper.parseXsdAndCompile(in); + } + + Class<?> xmlParser = result.loadClass("XmlParser"); + Class<?> person = result.loadClass("Person"); + Class<?> shoeSize = result.loadClass("ShoeSize"); + Class<?> generalPrice = result.loadClass("GeneralPrice"); + Class<?> usAddress = result.loadClass("USAddress"); + Class<?> krAddress = result.loadClass("KRAddress"); + + Object instance; + try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("simple_complex_content.xml")) { + instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in); + } + + String name = (String)person.getMethod("getName").invoke(instance); + Object shoeSizeInstance = person.getMethod("getShoeSize").invoke(instance); + String sizing = (String)shoeSize.getMethod("getSizing").invoke(shoeSizeInstance); + BigDecimal shoeSizeValue = (BigDecimal)shoeSize.getMethod("getValue").invoke(shoeSizeInstance); + + Object generalPriceInstance = person.getMethod("getGeneralPrice").invoke(instance); + String currency = (String)generalPrice.getMethod("getCurrency").invoke(generalPriceInstance); + BigDecimal generalPriceValue = (BigDecimal)generalPrice.getMethod("getValue").invoke(generalPriceInstance); + + Object usAddressInstance = person.getMethod("getUSAddress").invoke(instance); + String usStreet = (String)usAddress.getMethod("getStreet").invoke(usAddressInstance); + BigInteger usZipcode = (BigInteger)usAddress.getMethod("getZipcode").invoke(usAddressInstance); + + Object krAddressInstance = person.getMethod("getKRAddress").invoke(instance); + String krStreet = (String)krAddress.getMethod("getStreet").invoke(krAddressInstance); + + assertThat(name, is("Petr")); + assertThat(sizing, is("Korea")); + assertThat(shoeSizeValue, is(new BigDecimal("265"))); + assertThat(currency, is("dollar")); + assertThat(generalPriceValue, is(new BigDecimal("1234.5678"))); + assertThat(usStreet, is("street fighter")); + assertThat(usZipcode, is(new BigInteger("3232323183298523436434"))); + assertThat(krStreet, is("Nokdu Street")); + } + + @Test + public void testPredefinedTypes() throws Exception { + TestCompilationResult result; + try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("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"); + + Object instance; + try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("predefined_types.xml")) { + instance = xmlParser.getMethod("read", InputStream.class).invoke(null, in); + } + + { + 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"))); + } + + { + 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); + + DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); + assertThat(date, is(datatypeFactory.newXMLGregorianCalendar("2018-06-18"))); + assertThat(dateTime, 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"))); + } + + { + 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.5678"))); + assertThat(integer, is(new BigInteger("123456789012345678901234567890"))); + 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)); + } + + { + 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.5678)); + assertThat(_float, is(123.456f)); + 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")); + } + } + + @Test + public void testSimpleType() throws Exception { + TestCompilationResult result; + try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("simple_type.xsd")) { + result = TestHelper.parseXsdAndCompile(in); + } + + 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); + } + + 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"))); + } +}
\ No newline at end of file |