]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLWriter.java
Export XML Namespaces
[simantics/interop.git] / org.simantics.xml.sax.base / src / org / simantics / xml / sax / base / XMLWriter.java
1 package org.simantics.xml.sax.base;\r
2 \r
3 import java.lang.reflect.Constructor;\r
4 import java.lang.reflect.InvocationTargetException;\r
5 import java.util.HashMap;\r
6 import java.util.HashSet;\r
7 import java.util.LinkedHashSet;\r
8 import java.util.List;\r
9 import java.util.Map;\r
10 import java.util.Set;\r
11 \r
12 import javax.xml.stream.XMLStreamException;\r
13 import javax.xml.stream.XMLStreamWriter;\r
14 \r
15 import org.eclipse.core.runtime.IStatus;\r
16 import org.eclipse.core.runtime.Status;\r
17 import org.simantics.db.ReadGraph;\r
18 import org.simantics.db.Resource;\r
19 import org.simantics.db.Statement;\r
20 import org.simantics.db.common.utils.ListUtils;\r
21 import org.simantics.db.common.utils.NameUtils;\r
22 import org.simantics.db.exception.DatabaseException;\r
23 import org.simantics.layer0.Layer0;\r
24 import org.simantics.message.ILogger;\r
25 import org.simantics.xml.sax.ontology.XMLResource;\r
26 \r
27 public class XMLWriter {\r
28         \r
29         public static String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";\r
30         public static String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";\r
31         \r
32         private ReadGraph graph;\r
33         private Map<Resource, XMLWriter> subWriters = new HashMap<Resource, XMLWriter>();\r
34         private Map<Class<? extends XMLElementWriter>, XMLElementWriter> namedWriters = new HashMap<Class<? extends XMLElementWriter>, XMLElementWriter>();\r
35         private Map<Resource,XMLElementWriter> writers = new HashMap<>();\r
36         private String schemaURI;\r
37         private String ontologyURI;\r
38         private Resource ontology;\r
39         \r
40         private ILogger logger;\r
41         \r
42         public ReadGraph getGraph() {\r
43                 return graph;\r
44         }\r
45         \r
46         public void setGraph(ReadGraph graph) throws DatabaseException {\r
47                 this.graph = graph;\r
48                 for (XMLWriter p : subWriters.values())\r
49                         p.setGraph(graph);\r
50                 if (ontologyURI != null)\r
51                         this.ontology = graph.getResource(ontologyURI);\r
52         }\r
53         \r
54         public String getSchemaURI() {\r
55                 return schemaURI;\r
56         }\r
57         \r
58         public void setSchemaURI(String schemaURI) {\r
59                 this.schemaURI = schemaURI;\r
60         }\r
61         \r
62         public String getOntologyURI() {\r
63                 return ontologyURI;\r
64         }\r
65         \r
66         public void setOntologyURI(String ontologyURI) {\r
67                 this.ontologyURI = ontologyURI;\r
68         }\r
69         \r
70         public Resource getOntology() {\r
71                 return ontology;\r
72         }\r
73         \r
74         public void add(XMLElementWriter writer) throws DatabaseException {\r
75                 Resource type = writer.getType(graph);\r
76                 if (type != null)\r
77                         writers.put(type, writer);\r
78                 namedWriters.put(writer.getClass(), writer);\r
79         }\r
80         \r
81         public void add(XMLWriter writer) {\r
82                 subWriters.put(writer.getOntology(), writer);\r
83         }\r
84         \r
85         public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
86                 WriterElement element = new WriterElement(root);\r
87                 loadElement(element);\r
88                 write(element, writer);\r
89         }\r
90         \r
91         \r
92         protected void write(WriterElement instance, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
93                 XMLResource XML = XMLResource.getInstance(graph);\r
94 \r
95                 XMLElementWriter elementWriter = instance.writer;\r
96                 elementWriter.start(graph, instance, writer);\r
97                 if (instance.parent == null) {\r
98                         if(getSchemaURI() != null) {\r
99                                 writer.writeDefaultNamespace(getSchemaURI());\r
100                         }\r
101                         writer.writeNamespace("xsd", XML_SCHEMA_URI);\r
102                         writer.writeNamespace("xsi", XML_SCHEMA_INSTANCE_URI);\r
103                 }\r
104                 elementWriter.attributes(graph, instance, graph.getStatements(instance.instance, XML.hasAttribute), writer);\r
105                 if (graph.hasValue(instance.instance))\r
106                         elementWriter.characters(graph, instance, writer);\r
107                 // get all child elements\r
108                 Set<Statement> childElements = new HashSet<>();\r
109                 childElements.addAll(graph.getStatements(instance.instance, XML.hasElement));\r
110                 childElements.addAll(graph.getStatements(instance.instance, XML.hasComplexType));\r
111                 // load elements, assign writers\r
112                 Map<Resource,WriterElement> elementMap = new HashMap<>();\r
113                 for (Statement s : childElements) {\r
114                         WriterElement c = new WriterElement(instance,s);\r
115                         loadElement(c);\r
116                         elementMap.put(s.getObject(), c);\r
117                 }\r
118                 LinkedHashSet<Resource> sorted = new LinkedHashSet<>();\r
119                 if (graph.hasStatement(instance.instance, XML.hasOriginalElementList)) {\r
120                         Resource originalList = graph.getSingleObject(instance.instance, XML.hasOriginalElementList);\r
121                         List<Resource> l = ListUtils.toList(graph, originalList);\r
122                         sorted.addAll(l);\r
123                 }\r
124                 elementWriter.children(graph, instance, sorted);\r
125                 Set<Resource> processed = new HashSet<>();\r
126                 for (Resource r : sorted) {\r
127                         if (processed.contains(r)) // badly generated writer could report elements several times. \r
128                                 continue;\r
129                         WriterElement child = elementMap.get(r);\r
130                         if (child == null)\r
131                                 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, r) + " " + r);\r
132                         write(child, writer);\r
133                         processed.add(r);\r
134                 }\r
135                 //write the rest of the elements (in random order) \r
136                 for (Statement stm : childElements) {\r
137                         if (processed.contains(stm.getObject()))\r
138                                 continue;\r
139                         WriterElement child = elementMap.get(stm.getObject());\r
140                         if (child == null)\r
141                                 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, stm.getObject()) + " " + stm.getObject());\r
142                         write(child, writer);\r
143                 }\r
144         \r
145                 elementWriter.end(graph, instance, writer);\r
146                 \r
147         }\r
148         \r
149         private void loadElement(WriterElement child) throws DatabaseException {\r
150                 XMLElementWriter childWriter = null;\r
151                 if (child.parent != null && child.parent.writer instanceof XMLElementNamedChildWriter) {\r
152                         XMLElementNamedChildWriter namedParentWriter = (XMLElementNamedChildWriter)child.parent.writer;\r
153                         Class<? extends XMLElementWriter> childWriterClass = namedParentWriter.getWriter(graph, writers, child);\r
154                         if (childWriterClass != null) {\r
155                                 childWriter = this.writers.get(childWriterClass);\r
156                                 if (childWriter == null) {\r
157                                         try {\r
158                                                 Constructor<? extends XMLElementWriter> c = null;\r
159                                                 try {\r
160                                                         c = childWriterClass.getConstructor(ReadGraph.class);\r
161                                                         childWriter = c.newInstance(graph);\r
162                                                 } catch (NoSuchMethodException e) {\r
163                                                         c = childWriterClass.getConstructor();\r
164                                                         childWriter = c.newInstance();\r
165                                                 }\r
166                                                 //childWriter = childWriterClass.newInstance();\r
167                                                 \r
168                                                 namedWriters.put(childWriterClass, childWriter);\r
169                                         } catch (IllegalAccessException|InstantiationException|NoSuchMethodException|SecurityException|InvocationTargetException e) {\r
170                                                 String err = "Error processing " + childWriterClass.getName() + " : element writers must have accessible constructor with ReadGraph parameter";\r
171                                                 logger.log(new Status(IStatus.ERROR, XMLParser.PLUGIN_ID, err, e));\r
172                                         } \r
173                                 }\r
174                         }\r
175                 } else {\r
176                         Resource type = graph.getSingleType(child.instance);\r
177                         childWriter = writers.get(type);\r
178                 }\r
179                 if (childWriter == null) {\r
180                         Resource type = graph.getSingleType(child.instance);\r
181                         Resource ontology = getOntology(type);\r
182                         if (ontology != null) {\r
183                                 XMLWriter xmlWriter = subWriters.get(ontology);\r
184                                 if (xmlWriter != null) {\r
185                                         childWriter = xmlWriter.writers.get(type);\r
186                                         // wrap the child writer with namespace writer\r
187                                         if (childWriter instanceof XMLElementNamedChildWriter) {\r
188                                                 childWriter = new XMLNSNamedChildWriter((XMLElementNamedChildWriter)childWriter, xmlWriter.schemaURI);\r
189                                         } else {\r
190                                                 childWriter = new XMLNSElementWriter(childWriter, xmlWriter.schemaURI);\r
191                                         }\r
192                                 }\r
193                         }\r
194                         if (childWriter == null)\r
195                                 throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);\r
196                 }\r
197                 child.writer = childWriter;\r
198                 \r
199         }\r
200         \r
201         private Resource getOntology(Resource type) throws DatabaseException {\r
202                 Layer0 L0 = Layer0.getInstance(graph);\r
203                 Resource r = type;\r
204                 while (true) {\r
205                         r = graph.getPossibleObject(r, L0.PartOf);\r
206                         if (r != null && graph.isInstanceOf(r, L0.Ontology))\r
207                                 break;\r
208                 }\r
209                 return r;\r
210         }\r
211 \r
212 }\r