From 47791aa9453c9d90786bc8ca7de102fb3ee90f3b Mon Sep 17 00:00:00 2001 From: luukkainen Date: Fri, 20 Jan 2017 09:16:06 +0000 Subject: [PATCH] Initial support for multi-schema parsers Parsing multiline Base64 data did not work refs #6985 git-svn-id: https://www.simantics.org/svn/simantics/interoperability/trunk@33433 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../xml/sax/base/AbstractImporter.java | 21 ++++- .../org/simantics/xml/sax/base/Element.java | 19 +++- .../org/simantics/xml/sax/base/XMLParser.java | 92 ++++++++++++++----- .../simantics/xml/sax/ImporterGenerator.java | 46 +++++++--- .../xml/sax/SchemaConversionBase.java | 2 +- 5 files changed, 135 insertions(+), 45 deletions(-) diff --git a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/AbstractImporter.java b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/AbstractImporter.java index f175fc4..f47dd93 100644 --- a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/AbstractImporter.java +++ b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/AbstractImporter.java @@ -19,6 +19,7 @@ public abstract class AbstractImporter { private Session session; private File file; private ILogger logger; + private XMLParser parser; private static final boolean USE_DELAYED = false; @@ -26,6 +27,12 @@ public abstract class AbstractImporter { this.session = session; this.file = file; } + + public AbstractImporter(Session session, File file, XMLParser parser) { + this.session = session; + this.file = file; + this.parser = parser; + } public Resource doImport() throws DatabaseException { return doImport(MessageService.getDefault()); } @@ -47,7 +54,8 @@ public abstract class AbstractImporter { return file; } - public abstract void configure(XMLParser parser); + public void configure(XMLParser parser){}; + private class ImportRequest extends WriteRequest { private Resource result; @@ -86,8 +94,15 @@ public abstract class AbstractImporter { private Resource doImport(WriteGraph graph) throws DatabaseException { Layer0Utils.setDependenciesIndexingDisabled(graph, true); try { - XMLParser parser = new XMLParser(graph); - configure(parser); + + if (parser == null) { + parser = new XMLParser(); + parser.setGraph(graph); + configure(parser); + } else { + parser.setGraph(graph); + } + parser.parse(file, logger); System.out.println(file.getAbsolutePath() + " imported"); Resource root = parser.getRoot(); diff --git a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/Element.java b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/Element.java index 3aba943..62f1597 100644 --- a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/Element.java +++ b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/Element.java @@ -15,7 +15,8 @@ public class Element implements Serializable { String qName; Map attributes = new HashMap(); - XMLElementParser parser; + XMLElementParser elementParser; + XMLParser xmlParser; public Element(String uri, String localName, String qName, Attributes attributes) { this.uri = uri; @@ -65,12 +66,20 @@ public class Element implements Serializable { return data; } - public void setParser(XMLElementParser parser) { - this.parser = parser; + public void setElementParser(XMLElementParser parser) { + this.elementParser = parser; } - public XMLElementParser getParser() { - return parser; + public XMLElementParser getElementParser() { + return elementParser; + } + + public void setXMLParser(XMLParser parser) { + this.xmlParser = parser; + } + + public XMLParser getXMLParser() { + return xmlParser; } } \ No newline at end of file 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 index be8fef0..43a07c5 100644 --- 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 @@ -30,16 +30,37 @@ public class XMLParser extends DefaultHandler implements Serializable { private static final long serialVersionUID = 7360740940824360338L; private static final boolean debug = false; + private static String XML_SCHEMA_REF = "xmlns"; private ILogger logger; private Resource root; + private String schemaURI; private Deque current = new ArrayDeque(); private Map parsers = new HashMap(); private WriteGraph graph; - private Map, XMLElementParser> namedParsers = new HashMap, XMLElementParser>(); - public XMLParser(WriteGraph graph) { + private Map subParsers = new HashMap(); + + public XMLParser() { + + } + + public WriteGraph getGraph() { + return graph; + } + + public void setGraph(WriteGraph graph) { this.graph = graph; + for (XMLParser p : subParsers.values()) + p.setGraph(graph); + } + + public String getSchemaURI() { + return schemaURI; + } + + public void setSchemaURI(String schemaURI) { + this.schemaURI = schemaURI; } public void add(XMLElementParser parser) { @@ -48,6 +69,9 @@ public class XMLParser extends DefaultHandler implements Serializable { namedParsers.put(parser.getClass(), parser); } + public void add(XMLParser parser) { + subParsers.put(parser.getSchemaURI(), parser); + } private List idReferenceElements = new ArrayList(); private void loadElement(Deque parents, Element element) throws SAXException{ @@ -55,9 +79,15 @@ public class XMLParser extends DefaultHandler implements Serializable { Element parent = null; if (parents.size() > 0) { parent = parents.peek(); - if (parent.getParser() instanceof XMLElementNamedChildParser) { + // check for assigned subparser + if (parent.getXMLParser() != null && parent.getXMLParser() != this) { + element.setXMLParser(parent.getXMLParser()); + parent.getXMLParser().loadElement(parents, element); + return; + } + if (parent.getElementParser() instanceof XMLElementNamedChildParser) { // use parent's named child parser if it is supported - Class parserClass = ((XMLElementNamedChildParser)parent.getParser()).getParser(parsers,parent,element); + Class parserClass = ((XMLElementNamedChildParser)parent.getElementParser()).getParser(parsers,parent,element); if (parserClass != null) { parser = namedParsers.get(parserClass); if (parser == null) { @@ -65,7 +95,7 @@ public class XMLParser extends DefaultHandler implements Serializable { parser = parserClass.newInstance(); namedParsers.put(parserClass, parser); } catch (IllegalAccessException | InstantiationException e) { - String err = "Element parsers must have accessible default constructor"; + String err = "Error processing " + parserClass.getName() + " : element parsers must have accessible default constructor"; logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); throw new SAXException(err, e); } @@ -88,30 +118,38 @@ public class XMLParser extends DefaultHandler implements Serializable { element.setData(parser.create(graph, element)); if (parser instanceof IDReferenceParser) idReferenceElements.add(element); - element.setParser(parser); + element.setElementParser(parser); } catch (DatabaseException e) { throw new SAXException(e); } } else { - if (parent == null && parents.size() > 0) - parent = parents.peek(); - String err = "Unknown element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None"); - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); - if (debug) System.err.println(err); + // check for schema reference attempt to locate subparser for it. + Attribute schemaRef = element.getAttribute(XML_SCHEMA_REF); + if (schemaRef != null && subParsers.containsKey(schemaRef.value)) { + XMLParser subParser = subParsers.get(schemaRef.value); + subParser.loadElement(parents, element); + element.setXMLParser(subParser); + } else { + if (parent == null && parents.size() > 0) + parent = parents.peek(); + String err = "Unknown element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None"); + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); + if (debug) System.err.println(err); + } } } private Map idMap = new HashMap(); private void handleElement(Deque parents, Element element) throws SAXException{ - XMLElementParser parser = element.getParser(); + XMLElementParser parser = element.getElementParser(); if (parser != null) { try { parser.configure(graph, parents, element); if (parents.size() > 0) { Element parent = parents.peek(); - if (parent.getParser() != null) { - if (!parent.getParser().connectChild(graph, parent, element)) + if (parent.getElementParser() != null) { + if (!parent.getElementParser().connectChild(graph, parent, element)) if (!parser.connectParent(graph, parent, element)) { String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None"); logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); @@ -128,7 +166,7 @@ public class XMLParser extends DefaultHandler implements Serializable { Element existing = idMap.put(id, element); if (existing != null) { // report error + use id priorities to select the kept element. - boolean useExt = existing.parser.idPriority() > element.parser.idPriority(); + boolean useExt = existing.elementParser.idPriority() > element.elementParser.idPriority(); if (useExt) idMap.put(id, existing); String err = "Duplicate XML element id: " + id + " for " + element.getQName() + " and " + existing.getQName() + ", using " + (useExt ? existing.getQName() : element.getQName()); @@ -142,7 +180,7 @@ public class XMLParser extends DefaultHandler implements Serializable { } else { Element parent = parents.peek(); if (parent != null) { - parser = parent.getParser(); + parser = parent.getElementParser(); if (parser != null && parser instanceof UnrecognizedElementParser) { try { ((UnrecognizedElementParser)parser).configureChild(graph, parents, parent, element); @@ -155,7 +193,7 @@ public class XMLParser extends DefaultHandler implements Serializable { } private void handleCharacters(Element element, String string) throws SAXException{ - XMLElementParser parser = element.getParser(); + XMLElementParser parser = element.getElementParser(); if (parser != null) { try { parser.configure(graph, element, string); @@ -187,12 +225,16 @@ public class XMLParser extends DefaultHandler implements Serializable { return root; } + StringBuilder charactersValue; + @Override public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { Element e = new Element(uri,localName,name,attributes); loadElement(current,e); current.push(e); + + charactersValue = new StringBuilder(); } @Override @@ -203,22 +245,26 @@ public class XMLParser extends DefaultHandler implements Serializable { e = current.pop(); } if (e != null) { + if (charactersValue.length() > 0) + handleCharacters(e, charactersValue.toString()); handleElement(current,e); } if (current.isEmpty()) { root = e.getData(); } + + charactersValue = new StringBuilder(); } @Override public void characters(char[] ch, int start, int length) throws SAXException { - - if (!current.isEmpty()) { - String s = new String(ch,start,length); - Element e = current.peek(); - handleCharacters(e, s); - } + charactersValue.append(new String(ch,start,length)); +// if (!current.isEmpty()) { +// String s = new String(ch,start,length); +// Element e = current.peek(); +// handleCharacters(e, s); +// } } diff --git a/org.simantics.xml.sax/src/org/simantics/xml/sax/ImporterGenerator.java b/org.simantics.xml.sax/src/org/simantics/xml/sax/ImporterGenerator.java index d192ad7..4245e3e 100644 --- a/org.simantics.xml.sax/src/org/simantics/xml/sax/ImporterGenerator.java +++ b/org.simantics.xml.sax/src/org/simantics/xml/sax/ImporterGenerator.java @@ -65,6 +65,7 @@ public class ImporterGenerator extends SchemaConversionBase{ ontShort +="."; String parserPackagePostfix = "_elem"; String importerClassPostfix = "Importer"; + String parserClassPostfix = "Parser"; elementPackageName = name+parserPackagePostfix; importParserDir= new File(converter.getParserDir().getAbsolutePath()+"/"+elementPackageName); @@ -72,26 +73,47 @@ public class ImporterGenerator extends SchemaConversionBase{ importParserDir.mkdirs(); handle(schema); - - File importParserFile = new File(converter.getParserDir().getAbsolutePath()+"/"+name+importerClassPostfix+".java"); - PrintWriter mainWriter = createFile(importParserFile); + // Create Importer class + File importerFile = new File(converter.getParserDir().getAbsolutePath()+"/"+name+importerClassPostfix+".java"); + PrintWriter mainWriter = createFile(importerFile); mainWriter.println("package " + converter.getPluginName() +";"); mainWriter.println(); mainWriter.println("import java.io.File;"); mainWriter.println("import org.simantics.db.Session;"); mainWriter.println("import org.simantics.xml.sax.base.AbstractImporter;"); - mainWriter.println("import org.simantics.xml.sax.base.XMLParser;"); mainWriter.println(); mainWriter.println("public class " + name + importerClassPostfix+" extends AbstractImporter {"); mainWriter.println(); mainWriter.println(" public " + name + importerClassPostfix+"(Session session, File file) {"); - mainWriter.println(" super(session,file);"); + mainWriter.println(" super(session, file, new "+name + parserClassPostfix+"());"); mainWriter.println(" }"); mainWriter.println(); - mainWriter.println(" @Override"); - mainWriter.println(" public void configure(XMLParser parser) {"); +// mainWriter.println(" @Override"); +// mainWriter.println(" public void configure(XMLParser parser) {"); +// for (String s : ruleClassNames) { +// mainWriter.println(" parser.add(new "+s+"());"); +// } +// mainWriter.println(" }"); + mainWriter.println("}"); + + mainWriter.println(); + mainWriter.flush(); + mainWriter.close(); + + // Create Parser class + File parserFile = new File(converter.getParserDir().getAbsolutePath()+"/"+name+parserClassPostfix+".java"); + mainWriter = createFile(parserFile); + mainWriter.println("package " + converter.getPluginName() +";"); + mainWriter.println(); + mainWriter.println("import org.simantics.xml.sax.base.XMLParser;"); + mainWriter.println(); + mainWriter.println("public class " + name + parserClassPostfix+" extends XMLParser {"); + mainWriter.println(); + mainWriter.println(" public " + name + parserClassPostfix+"() {"); + if (schema.getTargetNamespace() != null) + mainWriter.println(" setSchemaURI(\""+schema.getTargetNamespace()+"\");"); for (String s : ruleClassNames) { - mainWriter.println(" parser.add(new "+s+"());"); + mainWriter.println(" add(new "+s+"());"); } mainWriter.println(" }"); mainWriter.println("}"); @@ -359,7 +381,7 @@ public class ImporterGenerator extends SchemaConversionBase{ if (!className.equals(refClassName)) fw.writer.println(" addParser("+refClassName+".class);"); - fw.delayedWriter.println(" if (child.getParser() instanceof "+refClassName+"){"); + fw.delayedWriter.println(" if (child.getElementParser() instanceof "+refClassName+"){"); fw.delayedWriter.println(" graph.claim(element.getData(), "+ontShort+getName(parent)+"_has"+ref + ", child.getData());"); if (useElementList(parent, indicator,element, reference, ref, refType)) { @@ -397,7 +419,7 @@ public class ImporterGenerator extends SchemaConversionBase{ fw.writer.println(" addParser(\""+ ref +"\", "+getName(parent) +"_" +ref+".class);"); fw.delayedWriter2.println(" public static class " + getName(parent) +"_" +ref+" extends org.simantics.xml.sax.base.ValueElementParser {"); - fw.delayedWriter2.println(" "+ getName(parent) +"_" +ref +"(){"); + fw.delayedWriter2.println(" public "+ getName(parent) +"_" +ref +"(){"); fw.delayedWriter2.println(" super(\""+ref+"\"," +this.ontologyClassName+".URIs."+getName(parent) + "_has"+ref+", "+binding+");"); fw.delayedWriter2.println(" }"); fw.delayedWriter2.println(" }"); @@ -426,7 +448,7 @@ public class ImporterGenerator extends SchemaConversionBase{ else fw.writer.println(" addParser("+className+".class);"); - fw.delayedWriter.println(" if (child.getParser() instanceof "+className+"){"); + fw.delayedWriter.println(" if (child.getElementParser() instanceof "+className+"){"); fw.delayedWriter.println(" graph.claim(element.getData(), "+ontShort+getName(parent)+"_has"+ref + ", child.getData());"); if (useElementList(parent, indicator,element, reference, ref, new QName(obj.getName()))) { @@ -835,8 +857,6 @@ public class ImporterGenerator extends SchemaConversionBase{ } private Inheritance getElementInheritance(SchemaObject topLevelElementObj) { - if (topLevelElementObj.getElement() != null && topLevelElementObj.getElement().getName().equals("ByteString")) - System.out.println(); Element topLevelElement = topLevelElementObj.getElement(); Inheritance inheritance = new Inheritance(); if (topLevelElement.getType() != null) { diff --git a/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConversionBase.java b/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConversionBase.java index 38c934a..bcff698 100644 --- a/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConversionBase.java +++ b/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConversionBase.java @@ -89,7 +89,7 @@ public abstract class SchemaConversionBase { schemaTypes.put("unsignedByte", new TypeEntry("L0.Byte", "Bindings.BYTE", "byte", "0","java.lang.Byte.parseByte(",")")); schemaTypes.put("long", new TypeEntry("L0.Long", "Bindings.LONG", "long", "0","java.lang.Long.parseLong(",")")); schemaTypes.put("unsignedLong", new TypeEntry("L0.Long", "Bindings.LONG", "long", "0","java.lang.Long.parseLong(",")")); - schemaTypes.put("base64Binary", new TypeEntry("L0.ByteArray", "Bindings.BYTE_ARRAY", "byte[]", "new byte[0]","java.util.Base64.getDecoder().decode(",")")); + schemaTypes.put("base64Binary", new TypeEntry("L0.ByteArray", "Bindings.BYTE_ARRAY", "byte[]", "new byte[0]","",".getBytes(org.simantics.databoard.util.binary.UTF8.CHARSET)")); -- 2.47.1