]> gerrit.simantics Code Review - simantics/interop.git/blobdiff - org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLWriter.java
Don't continue parsing XML file if root element is not recognised
[simantics/interop.git] / org.simantics.xml.sax.base / src / org / simantics / xml / sax / base / XMLWriter.java
index 3fd881ba3c3d86da100a06c87190c32a06f54512..ce5cb90068aa16cedfa7483ae04d00dbeb0c4780 100644 (file)
@@ -2,8 +2,9 @@ package org.simantics.xml.sax.base;
 \r
 import java.lang.reflect.Constructor;\r
 import java.lang.reflect.InvocationTargetException;\r
-import java.util.Collection;\r
 import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.LinkedHashSet;\r
 import java.util.List;\r
 import java.util.Map;\r
 import java.util.Set;\r
@@ -19,16 +20,22 @@ import org.simantics.db.Statement;
 import org.simantics.db.common.utils.ListUtils;\r
 import org.simantics.db.common.utils.NameUtils;\r
 import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
 import org.simantics.message.ILogger;\r
 import org.simantics.xml.sax.ontology.XMLResource;\r
 \r
 public class XMLWriter {\r
        \r
+       public static String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";\r
+       public static String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";\r
+       \r
        private ReadGraph graph;\r
-       private Map<String, XMLWriter> subWriters = new HashMap<String, XMLWriter>();\r
+       private Map<Resource, XMLWriter> subWriters = new HashMap<Resource, XMLWriter>();\r
        private Map<Class<? extends XMLElementWriter>, XMLElementWriter> namedWriters = new HashMap<Class<? extends XMLElementWriter>, XMLElementWriter>();\r
        private Map<Resource,XMLElementWriter> writers = new HashMap<>();\r
        private String schemaURI;\r
+       private String ontologyURI;\r
+       private Resource ontology;\r
        \r
        private ILogger logger;\r
        \r
@@ -36,10 +43,12 @@ public class XMLWriter {
                return graph;\r
        }\r
        \r
-       public void setGraph(ReadGraph graph) {\r
+       public void setGraph(ReadGraph graph) throws DatabaseException {\r
                this.graph = graph;\r
                for (XMLWriter p : subWriters.values())\r
                        p.setGraph(graph);\r
+               if (ontologyURI != null)\r
+                       this.ontology = graph.getResource(ontologyURI);\r
        }\r
        \r
        public String getSchemaURI() {\r
@@ -50,6 +59,18 @@ public class XMLWriter {
                this.schemaURI = schemaURI;\r
        }\r
        \r
+       public String getOntologyURI() {\r
+               return ontologyURI;\r
+       }\r
+       \r
+       public void setOntologyURI(String ontologyURI) {\r
+               this.ontologyURI = ontologyURI;\r
+       }\r
+       \r
+       public Resource getOntology() {\r
+               return ontology;\r
+       }\r
+       \r
        public void add(XMLElementWriter writer) throws DatabaseException {\r
                Resource type = writer.getType(graph);\r
                if (type != null)\r
@@ -58,7 +79,7 @@ public class XMLWriter {
        }\r
        \r
        public void add(XMLWriter writer) {\r
-               subWriters.put(writer.getSchemaURI(), writer);\r
+               subWriters.put(writer.getOntology(), writer);\r
        }\r
        \r
        public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
@@ -73,11 +94,20 @@ public class XMLWriter {
 \r
                XMLElementWriter elementWriter = instance.writer;\r
                elementWriter.start(graph, instance, writer);\r
+               if (instance.parent == null) {\r
+                       if(getSchemaURI() != null) {\r
+                               writer.writeDefaultNamespace(getSchemaURI());\r
+                       }\r
+                       writer.writeNamespace("xsd", XML_SCHEMA_URI);\r
+                       writer.writeNamespace("xsi", XML_SCHEMA_INSTANCE_URI);\r
+               }\r
                elementWriter.attributes(graph, instance, graph.getStatements(instance.instance, XML.hasAttribute), writer);\r
                if (graph.hasValue(instance.instance))\r
                        elementWriter.characters(graph, instance, writer);\r
                // get all child elements\r
-               Collection<Statement> childElements = graph.getStatements(instance.instance, XML.hasElement);\r
+               Set<Statement> childElements = new HashSet<>();\r
+               childElements.addAll(graph.getStatements(instance.instance, XML.hasElement));\r
+               childElements.addAll(graph.getStatements(instance.instance, XML.hasComplexType));\r
                // load elements, assign writers\r
                Map<Resource,WriterElement> elementMap = new HashMap<>();\r
                for (Statement s : childElements) {\r
@@ -85,17 +115,30 @@ public class XMLWriter {
                        loadElement(c);\r
                        elementMap.put(s.getObject(), c);\r
                }\r
-               List<Resource> sorted = elementWriter.children(graph, instance, writer);\r
-                       \r
+               LinkedHashSet<Resource> sorted = new LinkedHashSet<>();\r
+               if (graph.hasStatement(instance.instance, XML.hasOriginalElementList)) {\r
+                       Resource originalList = graph.getSingleObject(instance.instance, XML.hasOriginalElementList);\r
+                       List<Resource> l = ListUtils.toList(graph, originalList);\r
+                       sorted.addAll(l);\r
+               }\r
+               elementWriter.children(graph, instance, sorted);\r
+               Set<Resource> processed = new HashSet<>();\r
                for (Resource r : sorted) {\r
+                       if (processed.contains(r)) // badly generated writer could report elements several times. \r
+                               continue;\r
                        WriterElement child = elementMap.get(r);\r
+                       if (child == null)\r
+                               throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, r) + " " + r);\r
                        write(child, writer);\r
+                       processed.add(r);\r
                }\r
                //write the rest of the elements (in random order) \r
                for (Statement stm : childElements) {\r
-                       if (sorted.contains(stm.getObject()))\r
+                       if (processed.contains(stm.getObject()))\r
                                continue;\r
                        WriterElement child = elementMap.get(stm.getObject());\r
+                       if (child == null)\r
+                               throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, stm.getObject()) + " " + stm.getObject());\r
                        write(child, writer);\r
                }\r
        \r
@@ -103,53 +146,6 @@ public class XMLWriter {
                \r
        }\r
        \r
-//     public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
-//             XMLResource XML = XMLResource.getInstance(graph);\r
-//             \r
-//             Deque<Element> stack = new ArrayDeque<>();\r
-//             Element rootElement = new Element(root);\r
-//             loadElement(rootElement);\r
-//             stack.push(rootElement);\r
-//             while (!stack.isEmpty()) {\r
-//                     \r
-//                     Element instance = stack.pop();\r
-//                     XMLElementWriter elementWriter = instance.writer;\r
-//                     elementWriter.start(graph, instance.instance, writer);\r
-//                     elementWriter.attributes(graph, graph.getStatements(instance.instance, XML.hasAttribute), writer);\r
-//                     // get all child elements\r
-//                     Collection<Statement> childElements = graph.getStatements(instance.instance, XML.hasElement);\r
-//                     // get original element order, if available\r
-//                     Resource originalElementList = graph.getPossibleObject(instance.instance, XML.hasOriginalElementList);\r
-//                     List<Resource> originalList = null;\r
-//                     if (originalElementList != null) {\r
-//                             originalList = ListUtils.toList(graph, originalElementList);\r
-//                     }\r
-//                     if (originalList != null) {\r
-//                             // check for elements that are missing form the original list (should be empty).  \r
-//                             for (Statement stm : childElements) {\r
-//                                     if (originalList.contains(stm.getObject()))\r
-//                                             continue;\r
-//                                     Element child = new Element(instance,stm.getObject());\r
-//                                     loadElement(child);\r
-//                                     stack.push(child);\r
-//                             }\r
-//                             // process the list in reverse order so that the stack processing processes the items in correct order.\r
-//                             for (int i = originalList.size()-1; i >= 0; i--) {\r
-//                                     Resource r = originalList.get(i);\r
-//                                     Element child = new Element(instance, r);\r
-//                                     loadElement(child);\r
-//                                     stack.push(child);\r
-//                             }\r
-//                     } else {\r
-//                             for (Statement stm : childElements) {\r
-//                                     Element child = new Element(instance, stm.getObject());\r
-//                                     loadElement(child);\r
-//                                     stack.push(child);\r
-//                             }\r
-//                     }\r
-//             }\r
-//     }\r
-       \r
        private void loadElement(WriterElement child) throws DatabaseException {\r
                XMLElementWriter childWriter = null;\r
                if (child.parent != null && child.parent.writer instanceof XMLElementNamedChildWriter) {\r
@@ -159,13 +155,18 @@ public class XMLWriter {
                                childWriter = this.writers.get(childWriterClass);\r
                                if (childWriter == null) {\r
                                        try {\r
-                                               Constructor<? extends XMLElementWriter> c = childWriterClass.getConstructor(ReadGraph.class);\r
-                                               //childWriter = childWriterClass.newInstance();\r
-                                               childWriter = c.newInstance(graph);\r
+                                               Constructor<? extends XMLElementWriter> c = null;\r
+                                               try {\r
+                                                       c = childWriterClass.getConstructor(ReadGraph.class);\r
+                                                       childWriter = c.newInstance(graph);\r
+                                               } catch (NoSuchMethodException e) {\r
+                                                       c = childWriterClass.getConstructor();\r
+                                                       childWriter = c.newInstance();\r
+                                               }\r
                                                namedWriters.put(childWriterClass, childWriter);\r
                                        } catch (IllegalAccessException|InstantiationException|NoSuchMethodException|SecurityException|InvocationTargetException e) {\r
                                                String err = "Error processing " + childWriterClass.getName() + " : element writers must have accessible constructor with ReadGraph parameter";\r
-                                               logger.log(new Status(IStatus.ERROR, XMLParser.PLUGIN_ID, err));\r
+                                               logger.log(new Status(IStatus.ERROR, XMLParser.PLUGIN_ID, err, e));\r
                                        } \r
                                }\r
                        }\r
@@ -174,10 +175,39 @@ public class XMLWriter {
                        childWriter = writers.get(type);\r
                }\r
                if (childWriter == null) {\r
-                       throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);\r
+                       // try child ontology/schema\r
+                       Resource type = graph.getSingleType(child.instance);\r
+                       Resource ontology = getOntology(type);\r
+                       if (ontology != null) {\r
+                               XMLWriter xmlWriter = subWriters.get(ontology);\r
+                               if (xmlWriter != null) {\r
+                                       childWriter = xmlWriter.writers.get(type);\r
+                                       // wrap the child writer with namespace writer\r
+                                       if (childWriter != null) {\r
+                                               if (childWriter instanceof XMLElementNamedChildWriter) {\r
+                                                       childWriter = new XMLNSNamedChildWriter((XMLElementNamedChildWriter)childWriter, xmlWriter.schemaURI);\r
+                                               } else {\r
+                                                       childWriter = new XMLNSElementWriter(childWriter, xmlWriter.schemaURI);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       if (childWriter == null)\r
+                               throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);\r
                }\r
                child.writer = childWriter;\r
                \r
        }\r
+       \r
+       private Resource getOntology(Resource type) throws DatabaseException {\r
+               Layer0 L0 = Layer0.getInstance(graph);\r
+               Resource r = type;\r
+               while (true) {\r
+                       r = graph.getPossibleObject(r, L0.PartOf);\r
+                       if (r != null && graph.isInstanceOf(r, L0.Ontology))\r
+                               break;\r
+               }\r
+               return r;\r
+       }\r
 \r
 }\r