X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.xml.sax%2Fsrc%2Forg%2Fsimantics%2Fxml%2Fsax%2FSchemaConverter.java;h=660b990975f640c66bc093f541fa024ccda7f16f;hb=HEAD;hp=523788c8e33971819ed2c709cc79c48c642edb66;hpb=ada38ab0a1a98dcb413bef3273064da36ce2d273;p=simantics%2Finterop.git diff --git a/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConverter.java b/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConverter.java index 523788c..660b990 100644 --- a/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConverter.java +++ b/org.simantics.xml.sax/src/org/simantics/xml/sax/SchemaConverter.java @@ -1,121 +1,415 @@ -package org.simantics.xml.sax; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Date; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; - -import org.simantics.xml.sax.configuration.Configuration; -import org.w3._2001.xmlschema.Schema; - -/** - * This file is developed for XMpLant / Proteus schema conversion is not able to handle all XML Schema definitions. - * - * @author mlmarko - * - */ -public class SchemaConverter { - - File schemaFile; - File conversionFile; - File ontologyFile; - File parserDir; - Schema schema; - Configuration configuration; - - String pluginName; - - private String[] header; - - - public void convertSchema(File schemaFile, File conversionFile, File outputPlugin) throws JAXBException, IOException { - pluginName = outputPlugin.getName(); - String packageParts[] = pluginName.split("\\."); - String outputLoc = outputPlugin.getAbsolutePath(); - outputLoc += "/src"; - for (String s : packageParts) - outputLoc += "/"+s; - String outputGraph = outputPlugin.getAbsolutePath(); - outputGraph += "/graph"; - outputGraph += "/" + schemaFile.getName().substring(0, schemaFile.getName().length()-4) +".pgraph"; - - this.schemaFile = schemaFile; - this.conversionFile = conversionFile; - this.ontologyFile = new File(outputGraph); - this.parserDir = new File(outputLoc); - - if (!ontologyFile.exists()) { - ontologyFile.getParentFile().mkdirs(); - ontologyFile.createNewFile(); - } - if (!parserDir.exists()) - parserDir.mkdirs(); - - convert(); - - } - - private void convert() throws JAXBException, IOException { - JAXBContext jc = JAXBContext.newInstance("org.w3._2001.xmlschema"); - Unmarshaller u = jc.createUnmarshaller(); - //u.setSchema(schema); - InputStream fileStream = new FileInputStream(schemaFile); - schema = (Schema)u.unmarshal(fileStream); - - if (conversionFile != null) { - jc = JAXBContext.newInstance("org.simantics.xml.sax.configuration"); - u = jc.createUnmarshaller(); - fileStream = new FileInputStream(conversionFile); - configuration = (Configuration)((JAXBElement)u.unmarshal(fileStream)).getValue(); - } else { - configuration = new Configuration(); - } - - header = new String[4]; - header[0] = "Generated with org.simantics.xml.sax XML schema converter"; - header[1] = ""; - header[2] = "File " + schemaFile.getAbsolutePath(); - header[3] = "Date " + new Date().toString(); - - - OntologyGenerator ontologyGenerator = new OntologyGenerator(configuration); - ontologyGenerator.createOntology(schema, this); - ImporterGenerator importerGenerator = new ImporterGenerator(configuration); - importerGenerator.createParser(schema, ontologyGenerator.getClassName(), this); - } - - public File getOntologyFile() { - return ontologyFile; - } - public File getParserDir() { - return parserDir; - } - - public Schema getSchema() { - return schema; - } - - public File getSchemaFile() { - return schemaFile; - } - - public String getPluginName() { - return pluginName; - } - - public String[] getHeader() { - return header; - } - - public Configuration getConfiguration() { - return configuration; - } - - -} +package org.simantics.xml.sax; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.simantics.utils.datastructures.MapList; +import org.simantics.xml.sax.configuration.Configuration; +import org.w3._2001.xmlschema.Annotation; +import org.w3._2001.xmlschema.Import; +import org.w3._2001.xmlschema.Include; +import org.w3._2001.xmlschema.OpenAttrs; +import org.w3._2001.xmlschema.Schema; + +/** + * This file is developed for XMpLant / Proteus schema conversion is not able to handle all XML Schema definitions. + * + * @author mlmarko + * + */ +public class SchemaConverter { + + protected File outputPlugin; + protected File schemaFile; + protected File conversionFile; + protected File ontologyFile; + protected File parserDir; + protected Schema schema; + protected Configuration configuration; + + protected String pluginName; + + private String[] header; + + boolean createPGraph = true; + boolean createImporter = true; + boolean createExporter = true; + + private List parent = new ArrayList<>(); + private List subConverters = new ArrayList<>(); + private Map fileMap; + private MapList schemaNSMap; + private MapList shortNameMap; + + protected String schemaNs; + protected String ontologyUri; + protected String className; + protected String name; + protected String shortName; + + protected SchemaConversionBase base; + + private ManualSchemaFileImport fileImport; + + public SchemaConverter(File schemaFile, File conversionFile, File outputPlugin) throws IOException { + this(null,schemaFile,conversionFile,outputPlugin); + } + + public SchemaConverter(SchemaConverter parent,File schemaFile, File conversionFile, File outputPlugin) throws IOException { + if (schemaFile == null || outputPlugin == null) + throw new IllegalArgumentException(); + this.outputPlugin = outputPlugin; + this.schemaFile = schemaFile; + this.conversionFile = conversionFile; + + pluginName = outputPlugin.getName(); + String packageParts[] = pluginName.split("\\."); + String outputLoc = outputPlugin.getAbsolutePath(); + outputLoc += "/src"; + for (String s : packageParts) + outputLoc += "/"+s; + String outputGraph = outputPlugin.getAbsolutePath(); + outputGraph += "/graph"; + outputGraph += "/" + schemaFile.getName().substring(0, schemaFile.getName().length()-4) +".pgraph"; + + + this.ontologyFile = new File(outputGraph); + this.parserDir = new File(outputLoc); + + if (parent != null) { + this.parent.add(parent); + parent.subConverters.add(this); + } else { + fileMap = new LinkedHashMap<>(); + schemaNSMap = new MapList<>(); + shortNameMap = new MapList<>(); + } + getRoot().fileMap.put(schemaFile.getAbsolutePath(), this); + } + + public List getConverter(String schemaNS) { + return getRoot().schemaNSMap.getValues(schemaNS); + } + + public void setFileImport(ManualSchemaFileImport fileImport) { + this.fileImport = fileImport; + } + + + public void setCreateExporter(boolean createExporter) { + this.createExporter = createExporter; + } + + public void setCreateImporter(boolean createImporter) { + this.createImporter = createImporter; + } + + public void setCreatePGraph(boolean createPGraph) { + this.createPGraph = createPGraph; + } + + protected SchemaConverter createSubConverter(String location, String ns) throws JAXBException, IOException { + File directory = schemaFile.getParentFile(); + File schemaFile = new File(directory.getAbsolutePath()+File.separator+location); + if (!schemaFile.exists()) { + if (getRoot().fileImport != null) { + schemaFile = getRoot().fileImport.getFileForLocation(location); + } + if (!schemaFile.exists()) + throw new FileNotFoundException(schemaFile.getAbsolutePath()); + } + SchemaConverter subConverter = getRoot().fileMap.get((schemaFile.getAbsolutePath())); + if (subConverter == null) { + subConverter = constructSubConverter(this, schemaFile, conversionFile, outputPlugin, ns); + subConverter.createPGraph = this.createPGraph; + subConverter.createImporter = this.createImporter; + subConverter.createExporter = this.createExporter; + } else { + subConverter.parent.add(this); + subConverters.add(subConverter); + } + return subConverter; + } + + protected SchemaConverter constructSubConverter(SchemaConverter parent, File schemaFile, File conversionFile, File outputPlugin, String ns) throws IOException { + return new SchemaConverter(parent,schemaFile, conversionFile, outputPlugin); + } + + protected SchemaConverter getRoot() { + if (this.fileMap != null) + return this; + Set processed = new HashSet<>(); + return _getRoot(processed); + } + + protected SchemaConverter _getRoot(Set processed) { + if (processed.contains(this)) + return null; + if (this.fileMap != null) + return this; + processed.add(this); + + for (SchemaConverter sc : this.parent) { + if (sc.fileMap != null) + return sc; + } + for (SchemaConverter sc : this.parent) { + SchemaConverter root = sc._getRoot(processed); + if (root != null) + return root; + } + return null; + } + + public void convert() throws JAXBException, IOException { + + init(); + for (SchemaConverter sc : getRoot().fileMap.values()) { + sc.doConvert(); + } + } + + boolean init = false; + + protected void assignShortName() { + shortName = name.substring(0, 3).toUpperCase(); + SchemaConverter root = getRoot(); + if (!root.shortNameMap.containsKey(shortName)) { + root.shortNameMap.add(shortName, this); + return; + } else { + SchemaConverter sc = root.shortNameMap.getValues(shortName).get(0); + if (sc.schemaNs.equals(schemaNs)) { + root.shortNameMap.add(shortName, this); + return; + } + } + int i = 1; + while (true) { + String n = shortName+i; + if (!root.shortNameMap.containsKey(n)) { + shortName = n; + root.shortNameMap.add(shortName, this); + return; + } else { + SchemaConverter sc = root.shortNameMap.getValues(n).get(0); + if (sc.schemaNs.equals(schemaNs)) { + shortName = n; + root.shortNameMap.add(shortName, this); + return; + } + } + i++; + } + } + + protected Schema createSchema() throws JAXBException, FileNotFoundException { + JAXBContext jc = JAXBContext.newInstance("org.w3._2001.xmlschema"); + Unmarshaller u = jc.createUnmarshaller(); + //u.setSchema(schema); + InputStream fileStream = new FileInputStream(schemaFile); + return (Schema)u.unmarshal(fileStream); + } + + protected void init() throws IOException, JAXBException { + if (init) + return; + init = true; + + schema = createSchema(); + + if (conversionFile != null) { + JAXBContext jc = JAXBContext.newInstance("org.simantics.xml.sax.configuration"); + Unmarshaller u = jc.createUnmarshaller(); + InputStream fileStream = new FileInputStream(conversionFile); + configuration = (Configuration)((JAXBElement)u.unmarshal(fileStream)).getValue(); + } else { + configuration = new Configuration(); + } + + header = new String[4]; + header[0] = "Generated with org.simantics.xml.sax XML schema converter"; + header[1] = ""; + header[2] = "File " + schemaFile.getAbsolutePath().replaceAll(Matcher.quoteReplacement("\\"), "/"); + header[3] = "Date " + new Date().toString(); + + schemaNs = schema.getTargetNamespace(); + + ontologyUri = schemaNs; + if (ontologyUri == null) { + ontologyUri = getSchemaFile().getName(); + + int index = ontologyUri.lastIndexOf("."); + if (index > 0) + ontologyUri = ontologyUri.substring(0, index); + schemaNs = ""; + } else { + // Special case for XAML + if (ontologyUri.startsWith("clr-namespace:")) { + ontologyUri = ontologyUri.substring("clr-namespace:".length()); + int i = ontologyUri.indexOf(";assembly"); + if (i > 0) + ontologyUri = ontologyUri.substring(0, i); + } + } + ontologyUri = ontologyUri.replaceAll(" ", "_"); + ontologyUri = ontologyUri.replaceAll(":", "_"); + ontologyUri = ontologyUri.replaceAll(";", "_"); + String parts[] = ontologyUri.split("/"); + for (int i = parts.length-1; i >= 0; i--) { + name = parts[i]; + if (!Character.isDigit(name.charAt(0))) + break; + } + if (name == null) { + throw new JAXBException("Could not resolve proper name for schema " + ontologyUri); + } + + + name = name.replaceAll("\\.", "_"); + if (!ontologyUri.startsWith("http://")) + ontologyUri = "http://" + ontologyUri.replaceAll("/", "_"); + else + ontologyUri = "http://" + ontologyUri.substring("http://".length()).replaceAll("/", "_"); + + String version = schema.getVersion(); + if (version == null) + version = "1.0"; + ontologyUri +="-"+ version; + + + className = getPluginName() + "." + name + "Ontology"; + assignShortName(); + if (schemaNs != null) + getRoot().schemaNSMap.add(schemaNs, this); + + base = new SchemaConversionBase(this,ontologyUri,className); + base.init(schema); + + for (OpenAttrs attrs : schema.getIncludeOrImportOrRedefine()) { + if (attrs instanceof Import) { + Import imp = (Import)attrs; + String location = imp.getSchemaLocation(); + SchemaConverter sc = createSubConverter(location, imp.getNamespace()); + sc.init(); + } else if (attrs instanceof Include) { + Include inc = (Include)attrs; + String location = inc.getSchemaLocation(); + SchemaConverter sc = createSubConverter(location, null); + sc.init(); + } else if (attrs instanceof Annotation) { + + } else { + throw new IOException("Cannot handle schema file " + schemaFile.getName() + ", the schema uses redefine elements."); + } + } + } + + private boolean converting = false; + + protected void doConvert() throws IOException, JAXBException { + if (converting) + return; + converting = true; + if (!ontologyFile.exists()) { + ontologyFile.getParentFile().mkdirs(); + ontologyFile.createNewFile(); + } + if (!parserDir.exists()) + parserDir.mkdirs(); + + if (createPGraph) { + OntologyGenerator ontologyGenerator = new OntologyGenerator(this,base); + ontologyGenerator.createOntology(); + } + if (createImporter) { + ImporterGenerator importerGenerator = new ImporterGenerator(this,base); + importerGenerator.createParser(); + } + if (createExporter) { + ExporterGenerator exporterGenerator = new ExporterGenerator(this,base); + exporterGenerator.createParser(); + } + base.component = null; + } + + public File getOntologyFile() { + return ontologyFile; + } + public File getParserDir() { + return parserDir; + } + + public Schema getSchema() { + return schema; + } + + public File getSchemaFile() { + return schemaFile; + } + + public String getPluginName() { + return pluginName; + } + + public String[] getHeader() { + return header; + } + + public Configuration getConfiguration() { + return configuration; + } + + public List getParent() { + return parent; + } + + public List getSubConverters() { + return subConverters; + } + + public boolean isPrimary() { + return true; +// if (getRoot() == this) +// return true; +// List conv = new ArrayList<>(getRoot().fileMap.values()); +// int current = conv.indexOf(this); + + } + + public String getShortName(String namespaceURI) { + List converters = getRoot().getConverter(namespaceURI); + for (SchemaConverter conv : converters) { + if (conv.shortName != null) + return conv.shortName; + } + return null; + } + + public String getOntologyClassName(String namespaceURI) { + List converters = getRoot().getConverter(namespaceURI); + for (SchemaConverter conv : converters) { + if (conv.className != null) + return conv.className; + } + return null; + } + + +}