]> gerrit.simantics Code Review - simantics/interop.git/commitdiff
Generate SCL bindings for multi-version ontology references classes. 67/2167/1
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Thu, 13 Sep 2018 10:26:37 +0000 (13:26 +0300)
committerMarko Luukkainen <marko.luukkainen@semantum.fi>
Thu, 13 Sep 2018 10:26:37 +0000 (13:26 +0300)
* Additionally, added SCL bindings to XML time/date data types

gitlab #5

Change-Id: Ia1b5786becf99b691a66d48b63bd2689cb646d9a

org.simantics.xml.sax.base/scl/xml/XMLDataTypes.scl [new file with mode: 0644]
org.simantics.xml.sax.ui/src/org/simantics/xml/sax/ui/wizard/SchemaCombinationPage.java
org.simantics.xml.sax/src/org/simantics/xml/sax/OntologyCombinator.java
org.simantics.xml.sax/src/org/simantics/xml/sax/SCLCombinator.java [new file with mode: 0644]

diff --git a/org.simantics.xml.sax.base/scl/xml/XMLDataTypes.scl b/org.simantics.xml.sax.base/scl/xml/XMLDataTypes.scl
new file mode 100644 (file)
index 0000000..cf62097
--- /dev/null
@@ -0,0 +1,48 @@
+importJava "org.simantics.xml.sax.base.datatypes.literal.Date" where
+  data XMLDate
+  
+  @JavaName getYear
+  dateYear :: XMLDate -> Integer
+  @JavaName getMonth
+  dateMonth :: XMLDate -> Integer
+  @JavaName getDate
+  dateDay :: XMLDate -> Integer
+  @JavaName getTimezoneOffset
+  dateTimezoneOffset :: XMLDate -> Integer
+  @JavaName toString
+  dateAsString :: XMLDate -> String
+  
+importJava "org.simantics.xml.sax.base.datatypes.literal.Time" where
+  data XMLTime
+  
+  @JavaName getHours
+  timeHours :: XMLTime -> Integer
+  @JavaName getMinutes
+  timeMinutes :: XMLTime -> Integer
+  @JavaName getSeconds
+  timeSeconds :: XMLTime -> Integer
+  @JavaName getTimezoneOffset
+  timeTimezoneOffset :: XMLTime -> Integer
+  @JavaName toString
+  timeAsString :: XMLTime -> String
+  
+  
+importJava "org.simantics.xml.sax.base.datatypes.literal.DateTime" where
+  data XMLDateTime
+  
+  @JavaName getYear
+  dateTimeYear :: XMLDateTime -> Integer
+  @JavaName getMonth
+  dateTimeMonth ::XMLDateTime -> Integer
+  @JavaName getDate
+  dateTimeDay :: XMLDateTime -> Integer
+  @JavaName getHours
+  dateTimeHours :: XMLDateTime -> Integer
+  @JavaName getMinutes
+  dateTimeMinutes :: XMLDateTime -> Integer
+  @JavaName getSeconds
+  dateTimeSeconds :: XMLDateTime -> Integer
+  @JavaName getTimezoneOffset
+  dateTimeTimezoneOffset :: XMLDateTime -> Integer
+  @JavaName toString
+  dateTimeAsString :: XMLDateTime -> String
index 1539f508c3fb1d808d3a601d45658d32f3d5bd8f..dd5d97f5d64fafeafa59adbf1904430f36d383fc 100644 (file)
-package org.simantics.xml.sax.ui.wizard;\r
-\r
-import java.io.File;\r
-import java.io.FilenameFilter;\r
-import java.io.IOException;\r
-import java.util.Arrays;\r
-\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.viewers.CheckboxTableViewer;\r
-import org.eclipse.jface.viewers.IStructuredContentProvider;\r
-import org.eclipse.jface.viewers.ITableLabelProvider;\r
-import org.eclipse.jface.viewers.LabelProvider;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.jface.wizard.WizardPage;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.events.SelectionAdapter;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.graphics.Image;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Button;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Label;\r
-import org.eclipse.swt.widgets.Text;\r
-import org.simantics.xml.sax.OntologyCombinator;\r
-\r
-public class SchemaCombinationPage extends WizardPage {\r
-       private Composite composite;\r
-       \r
-       File outputPlugin;\r
-       File srcDir;\r
-       \r
-       CheckboxTableViewer fileSelector;\r
-       Text outputText;\r
-       \r
-       public SchemaCombinationPage() {\r
-               super("XML Schema conversion","Combining schema versions", null);\r
-               setPageComplete(false);\r
-       }\r
-       \r
-       @Override\r
-       public void setVisible(boolean visible) {\r
-               super.setVisible(visible);\r
-               if (visible) {\r
-                       if (outputPlugin == null) {\r
-                               Label label = new Label(composite, SWT.NONE);\r
-                               label.setText("Output plug-in has not been set, cannot create combination resources");\r
-                               return;\r
-                       }\r
-                       String name = outputPlugin.getName();\r
-                       name = name.replaceAll("\\.", "/");\r
-                       srcDir = new File(outputPlugin.getAbsolutePath() +"/src/" + name);\r
-                       fileSelector.setInput(srcDir);\r
-               }\r
-       }\r
-       \r
-       \r
-       @Override\r
-       public void createControl(Composite parent) {\r
-               composite = new Composite(parent, SWT.NONE);\r
-               composite.setLayout(new GridLayout(1,true));\r
-               setControl(composite);  \r
-\r
-               Label label = new Label(composite, SWT.NONE);\r
-               label.setText("Ontology resource files");\r
-               fileSelector = CheckboxTableViewer.newCheckList(composite, SWT.BORDER);\r
-               fileSelector.setContentProvider(new FileContentProvider());\r
-               fileSelector.setLabelProvider(new FileLabelProvider());\r
-\r
-               label = new Label(composite, SWT.NONE);\r
-               label.setText("Output file");\r
-               outputText = new Text(composite, SWT.BORDER|SWT.SINGLE);\r
-               Button button = new Button(composite, SWT.PUSH);\r
-               button.setText("Combine");\r
-               button.addSelectionListener(new SelectionAdapter() {\r
-                       @Override\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               doCombination();\r
-                       }\r
-               });\r
-               \r
-               GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(fileSelector.getControl());\r
-               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(outputText);\r
-               GridDataFactory.fillDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(button);\r
-       }\r
-       \r
-       public void setOutputPlugin(File outputPlugin) {\r
-               this.outputPlugin = outputPlugin;\r
-       }\r
-       \r
-       private void doCombination() {\r
-               String outputName = outputText.getText();\r
-               if (outputName == null || outputName.length() < 2)\r
-                       return;\r
-               if (!outputName.endsWith(".java"))\r
-                       outputName+=".java";\r
-               \r
-               File outputFile = new File(srcDir.getAbsolutePath()+"/"+outputName);\r
-               \r
-               Object sel[] = fileSelector.getCheckedElements();\r
-               File inputFiles[] = new File[sel.length];\r
-               for (int i = 0; i < sel.length; i++) {\r
-                       inputFiles[i] = (File)sel[i];\r
-               }\r
-               \r
-               try {\r
-                       OntologyCombinator.combine(inputFiles, outputFile);\r
-                       setPageComplete(true);\r
-               } catch (IOException e) {\r
-                       setErrorMessage(e.getMessage());\r
-                       e.printStackTrace();\r
-               }\r
-               \r
-       }\r
-       \r
-       private static class FileContentProvider implements IStructuredContentProvider {\r
-               @Override\r
-               public Object[] getElements(Object inputElement) {\r
-                       File directory = (File)inputElement;\r
-                       if (!directory.isDirectory())\r
-                               return new Object[0];\r
-                       File[] files = directory.listFiles(new FilenameFilter() {\r
-                               \r
-                               @Override\r
-                               public boolean accept(File dir, String name) {\r
-                                       return name.endsWith("java");\r
-                               }\r
-                       });\r
-                       return files;\r
-               }\r
-               \r
-               @Override\r
-               public void dispose() {\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
-                       \r
-               }\r
-       }\r
-       \r
-       private static class FileLabelProvider extends LabelProvider implements ITableLabelProvider {\r
-               @Override\r
-               public Image getColumnImage(Object element, int columnIndex) {\r
-                       return null;\r
-               }\r
-               \r
-               @Override\r
-               public String getColumnText(Object element, int columnIndex) {\r
-                       File file = (File)element;\r
-                       if (columnIndex == 0)\r
-                               return file.getName();\r
-                       else\r
-                               return null;\r
-               }\r
-       }\r
-\r
-}\r
+package org.simantics.xml.sax.ui.wizard;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.simantics.xml.sax.OntologyCombinator;
+import org.simantics.xml.sax.SCLCombinator;
+
+public class SchemaCombinationPage extends WizardPage {
+       private Composite composite;
+       
+       File outputPlugin;
+       File srcDir;
+       
+       CheckboxTableViewer fileSelector;
+       Text javaOutputText;
+       Text sclOutputText;
+       
+       public SchemaCombinationPage() {
+               super("XML Schema conversion","Combining schema versions", null);
+               setPageComplete(false);
+       }
+       
+       @Override
+       public void setVisible(boolean visible) {
+               super.setVisible(visible);
+               if (visible) {
+                       if (outputPlugin == null) {
+                               Label label = new Label(composite, SWT.NONE);
+                               label.setText("Output plug-in has not been set, cannot create combination resources");
+                               return;
+                       }
+                       String name = outputPlugin.getName();
+                       name = name.replaceAll("\\.", "/");
+                       srcDir = new File(outputPlugin.getAbsolutePath() +"/src/" + name);
+                       fileSelector.setInput(srcDir);
+               }
+       }
+       
+       
+       @Override
+       public void createControl(Composite parent) {
+               composite = new Composite(parent, SWT.NONE);
+               composite.setLayout(new GridLayout(1,true));
+               setControl(composite);  
+
+               Label label = new Label(composite, SWT.NONE);
+               label.setText("Ontology resource files");
+               fileSelector = CheckboxTableViewer.newCheckList(composite, SWT.BORDER);
+               fileSelector.setContentProvider(new FileContentProvider());
+               fileSelector.setLabelProvider(new FileLabelProvider());
+
+               label = new Label(composite, SWT.NONE);
+               label.setText("Java Output file");
+               javaOutputText = new Text(composite, SWT.BORDER|SWT.SINGLE);
+               
+               label = new Label(composite, SWT.NONE);
+               label.setText("SCL Output file");
+               sclOutputText = new Text(composite, SWT.BORDER|SWT.SINGLE);
+               
+               Button button = new Button(composite, SWT.PUSH);
+               button.setText("Combine");
+               button.addSelectionListener(new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               doCombination();
+                       }
+               });
+               
+               GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(fileSelector.getControl());
+               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(javaOutputText);
+               GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(sclOutputText);
+               GridDataFactory.fillDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(button);
+       }
+       
+       public void setOutputPlugin(File outputPlugin) {
+               this.outputPlugin = outputPlugin;
+       }
+       
+       private void doCombination() {
+               Object sel[] = fileSelector.getCheckedElements();
+               File inputFiles[] = new File[sel.length];
+               for (int i = 0; i < sel.length; i++) {
+                       inputFiles[i] = (File)sel[i];
+               }
+               
+               try {
+                       String javaOutputName = javaOutputText.getText();
+                       if (javaOutputName != null && javaOutputName.length() > 2) {
+                               if (!javaOutputName.endsWith(".java"))
+                                       javaOutputName+=".java";
+                               
+                               File outputFile = new File(srcDir.getAbsolutePath()+"/"+javaOutputName);
+                               OntologyCombinator combinator = new OntologyCombinator();
+                               combinator.combine(inputFiles, outputFile);
+                               
+                       }
+                   // TODO: SCL code depends on Java, allowing generating just SCL makes sense only for testing purposes.
+                       String sclOutputName = sclOutputText.getText();
+                       if (sclOutputName != null && sclOutputName.length() > 2) {
+                               if (!sclOutputName.endsWith(".scl"))
+                                       sclOutputName+=".scl";
+                               
+                               File outputFile = new File(srcDir.getAbsolutePath()+"/"+sclOutputName);
+                               OntologyCombinator combinator = new SCLCombinator();
+                               combinator.combine(inputFiles, outputFile);                     
+                       }
+                       
+                       setPageComplete(true);
+               } catch (IOException e) {
+                       setErrorMessage(e.getMessage());
+                       e.printStackTrace();
+               }
+               
+       }
+       
+       private static class FileContentProvider implements IStructuredContentProvider {
+               @Override
+               public Object[] getElements(Object inputElement) {
+                       File directory = (File)inputElement;
+                       if (!directory.isDirectory())
+                               return new Object[0];
+                       File[] files = directory.listFiles(new FilenameFilter() {
+                               
+                               @Override
+                               public boolean accept(File dir, String name) {
+                                       return name.endsWith("java");
+                               }
+                       });
+                       return files;
+               }
+               
+               @Override
+               public void dispose() {
+                       
+               }
+               
+               @Override
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       
+               }
+       }
+       
+       private static class FileLabelProvider extends LabelProvider implements ITableLabelProvider {
+               @Override
+               public Image getColumnImage(Object element, int columnIndex) {
+                       return null;
+               }
+               
+               @Override
+               public String getColumnText(Object element, int columnIndex) {
+                       File file = (File)element;
+                       if (columnIndex == 0)
+                               return file.getName();
+                       else
+                               return null;
+               }
+       }
+
+}
index 0d084161dc4839b421a58ad2bd6585cddebaffeb..733d027103d964ac31fa5ea982462de6ef0c1a1e 100644 (file)
-package org.simantics.xml.sax;\r
-\r
-import java.io.BufferedReader;\r
-import java.io.BufferedWriter;\r
-import java.io.File;\r
-import java.io.FileReader;\r
-import java.io.FileWriter;\r
-import java.io.IOException;\r
-import java.io.PrintWriter;\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-public class OntologyCombinator {\r
-       \r
-       \r
-       public static void combine(File[] inputFiles, File outputFile) throws IOException{\r
-               Set<String> resources = new HashSet<>();\r
-               List<String> ontologyUris = new ArrayList<>();\r
-               List<String> classNames = new ArrayList<>();\r
-               String packageLine = null;\r
-               \r
-               \r
-               String packageLineStart = "package";\r
-               String resourceLineStart = "public final Resource ";\r
-               String uriLineStart = "public static final String ";\r
-               \r
-               \r
-               \r
-               for (File inputFile : inputFiles) {\r
-                       BufferedReader reader = new BufferedReader(new FileReader(inputFile));\r
-                       try {\r
-                               String line;\r
-                               String uri = null;\r
-                               String filename = inputFile.getName();\r
-                               String classname = filename.substring(0,filename.length()-5);\r
-                               classNames.add(classname);\r
-                               while ((line = reader.readLine()) != null) {\r
-                                       line = line.trim();\r
-                                       if (line.startsWith(resourceLineStart)) {\r
-                                               String res = line.substring(resourceLineStart.length(), line.length()-1);\r
-                                               resources.add(res);\r
-                                       } else if (line.startsWith(uriLineStart)) {\r
-                                               String euri = line.substring(line.indexOf('"')+1, line.length()-2);\r
-                                               if (uri == null) {\r
-                                                       uri = euri;\r
-                                               } else {\r
-                                                       int max = Math.min(euri.length(), uri.length());\r
-                                                       for (int i = 0; i < max; i++) {\r
-                                                               if (euri.charAt(i) != uri.charAt(i)) {\r
-                                                                       uri = uri.substring(0,i);\r
-                                                                       break;\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                       } else if (line.startsWith(packageLineStart)) {\r
-                                               packageLine = line;\r
-                                       }\r
-                               }\r
-                               if (uri != null && uri.length() > 6) {\r
-                                       if (uri.endsWith("/")) {\r
-                                               uri = uri.substring(0, uri.length()-1);\r
-                                       }\r
-                                       ontologyUris.add(uri);\r
-                               }\r
-                               else\r
-                                       throw new IOException("Could not resolve ontology uri for file " + inputFile.getName());\r
-                       } finally {\r
-                               reader.close();\r
-                       }\r
-               }\r
-               List<String> sortedResourcses = new ArrayList<>();\r
-               sortedResourcses.addAll(resources);\r
-               Collections.sort(sortedResourcses);\r
-               \r
-               PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));\r
-               String className = outputFile.getName();\r
-               int dp = className.indexOf(".");\r
-               if (dp > 0)\r
-                       className = className.substring(0,dp);\r
-               \r
-               try {\r
-                       writer.println(packageLine);\r
-                       writer.println();\r
-                       writer.println("import java.lang.reflect.Field;");\r
-                       writer.println("import java.util.Collection;");\r
-                       writer.println("import java.util.HashMap;");\r
-                       writer.println("import java.util.Map;");\r
-                       writer.println("import org.simantics.Simantics;");\r
-                       writer.println("import org.simantics.db.ReadGraph;");\r
-                       writer.println("import org.simantics.db.Resource;");\r
-                       writer.println("import org.simantics.db.exception.DatabaseException;");\r
-                       writer.println("import org.simantics.db.request.Read;");\r
-                       writer.println("import org.simantics.layer0.Layer0;");\r
-                       writer.println();\r
-                       writer.println();\r
-                       writer.println("public class " + className + " {");\r
-                       writer.println("  private static boolean init = false;");\r
-                       writer.println("  private static Map<Resource, Object> resourceObjects = new HashMap<>();");\r
-                       writer.println("  private static Map<Resource, "+className+"> loaderObjects = new HashMap<>();");\r
-                       writer.println();\r
-                       writer.println("  private Resource ontologyResource;");\r
-                       writer.println("  private Object resourceObject;");\r
-                       writer.println();\r
-                       writer.println("  static void init(ReadGraph graph) throws DatabaseException{");\r
-                       writer.println("     if (init)");\r
-                       writer.println("       return;");\r
-                       writer.println("     ");\r
-                       for (int i = 0; i < inputFiles.length; i++) {\r
-                       writer.println("     add(graph.getResource(\"" +ontologyUris.get(i) +"\"), " + classNames.get(i) +".getInstance(graph));");\r
-                       }\r
-                       writer.println("     ");\r
-                       writer.println("     init = true;");\r
-                       writer.println("  }");\r
-                       writer.println("  ");\r
-                       writer.println("  public static void add(Resource resource, Object object) {");\r
-                       writer.println("     if (resource == null || object == null)");\r
-                       writer.println("        throw new IllegalArgumentException();");\r
-                       writer.println("     resourceObjects.put(resource, object);");\r
-                       writer.println("     loaderObjects.put(resource, new "+className+"(resource, object));");\r
-                       writer.println("  }");\r
-                       writer.println("  ");\r
-                       writer.println("  public static "+className+" getOntology(final Resource res) throws DatabaseException {");\r
-                       writer.println("    return Simantics.getSession().syncRequest(new Read<"+className+">() {");\r
-                       writer.println("        @Override");\r
-                       writer.println("        public "+className+" perform(ReadGraph graph) throws DatabaseException {");\r
-                       writer.println("          return getOntology(graph, res);");\r
-                       writer.println("        }");\r
-                       writer.println("    });");\r
-                       writer.println("  }");\r
-                       writer.println("  ");\r
-                       writer.println("  public static "+className+" getOntology(ReadGraph graph, Resource res) throws DatabaseException{");\r
-                       writer.println("     init(graph);");\r
-                       writer.println("     Layer0 L0 = Layer0.getInstance(graph);");\r
-                       writer.println("     Collection<Resource> types = graph.getTypes(res);");\r
-                       writer.println("     for (Resource type : types) {");\r
-                       writer.println("        Resource part = graph.getPossibleObject(type, L0.PartOf);");\r
-                       writer.println("        while (part != null) {");\r
-                       writer.println("          if (loaderObjects.containsKey(part))");\r
-                       writer.println("             return loaderObjects.get(part);");\r
-                       writer.println("          part = graph.getPossibleObject(part, L0.PartOf);");\r
-                       writer.println("        }");\r
-                       writer.println("     }");\r
-                       writer.println("     return null;");\r
-                       writer.println("  }");\r
-                       writer.println("  ");\r
-                       writer.println("  private "+className+"(Resource ontologyRes, Object resourceObject) {");\r
-                       writer.println("     this.ontologyResource = ontologyRes;");\r
-                       writer.println("     this.resourceObject = resourceObject;");\r
-                       writer.println("     init();");\r
-                       writer.println("  }");\r
-                       writer.println("  ");\r
-                       writer.println("  private Resource get(String name)  {");\r
-                       writer.println("    try {");\r
-                       writer.println("      Field field = resourceObject.getClass().getDeclaredField(name);");\r
-                       writer.println("      return (Resource)field.get(resourceObject);");\r
-                       writer.println("    } catch (Exception e){");\r
-                       writer.println("      return null;");\r
-                       writer.println("    }");\r
-                       writer.println("  }");\r
-                       writer.println("  ");\r
-                       for (String s : sortedResourcses) {\r
-                   writer.println("  public Resource "+s+";");\r
-                       }\r
-                       writer.println("  ");\r
-                       writer.println("  private void init() {");\r
-                       for (String s : sortedResourcses) {\r
-                       writer.println("        "+s+" = get(\""+s+"\");");\r
-                       }\r
-                       writer.println("  }");\r
-                       writer.println("}");\r
-                       \r
-                       \r
-               }       finally {\r
-                       writer.close();\r
-               }\r
-               \r
-       }\r
-}\r
+package org.simantics.xml.sax;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class OntologyCombinator {
+       
+       String packageLineStart = new String("package");
+       String resourceLineStart = "public final Resource ";
+       String uriLineStart = "public static final String ";
+       
+       Set<String> resources = new HashSet<>();
+       List<String> ontologyUris = new ArrayList<>();
+       List<String> classNames = new ArrayList<>();
+       String packageLine = null;
+       List<String> sortedResourcses;
+       
+       protected void process(File[] inputFiles) throws IOException {
+               for (File inputFile : inputFiles) {
+                       BufferedReader reader = new BufferedReader(new FileReader(inputFile));
+                       try {
+                               String line;
+                               String uri = null;
+                               String filename = inputFile.getName();
+                               String classname = filename.substring(0,filename.length()-5);
+                               classNames.add(classname);
+                               while ((line = reader.readLine()) != null) {
+                                       line = line.trim();
+                                       if (line.startsWith(resourceLineStart)) {
+                                               String res = line.substring(resourceLineStart.length(), line.length()-1);
+                                               resources.add(res);
+                                       } else if (line.startsWith(uriLineStart)) {
+                                               String euri = line.substring(line.indexOf('"')+1, line.length()-2);
+                                               if (uri == null) {
+                                                       uri = euri;
+                                               } else {
+                                                       int max = Math.min(euri.length(), uri.length());
+                                                       for (int i = 0; i < max; i++) {
+                                                               if (euri.charAt(i) != uri.charAt(i)) {
+                                                                       uri = uri.substring(0,i);
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       } else if (line.startsWith(packageLineStart)) {
+                                               packageLine = line;
+                                       }
+                               }
+                               if (uri != null && uri.length() > 6) {
+                                       if (uri.endsWith("/")) {
+                                               uri = uri.substring(0, uri.length()-1);
+                                       }
+                                       ontologyUris.add(uri);
+                               }
+                               else
+                                       throw new IOException("Could not resolve ontology uri for file " + inputFile.getName());
+                       } finally {
+                               reader.close();
+                       }
+               }
+               
+               sortedResourcses = new ArrayList<>();
+               sortedResourcses.addAll(resources);
+               Collections.sort(sortedResourcses);
+               
+       }
+       
+       public void combine(File[] inputFiles, File outputFile) throws IOException{
+               process(inputFiles);
+               
+               PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
+               String className = outputFile.getName();
+               int dp = className.indexOf(".");
+               if (dp > 0)
+                       className = className.substring(0,dp);
+               
+               try {
+                       writer.println(packageLine);
+                       writer.println();
+                       writer.println("import java.lang.reflect.Field;");
+                       writer.println("import java.util.Collection;");
+                       writer.println("import java.util.HashMap;");
+                       writer.println("import java.util.Map;");
+                       writer.println("import org.simantics.Simantics;");
+                       writer.println("import org.simantics.db.ReadGraph;");
+                       writer.println("import org.simantics.db.Resource;");
+                       writer.println("import org.simantics.db.exception.DatabaseException;");
+                       writer.println("import org.simantics.db.request.Read;");
+                       writer.println("import org.simantics.layer0.Layer0;");
+                       writer.println();
+                       writer.println();
+                       writer.println("public class " + className + " {");
+                       writer.println("  private static boolean init = false;");
+                       writer.println("  private static Map<Resource, Object> resourceObjects = new HashMap<>();");
+                       writer.println("  private static Map<Resource, "+className+"> loaderObjects = new HashMap<>();");
+                       writer.println();
+                       writer.println("  private Resource ontologyResource;");
+                       writer.println("  private Object resourceObject;");
+                       writer.println();
+                       writer.println("  static void init(ReadGraph graph) throws DatabaseException{");
+                       writer.println("     if (init)");
+                       writer.println("       return;");
+                       writer.println("     ");
+                       for (int i = 0; i < inputFiles.length; i++) {
+                       writer.println("     add(graph.getResource(\"" +ontologyUris.get(i) +"\"), " + classNames.get(i) +".getInstance(graph));");
+                       }
+                       writer.println("     ");
+                       writer.println("     init = true;");
+                       writer.println("  }");
+                       writer.println("  ");
+                       writer.println("  public static void add(Resource resource, Object object) {");
+                       writer.println("     if (resource == null || object == null)");
+                       writer.println("        throw new IllegalArgumentException();");
+                       writer.println("     resourceObjects.put(resource, object);");
+                       writer.println("     loaderObjects.put(resource, new "+className+"(resource, object));");
+                       writer.println("  }");
+                       writer.println("  ");
+                       writer.println("  public static "+className+" getOntology(final Resource res) throws DatabaseException {");
+                       writer.println("    return Simantics.getSession().syncRequest(new Read<"+className+">() {");
+                       writer.println("        @Override");
+                       writer.println("        public "+className+" perform(ReadGraph graph) throws DatabaseException {");
+                       writer.println("          return getOntology(graph, res);");
+                       writer.println("        }");
+                       writer.println("    });");
+                       writer.println("  }");
+                       writer.println("  ");
+                       writer.println("  public static "+className+" getOntology(ReadGraph graph, Resource res) throws DatabaseException{");
+                       writer.println("     init(graph);");
+                       writer.println("     Layer0 L0 = Layer0.getInstance(graph);");
+                       writer.println("     Collection<Resource> types = graph.getTypes(res);");
+                       writer.println("     for (Resource type : types) {");
+                       writer.println("        Resource part = graph.getPossibleObject(type, L0.PartOf);");
+                       writer.println("        while (part != null) {");
+                       writer.println("          if (loaderObjects.containsKey(part))");
+                       writer.println("             return loaderObjects.get(part);");
+                       writer.println("          part = graph.getPossibleObject(part, L0.PartOf);");
+                       writer.println("        }");
+                       writer.println("     }");
+                       writer.println("     return null;");
+                       writer.println("  }");
+                       writer.println("  ");
+                       writer.println("  private "+className+"(Resource ontologyRes, Object resourceObject) {");
+                       writer.println("     this.ontologyResource = ontologyRes;");
+                       writer.println("     this.resourceObject = resourceObject;");
+                       writer.println("     init();");
+                       writer.println("  }");
+                       writer.println("  ");
+                       writer.println("  private Resource get(String name)  {");
+                       writer.println("    try {");
+                       writer.println("      Field field = resourceObject.getClass().getDeclaredField(name);");
+                       writer.println("      return (Resource)field.get(resourceObject);");
+                       writer.println("    } catch (Exception e){");
+                       writer.println("      return null;");
+                       writer.println("    }");
+                       writer.println("  }");
+                       writer.println("  ");
+                       for (String s : sortedResourcses) {
+                   writer.println("  public Resource "+s+";");
+                       }
+                       writer.println("  ");
+                       writer.println("  private void init() {");
+                       for (String s : sortedResourcses) {
+                       writer.println("        "+s+" = get(\""+s+"\");");
+                       }
+                       writer.println("  }");
+                       writer.println("}");
+                       
+                       
+               }       finally {
+                       writer.close();
+               }
+               
+       }
+}
diff --git a/org.simantics.xml.sax/src/org/simantics/xml/sax/SCLCombinator.java b/org.simantics.xml.sax/src/org/simantics/xml/sax/SCLCombinator.java
new file mode 100644 (file)
index 0000000..1a7fd0c
--- /dev/null
@@ -0,0 +1,49 @@
+package org.simantics.xml.sax;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * Creates a SCL module for Java combination class.
+ * 
+ * @see org.simantics.xml.sax.OntologyCombinator
+ * 
+ * @author luukkainen
+ *
+ */
+public class SCLCombinator extends OntologyCombinator{
+       
+       @Override
+       public void combine(File[] inputFiles, File outputFile) throws IOException {
+               super.process(inputFiles);
+               
+               PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
+               String className = outputFile.getName();
+               int dp = className.indexOf(".");
+               if (dp > 0)
+                       className = className.substring(0,dp);
+               
+               try {
+                       writer.println("import \"Simantics/DB\"");
+                       writer.println();
+                       writer.println("importJava \"" + packageLine.substring(packageLineStart.length()+1,packageLine.length()-1) + "." + className + "\" where");
+                       writer.println("  data " + className);
+                       writer.println("  ");
+                       writer.println("  @JavaName getOntology");
+                       writer.println("  getOntology :: Resource -> <ReadGraph> Maybe " + className);
+                       writer.println("  ");
+                       for (String s : sortedResourcses) {
+                   writer.println("  @JavaName "+s);
+                   writer.println("  "+s+" :: " + className + " -> Maybe Resource");
+                   writer.println("  ");
+                       }
+                       
+               }       finally {
+                       writer.close();
+               }
+       }
+
+}