1 package org.simantics.xml.sax.base;
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.LinkedHashSet;
10 import java.util.Map.Entry;
13 import javax.xml.stream.XMLStreamException;
14 import javax.xml.stream.XMLStreamWriter;
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.Status;
18 import org.simantics.db.ReadGraph;
19 import org.simantics.db.Resource;
20 import org.simantics.db.Session;
21 import org.simantics.db.Statement;
22 import org.simantics.db.common.utils.ListUtils;
23 import org.simantics.db.common.utils.NameUtils;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.layer0.Layer0;
26 import org.simantics.message.ILogger;
27 import org.simantics.xml.sax.ontology.XMLResource;
29 public class XMLWriter {
31 public static String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
32 public static String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
34 private ReadGraph graph;
35 private Map<Resource, XMLWriter> subWriters = new HashMap<Resource, XMLWriter>();
36 private Map<Class<? extends XMLElementWriter>, XMLElementWriter> namedWriters = new HashMap<Class<? extends XMLElementWriter>, XMLElementWriter>();
37 private Map<Resource,XMLElementWriter> writers = new HashMap<>();
38 private String schemaURI;
39 private String ontologyURI;
40 private Resource ontology;
42 private ILogger logger;
44 protected Map<String,String> nsPrefixes;
46 public ReadGraph getGraph() {
50 public void setGraph(ReadGraph graph) throws DatabaseException {
52 for (XMLWriter p : subWriters.values())
54 if (ontologyURI != null)
55 this.ontology = graph.getResource(ontologyURI);
58 public String getSchemaURI() {
62 public void setSchemaURI(String schemaURI) {
63 this.schemaURI = schemaURI;
66 public String getOntologyURI() {
70 public void setOntologyURI(String ontologyURI) {
71 this.ontologyURI = ontologyURI;
74 public Resource getOntology() {
78 public void add(XMLElementWriter writer) throws DatabaseException {
79 Resource type = writer.getType(graph);
81 writers.put(type, writer);
82 namedWriters.put(writer.getClass(), writer);
85 public void add(XMLWriter writer) {
86 subWriters.put(writer.getOntology(), writer);
89 public void configureWriter(XMLStreamWriter writer) throws XMLStreamException {
90 if (nsPrefixes == null)
92 for (Entry<String, String> nsEntry : nsPrefixes.entrySet()) {
93 writer.setPrefix(nsEntry.getValue(), nsEntry.getKey());
98 public void writeNS(XMLStreamWriter writer) throws XMLStreamException {
99 if (nsPrefixes == null)
101 for (Entry<String, String> nsEntry : nsPrefixes.entrySet()) {
102 writer.writeNamespace(nsEntry.getValue(), nsEntry.getKey());
107 public XMLWriter resolveDependencies(Session session) throws DatabaseException {
108 java.util.Map<String, XMLWriter> map = new java.util.HashMap<>();
109 map.put(this.schemaURI, this);
110 addDependencies(session,map);
111 nsPrefixes = new HashMap<>();
113 for (String ns : map.keySet()) {
114 if (this.schemaURI.equals(ns))
116 if (!nsPrefixes.containsKey(ns)) {
117 nsPrefixes.put(ns, "ns"+i);
124 public void addDependencies(Session session,java.util.Map<String,XMLWriter> map) throws DatabaseException {
128 public void write(Resource root, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {
129 WriterElement element = new WriterElement(root);
130 loadElement(element);
131 write(element, writer);
135 protected void write(WriterElement instance, XMLStreamWriter writer) throws DatabaseException, XMLStreamException {
136 XMLResource XML = XMLResource.getInstance(graph);
138 XMLElementWriter elementWriter = instance.writer;
139 elementWriter.start(graph, instance, writer);
140 if (instance.parent == null) {
141 if(getSchemaURI() != null) {
142 writer.writeDefaultNamespace(getSchemaURI());
144 writer.writeNamespace("xsd", XML_SCHEMA_URI);
145 writer.writeNamespace("xsi", XML_SCHEMA_INSTANCE_URI);
146 this.configureWriter(writer);
147 this.writeNS(writer);
150 elementWriter.attributes(graph, instance, graph.getStatements(instance.instance, XML.hasAttribute), writer);
151 if (graph.hasValue(instance.instance))
152 elementWriter.characters(graph, instance, writer);
153 // get all child elements
154 Set<Statement> childElements = new HashSet<>();
155 childElements.addAll(graph.getStatements(instance.instance, XML.hasElement));
156 childElements.addAll(graph.getStatements(instance.instance, XML.hasComplexType));
157 // load elements, assign writers
158 Map<Resource,WriterElement> elementMap = new HashMap<>();
159 for (Statement s : childElements) {
160 WriterElement c = new WriterElement(instance,s);
162 elementMap.put(s.getObject(), c);
164 LinkedHashSet<Resource> sorted = new LinkedHashSet<>();
165 if (graph.hasStatement(instance.instance, XML.hasOriginalElementList)) {
166 Resource originalList = graph.getSingleObject(instance.instance, XML.hasOriginalElementList);
167 List<Resource> l = ListUtils.toList(graph, originalList);
170 elementWriter.children(graph, instance, sorted);
171 Set<Resource> processed = new HashSet<>();
172 for (Resource r : sorted) {
173 if (processed.contains(r)) // badly generated writer could report elements several times.
175 WriterElement child = elementMap.get(r);
177 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, r) + " " + r);
178 write(child, writer);
181 //write the rest of the elements (in random order)
182 for (Statement stm : childElements) {
183 if (processed.contains(stm.getObject()))
185 WriterElement child = elementMap.get(stm.getObject());
187 throw new DatabaseException("Trying to export unregonized resource " +NameUtils.getSafeName(graph, stm.getObject()) + " " + stm.getObject());
188 write(child, writer);
191 elementWriter.end(graph, instance, writer);
195 private void loadElement(WriterElement child) throws DatabaseException {
196 if (child.instance.getResourceId() == 983084L)
197 System.out.println();
198 XMLElementWriter childWriter = null;
199 if (child.parent != null && child.parent.writer instanceof XMLElementNamedChildWriter) {
200 XMLElementNamedChildWriter namedParentWriter = (XMLElementNamedChildWriter)child.parent.writer;
201 Class<? extends XMLElementWriter> childWriterClass = namedParentWriter.getWriter(graph, writers, child);
202 if (childWriterClass != null) {
203 childWriter = this.writers.get(childWriterClass);
204 if (childWriter == null) {
206 Constructor<? extends XMLElementWriter> c = null;
208 c = childWriterClass.getConstructor(ReadGraph.class);
209 childWriter = c.newInstance(graph);
210 } catch (NoSuchMethodException e) {
211 c = childWriterClass.getConstructor();
212 childWriter = c.newInstance();
214 namedWriters.put(childWriterClass, childWriter);
215 } catch (IllegalAccessException|InstantiationException|NoSuchMethodException|SecurityException|InvocationTargetException e) {
216 String err = "Error processing " + childWriterClass.getName() + " : element writers must have accessible constructor with ReadGraph parameter";
217 logger.log(new Status(IStatus.ERROR, XMLParser.PLUGIN_ID, err, e));
222 Resource type = graph.getSingleType(child.instance);
223 childWriter = writers.get(type);
225 if (childWriter == null) {
226 // try child ontology/schema
227 //Resource type = graph.getSingleType(child.instance);
228 // hack fix for elements containing character data (Current schema conversion does not recognise such cases, leaving Literal type inheritance out).
229 XMLResource XML = XMLResource.getInstance(graph);
230 Resource type = graph.getSingleType(child.instance,XML.Element);
231 Resource ontology = getOntology(type);
232 if (ontology != null) {
233 XMLWriter xmlWriter = subWriters.get(ontology);
234 if (xmlWriter == null) {
235 // FIXME: We need better way to resolve correct ontology and writer.
236 for (XMLWriter w : subWriters.values()) {
237 xmlWriter = w.subWriters.get(ontology);
238 if (xmlWriter != null)
242 if (xmlWriter != null) {
243 childWriter = xmlWriter.writers.get(type);
244 // wrap the child writer with namespace writer
245 if (childWriter != null) {
246 if (childWriter instanceof XMLElementNamedChildWriter) {
247 childWriter = new XMLNSNamedChildWriter((XMLElementNamedChildWriter)childWriter, xmlWriter.schemaURI);
249 childWriter = new XMLNSElementWriter(childWriter, xmlWriter.schemaURI);
254 if (childWriter == null)
255 throw new DatabaseException("Cannot locate writer for " + NameUtils.getSafeName(graph, child.instance) + ", " + child.instance);
257 child.writer = childWriter;
261 private Resource getOntology(Resource type) throws DatabaseException {
262 Layer0 L0 = Layer0.getInstance(graph);
265 r = graph.getPossibleObject(r, L0.PartOf);
266 if (r != null && graph.isInstanceOf(r, L0.Ontology))