]> gerrit.simantics Code Review - simantics/interop.git/blobdiff - org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLWriter.java
Attribute namespace + multi-schema data export
[simantics/interop.git] / org.simantics.xml.sax.base / src / org / simantics / xml / sax / base / XMLWriter.java
index ce5cb90068aa16cedfa7483ae04d00dbeb0c4780..dba343b59e71462c4efb87e88e5f070b1c2e624c 100644 (file)
-package org.simantics.xml.sax.base;\r
-\r
-import java.lang.reflect.Constructor;\r
-import java.lang.reflect.InvocationTargetException;\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
-\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.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<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
-       public ReadGraph getGraph() {\r
-               return graph;\r
-       }\r
-       \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
-               return schemaURI;\r
-       }\r
-       \r
-       public void setSchemaURI(String schemaURI) {\r
-               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
-                       writers.put(type, writer);\r
-               namedWriters.put(writer.getClass(), writer);\r
-       }\r
-       \r
-       public void add(XMLWriter writer) {\r
-               subWriters.put(writer.getOntology(), 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
-               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
-               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
-                       WriterElement c = new WriterElement(instance,s);\r
-                       loadElement(c);\r
-                       elementMap.put(s.getObject(), c);\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 (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
-               elementWriter.end(graph, instance, writer);\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 = 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, e));\r
-                                       } \r
-                               }\r
-                       }\r
-               } else {\r
-                       Resource type = graph.getSingleType(child.instance);\r
-                       childWriter = writers.get(type);\r
-               }\r
-               if (childWriter == null) {\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
+package org.simantics.xml.sax.base;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.Statement;
+import org.simantics.db.common.utils.ListUtils;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.layer0.Layer0;
+import org.simantics.message.ILogger;
+import org.simantics.xml.sax.ontology.XMLResource;
+
+public class XMLWriter {
+       
+       public static String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
+       public static String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
+       
+       private ReadGraph graph;
+       private Map<Resource, XMLWriter> subWriters = new HashMap<Resource, XMLWriter>();
+       private Map<Class<? extends XMLElementWriter>, XMLElementWriter> namedWriters = new HashMap<Class<? extends XMLElementWriter>, XMLElementWriter>();
+       private Map<Resource,XMLElementWriter> writers = new HashMap<>();
+       private String schemaURI;
+       private String ontologyURI;
+       private Resource ontology;
+       
+       private ILogger logger;
+       
+       protected Map<String,String> nsPrefixes;
+       
+       public ReadGraph getGraph() {
+               return graph;
+       }
+       
+       public void setGraph(ReadGraph graph) throws DatabaseException {
+               this.graph = graph;
+               for (XMLWriter p : subWriters.values())
+                       p.setGraph(graph);
+               if (ontologyURI != null)
+                       this.ontology = graph.getResource(ontologyURI);
+       }
+       
+       public String getSchemaURI() {
+               return schemaURI;
+       }
+       
+       public void setSchemaURI(String schemaURI) {
+               this.schemaURI = schemaURI;
+       }
+       
+       public String getOntologyURI() {
+               return ontologyURI;
+       }
+       
+       public void setOntologyURI(String ontologyURI) {
+               this.ontologyURI = ontologyURI;
+       }
+       
+       public Resource getOntology() {
+               return ontology;
+       }
+       
+       public void add(XMLElementWriter writer) throws DatabaseException {
+               Resource type = writer.getType(graph);
+               if (type != null)
+                       writers.put(type, writer);
+               namedWriters.put(writer.getClass(), writer);
+       }
+       
+       public void add(XMLWriter writer) {
+               subWriters.put(writer.getOntology(), writer);
+       }
+       
+       public void configureWriter(XMLStreamWriter writer) throws XMLStreamException {
+               if (nsPrefixes == null)
+                       return;
+               for (Entry<String, String> nsEntry : nsPrefixes.entrySet()) {
+                       writer.setPrefix(nsEntry.getValue(), nsEntry.getKey());
+               }
+                       
+       }
+       
+       public void writeNS(XMLStreamWriter writer) throws XMLStreamException {
+               if (nsPrefixes == null)
+                       return;
+               for (Entry<String, String> nsEntry : nsPrefixes.entrySet()) {
+                       writer.writeNamespace(nsEntry.getValue(), nsEntry.getKey());
+               }
+                       
+       }
+       
+       public XMLWriter resolveDependencies(Session session) throws DatabaseException {
+               java.util.Map<String, XMLWriter> map = new java.util.HashMap<>();
+               map.put(this.schemaURI, this);
+               addDependencies(session,map);
+               nsPrefixes = new HashMap<>();
+               int i = 0;
+               for (String ns : map.keySet()) {
+                       if (this.schemaURI.equals(ns))
+                               continue;
+                       if (!nsPrefixes.containsKey(ns)) {
+                               nsPrefixes.put(ns, "ns"+i);
+                               i++;
+                       }
+               }
+               return this;
+       }
+       
+       public void addDependencies(Session session,java.util.Map<String,XMLWriter> map) throws DatabaseException {
+               
+       }
+       
+       public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {
+               WriterElement element = new WriterElement(root);
+               loadElement(element);
+               write(element, writer);
+       }
+       
+       
+       protected void write(WriterElement instance, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {
+               XMLResource XML = XMLResource.getInstance(graph);
+
+               XMLElementWriter elementWriter = instance.writer;
+               elementWriter.start(graph, instance, writer);
+               if (instance.parent == null) {
+                       if(getSchemaURI() != null) {
+                               writer.writeDefaultNamespace(getSchemaURI());
+                       }
+                       writer.writeNamespace("xsd", XML_SCHEMA_URI);
+                       writer.writeNamespace("xsi", XML_SCHEMA_INSTANCE_URI);
+                       this.configureWriter(writer);
+                       this.writeNS(writer);
+               }
+               
+               elementWriter.attributes(graph, instance, graph.getStatements(instance.instance, XML.hasAttribute), writer);
+               if (graph.hasValue(instance.instance))
+                       elementWriter.characters(graph, instance, writer);
+               // get all child elements
+               Set<Statement> childElements = new HashSet<>();
+               childElements.addAll(graph.getStatements(instance.instance, XML.hasElement));
+               childElements.addAll(graph.getStatements(instance.instance, XML.hasComplexType));
+               // load elements, assign writers
+               Map<Resource,WriterElement> elementMap = new HashMap<>();
+               for (Statement s : childElements) {
+                       WriterElement c = new WriterElement(instance,s);
+                       loadElement(c);
+                       elementMap.put(s.getObject(), c);
+               }
+               LinkedHashSet<Resource> sorted = new LinkedHashSet<>();
+               if (graph.hasStatement(instance.instance, XML.hasOriginalElementList)) {
+                       Resource originalList = graph.getSingleObject(instance.instance, XML.hasOriginalElementList);
+                       List<Resource> l = ListUtils.toList(graph, originalList);
+                       sorted.addAll(l);
+               }
+               elementWriter.children(graph, instance, sorted);
+               Set<Resource> processed = new HashSet<>();
+               for (Resource r : sorted) {
+                       if (processed.contains(r)) // badly generated writer could report elements several times. 
+                               continue;
+                       WriterElement child = elementMap.get(r);
+                       if (child == null)
+                               throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, r) + " " + r);
+                       write(child, writer);
+                       processed.add(r);
+               }
+               //write the rest of the elements (in random order) 
+               for (Statement stm : childElements) {
+                       if (processed.contains(stm.getObject()))
+                               continue;
+                       WriterElement child = elementMap.get(stm.getObject());
+                       if (child == null)
+                               throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, stm.getObject()) + " " + stm.getObject());
+                       write(child, writer);
+               }
+       
+               elementWriter.end(graph, instance, writer);
+               
+       }
+       
+       private void loadElement(WriterElement child) throws DatabaseException {
+               if (child.instance.getResourceId() == 983084L)
+                       System.out.println();
+               XMLElementWriter childWriter = null;
+               if (child.parent != null && child.parent.writer instanceof XMLElementNamedChildWriter) {
+                       XMLElementNamedChildWriter namedParentWriter = (XMLElementNamedChildWriter)child.parent.writer;
+                       Class<? extends XMLElementWriter> childWriterClass = namedParentWriter.getWriter(graph, writers, child);
+                       if (childWriterClass != null) {
+                               childWriter = this.writers.get(childWriterClass);
+                               if (childWriter == null) {
+                                       try {
+                                               Constructor<? extends XMLElementWriter> c = null;
+                                               try {
+                                                       c = childWriterClass.getConstructor(ReadGraph.class);
+                                                       childWriter = c.newInstance(graph);
+                                               } catch (NoSuchMethodException e) {
+                                                       c = childWriterClass.getConstructor();
+                                                       childWriter = c.newInstance();
+                                               }
+                                               namedWriters.put(childWriterClass, childWriter);
+                                       } catch (IllegalAccessException|InstantiationException|NoSuchMethodException|SecurityException|InvocationTargetException e) {
+                                               String err = "Error processing " + childWriterClass.getName() + " : element writers must have accessible constructor with ReadGraph parameter";
+                                               logger.log(new Status(IStatus.ERROR, XMLParser.PLUGIN_ID, err, e));
+                                       } 
+                               }
+                       }
+               } else {
+                       Resource type = graph.getSingleType(child.instance);
+                       childWriter = writers.get(type);
+               }
+               if (childWriter == null) {
+                       // try child ontology/schema
+                       //Resource type = graph.getSingleType(child.instance);
+                       // hack fix for elements containing character data (Current schema conversion does not recognise such cases, leaving Literal type inheritance out).
+                       XMLResource XML = XMLResource.getInstance(graph);
+                       Resource type = graph.getSingleType(child.instance,XML.Element);
+                       Resource ontology = getOntology(type);
+                       if (ontology != null) {
+                               XMLWriter xmlWriter = subWriters.get(ontology);
+                               if (xmlWriter == null) {
+                                       // FIXME: We need better way to resolve correct ontology and writer.
+                                       for (XMLWriter w : subWriters.values()) {
+                                               xmlWriter = w.subWriters.get(ontology);
+                                               if (xmlWriter != null)
+                                                       break;
+                                       }
+                               }
+                               if (xmlWriter != null) {
+                                       childWriter = xmlWriter.writers.get(type);
+                                       // wrap the child writer with namespace writer
+                                       if (childWriter != null) {
+                                               if (childWriter instanceof XMLElementNamedChildWriter) {
+                                                       childWriter = new XMLNSNamedChildWriter((XMLElementNamedChildWriter)childWriter, xmlWriter.schemaURI);
+                                               } else {
+                                                       childWriter = new XMLNSElementWriter(childWriter, xmlWriter.schemaURI);
+                                               }
+                                       }
+                               }
+                       }
+                       if (childWriter == null)
+                               throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);
+               }
+               child.writer = childWriter;
+               
+       }
+       
+       private Resource getOntology(Resource type) throws DatabaseException {
+               Layer0 L0 = Layer0.getInstance(graph);
+               Resource r = type;
+               while (true) {
+                       r = graph.getPossibleObject(r, L0.PartOf);
+                       if (r != null && graph.isInstanceOf(r, L0.Ontology))
+                               break;
+               }
+               return r;
+       }
+
+}