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 private ReadGraph graph;
\r
30 private Map<Resource, XMLWriter> subWriters = new HashMap<Resource, 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 private String ontologyURI;
\r
35 private Resource ontology;
\r
37 private ILogger logger;
\r
39 public ReadGraph getGraph() {
\r
43 public void setGraph(ReadGraph graph) throws DatabaseException {
\r
45 for (XMLWriter p : subWriters.values())
\r
47 if (ontologyURI != null)
\r
48 this.ontology = graph.getResource(ontologyURI);
\r
51 public String getSchemaURI() {
\r
55 public void setSchemaURI(String schemaURI) {
\r
56 this.schemaURI = schemaURI;
\r
59 public String getOntologyURI() {
\r
63 public void setOntologyURI(String ontologyURI) {
\r
64 this.ontologyURI = ontologyURI;
\r
67 public Resource getOntology() {
\r
71 public void add(XMLElementWriter writer) throws DatabaseException {
\r
72 Resource type = writer.getType(graph);
\r
74 writers.put(type, writer);
\r
75 namedWriters.put(writer.getClass(), writer);
\r
78 public void add(XMLWriter writer) {
\r
79 subWriters.put(writer.getOntology(), writer);
\r
82 public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {
\r
83 WriterElement element = new WriterElement(root);
\r
84 loadElement(element);
\r
85 write(element, writer);
\r
89 protected void write(WriterElement instance, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {
\r
90 XMLResource XML = XMLResource.getInstance(graph);
\r
92 XMLElementWriter elementWriter = instance.writer;
\r
93 elementWriter.start(graph, instance, writer);
\r
94 if (instance.parent == null) {
\r
95 if(getSchemaURI() != null) {
\r
96 writer.writeDefaultNamespace(getSchemaURI());
\r
99 elementWriter.attributes(graph, instance, graph.getStatements(instance.instance, XML.hasAttribute), writer);
\r
100 if (graph.hasValue(instance.instance))
\r
101 elementWriter.characters(graph, instance, writer);
\r
102 // get all child elements
\r
103 Set<Statement> childElements = new HashSet<>();
\r
104 childElements.addAll(graph.getStatements(instance.instance, XML.hasElement));
\r
105 childElements.addAll(graph.getStatements(instance.instance, XML.hasComplexType));
\r
106 // load elements, assign writers
\r
107 Map<Resource,WriterElement> elementMap = new HashMap<>();
\r
108 for (Statement s : childElements) {
\r
109 WriterElement c = new WriterElement(instance,s);
\r
111 elementMap.put(s.getObject(), c);
\r
113 LinkedHashSet<Resource> sorted = new LinkedHashSet<>();
\r
114 if (graph.hasStatement(instance.instance, XML.hasOriginalElementList)) {
\r
115 Resource originalList = graph.getSingleObject(instance.instance, XML.hasOriginalElementList);
\r
116 List<Resource> l = ListUtils.toList(graph, originalList);
\r
119 elementWriter.children(graph, instance, sorted);
\r
120 Set<Resource> processed = new HashSet<>();
\r
121 for (Resource r : sorted) {
\r
122 if (processed.contains(r)) // badly generated writer could report elements several times.
\r
124 WriterElement child = elementMap.get(r);
\r
126 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, r) + " " + r);
\r
127 write(child, writer);
\r
130 //write the rest of the elements (in random order)
\r
131 for (Statement stm : childElements) {
\r
132 if (processed.contains(stm.getObject()))
\r
134 WriterElement child = elementMap.get(stm.getObject());
\r
136 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, stm.getObject()) + " " + stm.getObject());
\r
137 write(child, writer);
\r
140 elementWriter.end(graph, instance, writer);
\r
144 private void loadElement(WriterElement child) throws DatabaseException {
\r
145 XMLElementWriter childWriter = null;
\r
146 if (child.parent != null && child.parent.writer instanceof XMLElementNamedChildWriter) {
\r
147 XMLElementNamedChildWriter namedParentWriter = (XMLElementNamedChildWriter)child.parent.writer;
\r
148 Class<? extends XMLElementWriter> childWriterClass = namedParentWriter.getWriter(graph, writers, child);
\r
149 if (childWriterClass != null) {
\r
150 childWriter = this.writers.get(childWriterClass);
\r
151 if (childWriter == null) {
\r
153 Constructor<? extends XMLElementWriter> c = null;
\r
155 c = childWriterClass.getConstructor(ReadGraph.class);
\r
156 childWriter = c.newInstance(graph);
\r
157 } catch (NoSuchMethodException e) {
\r
158 c = childWriterClass.getConstructor();
\r
159 childWriter = c.newInstance();
\r
161 //childWriter = childWriterClass.newInstance();
\r
163 namedWriters.put(childWriterClass, childWriter);
\r
164 } catch (IllegalAccessException|InstantiationException|NoSuchMethodException|SecurityException|InvocationTargetException e) {
\r
165 String err = "Error processing " + childWriterClass.getName() + " : element writers must have accessible constructor with ReadGraph parameter";
\r
166 logger.log(new Status(IStatus.ERROR, XMLParser.PLUGIN_ID, err, e));
\r
171 Resource type = graph.getSingleType(child.instance);
\r
172 childWriter = writers.get(type);
\r
174 if (childWriter == null) {
\r
175 Resource type = graph.getSingleType(child.instance);
\r
176 Resource ontology = getOntology(type);
\r
177 if (ontology != null) {
\r
178 XMLWriter xmlWriter = subWriters.get(ontology);
\r
179 if (xmlWriter != null) {
\r
180 childWriter = xmlWriter.writers.get(type);
\r
183 if (childWriter == null)
\r
184 throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);
\r
186 child.writer = childWriter;
\r
190 private Resource getOntology(Resource type) throws DatabaseException {
\r
191 Layer0 L0 = Layer0.getInstance(graph);
\r
194 r = graph.getPossibleObject(r, L0.PartOf);
\r
195 if (r != null && graph.isInstanceOf(r, L0.Ontology))
\r