From: jsimomaa Date: Fri, 28 Apr 2017 10:05:56 +0000 (+0300) Subject: Added Simantics/PGraph SCL API for compiling shared ontologies TGs X-Git-Tag: v1.29.0~78 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F67%2F467%2F3;p=simantics%2Fplatform.git Added Simantics/PGraph SCL API for compiling shared ontologies TGs Moved CompilePGraph action implementation to org.simantics.modeling and made the code headless. UI problem reporting can be done using the provided CompilePGraphs.UserAgent interface. refs #7181 Change-Id: I0c9e7fe5e4916077268651a6dea6c869f08a7d72 --- diff --git a/bundles/org.simantics.modeling.ui/adapters.xml b/bundles/org.simantics.modeling.ui/adapters.xml index 274db7a09..891ac0d46 100644 --- a/bundles/org.simantics.modeling.ui/adapters.xml +++ b/bundles/org.simantics.modeling.ui/adapters.xml @@ -337,7 +337,7 @@ + class="org.simantics.modeling.ui.actions.CompilePGraphsAction" /> diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphs.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphs.java deleted file mode 100644 index 4272b9de7..000000000 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphs.java +++ /dev/null @@ -1,420 +0,0 @@ -package org.simantics.modeling.ui.actions; - -import static org.simantics.db.common.utils.Transaction.endTransaction; - -import java.io.ByteArrayInputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.jface.layout.GridLayoutFactory; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.osgi.framework.Bundle; -import org.simantics.PlatformException; -import org.simantics.Simantics; -import org.simantics.databoard.Bindings; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.IndexRoot; -import org.simantics.db.common.request.ObjectsWithType; -import org.simantics.db.common.request.ReadRequest; -import org.simantics.db.common.request.UniqueRead; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.utils.Logger; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.adapter.ActionFactory; -import org.simantics.db.layer0.adapter.CopyHandler; -import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus; -import org.simantics.db.layer0.adapter.impl.DefaultCopyHandler; -import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler; -import org.simantics.db.layer0.adapter.impl.DefaultPasteImportAdvisor; -import org.simantics.db.layer0.util.ClipboardUtils; -import org.simantics.db.layer0.util.DomainProcessorState; -import org.simantics.db.layer0.util.Layer0Utils; -import org.simantics.db.layer0.util.ModelTransferableGraphSource; -import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest; -import org.simantics.db.layer0.util.SimanticsClipboard.Representation; -import org.simantics.db.layer0.util.SimanticsClipboardImpl; -import org.simantics.db.layer0.util.SimanticsKeys; -import org.simantics.db.layer0.util.TransferableGraphConfiguration2; -import org.simantics.db.service.SerialisationSupport; -import org.simantics.graph.compiler.CompilationResult; -import org.simantics.graph.compiler.ExternalFileLoader; -import org.simantics.graph.compiler.GraphCompiler; -import org.simantics.graph.compiler.GraphCompilerPreferences; -import org.simantics.graph.compiler.ValidationMode; -import org.simantics.graph.db.TransferableGraphSource; -import org.simantics.graph.db.TransferableGraphs; -import org.simantics.graph.diff.Diff; -import org.simantics.graph.diff.TransferableGraphDelta1; -import org.simantics.graph.representation.Identity; -import org.simantics.graph.representation.Root; -import org.simantics.graph.representation.TransferableGraph1; -import org.simantics.graphfile.ontology.GraphFileResource; -import org.simantics.layer0.Layer0; -import org.simantics.ltk.ISource; -import org.simantics.ltk.Problem; -import org.simantics.modeling.ui.Activator; -import org.simantics.utils.datastructures.Pair; - -/** - * @author Antti Villberg - */ -public class CompilePGraphs implements ActionFactory { - - @Override - public Runnable create(Object target) { - - if (!(target instanceof Resource)) - return null; - - final Resource r = (Resource)target; - - return new Runnable() { - - private void uncheckedClose(Closeable closeable) { - try { - if (closeable != null) - closeable.close(); - } catch (IOException e) { - //ignore - } - } - - private File copyResource(URL url, File targetFile) throws IOException, FileNotFoundException { - FileOutputStream os = null; - InputStream is = null; - try { - if (targetFile.exists()) - targetFile.delete(); - - is = url.openStream(); - int read; - byte [] buffer = new byte [16384]; - os = new FileOutputStream (targetFile); - while ((read = is.read (buffer)) != -1) { - os.write(buffer, 0, read); - } - os.close (); - is.close (); - - return targetFile; - } finally { - uncheckedClose(os); - uncheckedClose(is); - } - } - - private File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException { - String tmpDirStr = System.getProperty("java.io.tmpdir"); - if (tmpDirStr == null) - throw new NullPointerException("java.io.tmpdir property is null"); - File tmpDir = new File(tmpDirStr); - File libFile = new File(tmpDir, libName); - return copyResource(libURL, libFile); - } - - private File url2file(URL url, String fileName) { - if ("file".equals(url.getProtocol())) { - try { - File path = new File(URLDecoder.decode(url.getPath(), "UTF-8")); - return path; - } catch (UnsupportedEncodingException e) { - Logger.defaultLogError(e); - } - } else if ("jar".equals(url.getProtocol())) { - try { - File libFile = extractLib(url, fileName); - return libFile; - } catch (FileNotFoundException e) { - Logger.defaultLogError(e); - } catch (IOException e) { - Logger.defaultLogError(e); - } - } else { - System.err.println("Unsupported URL protocol '" + url + "' for FastLZ native library file '" + fileName); - } - return null; - } - @Override - public void run() { - - try { - - final Collection sources = new ArrayList(); - Collection dependencies = new ArrayList(); - - for(Bundle b : Activator.getContext().getBundles()) { - URL tg = b.getEntry("/graph.tg"); - if(tg == null) continue; - File f = url2file(FileLocator.resolve(tg), b.getSymbolicName()); - dependencies.add(GraphCompiler.read(f)); - } - - final TransferableGraph1 thisOntology = Simantics.sync(new UniqueRead() { - - @Override - public TransferableGraph1 perform(ReadGraph graph) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - Resource parent = graph.getSingleObject(r, L0.PartOf); - - CopyHandler ch = new DefaultCopyHandler(r) { - - protected TransferableGraphConfiguration2 createConfiguration(ReadGraph graph, boolean cut) throws DatabaseException { - - Map preStatus = new HashMap(); - preStatus.put(r, ExtentStatus.EXTERNAL); - if(!parent.equals(graph.getRootLibrary())) - preStatus.put(parent, ExtentStatus.EXTERNAL); - - return new TransferableGraphConfiguration2(null, Collections.emptyList(), preStatus, true, true); - - } - - protected TransferableGraphSource computeSource(ReadGraph graph, TransferableGraphConfiguration2 conf) throws DatabaseException { - return graph.syncRequest(new ModelTransferableGraphSourceRequest(conf) { - - protected ModelTransferableGraphSource getSource(ReadGraph graph, TransferableGraphConfiguration2 configuration, DomainProcessorState state, File otherStatementsFile, File valueFile) throws DatabaseException { - return new ModelTransferableGraphSource(graph, configuration, state, otherStatementsFile, valueFile) { - - @Override - protected Identity getRootIdentity(DomainProcessorState state, SerialisationSupport support, Resource rootLibrary) throws DatabaseException { - return new Identity(state.ids.get(support.getTransientId(rootLibrary)), new Root("", "")); - } - - }; - } - - }); - } - - }; - SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl(); - ch.copyToClipboard(graph, clipboard); - for (Set object : clipboard.getContents()) { - TransferableGraph1 tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH); - if(tg != null) return tg; - } - return null; - } - - }); - - dependencies.add(thisOntology); - - Simantics.sync(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - for(Resource file : graph.syncRequest(new ObjectsWithType(r, L0.ConsistsOf, L0.PGraph))) { - - final String src = graph.getRelatedValue(file, L0.PGraph_definition, Bindings.STRING); - - final ByteArrayInputStream baos = new ByteArrayInputStream(src.getBytes()); - - sources.add(new ISource() { - - @Override - public int startPos() { - return 0; - } - - @Override - public int startLine() { - return 0; - } - - @Override - public InputStream open() throws IOException { - return baos; - } - - @Override - public int length() throws IOException { - return src.length(); - } - - @Override - public String getName() { - return "Source"; - } - - }); - - } - } - - }); - - final StringBuilder errorStringBuilder = new StringBuilder(); - GraphCompilerPreferences prefs = new GraphCompilerPreferences(); - prefs.validate = true; - prefs.validateRelationRestrictions = ValidationMode.ERROR; - prefs.validateResourceHasType = ValidationMode.IGNORE; - - final CompilationResult result = Simantics.sync(new UniqueRead() { - - @Override - public CompilationResult perform(ReadGraph graph) throws DatabaseException { - - final Resource root = graph.syncRequest(new IndexRoot(r)); - final String baseURI = graph.getURI(root); - - ExternalFileLoader fileLoader = new ExternalFileLoader() { - @Override - public byte[] load(String fileName) throws IOException { - try { - GraphFileResource GF = GraphFileResource.getInstance(graph); - Resource file = graph.getResource(baseURI + "/" + fileName); - return graph.getRelatedValue(file, GF.HasFiledata, Bindings.BYTE_ARRAY); - } catch (DatabaseException e) { - throw new IOException(e); - } - } - }; - - return GraphCompiler.compile("1.1", sources, dependencies, fileLoader, prefs); - - } - - }); - - for(Problem problem : result.getErrors()) - errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n"); - for(Problem problem : result.getWarnings()) - errorStringBuilder.append(problem.getLocation() + ": " + problem.getDescription() + "\n"); - - if(!result.getErrors().isEmpty() || !result.getWarnings().isEmpty()) { - - class ErrorMessageDialog extends MessageDialog { - - public ErrorMessageDialog(Shell shell) { - super(shell, - "Unsatisfied dependencies", null, - "The following dependencies were missing. Please import the dependencies and try again.", - MessageDialog.ERROR, new String[] { "Continue" }, 0); - } - - @Override - protected Control createCustomArea(Composite composite) { - - GridLayoutFactory.fillDefaults().applyTo(composite); - - org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(composite, SWT.BORDER | SWT.READ_ONLY); - GridDataFactory.fillDefaults().grab(true, true).applyTo(list); - for(Problem problem : result.getErrors()) - list.add(problem.getLocation() + ": " + problem.getDescription() + "\n"); - for(Problem problem : result.getWarnings()) - list.add(problem.getLocation() + ": " + problem.getDescription() + "\n"); - - return composite; - - } - - } - - ErrorMessageDialog md = new ErrorMessageDialog(Display.getCurrent().getActiveShell()); - md.open(); - - return; - } - - - final Pair existing = Simantics.sync(new UniqueRead>() { - - @Override - public Pair perform(ReadGraph graph) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - TransferableGraph1 tg = graph.getPossibleRelatedValue(r, L0.SharedOntology_tg, Bindings.getBindingUnchecked( TransferableGraph1.class )); - if(tg == null) return null; - long[] tgResources = graph.getPossibleRelatedValue(r, L0.SharedOntology_tgResources, Bindings.LONG_ARRAY); - if(tgResources == null) return null; - return Pair.make(tg, tgResources); - } - - }); - - if(existing != null) { - - try { - - Simantics.sync(new WriteRequest() { - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - - TransferableGraphDelta1 delta = new Diff(existing.first, result.getGraph()).diff(); - long[] resourceArray = TransferableGraphs.applyDelta(graph, existing.second, delta); - - Layer0 L0 = Layer0.getInstance(graph); - graph.claimLiteral(r, L0.SharedOntology_tg, result.getGraph(), Bindings.getBindingUnchecked( TransferableGraph1.class )); - graph.claimLiteral(r, L0.SharedOntology_tgResources, L0.ResourceIdArray, resourceArray, Bindings.LONG_ARRAY); - - Layer0Utils.addCommentMetadata(graph, "Compiled ontology " + graph.getURI(r)); - - } - - }); - - } catch (Throwable t) { - throw new PlatformException(t); - } finally { - endTransaction(); - } - - } else { - - final DefaultPasteImportAdvisor advisor = new DefaultPasteImportAdvisor(r); - - DefaultPasteHandler.defaultExecute(result.getGraph(), r, advisor); - - Simantics.sync(new WriteRequest() { - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - graph.claimLiteral(r, L0.SharedOntology_tg, result.getGraph(), Bindings.getBindingUnchecked( TransferableGraph1.class )); - graph.claimLiteral(r, L0.SharedOntology_tgResources, L0.ResourceIdArray, advisor.getResourceIds(), Bindings.LONG_ARRAY); - - Layer0Utils.addCommentMetadata(graph, "Compiled ontology " + graph.getURI(r)); - - } - - }); - - } - - } catch (Exception e) { - Logger.defaultLogError(e); - } - - } - - }; - - } - -} diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphsAction.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphsAction.java new file mode 100644 index 000000000..783244a61 --- /dev/null +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/CompilePGraphsAction.java @@ -0,0 +1,70 @@ +package org.simantics.modeling.ui.actions; + +import java.io.IOException; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.ActionFactory; +import org.simantics.graph.compiler.CompilationResult; +import org.simantics.ltk.Problem; +import org.simantics.modeling.CompilePGraphs; +import org.simantics.utils.ui.ExceptionUtils; + +/** + * @author Antti Villberg + */ +public class CompilePGraphsAction implements ActionFactory { + + @Override + public Runnable create(Object target) { + if (!(target instanceof Resource)) + return null; + return () -> { + try { + CompilePGraphs.compilePGraphs((Resource) target, new CompileUserAgent()); + } catch (IOException | DatabaseException e) { + ExceptionUtils.logAndShowError(e); + } + }; + } + + public static class CompileUserAgent implements CompilePGraphs.UserAgent { + @Override + public void reportProblems(CompilationResult result) { + class ErrorMessageDialog extends MessageDialog { + public ErrorMessageDialog(Shell shell) { + super(shell, + "Unsatisfied dependencies", null, + "The following dependencies were missing. Please import the dependencies and try again.", + MessageDialog.ERROR, new String[] { "Continue" }, 0); + } + + @Override + protected Control createCustomArea(Composite composite) { + GridLayoutFactory.fillDefaults().applyTo(composite); + + org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(composite, SWT.BORDER | SWT.READ_ONLY); + GridDataFactory.fillDefaults().grab(true, true).applyTo(list); + for (Problem problem : result.getErrors()) + list.add(problem.getLocation() + ": " + problem.getDescription() + "\n"); + for (Problem problem : result.getWarnings()) + list.add(problem.getLocation() + ": " + problem.getDescription() + "\n"); + + return composite; + } + } + + ErrorMessageDialog md = new ErrorMessageDialog(Display.getCurrent().getActiveShell()); + md.open(); + } + } + +} diff --git a/bundles/org.simantics.modeling/META-INF/MANIFEST.MF b/bundles/org.simantics.modeling/META-INF/MANIFEST.MF index 7f81e56f2..bcdf14219 100644 --- a/bundles/org.simantics.modeling/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.modeling/META-INF/MANIFEST.MF @@ -38,7 +38,10 @@ Require-Bundle: org.simantics.simulation;bundle-version="1.0.0", org.simantics.selectionview.ontology;bundle-version="1.2.0", org.simantics.scl.ui;bundle-version="0.5.0", org.slf4j.api, - org.apache.batik + org.simantics.graphfile.ontology, + org.apache.batik, + org.simantics.ltk, + org.simantics.graph.compiler Export-Package: org.simantics.modeling, org.simantics.modeling.actions, org.simantics.modeling.adapters, diff --git a/bundles/org.simantics.modeling/scl/Simantics/PGraph.scl b/bundles/org.simantics.modeling/scl/Simantics/PGraph.scl new file mode 100644 index 000000000..31afde301 --- /dev/null +++ b/bundles/org.simantics.modeling/scl/Simantics/PGraph.scl @@ -0,0 +1,4 @@ +import "Simantics/DB" + +importJava "org.simantics.modeling.CompilePGraphs" where + compilePGraphs :: Resource -> () \ No newline at end of file diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/CompilePGraphs.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/CompilePGraphs.java new file mode 100644 index 000000000..9b620c2f7 --- /dev/null +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/CompilePGraphs.java @@ -0,0 +1,314 @@ +package org.simantics.modeling; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.FileLocator; +import org.osgi.framework.Bundle; +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.IndexRoot; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.Logger; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.CopyHandler; +import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus; +import org.simantics.db.layer0.adapter.impl.DefaultCopyHandler; +import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler; +import org.simantics.db.layer0.adapter.impl.DefaultPasteImportAdvisor; +import org.simantics.db.layer0.util.ClipboardUtils; +import org.simantics.db.layer0.util.DomainProcessorState; +import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.db.layer0.util.ModelTransferableGraphSource; +import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest; +import org.simantics.db.layer0.util.SimanticsClipboard.Representation; +import org.simantics.db.layer0.util.SimanticsClipboardImpl; +import org.simantics.db.layer0.util.SimanticsKeys; +import org.simantics.db.layer0.util.TransferableGraphConfiguration2; +import org.simantics.db.service.SerialisationSupport; +import org.simantics.graph.compiler.CompilationResult; +import org.simantics.graph.compiler.ExternalFileLoader; +import org.simantics.graph.compiler.GraphCompiler; +import org.simantics.graph.compiler.GraphCompilerPreferences; +import org.simantics.graph.compiler.ValidationMode; +import org.simantics.graph.db.TransferableGraphException; +import org.simantics.graph.db.TransferableGraphSource; +import org.simantics.graph.db.TransferableGraphs; +import org.simantics.graph.diff.Diff; +import org.simantics.graph.diff.TransferableGraphDelta1; +import org.simantics.graph.representation.Identity; +import org.simantics.graph.representation.Root; +import org.simantics.graph.representation.TransferableGraph1; +import org.simantics.graphfile.ontology.GraphFileResource; +import org.simantics.layer0.Layer0; +import org.simantics.ltk.ISource; +import org.simantics.ltk.Problem; +import org.simantics.modeling.internal.Activator; +import org.simantics.utils.FileUtils; +import org.simantics.utils.datastructures.Pair; + +/** + * @author Antti Villberg + */ +public class CompilePGraphs { + + public static interface UserAgent { + void reportProblems(CompilationResult result); + } + + /** + * Simantics/PGraph#compilePGraphs SCL API. + * + * @param r + * @throws IOException + * @throws DatabaseException + */ + public static void compilePGraphs(Resource r) throws IOException, DatabaseException { + compilePGraphs(r, null); + } + + public static void compilePGraphs(Resource r, UserAgent userAgent) throws IOException, DatabaseException { + final Collection sources = new ArrayList<>(); + Collection dependencies = new ArrayList<>(); + + for (Bundle b : Activator.getContext().getBundles()) { + URL tg = b.getEntry("/graph.tg"); + if (tg == null) continue; + File f = url2file(FileLocator.resolve(tg), b.getSymbolicName()); + try { + dependencies.add(GraphCompiler.read(f)); + } catch (Exception e) { + throw new IOException("Failed to read compiled transferable graph as dependency: " + f, e); + } + } + + final TransferableGraph1 thisOntology = Simantics.sync(new UniqueRead() { + + @Override + public TransferableGraph1 perform(ReadGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + Resource parent = graph.getSingleObject(r, L0.PartOf); + + CopyHandler ch = new DefaultCopyHandler(r) { + protected TransferableGraphConfiguration2 createConfiguration(ReadGraph graph, boolean cut) throws DatabaseException { + Map preStatus = new HashMap<>(); + preStatus.put(r, ExtentStatus.EXTERNAL); + if (!parent.equals(graph.getRootLibrary())) + preStatus.put(parent, ExtentStatus.EXTERNAL); + return new TransferableGraphConfiguration2(null, Collections.emptyList(), preStatus, true, true); + } + + protected TransferableGraphSource computeSource(ReadGraph graph, TransferableGraphConfiguration2 conf) throws DatabaseException { + return graph.syncRequest(new ModelTransferableGraphSourceRequest(conf) { + protected ModelTransferableGraphSource getSource(ReadGraph graph, TransferableGraphConfiguration2 configuration, DomainProcessorState state, File otherStatementsFile, File valueFile) throws DatabaseException { + return new ModelTransferableGraphSource(graph, configuration, state, otherStatementsFile, valueFile) { + @Override + protected Identity getRootIdentity(DomainProcessorState state, SerialisationSupport support, Resource rootLibrary) throws DatabaseException { + return new Identity(state.ids.get(support.getTransientId(rootLibrary)), new Root("", "")); + } + }; + } + }); + } + }; + + SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl(); + ch.copyToClipboard(graph, clipboard); + for (Set object : clipboard.getContents()) { + TransferableGraph1 tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH); + if (tg != null) + return tg; + } + + return null; + } + }); + + if (thisOntology == null) + throw new DatabaseException("Failed to dump the containing ontology of " + r + " into TransferableGraph1"); + + dependencies.add(thisOntology); + + Simantics.sync(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + for (Resource file : graph.syncRequest(new ObjectsWithType(r, L0.ConsistsOf, L0.PGraph))) { + String src = graph.getRelatedValue(file, L0.PGraph_definition, Bindings.STRING); + sources.add(new StringSource(src)); + } + } + }); + + GraphCompilerPreferences prefs = new GraphCompilerPreferences(); + prefs.validate = true; + prefs.validateRelationRestrictions = ValidationMode.ERROR; + prefs.validateResourceHasType = ValidationMode.IGNORE; + final CompilationResult result = Simantics.sync(new UniqueRead() { + @Override + public CompilationResult perform(ReadGraph graph) throws DatabaseException { + final Resource root = graph.syncRequest(new IndexRoot(r)); + final String baseURI = graph.getURI(root); + + GraphFileResource GF = GraphFileResource.getInstance(graph); + ExternalFileLoader fileLoader = fileName -> { + try { + Resource file = graph.getResource(baseURI + "/" + fileName); + return graph.getRelatedValue(file, GF.HasFiledata, Bindings.BYTE_ARRAY); + } catch (DatabaseException e) { + throw new IOException(e); + } + }; + + return GraphCompiler.compile("1.1", sources, dependencies, fileLoader, prefs); + } + }); + + if (!result.getErrors().isEmpty() || !result.getWarnings().isEmpty()) { + if (userAgent != null) { + userAgent.reportProblems(result); + return; + } else { + StringBuilder error = new StringBuilder(); + for (Problem problem : result.getErrors()) + error.append(problem.getLocation() + ": " + problem.getDescription() + "\n"); + for (Problem problem : result.getWarnings()) + error.append(problem.getLocation() + ": " + problem.getDescription() + "\n"); + throw new DatabaseException(error.toString()); + } + } + + final Pair existing = Simantics.sync(new UniqueRead>() { + @Override + public Pair perform(ReadGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + TransferableGraph1 tg = graph.getPossibleRelatedValue(r, L0.SharedOntology_tg, Bindings.getBindingUnchecked( TransferableGraph1.class )); + if(tg == null) return null; + long[] tgResources = graph.getPossibleRelatedValue(r, L0.SharedOntology_tgResources, Bindings.LONG_ARRAY); + if(tgResources == null) return null; + return Pair.make(tg, tgResources); + } + }); + + if (existing != null) { + Simantics.sync(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + TransferableGraphDelta1 delta = new Diff(existing.first, result.getGraph()).diff(); + long[] resourceArray = TransferableGraphs.applyDelta(graph, existing.second, delta); + + Layer0 L0 = Layer0.getInstance(graph); + graph.claimLiteral(r, L0.SharedOntology_tg, result.getGraph(), Bindings.getBindingUnchecked( TransferableGraph1.class )); + graph.claimLiteral(r, L0.SharedOntology_tgResources, L0.ResourceIdArray, resourceArray, Bindings.LONG_ARRAY); + + Layer0Utils.addCommentMetadata(graph, "Compiled ontology " + graph.getURI(r)); + } + }); + } else { + final DefaultPasteImportAdvisor advisor = new DefaultPasteImportAdvisor(r); + try { + DefaultPasteHandler.defaultExecute(result.getGraph(), r, advisor); + } catch (TransferableGraphException e) { + // TODO: defaultExecute never actually throws this exception! + throw new DatabaseException(e); + } + + Simantics.sync(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + graph.claimLiteral(r, L0.SharedOntology_tg, result.getGraph(), Bindings.getBindingUnchecked( TransferableGraph1.class )); + graph.claimLiteral(r, L0.SharedOntology_tgResources, L0.ResourceIdArray, advisor.getResourceIds(), Bindings.LONG_ARRAY); + + Layer0Utils.addCommentMetadata(graph, "Compiled ontology " + graph.getURI(r)); + } + }); + } + } + + private static File extractLib(URL libURL, String libName) throws FileNotFoundException, IOException { + String tmpDirStr = System.getProperty("java.io.tmpdir"); + if (tmpDirStr == null) + throw new NullPointerException("java.io.tmpdir property is null"); + File tmpDir = new File(tmpDirStr); + File libFile = new File(tmpDir, libName); + return FileUtils.copyResource(libURL, libFile, false); + } + + private static File url2file(URL url, String fileName) { + if ("file".equals(url.getProtocol())) { + try { + File path = new File(URLDecoder.decode(url.getPath(), "UTF-8")); + return path; + } catch (UnsupportedEncodingException e) { + Logger.defaultLogError(e); + } + } else if ("jar".equals(url.getProtocol())) { + try { + File libFile = extractLib(url, fileName); + return libFile; + } catch (FileNotFoundException e) { + Logger.defaultLogError(e); + } catch (IOException e) { + Logger.defaultLogError(e); + } + } else { + System.err.println("Unsupported URL protocol '" + url + "' for FastLZ native library file '" + fileName); + } + return null; + } + + private static class StringSource implements ISource { + private String src; + private ByteArrayInputStream baos; + + public StringSource(String s) { + this.src = s; + this.baos = new ByteArrayInputStream(src.getBytes()); + } + + @Override + public int startPos() { + return 0; + } + + @Override + public int startLine() { + return 0; + } + + @Override + public InputStream open() throws IOException { + return baos; + } + + @Override + public int length() throws IOException { + return src.length(); + } + + @Override + public String getName() { + return "Source"; + } + } + +}