]> gerrit.simantics Code Review - simantics/interop.git/blobdiff - org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java
XML Schema converter
[simantics/interop.git] / org.simantics.xml.sax.base / src / org / simantics / xml / sax / base / XMLParser.java
diff --git a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java
new file mode 100644 (file)
index 0000000..be8fef0
--- /dev/null
@@ -0,0 +1,237 @@
+package org.simantics.xml.sax.base;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.Serializable;\r
+import java.util.ArrayDeque;\r
+import java.util.ArrayList;\r
+import java.util.Deque;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import javax.xml.parsers.SAXParser;\r
+import javax.xml.parsers.SAXParserFactory;\r
+\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.message.ILogger;\r
+import org.xml.sax.Attributes;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.XMLReader;\r
+import org.xml.sax.helpers.DefaultHandler;\r
+\r
+public class XMLParser extends DefaultHandler implements Serializable {\r
+\r
+       private static final long serialVersionUID = 7360740940824360338L;\r
+       private static final boolean debug = false;\r
+       private ILogger logger;\r
+       private Resource root;\r
+       private Deque<Element> current = new ArrayDeque<Element>();\r
+       private Map<String, XMLElementParser> parsers = new HashMap<String, XMLElementParser>();\r
+       private WriteGraph graph;\r
+       \r
+       private Map<Class<? extends XMLElementParser>, XMLElementParser> namedParsers = new HashMap<Class<? extends XMLElementParser>, XMLElementParser>();\r
+       \r
+       public XMLParser(WriteGraph graph) {\r
+               this.graph = graph;\r
+       }\r
+       \r
+       public void add(XMLElementParser parser) {\r
+               if (parser.getElementId() != null)\r
+                       parsers.put(parser.getElementId(), parser);\r
+               namedParsers.put(parser.getClass(), parser);\r
+       }\r
+       \r
+       \r
+       private List<Element> idReferenceElements = new ArrayList<Element>();\r
+       private void loadElement(Deque<Element> parents, Element element) throws SAXException{\r
+               XMLElementParser parser = null;\r
+               Element parent = null;\r
+               if (parents.size() > 0) {\r
+                       parent = parents.peek();\r
+                       if (parent.getParser() instanceof XMLElementNamedChildParser) {\r
+                               // use parent's named child parser if it is supported\r
+                               Class<? extends XMLElementParser> parserClass = ((XMLElementNamedChildParser)parent.getParser()).getParser(parsers,parent,element);\r
+                               if (parserClass != null) {\r
+                                       parser = namedParsers.get(parserClass);\r
+                                       if (parser == null) {\r
+                                               try {\r
+                                                       parser = parserClass.newInstance();\r
+                                                       namedParsers.put(parserClass, parser);\r
+                                               } catch (IllegalAccessException | InstantiationException e) {\r
+                                                       String err = "Element parsers must have accessible default constructor";\r
+                                                       logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
+                                                       throw new SAXException(err, e);\r
+                                               }\r
+                                       }\r
+                               } \r
+//                             if (parser == null && ((XMLElementNamedChildParser)parent.getParser()).useGlobalRules())\r
+//                                     parser = parsers.get(element.qName);\r
+                       } else {\r
+                               // otherwise use globally configured element parser\r
+                               parser = parsers.get(element.qName);\r
+                       }\r
+               } else {\r
+                       // use globally configured element parser\r
+                       parser = parsers.get(element.qName);\r
+               }\r
+               \r
+               if (parser != null) {\r
+                       try {\r
+                               \r
+                               element.setData(parser.create(graph, element));\r
+                               if (parser instanceof IDReferenceParser)\r
+                                       idReferenceElements.add(element);\r
+                               element.setParser(parser);\r
+                       } catch (DatabaseException e) {\r
+                               throw new SAXException(e);\r
+                       }\r
+               } else {\r
+                       if (parent == null && parents.size() > 0)\r
+                               parent = parents.peek();\r
+                       String err = "Unknown element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None");\r
+                       logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
+                       if (debug) System.err.println(err);\r
+               }\r
+       }\r
+       \r
+       private Map<String, Element> idMap = new HashMap<String, Element>();\r
+       \r
+       private void handleElement(Deque<Element> parents, Element element) throws SAXException{\r
+               XMLElementParser parser = element.getParser();\r
+               if (parser != null) {\r
+                       try {\r
+                               parser.configure(graph, parents, element);\r
+                               if (parents.size() > 0) {\r
+                                       Element parent = parents.peek();\r
+                                       if (parent.getParser() != null) {\r
+                                               if (!parent.getParser().connectChild(graph, parent, element))\r
+                                                       if (!parser.connectParent(graph, parent, element)) {\r
+                                                               String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None");\r
+                                                               logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
+                                                               if (debug) System.err.println(err);\r
+                                                       }\r
+                                       } else {\r
+                                               String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None") + " was not imported";\r
+                                               logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
+                                               if (debug) System.err.println(err);\r
+                                       }\r
+                               }\r
+                               String id = parser.getID();\r
+                               if (id != null) {\r
+                                       Element existing = idMap.put(id, element);\r
+                                       if (existing != null) {\r
+                                               // report error + use id priorities to select the kept element.\r
+                                               boolean useExt = existing.parser.idPriority() > element.parser.idPriority();\r
+                                               if (useExt)\r
+                                                       idMap.put(id, existing);\r
+                                               String err = "Duplicate XML element id: " + id + " for " + element.getQName() + " and " + existing.getQName() + ", using " + (useExt ? existing.getQName() : element.getQName());\r
+                                               logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
+                                               if (debug) System.err.println(err);\r
+                                       }\r
+                               }\r
+                       } catch (DatabaseException e) {\r
+                               throw new SAXException(e);\r
+                       }\r
+               } else {\r
+                       Element parent = parents.peek();\r
+                       if (parent != null) { \r
+                               parser = parent.getParser();\r
+                               if (parser != null && parser instanceof UnrecognizedElementParser) {\r
+                                       try {\r
+                                               ((UnrecognizedElementParser)parser).configureChild(graph, parents, parent, element);\r
+                                       } catch (DatabaseException e) {\r
+                                               throw new SAXException(e);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       private void handleCharacters(Element element, String string) throws SAXException{\r
+               XMLElementParser parser = element.getParser();\r
+               if (parser != null) {\r
+                       try {\r
+                               parser.configure(graph, element, string);\r
+                       } catch (DatabaseException e) {\r
+                               logger.log(new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage()));\r
+                               throw new SAXException(e);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       private static String PLUGIN_ID = "org.simantics.xml.sax.base";\r
+       \r
+       public void done() throws SAXException{\r
+               try {\r
+                       for (Element e : idReferenceElements) {\r
+                               IDReferenceParser parser = (IDReferenceParser)parsers.get(e.qName);\r
+                               if (!parser.connectReferences(graph, e, idMap)) {\r
+                                       String err ="Could not resolve ID references for " + e.getQName() + " " + e.getUri();\r
+                                       logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err));\r
+                                       if (debug) System.err.println(err);\r
+                               }\r
+                       }\r
+               } catch (DatabaseException e) {\r
+                       throw new SAXException(e);\r
+               }\r
+       }\r
+       \r
+       public Resource getRoot() {\r
+               return root;\r
+       }\r
+       \r
+       @Override\r
+       public void startElement(String uri, String localName, String name,     Attributes attributes) throws SAXException {\r
+               Element e = new Element(uri,localName,name,attributes);\r
+               \r
+               loadElement(current,e);\r
+               current.push(e);\r
+       }\r
+       \r
+       @Override\r
+       public void endElement(String uri, String localName, String name)\r
+                       throws SAXException {\r
+               Element e = null;\r
+               if (!current.isEmpty()) {\r
+                       e = current.pop();\r
+               }\r
+               if (e != null) {\r
+                       handleElement(current,e);\r
+               }\r
+               if (current.isEmpty()) {\r
+                       root = e.getData();\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public void characters(char[] ch, int start, int length)\r
+                       throws SAXException {\r
+               \r
+               if (!current.isEmpty()) {\r
+                       String s = new String(ch,start,length);\r
+                       Element e = current.peek();\r
+                       handleCharacters(e, s);\r
+               }\r
+               \r
+       }\r
+       \r
+       public void parse(File file, ILogger logger) throws Exception {\r
+               this.logger = logger;\r
+               SAXParserFactory spf = SAXParserFactory.newInstance();\r
+               SAXParser saxParser = spf.newSAXParser();\r
+               \r
+               XMLReader reader = saxParser.getXMLReader();\r
+               reader.setContentHandler(this);\r
+               reader.parse(new InputSource(new BufferedInputStream(new FileInputStream(file))));\r
+               done();\r
+       }\r
+       \r
+       \r
+}
\ No newline at end of file