Throw an exception for unsupported features
am: d24d2872bd

Change-Id: I440f7fc9724c0932be5f782279484b2c54fde420
diff --git a/src/com/android/xsdc/XsdHandler.java b/src/com/android/xsdc/XsdHandler.java
index 247562b..30d34f5 100644
--- a/src/com/android/xsdc/XsdHandler.java
+++ b/src/com/android/xsdc/XsdHandler.java
@@ -150,11 +150,32 @@
                 case "sequence":
                     stateStack.peek().tags.addAll(makeSequence(state.attributeMap, state.tags));
                     break;
+                case "fractionDigits":
+                case "enumeration":
+                case "length":
+                case "maxExclusive":
+                case "maxInclusive":
+                case "maxLength":
+                case "minExclusive":
+                case "minInclusive":
+                case "minLength":
+                case "pattern":
+                case "totalDigits":
+                case "whiteSpace":
+                    // Tags under simpleType <restriction>. They are ignored.
+                    break;
+                case "annotation":
+                case "documentation":
+                case "appinfo":
+                    // They function like comments, so are ignored.
+                    break;
+                default:
+                    throw new XsdParserException(String.format("unsupported tag : %s", state.name));
             }
         } catch (XsdParserException e) {
             throw new SAXException(
-                    String.format("Line %d, Column %d",
-                            locator.getLineNumber(), locator.getColumnNumber()), e);
+                    String.format("Line %d, Column %d - %s",
+                            locator.getLineNumber(), locator.getColumnNumber(), e.getMessage()));
         }
     }
 
@@ -182,8 +203,21 @@
         String name = attributeMap.get("name");
         QName typename = parseQName(attributeMap.get("type"));
         QName ref = parseQName(attributeMap.get("ref"));
+        String isAbstract = attributeMap.get("abstract");
+        String defVal = attributeMap.get("default");
+        String substitutionGroup = attributeMap.get("substitutionGroup");
         String maxOccurs = attributeMap.get("maxOccurs");
 
+        if ("true".equals(isAbstract)) {
+            throw new XsdParserException("abstract element is not supported.");
+        }
+        if (defVal != null) {
+            throw new XsdParserException("default value of an element is not supported.");
+        }
+        if (substitutionGroup != null) {
+            throw new XsdParserException("substitution group of an element is not supported.");
+        }
+
         boolean multiple = false;
         if (maxOccurs != null) {
             if (maxOccurs.equals("0")) return null;
@@ -209,8 +243,13 @@
         String name = attributeMap.get("name");
         QName typename = parseQName(attributeMap.get("type"));
         QName ref = parseQName(attributeMap.get("ref"));
+        String defVal = attributeMap.get("default");
         String use = attributeMap.get("use");
 
+        if (defVal != null) {
+            throw new XsdParserException("default value of an attribute is not supported.");
+        }
+
         if (use != null && use.equals("prohibited")) return null;
 
         XsdType type = null;
@@ -227,8 +266,18 @@
         return new XsdAttribute(name, ref, type);
     }
 
-    private XsdComplexType makeComplexType(Map<String, String> attributeMap, List<XsdTag> tags) {
+    private XsdComplexType makeComplexType(Map<String, String> attributeMap, List<XsdTag> tags)
+            throws XsdParserException {
         String name = attributeMap.get("name");
+        String isAbstract = attributeMap.get("abstract");
+        String mixed = attributeMap.get("mixed");
+
+        if ("true".equals(isAbstract)) {
+            throw new XsdParserException("abstract complex type is not supported.");
+        }
+        if ("true".equals(mixed)) {
+            throw new XsdParserException("mixed option of a complex type is not supported.");
+        }
 
         List<XsdAttribute> attributes = new ArrayList<>();
         List<XsdElement> elements = new ArrayList<>();
@@ -254,9 +303,13 @@
     }
 
     private XsdComplexContent makeComplexContent(Map<String, String> attributeMap,
-            List<XsdTag> tags) {
-        XsdComplexContent content = null;
+            List<XsdTag> tags) throws XsdParserException {
+        String mixed = attributeMap.get("mixed");
+        if ("true".equals(mixed)) {
+            throw new XsdParserException("mixed option of a complex content is not supported.");
+        }
 
+        XsdComplexContent content = null;
         for (XsdTag tag : tags) {
             if (tag == null) continue;
             if (tag instanceof XsdGeneralExtension) {
@@ -391,7 +444,15 @@
     }
 
     private static List<XsdElement> makeSequence(Map<String, String> attributeMap,
-            List<XsdTag> tags) {
+            List<XsdTag> tags) throws XsdParserException {
+        String minOccurs = attributeMap.get("minOccurs");
+        String maxOccurs = attributeMap.get("maxOccurs");
+
+        if (minOccurs != null || maxOccurs != null) {
+            throw new XsdParserException(
+                    "minOccurs, maxOccurs options of a sequence is not supported");
+        }
+
         List<XsdElement> elements = new ArrayList<>();
         for (XsdTag tag : tags) {
             if (tag == null) continue;
diff --git a/tests/resources/unsupported_attribute.xsd b/tests/resources/unsupported_attribute.xsd
new file mode 100644
index 0000000..9e3d317
--- /dev/null
+++ b/tests/resources/unsupported_attribute.xsd
@@ -0,0 +1,5 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
+           targetNamespace="unsuppported_attribute" xmlns="unsuppported_attribute">
+    <xs:element name="animal" type="xs:string"/>
+    <xs:element name="cat" substitutionGroup="animal"/>
+</xs:schema>
\ No newline at end of file
diff --git a/tests/resources/unsupported_tag.xsd b/tests/resources/unsupported_tag.xsd
new file mode 100644
index 0000000..4a75c1f
--- /dev/null
+++ b/tests/resources/unsupported_tag.xsd
@@ -0,0 +1,5 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
+           targetNamespace="unsupported_tag" xmlns="unsupported_tag">
+    <xs:import namespace="reference" schemaLocation="reference.xsd"/>
+    <xs:element name="dummy" type="xs:string"/>
+</xs:schema>
\ 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 154790d..ba4f44e 100644
--- a/tests/src/com/android/xsdc/tests/XmlParserTest.java
+++ b/tests/src/com/android/xsdc/tests/XmlParserTest.java
@@ -19,7 +19,10 @@
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.*;
 
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.xml.sax.SAXException;
 
 import javax.xml.datatype.DatatypeFactory;
 import javax.xml.datatype.Duration;
@@ -350,4 +353,29 @@
 
         assertThat(student, is(Arrays.asList("Sam", "Paul", "Peter")));
     }
+
+    @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);
+        }
+    }
+
+    @Test
+    public void testUnsupportedAttribute() throws Exception {
+        thrown.expect(SAXException.class);
+        thrown.expectMessage("substitution group of an element is not supported.");
+
+        try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(
+                "unsupported_attribute.xsd")) {
+            TestHelper.parseXsdAndCompile(in);
+        }
+    }
 }
\ No newline at end of file