1 package org.simantics.xml.sax;
4 import java.io.FileInputStream;
5 import java.io.FileNotFoundException;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.util.ArrayList;
10 import java.util.HashSet;
11 import java.util.LinkedHashMap;
12 import java.util.List;
15 import java.util.regex.Matcher;
17 import javax.xml.bind.JAXBContext;
18 import javax.xml.bind.JAXBElement;
19 import javax.xml.bind.JAXBException;
20 import javax.xml.bind.Unmarshaller;
22 import org.simantics.utils.datastructures.MapList;
23 import org.simantics.xml.sax.configuration.Configuration;
24 import org.w3._2001.xmlschema.Annotation;
25 import org.w3._2001.xmlschema.Import;
26 import org.w3._2001.xmlschema.Include;
27 import org.w3._2001.xmlschema.OpenAttrs;
28 import org.w3._2001.xmlschema.Schema;
31 * This file is developed for XMpLant / Proteus schema conversion is not able to handle all XML Schema definitions.
36 public class SchemaConverter {
38 protected File outputPlugin;
39 protected File schemaFile;
40 protected File conversionFile;
41 protected File ontologyFile;
42 protected File parserDir;
43 protected Schema schema;
44 protected Configuration configuration;
46 protected String pluginName;
48 private String[] header;
50 boolean createPGraph = true;
51 boolean createImporter = true;
52 boolean createExporter = true;
54 private List<SchemaConverter> parent = new ArrayList<>();
55 private List<SchemaConverter> subConverters = new ArrayList<>();
56 private Map<String,SchemaConverter> fileMap;
57 private MapList<String,SchemaConverter> schemaNSMap;
58 private MapList<String,SchemaConverter> shortNameMap;
60 protected String schemaNs;
61 protected String ontologyUri;
62 protected String className;
63 protected String name;
64 protected String shortName;
66 protected SchemaConversionBase base;
68 private ManualSchemaFileImport fileImport;
70 public SchemaConverter(File schemaFile, File conversionFile, File outputPlugin) throws IOException {
71 this(null,schemaFile,conversionFile,outputPlugin);
74 public SchemaConverter(SchemaConverter parent,File schemaFile, File conversionFile, File outputPlugin) throws IOException {
75 if (schemaFile == null || outputPlugin == null)
76 throw new IllegalArgumentException();
77 this.outputPlugin = outputPlugin;
78 this.schemaFile = schemaFile;
79 this.conversionFile = conversionFile;
81 pluginName = outputPlugin.getName();
82 String packageParts[] = pluginName.split("\\.");
83 String outputLoc = outputPlugin.getAbsolutePath();
85 for (String s : packageParts)
87 String outputGraph = outputPlugin.getAbsolutePath();
88 outputGraph += "/graph";
89 outputGraph += "/" + schemaFile.getName().substring(0, schemaFile.getName().length()-4) +".pgraph";
92 this.ontologyFile = new File(outputGraph);
93 this.parserDir = new File(outputLoc);
96 this.parent.add(parent);
97 parent.subConverters.add(this);
99 fileMap = new LinkedHashMap<>();
100 schemaNSMap = new MapList<>();
101 shortNameMap = new MapList<>();
103 getRoot().fileMap.put(schemaFile.getAbsolutePath(), this);
106 public List<SchemaConverter> getConverter(String schemaNS) {
107 return getRoot().schemaNSMap.getValues(schemaNS);
110 public void setFileImport(ManualSchemaFileImport fileImport) {
111 this.fileImport = fileImport;
115 public void setCreateExporter(boolean createExporter) {
116 this.createExporter = createExporter;
119 public void setCreateImporter(boolean createImporter) {
120 this.createImporter = createImporter;
123 public void setCreatePGraph(boolean createPGraph) {
124 this.createPGraph = createPGraph;
127 protected SchemaConverter createSubConverter(String location, String ns) throws JAXBException, IOException {
128 File directory = schemaFile.getParentFile();
129 File schemaFile = new File(directory.getAbsolutePath()+File.separator+location);
130 if (!schemaFile.exists()) {
131 if (getRoot().fileImport != null) {
132 schemaFile = getRoot().fileImport.getFileForLocation(location);
134 if (!schemaFile.exists())
135 throw new FileNotFoundException(schemaFile.getAbsolutePath());
137 SchemaConverter subConverter = getRoot().fileMap.get((schemaFile.getAbsolutePath()));
138 if (subConverter == null) {
139 subConverter = constructSubConverter(this, schemaFile, conversionFile, outputPlugin, ns);
140 subConverter.createPGraph = this.createPGraph;
141 subConverter.createImporter = this.createImporter;
142 subConverter.createExporter = this.createExporter;
144 subConverter.parent.add(this);
145 subConverters.add(subConverter);
150 protected SchemaConverter constructSubConverter(SchemaConverter parent, File schemaFile, File conversionFile, File outputPlugin, String ns) throws IOException {
151 return new SchemaConverter(parent,schemaFile, conversionFile, outputPlugin);
154 protected SchemaConverter getRoot() {
155 if (this.fileMap != null)
157 Set<SchemaConverter> processed = new HashSet<>();
158 return _getRoot(processed);
161 protected SchemaConverter _getRoot(Set<SchemaConverter> processed) {
162 if (processed.contains(this))
164 if (this.fileMap != null)
168 for (SchemaConverter sc : this.parent) {
169 if (sc.fileMap != null)
172 for (SchemaConverter sc : this.parent) {
173 SchemaConverter root = sc._getRoot(processed);
180 public void convert() throws JAXBException, IOException {
183 for (SchemaConverter sc : getRoot().fileMap.values()) {
188 boolean init = false;
190 protected void assignShortName() {
191 shortName = name.substring(0, 3).toUpperCase();
192 SchemaConverter root = getRoot();
193 if (!root.shortNameMap.containsKey(shortName)) {
194 root.shortNameMap.add(shortName, this);
197 SchemaConverter sc = root.shortNameMap.getValues(shortName).get(0);
198 if (sc.schemaNs.equals(schemaNs)) {
199 root.shortNameMap.add(shortName, this);
205 String n = shortName+i;
206 if (!root.shortNameMap.containsKey(n)) {
208 root.shortNameMap.add(shortName, this);
211 SchemaConverter sc = root.shortNameMap.getValues(n).get(0);
212 if (sc.schemaNs.equals(schemaNs)) {
214 root.shortNameMap.add(shortName, this);
222 protected Schema createSchema() throws JAXBException, FileNotFoundException {
223 JAXBContext jc = JAXBContext.newInstance("org.w3._2001.xmlschema");
224 Unmarshaller u = jc.createUnmarshaller();
225 //u.setSchema(schema);
226 InputStream fileStream = new FileInputStream(schemaFile);
227 return (Schema)u.unmarshal(fileStream);
230 protected void init() throws IOException, JAXBException {
235 schema = createSchema();
237 if (conversionFile != null) {
238 JAXBContext jc = JAXBContext.newInstance("org.simantics.xml.sax.configuration");
239 Unmarshaller u = jc.createUnmarshaller();
240 InputStream fileStream = new FileInputStream(conversionFile);
241 configuration = (Configuration)((JAXBElement<?>)u.unmarshal(fileStream)).getValue();
243 configuration = new Configuration();
246 header = new String[4];
247 header[0] = "Generated with org.simantics.xml.sax XML schema converter";
249 header[2] = "File " + schemaFile.getAbsolutePath().replaceAll(Matcher.quoteReplacement("\\"), "/");
250 header[3] = "Date " + new Date().toString();
252 schemaNs = schema.getTargetNamespace();
254 ontologyUri = schemaNs;
255 if (ontologyUri == null) {
256 ontologyUri = getSchemaFile().getName();
258 int index = ontologyUri.lastIndexOf(".");
260 ontologyUri = ontologyUri.substring(0, index);
263 // Special case for XAML
264 if (ontologyUri.startsWith("clr-namespace:")) {
265 ontologyUri = ontologyUri.substring("clr-namespace:".length());
266 int i = ontologyUri.indexOf(";assembly");
268 ontologyUri = ontologyUri.substring(0, i);
271 ontologyUri = ontologyUri.replaceAll(" ", "_");
272 ontologyUri = ontologyUri.replaceAll(":", "_");
273 ontologyUri = ontologyUri.replaceAll(";", "_");
274 String parts[] = ontologyUri.split("/");
275 for (int i = parts.length-1; i >= 0; i--) {
277 if (!Character.isDigit(name.charAt(0)))
281 throw new JAXBException("Could not resolve proper name for schema " + ontologyUri);
285 name = name.replaceAll("\\.", "_");
286 if (!ontologyUri.startsWith("http://"))
287 ontologyUri = "http://" + ontologyUri.replaceAll("/", "_");
289 ontologyUri = "http://" + ontologyUri.substring("http://".length()).replaceAll("/", "_");
291 String version = schema.getVersion();
294 ontologyUri +="-"+ version;
297 className = getPluginName() + "." + name + "Ontology";
299 if (schemaNs != null)
300 getRoot().schemaNSMap.add(schemaNs, this);
302 base = new SchemaConversionBase(this,ontologyUri,className);
305 for (OpenAttrs attrs : schema.getIncludeOrImportOrRedefine()) {
306 if (attrs instanceof Import) {
307 Import imp = (Import)attrs;
308 String location = imp.getSchemaLocation();
309 SchemaConverter sc = createSubConverter(location, imp.getNamespace());
311 } else if (attrs instanceof Include) {
312 Include inc = (Include)attrs;
313 String location = inc.getSchemaLocation();
314 SchemaConverter sc = createSubConverter(location, null);
316 } else if (attrs instanceof Annotation) {
319 throw new IOException("Cannot handle schema file " + schemaFile.getName() + ", the schema uses redefine elements.");
324 private boolean converting = false;
326 protected void doConvert() throws IOException, JAXBException {
330 if (!ontologyFile.exists()) {
331 ontologyFile.getParentFile().mkdirs();
332 ontologyFile.createNewFile();
334 if (!parserDir.exists())
338 OntologyGenerator ontologyGenerator = new OntologyGenerator(this,base);
339 ontologyGenerator.createOntology();
341 if (createImporter) {
342 ImporterGenerator importerGenerator = new ImporterGenerator(this,base);
343 importerGenerator.createParser();
345 if (createExporter) {
346 ExporterGenerator exporterGenerator = new ExporterGenerator(this,base);
347 exporterGenerator.createParser();
349 base.component = null;
352 public File getOntologyFile() {
355 public File getParserDir() {
359 public Schema getSchema() {
363 public File getSchemaFile() {
367 public String getPluginName() {
371 public String[] getHeader() {
375 public Configuration getConfiguration() {
376 return configuration;
379 public List<SchemaConverter> getParent() {
383 public List<SchemaConverter> getSubConverters() {
384 return subConverters;
387 public boolean isPrimary() {
389 // if (getRoot() == this)
391 // List<SchemaConverter> conv = new ArrayList<>(getRoot().fileMap.values());
392 // int current = conv.indexOf(this);
396 public String getShortName(String namespaceURI) {
397 List<SchemaConverter> converters = getRoot().getConverter(namespaceURI);
398 for (SchemaConverter conv : converters) {
399 if (conv.shortName != null)
400 return conv.shortName;
405 public String getOntologyClassName(String namespaceURI) {
406 List<SchemaConverter> converters = getRoot().getConverter(namespaceURI);
407 for (SchemaConverter conv : converters) {
408 if (conv.className != null)
409 return conv.className;