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.HashMap; import java.util.List; import java.util.Map; 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 javax.xml.namespace.QName; 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 { File outputPlugin; File schemaFile; File conversionFile; File ontologyFile; File parserDir; Schema schema; Configuration configuration; 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; String schemaNs; String ontologyUri; String className; String name; String shortName; 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 { 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 HashMap<>(); 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) 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 = new SchemaConverter(this,schemaFile, conversionFile, outputPlugin); subConverter.createPGraph = this.createPGraph; subConverter.createImporter = this.createImporter; subConverter.createExporter = this.createExporter; } else { subConverter.parent.add(this); } return subConverter; } protected SchemaConverter getRoot() { SchemaConverter s = this; if (s.fileMap != null) return s; while (s.parent.size() > 0) { s = s.parent.get(0); if (s.fileMap != null) return s; } return s; } public void convert() throws JAXBException, IOException { init(); 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 void init() throws IOException, JAXBException { if (init) return; init = true; 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().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 = ""; } 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; assignShortName(); if (schemaNs != null) getRoot().schemaNSMap.add(schemaNs, this); for (OpenAttrs attrs : schema.getIncludeOrImportOrRedefine()) { if (attrs instanceof Import) { Import imp = (Import)attrs; String location = imp.getSchemaLocation(); SchemaConverter sc = createSubConverter(location); sc.init(); } else if (attrs instanceof Include) { Include inc = (Include)attrs; String location = inc.getSchemaLocation(); SchemaConverter sc = createSubConverter(location); sc.init(); } else if (attrs instanceof Annotation) { } else { throw new IOException("Cannot handle schema file " + schemaFile.getName() + ", the schema uses redefine elements."); } } } protected void doConvert() throws IOException, JAXBException { if (!ontologyFile.exists()) { ontologyFile.getParentFile().mkdirs(); ontologyFile.createNewFile(); } if (!parserDir.exists()) parserDir.mkdirs(); for (SchemaConverter sc : subConverters) sc.doConvert(); base = new SchemaConversionBase(this,ontologyUri,className); base.init(schema); 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 boolean isPrimary() { return getRoot() == 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; } }