]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLWriter.java
0881a5d109d3b3b56ba7e287e594da67c282078e
[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.Collection;\r
6 import java.util.HashMap;\r
7 import java.util.HashSet;\r
8 import java.util.LinkedHashSet;\r
9 import java.util.List;\r
10 import java.util.Map;\r
11 import java.util.Set;\r
12 \r
13 import javax.xml.stream.XMLStreamException;\r
14 import javax.xml.stream.XMLStreamWriter;\r
15 \r
16 import org.eclipse.core.runtime.IStatus;\r
17 import org.eclipse.core.runtime.Status;\r
18 import org.simantics.db.ReadGraph;\r
19 import org.simantics.db.Resource;\r
20 import org.simantics.db.Statement;\r
21 import org.simantics.db.common.utils.ListUtils;\r
22 import org.simantics.db.common.utils.NameUtils;\r
23 import org.simantics.db.exception.DatabaseException;\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         private ReadGraph graph;\r
30         private Map<String, XMLWriter> subWriters = new HashMap<String, XMLWriter>();\r
31         private Map<Class<? extends XMLElementWriter>, XMLElementWriter> namedWriters = new HashMap<Class<? extends XMLElementWriter>, XMLElementWriter>();\r
32         private Map<Resource,XMLElementWriter> writers = new HashMap<>();\r
33         private String schemaURI;\r
34         \r
35         private ILogger logger;\r
36         \r
37         public ReadGraph getGraph() {\r
38                 return graph;\r
39         }\r
40         \r
41         public void setGraph(ReadGraph graph) {\r
42                 this.graph = graph;\r
43                 for (XMLWriter p : subWriters.values())\r
44                         p.setGraph(graph);\r
45         }\r
46         \r
47         public String getSchemaURI() {\r
48                 return schemaURI;\r
49         }\r
50         \r
51         public void setSchemaURI(String schemaURI) {\r
52                 this.schemaURI = schemaURI;\r
53         }\r
54         \r
55         public void add(XMLElementWriter writer) throws DatabaseException {\r
56                 Resource type = writer.getType(graph);\r
57                 if (type != null)\r
58                         writers.put(type, writer);\r
59                 namedWriters.put(writer.getClass(), writer);\r
60         }\r
61         \r
62         public void add(XMLWriter writer) {\r
63                 subWriters.put(writer.getSchemaURI(), writer);\r
64         }\r
65         \r
66         public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
67                 WriterElement element = new WriterElement(root);\r
68                 loadElement(element);\r
69                 write(element, writer);\r
70         }\r
71         \r
72         \r
73         protected void write(WriterElement instance, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {\r
74                 XMLResource XML = XMLResource.getInstance(graph);\r
75 \r
76                 XMLElementWriter elementWriter = instance.writer;\r
77                 elementWriter.start(graph, instance, writer);\r
78                 if (instance.parent == null) {\r
79                         if(getSchemaURI() != null) {\r
80                                 writer.writeDefaultNamespace(getSchemaURI());\r
81                         }\r
82                 }\r
83                 elementWriter.attributes(graph, instance, graph.getStatements(instance.instance, XML.hasAttribute), writer);\r
84                 if (graph.hasValue(instance.instance))\r
85                         elementWriter.characters(graph, instance, writer);\r
86                 // get all child elements\r
87                 Collection<Statement> childElements = graph.getStatements(instance.instance, XML.hasElement);\r
88                 // load elements, assign writers\r
89                 Map<Resource,WriterElement> elementMap = new HashMap<>();\r
90                 for (Statement s : childElements) {\r
91                         WriterElement c = new WriterElement(instance,s);\r
92                         loadElement(c);\r
93                         elementMap.put(s.getObject(), c);\r
94                 }\r
95                 LinkedHashSet<Resource> sorted = new LinkedHashSet<>();\r
96                 if (graph.hasStatement(instance.instance, XML.hasOriginalElementList)) {\r
97                         Resource originalList = graph.getSingleObject(instance.instance, XML.hasOriginalElementList);\r
98                         List<Resource> l = ListUtils.toList(graph, originalList);\r
99                         sorted.addAll(l);\r
100                 }\r
101                 elementWriter.children(graph, instance, sorted);\r
102                 Set<Resource> processed = new HashSet<>();\r
103                 for (Resource r : sorted) {\r
104                         if (processed.contains(r)) // badly generated writer could report elements several times. \r
105                                 continue;\r
106                         WriterElement child = elementMap.get(r);\r
107                         write(child, writer);\r
108                         processed.add(r);\r
109                 }\r
110                 //write the rest of the elements (in random order) \r
111                 for (Statement stm : childElements) {\r
112                         if (processed.contains(stm.getObject()))\r
113                                 continue;\r
114                         WriterElement child = elementMap.get(stm.getObject());\r
115                         write(child, writer);\r
116                 }\r
117         \r
118                 elementWriter.end(graph, instance, writer);\r
119                 \r
120         }\r
121         \r
122         private void loadElement(WriterElement child) throws DatabaseException {\r
123                 XMLElementWriter childWriter = null;\r
124                 if (child.parent != null && child.parent.writer instanceof XMLElementNamedChildWriter) {\r
125                         XMLElementNamedChildWriter namedParentWriter = (XMLElementNamedChildWriter)child.parent.writer;\r
126                         Class<? extends XMLElementWriter> childWriterClass = namedParentWriter.getWriter(graph, writers, child);\r
127                         if (childWriterClass != null) {\r
128                                 childWriter = this.writers.get(childWriterClass);\r
129                                 if (childWriter == null) {\r
130                                         try {\r
131                                                 Constructor<? extends XMLElementWriter> c = childWriterClass.getConstructor(ReadGraph.class);\r
132                                                 //childWriter = childWriterClass.newInstance();\r
133                                                 childWriter = c.newInstance(graph);\r
134                                                 namedWriters.put(childWriterClass, childWriter);\r
135                                         } catch (IllegalAccessException|InstantiationException|NoSuchMethodException|SecurityException|InvocationTargetException e) {\r
136                                                 String err = "Error processing " + childWriterClass.getName() + " : element writers must have accessible constructor with ReadGraph parameter";\r
137                                                 logger.log(new Status(IStatus.ERROR, XMLParser.PLUGIN_ID, err));\r
138                                         } \r
139                                 }\r
140                         }\r
141                 } else {\r
142                         Resource type = graph.getSingleType(child.instance);\r
143                         childWriter = writers.get(type);\r
144                 }\r
145                 if (childWriter == null) {\r
146                         throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);\r
147                 }\r
148                 child.writer = childWriter;\r
149                 \r
150         }\r
151 \r
152 }\r