X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.db%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fdb%2FSCLFunctions.java;h=59923933f6107f3e8f0d25e928c9b2fdc7229f1e;hp=76891be980942418f998c3878991c1bc81b2d016;hb=309b4b814a1375c2e2bd67bdee77d62bc9abf073;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.scl.db/src/org/simantics/scl/db/SCLFunctions.java b/bundles/org.simantics.scl.db/src/org/simantics/scl/db/SCLFunctions.java index 76891be98..59923933f 100644 --- a/bundles/org.simantics.scl.db/src/org/simantics/scl/db/SCLFunctions.java +++ b/bundles/org.simantics.scl.db/src/org/simantics/scl/db/SCLFunctions.java @@ -1,266 +1,356 @@ -package org.simantics.scl.db; - -import java.io.IOException; - -import org.simantics.Simantics; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.VirtualGraph; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; -import org.simantics.db.common.request.BinaryRead; -import org.simantics.db.common.request.DelayedWriteRequest; -import org.simantics.db.common.request.ReadRequest; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.request.WriteResultRequest; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.util.Layer0Utils; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.request.Read; -import org.simantics.db.service.ClusterControl; -import org.simantics.db.service.SerialisationSupport; -import org.simantics.db.service.VirtualGraphSupport; -import org.simantics.layer0.utils.triggers.IActivationManager; -import org.simantics.scl.runtime.SCLContext; -import org.simantics.scl.runtime.function.Function; -import org.simantics.scl.runtime.function.Function1; -import org.simantics.scl.runtime.tuple.Tuple0; -import org.simantics.utils.DataContainer; - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class SCLFunctions { - - public static final String GRAPH = "graph"; - - public static T safeExec(final Function f) { - try { - return (T)f.apply(Tuple0.INSTANCE); - } catch (Throwable t) { - t.printStackTrace(); - return null; - } - } - - public static void asyncRead(final Function f) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - Object graph = context.get(GRAPH); - if (graph != null) { - f.apply(Tuple0.INSTANCE); - } else { - Simantics.getSession().asyncRequest(new ReadRequest() { - @Override - public void run(ReadGraph graph) throws DatabaseException { - SCLContext.push(context); - ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); - try { - f.apply(Tuple0.INSTANCE); - } finally { - context.put(GRAPH, oldGraph); - SCLContext.pop(); - } - } - }); - } - } - - public static T syncRead(final Function f) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - Object graph = context.get(GRAPH); - if (graph != null) { - return (T)f.apply(Tuple0.INSTANCE); - } else { - return Simantics.getSession().syncRequest(new Read() { - @Override - public T perform(ReadGraph graph) throws DatabaseException { - SCLContext.push(context); - ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); - try { - return (T)f.apply(Tuple0.INSTANCE); - } finally { - context.put(GRAPH, oldGraph); - SCLContext.pop(); - } - } - }); - } - } - - public static void asyncWrite(final Function f) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - Object graph = context.get(GRAPH); - if (graph != null) { - f.apply(Tuple0.INSTANCE); - } else { - Simantics.getSession().asyncRequest(new WriteRequest() { - @Override - public void perform(WriteGraph graph) throws DatabaseException { - SCLContext.push(context); - ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); - try { - f.apply(Tuple0.INSTANCE); - } finally { - context.put(GRAPH, oldGraph); - SCLContext.pop(); - } - } - }); - } - } - - public static T syncWrite(final Function f) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - Object graph = context.get(GRAPH); - if (graph != null) { - return (T)f.apply(Tuple0.INSTANCE); - } else { - return Simantics.getSession().syncRequest(new WriteResultRequest() { - @Override - public T perform(WriteGraph graph) throws DatabaseException { - SCLContext.push(context); - ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); - try { - return (T)f.apply(Tuple0.INSTANCE); - } finally { - context.put(GRAPH, oldGraph); - SCLContext.pop(); - } - } - }); - } - } - - public static T delayedSyncWrite(final Function f) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - final DataContainer dc = new DataContainer(null); - - DelayedWriteRequest request = new DelayedWriteRequest() { - @Override - public void perform(WriteGraph graph) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - SCLContext.push(context); - ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); - try { - dc.set((T)f.apply(Tuple0.INSTANCE)); - } finally { - context.put(GRAPH, oldGraph); - SCLContext.pop(); - } - } - }; - - Object graph = context.get(GRAPH); - if (graph != null) { - if (graph instanceof WriteGraph) { - ((WriteGraph)graph).syncRequest(request); - } else { - throw new DatabaseException("Caller is inside a read transaction."); - } - } else { - Simantics.getSession().syncRequest(request); - } - return dc.get(); - } - - public static T virtualSyncWriteMem(WriteGraph graph, String virtualGraphId, final Function f) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); - VirtualGraph vg = vgs.getMemoryPersistent(virtualGraphId); - return graph.syncRequest(new WriteResultRequest(vg) { - @Override - public T perform(WriteGraph graph) throws DatabaseException { - SCLContext.push(context); - ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); - try { - return (T)f.apply(Tuple0.INSTANCE); - } finally { - context.put(GRAPH, oldGraph); - SCLContext.pop(); - } - } - }); - } - - public static T virtualSyncWriteWS(WriteGraph graph, String virtualGraphId, final Function f) throws DatabaseException { - final SCLContext context = SCLContext.getCurrent(); - VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); - VirtualGraph vg = vgs.getWorkspacePersistent(virtualGraphId); - return graph.syncRequest(new WriteResultRequest(vg) { - @Override - public T perform(WriteGraph graph) throws DatabaseException { - SCLContext.push(context); - ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); - try { - return (T)f.apply(Tuple0.INSTANCE); - } finally { - context.put(GRAPH, oldGraph); - SCLContext.pop(); - } - } - }); - } - - public static T readValue(final String uri) throws DatabaseException { - return Simantics.getSession().syncRequest(new Read() { - @Override - public T perform(ReadGraph graph) throws DatabaseException { - return Variables.getVariable(graph, uri).getValue(graph); - } - }); - } - - public static void writeValue(final String uri, final T value) throws DatabaseException { - Simantics.getSession().syncRequest(new WriteRequest() { - @Override - public void perform(WriteGraph graph) throws DatabaseException { - Variables.getVariable(graph, uri).setValue(graph, value); - } - }); - } - - public static void activateOnce(Resource r) { - Simantics.getSession().getService(IActivationManager.class).activateOnce(r); - } - - public static void syncActivateOnce(WriteGraph graph, Resource r) throws DatabaseException { - graph.getService(IActivationManager.class).activateOnce(graph, r); - } - - public static Resource resourceFromId(ReadGraph graph, long id) throws DatabaseException, IOException { - SerialisationSupport ss = graph.getService(SerialisationSupport.class); - return ss.getResource(id); - } - - public static void disableDependencies(WriteGraph graph) { - Layer0Utils.setDependenciesIndexingDisabled(graph, true); - } - - public static void enableDependencies(WriteGraph graph) { - Layer0Utils.setDependenciesIndexingDisabled(graph, false); - } - - public static void collectClusters() { - Simantics.getSession().getService(ClusterControl.class).collectClusters(Integer.MAX_VALUE); - } - - public static class SCLUnaryRead extends BinaryRead, Object, Object> { - - public SCLUnaryRead(Function1 parameter1, Object parameter2) { - super(parameter1, parameter2); - } - - @Override - public Object perform(ReadGraph graph) throws DatabaseException { - return Simantics.applySCLRead(graph, parameter, parameter2); - } - - } - - public static Object unaryQuery(ReadGraph graph, Function1 fn, Object value) throws DatabaseException { - return graph.syncRequest(new SCLUnaryRead(fn, value)); - } - - public static Object unaryQueryCached(ReadGraph graph, Function1 fn, Object value) throws DatabaseException { - return graph.syncRequest(new SCLUnaryRead(fn, value), TransientCacheAsyncListener.instance()); - } - -} +package org.simantics.scl.db; + +import java.io.IOException; + +import org.cojen.classfile.TypeDesc; +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.VirtualGraph; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.procedure.adapter.SyncListenerAdapter; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.common.request.BinaryRead; +import org.simantics.db.common.request.DelayedWriteRequest; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.request.WriteResultRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.request.Read; +import org.simantics.db.service.ClusterControl; +import org.simantics.db.service.SerialisationSupport; +import org.simantics.db.service.VirtualGraphSupport; +import org.simantics.layer0.utils.triggers.IActivationManager; +import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification; +import org.simantics.scl.compiler.errors.Failable; +import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator; +import org.simantics.scl.compiler.module.Module; +import org.simantics.scl.compiler.module.repository.ImportFailureException; +import org.simantics.scl.compiler.runtime.RuntimeEnvironment; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.osgi.SCLOsgi; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function; +import org.simantics.scl.runtime.function.Function1; +import org.simantics.scl.runtime.tuple.Tuple; +import org.simantics.scl.runtime.tuple.Tuple0; +import org.simantics.utils.DataContainer; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public class SCLFunctions { + + public static final String GRAPH = "graph"; + + public static T safeExec(final Function f) { + try { + return (T)f.apply(Tuple0.INSTANCE); + } catch (Throwable t) { + t.printStackTrace(); + return null; + } + } + + public static void asyncRead(final Function f) throws DatabaseException { + final SCLContext context = SCLContext.createDerivedContext(); + Simantics.getSession().asyncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + SCLContext.push(context); + context.put(GRAPH, graph); + try { + f.apply(Tuple0.INSTANCE); + } finally { + SCLContext.pop(); + } + } + }); + } + + public static T syncRead(final Function f) throws DatabaseException { + final SCLContext context = SCLContext.getCurrent(); + Object graph = context.get(GRAPH); + if (graph != null) { + return (T)f.apply(Tuple0.INSTANCE); + } else { + return Simantics.getSession().syncRequest(new Read() { + @Override + public T perform(ReadGraph graph) throws DatabaseException { + SCLContext.push(context); + ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); + try { + return (T)f.apply(Tuple0.INSTANCE); + } finally { + context.put(GRAPH, oldGraph); + SCLContext.pop(); + } + } + }); + } + } + + public static void asyncWrite(final Function f) throws DatabaseException { + SCLContext context = SCLContext.createDerivedContext(); + Simantics.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SCLContext.push(context); + context.put(GRAPH, graph); + try { + f.apply(Tuple0.INSTANCE); + } finally { + SCLContext.pop(); + } + } + }); + } + + public static T syncWrite(final Function f) throws DatabaseException { + final SCLContext context = SCLContext.getCurrent(); + Object graph = context.get(GRAPH); + if (graph != null) { + return (T)f.apply(Tuple0.INSTANCE); + } else { + return Simantics.getSession().syncRequest(new WriteResultRequest() { + @Override + public T perform(WriteGraph graph) throws DatabaseException { + SCLContext.push(context); + ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); + try { + return (T)f.apply(Tuple0.INSTANCE); + } finally { + context.put(GRAPH, oldGraph); + SCLContext.pop(); + } + } + }); + } + } + + public static T delayedSyncWrite(final Function f) throws DatabaseException { + final SCLContext context = SCLContext.getCurrent(); + final DataContainer dc = new DataContainer(null); + + DelayedWriteRequest request = new DelayedWriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + final SCLContext context = SCLContext.getCurrent(); + SCLContext.push(context); + ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); + try { + dc.set((T)f.apply(Tuple0.INSTANCE)); + } finally { + context.put(GRAPH, oldGraph); + SCLContext.pop(); + } + } + }; + + Object graph = context.get(GRAPH); + if (graph != null) { + if (graph instanceof WriteGraph) { + ((WriteGraph)graph).syncRequest(request); + } else { + throw new DatabaseException("Caller is inside a read transaction."); + } + } else { + Simantics.getSession().syncRequest(request); + } + return dc.get(); + } + + public static T virtualSyncWriteMem(WriteGraph graph, String virtualGraphId, final Function f) throws DatabaseException { + final SCLContext context = SCLContext.getCurrent(); + VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); + VirtualGraph vg = vgs.getMemoryPersistent(virtualGraphId); + return graph.syncRequest(new WriteResultRequest(vg) { + @Override + public T perform(WriteGraph graph) throws DatabaseException { + SCLContext.push(context); + ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); + try { + return (T)f.apply(Tuple0.INSTANCE); + } finally { + context.put(GRAPH, oldGraph); + SCLContext.pop(); + } + } + }); + } + + public static T virtualSyncWriteWS(WriteGraph graph, String virtualGraphId, final Function f) throws DatabaseException { + final SCLContext context = SCLContext.getCurrent(); + VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); + VirtualGraph vg = vgs.getWorkspacePersistent(virtualGraphId); + return graph.syncRequest(new WriteResultRequest(vg) { + @Override + public T perform(WriteGraph graph) throws DatabaseException { + SCLContext.push(context); + ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph); + try { + return (T)f.apply(Tuple0.INSTANCE); + } finally { + context.put(GRAPH, oldGraph); + SCLContext.pop(); + } + } + }); + } + + public static T readValue(final String uri) throws DatabaseException { + return Simantics.getSession().syncRequest(new Read() { + @Override + public T perform(ReadGraph graph) throws DatabaseException { + return Variables.getVariable(graph, uri).getValue(graph); + } + }); + } + + public static void writeValue(final String uri, final T value) throws DatabaseException { + Simantics.getSession().syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Variables.getVariable(graph, uri).setValue(graph, value); + } + }); + } + + public static void activateOnce(Resource r) { + Simantics.getSession().getService(IActivationManager.class).activateOnce(r); + } + + public static void syncActivateOnce(WriteGraph graph, Resource r) throws DatabaseException { + graph.getService(IActivationManager.class).activateOnce(graph, r); + } + + public static Resource resourceFromId(ReadGraph graph, long id) throws DatabaseException, IOException { + SerialisationSupport ss = graph.getService(SerialisationSupport.class); + return ss.getResource(id); + } + + public static void disableDependencies(WriteGraph graph) { + Layer0Utils.setDependenciesIndexingDisabled(graph, true); + } + + public static void enableDependencies(WriteGraph graph) { + Layer0Utils.setDependenciesIndexingDisabled(graph, false); + } + + public static void collectClusters() { + Simantics.getSession().getService(ClusterControl.class).collectClusters(Integer.MAX_VALUE); + } + + public static class SCLUnaryRead extends BinaryRead, Object, Object> { + + public SCLUnaryRead(Function1 parameter1, Object parameter2) { + super(parameter1, parameter2); + } + + @Override + public Object perform(ReadGraph graph) throws DatabaseException { + return Simantics.applySCLRead(graph, parameter, parameter2); + } + + } + + public static Object unaryQuery(ReadGraph graph, Function1 fn, Object value) throws DatabaseException { + return graph.syncRequest(new SCLUnaryRead(fn, value)); + } + + public static Object unaryQueryCached(ReadGraph graph, Function1 fn, Object value) throws DatabaseException { + return graph.syncRequest(new SCLUnaryRead(fn, value), TransientCacheAsyncListener.instance()); + } + + + private static class Subquery implements Read { + Function q; + + public Subquery(Function q) { + this.q = q; + } + + @Override + public Object perform(ReadGraph graph) throws DatabaseException { + SCLContext sclContext = SCLContext.getCurrent(); + Object oldGraph = sclContext.put("graph", graph); + try { + return q.apply(Tuple0.INSTANCE); + } catch (Throwable e) { + if(e instanceof DatabaseException) + throw (DatabaseException)e; + else + throw new DatabaseException(e); + } finally { + sclContext.put("graph", oldGraph); + } + } + + @Override + public int hashCode() { + return q.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) + return true; + if(obj == null || obj.getClass() != getClass()) + return false; + Subquery other = (Subquery)obj; + return q.equals(other.q); + } + } + + public static Object subquery(ReadGraph graph, Function q) throws DatabaseException { + return graph.syncRequest(new Subquery(q)); + } + + public static Object subqueryC(ReadGraph graph, Function q) throws DatabaseException { + return graph.syncRequest(new Subquery(q), TransientCacheAsyncListener.instance()); + } + + public static void subqueryL(ReadGraph graph, Function query, Function executeCallback, Function1 exceptionCallback, Function1 isDisposedCallback) throws DatabaseException { + graph.asyncRequest(new Subquery(query), new SyncListenerAdapter() { + + @Override + public void execute(ReadGraph graph, Object result) { + executeCallback.apply(result); + } + + @Override + public void exception(ReadGraph graph, Throwable t) { + exceptionCallback.apply(t); + } + + @Override + public boolean isDisposed() { + return isDisposedCallback.apply(Tuple0.INSTANCE); + } + }); + } + + public static Object possibleFromDynamic(Type expectedType, String moduleName, Object value) { + + try { + + + Failable failable = SCLOsgi.MODULE_REPOSITORY.getModule(moduleName); + Module module = failable.getResult(); + + RuntimeEnvironment env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment( + EnvironmentSpecification.of(moduleName, ""), module.getParentClassLoader()); + + JavaTypeTranslator tr = new JavaTypeTranslator(env.getEnvironment()); + TypeDesc desc = tr.toTypeDesc(expectedType); + String className = desc.getFullName(); + Class clazz = env.getMutableClassLoader().loadClass(className); + if (!clazz.isAssignableFrom(value.getClass())) + return null; + + } catch (ImportFailureException | ClassNotFoundException e) { + } + return value; + } + +}