]> gerrit.simantics Code Review - simantics/interop.git/blobdiff - org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLWriter.java
Initial support for XML export (order of Elements is not kept)
[simantics/interop.git] / org.simantics.xml.sax.base / src / org / simantics / xml / sax / base / XMLWriter.java
diff --git a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLWriter.java b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLWriter.java
new file mode 100644 (file)
index 0000000..3fd881b
--- /dev/null
@@ -0,0 +1,183 @@
+package org.simantics.xml.sax.base;\r
+\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.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import javax.xml.stream.XMLStreamException;\r
+import javax.xml.stream.XMLStreamWriter;\r
+\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+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.message.ILogger;\r
+import org.simantics.xml.sax.ontology.XMLResource;\r
+\r
+public class XMLWriter {\r
+       \r
+       private ReadGraph graph;\r
+       private Map<String, XMLWriter> subWriters = new HashMap<String, 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
+       \r
+       private ILogger logger;\r
+       \r
+       public ReadGraph getGraph() {\r
+               return graph;\r
+       }\r
+       \r
+       public void setGraph(ReadGraph graph) {\r
+               this.graph = graph;\r
+               for (XMLWriter p : subWriters.values())\r
+                       p.setGraph(graph);\r
+       }\r
+       \r
+       public String getSchemaURI() {\r
+               return schemaURI;\r
+       }\r
+       \r
+       public void setSchemaURI(String schemaURI) {\r
+               this.schemaURI = schemaURI;\r
+       }\r
+       \r
+       public void add(XMLElementWriter writer) throws DatabaseException {\r
+               Resource type = writer.getType(graph);\r
+               if (type != null)\r
+                       writers.put(type, writer);\r
+               namedWriters.put(writer.getClass(), writer);\r
+       }\r
+       \r
+       public void add(XMLWriter writer) {\r
+               subWriters.put(writer.getSchemaURI(), writer);\r
+       }\r
+       \r
+       public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
+               WriterElement element = new WriterElement(root);\r
+               loadElement(element);\r
+               write(element, writer);\r
+       }\r
+       \r
+       \r
+       protected void write(WriterElement instance, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
+               XMLResource XML = XMLResource.getInstance(graph);\r
+\r
+               XMLElementWriter elementWriter = instance.writer;\r
+               elementWriter.start(graph, instance, writer);\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
+               // load elements, assign writers\r
+               Map<Resource,WriterElement> elementMap = new HashMap<>();\r
+               for (Statement s : childElements) {\r
+                       WriterElement c = new WriterElement(instance,s);\r
+                       loadElement(c);\r
+                       elementMap.put(s.getObject(), c);\r
+               }\r
+               List<Resource> sorted = elementWriter.children(graph, instance, writer);\r
+                       \r
+               for (Resource r : sorted) {\r
+                       WriterElement child = elementMap.get(r);\r
+                       write(child, writer);\r
+               }\r
+               //write the rest of the elements (in random order) \r
+               for (Statement stm : childElements) {\r
+                       if (sorted.contains(stm.getObject()))\r
+                               continue;\r
+                       WriterElement child = elementMap.get(stm.getObject());\r
+                       write(child, writer);\r
+               }\r
+       \r
+               elementWriter.end(graph, instance, writer);\r
+               \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
+                       XMLElementNamedChildWriter namedParentWriter = (XMLElementNamedChildWriter)child.parent.writer;\r
+                       Class<? extends XMLElementWriter> childWriterClass = namedParentWriter.getWriter(graph, writers, child);\r
+                       if (childWriterClass != null) {\r
+                               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
+                                               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
+                                       } \r
+                               }\r
+                       }\r
+               } else {\r
+                       Resource type = graph.getSingleType(child.instance);\r
+                       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
+               }\r
+               child.writer = childWriter;\r
+               \r
+       }\r
+\r
+}\r