1 package org.simantics.xml.sax.base;
\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
12 import javax.xml.stream.XMLStreamException;
\r
13 import javax.xml.stream.XMLStreamWriter;
\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
27 public class XMLWriter {
\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
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
40 private ILogger logger;
\r
42 public ReadGraph getGraph() {
\r
46 public void setGraph(ReadGraph graph) throws DatabaseException {
\r
48 for (XMLWriter p : subWriters.values())
\r
50 if (ontologyURI != null)
\r
51 this.ontology = graph.getResource(ontologyURI);
\r
54 public String getSchemaURI() {
\r
58 public void setSchemaURI(String schemaURI) {
\r
59 this.schemaURI = schemaURI;
\r
62 public String getOntologyURI() {
\r
66 public void setOntologyURI(String ontologyURI) {
\r
67 this.ontologyURI = ontologyURI;
\r
70 public Resource getOntology() {
\r
74 public void add(XMLElementWriter writer) throws DatabaseException {
\r
75 Resource type = writer.getType(graph);
\r
77 writers.put(type, writer);
\r
78 namedWriters.put(writer.getClass(), writer);
\r
81 public void add(XMLWriter writer) {
\r
82 subWriters.put(writer.getOntology(), writer);
\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
92 protected void write(WriterElement instance, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {
\r
93 XMLResource XML = XMLResource.getInstance(graph);
\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
101 writer.writeNamespace("xsd", XML_SCHEMA_URI);
\r
102 writer.writeNamespace("xsi", XML_SCHEMA_INSTANCE_URI);
\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
116 elementMap.put(s.getObject(), c);
\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
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
129 WriterElement child = elementMap.get(r);
\r
131 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, r) + " " + r);
\r
132 write(child, writer);
\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
139 WriterElement child = elementMap.get(stm.getObject());
\r
141 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, stm.getObject()) + " " + stm.getObject());
\r
142 write(child, writer);
\r
145 elementWriter.end(graph, instance, writer);
\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
158 Constructor<? extends XMLElementWriter> c = null;
\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
166 //childWriter = childWriterClass.newInstance();
\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
176 Resource type = graph.getSingleType(child.instance);
\r
177 childWriter = writers.get(type);
\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
190 childWriter = new XMLNSElementWriter(childWriter, xmlWriter.schemaURI);
\r
194 if (childWriter == null)
\r
195 throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);
\r
197 child.writer = childWriter;
\r
201 private Resource getOntology(Resource type) throws DatabaseException {
\r
202 Layer0 L0 = Layer0.getInstance(graph);
\r
205 r = graph.getPossibleObject(r, L0.PartOf);
\r
206 if (r != null && graph.isInstanceOf(r, L0.Ontology))
\r