]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.db/src/org/simantics/scl/db/SCLFunctions.java
Graph bookkeeping gets broken in SCL request API
[simantics/platform.git] / bundles / org.simantics.scl.db / src / org / simantics / scl / db / SCLFunctions.java
1 package org.simantics.scl.db;
2
3 import java.io.IOException;
4
5 import org.cojen.classfile.TypeDesc;
6 import org.simantics.Simantics;
7 import org.simantics.db.ReadGraph;
8 import org.simantics.db.Resource;
9 import org.simantics.db.VirtualGraph;
10 import org.simantics.db.WriteGraph;
11 import org.simantics.db.common.procedure.adapter.SyncListenerAdapter;
12 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
13 import org.simantics.db.common.request.BinaryRead;
14 import org.simantics.db.common.request.DelayedWriteRequest;
15 import org.simantics.db.common.request.ReadRequest;
16 import org.simantics.db.common.request.UnaryRead;
17 import org.simantics.db.common.request.WriteRequest;
18 import org.simantics.db.common.request.WriteResultRequest;
19 import org.simantics.db.exception.DatabaseException;
20 import org.simantics.db.layer0.util.Layer0Utils;
21 import org.simantics.db.layer0.variable.Variables;
22 import org.simantics.db.request.Read;
23 import org.simantics.db.service.ClusterControl;
24 import org.simantics.db.service.SerialisationSupport;
25 import org.simantics.db.service.VirtualGraphSupport;
26 import org.simantics.layer0.utils.triggers.IActivationManager;
27 import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
28 import org.simantics.scl.compiler.errors.Failable;
29 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
30 import org.simantics.scl.compiler.module.Module;
31 import org.simantics.scl.compiler.module.repository.ImportFailureException;
32 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
33 import org.simantics.scl.compiler.types.Type;
34 import org.simantics.scl.osgi.SCLOsgi;
35 import org.simantics.scl.runtime.SCLContext;
36 import org.simantics.scl.runtime.function.Function;
37 import org.simantics.scl.runtime.function.Function1;
38 import org.simantics.scl.runtime.tuple.Tuple;
39 import org.simantics.scl.runtime.tuple.Tuple0;
40 import org.simantics.utils.DataContainer;
41
42 @SuppressWarnings({"rawtypes", "unchecked"})
43 public class SCLFunctions {
44
45     public static final String GRAPH = "graph";
46
47     public static <T> T safeExec(final Function f) {
48         try {
49             return (T)f.apply(Tuple0.INSTANCE);
50         } catch (Throwable t) {
51             t.printStackTrace();
52             return null;
53         }
54     }
55     
56     public static void asyncRead(final Function f) throws DatabaseException {
57         final SCLContext context = SCLContext.createDerivedContext();
58         Simantics.getSession().asyncRequest(new ReadRequest() {
59             @Override
60             public void run(ReadGraph graph) throws DatabaseException {
61                 SCLContext.push(context);
62                 context.put(GRAPH, graph);
63                 try {
64                     f.apply(Tuple0.INSTANCE);
65                 } finally {
66                     SCLContext.pop();
67                 }
68             }
69         });
70     }
71     
72     public static <T> T syncRead(final Function f) throws DatabaseException {
73         final SCLContext context = SCLContext.getCurrent();
74         Object graph = context.get(GRAPH);
75         if (graph != null) {
76             return (T)f.apply(Tuple0.INSTANCE);
77         } else {
78             return Simantics.getSession().syncRequest(new Read<T>() {
79                 @Override
80                 public T perform(ReadGraph graph) throws DatabaseException {
81                     SCLContext.push(context);
82                     ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
83                     try {
84                         return (T)f.apply(Tuple0.INSTANCE);
85                     } finally {
86                         context.put(GRAPH, oldGraph);
87                         SCLContext.pop();
88                     }
89                 }
90             });
91         }
92     }
93     
94     public static void asyncWrite(final Function f) throws DatabaseException {
95         SCLContext context = SCLContext.createDerivedContext();
96         Simantics.getSession().asyncRequest(new WriteRequest() {
97             @Override
98             public void perform(WriteGraph graph) throws DatabaseException {
99                 SCLContext.push(context);
100                 context.put(GRAPH, graph);
101                 try {
102                     f.apply(Tuple0.INSTANCE);
103                 } finally {
104                     SCLContext.pop();
105                 }
106             }
107         });
108     }
109     
110     public static <T> T syncWrite(final Function f) throws DatabaseException {
111         final SCLContext context = SCLContext.getCurrent();
112         Object graph = context.get(GRAPH);
113         if (graph != null) {
114             return (T)f.apply(Tuple0.INSTANCE);
115         } else {
116             return Simantics.getSession().syncRequest(new WriteResultRequest<T>() {
117                 @Override
118                 public T perform(WriteGraph graph) throws DatabaseException {
119                     SCLContext.push(context);
120                     ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
121                     try {
122                         return (T)f.apply(Tuple0.INSTANCE);
123                     } finally {
124                         context.put(GRAPH, oldGraph);
125                         SCLContext.pop();
126                     }
127                 }
128             });
129         }
130     }
131     
132     public static <T> T delayedSyncWrite(final Function f) throws DatabaseException {
133         final SCLContext context = SCLContext.getCurrent();
134         final DataContainer<T> dc = new DataContainer<T>(null);
135
136         DelayedWriteRequest request = new DelayedWriteRequest() {
137             @Override
138             public void perform(WriteGraph graph) throws DatabaseException {
139                 final SCLContext context = SCLContext.getCurrent();
140                 SCLContext.push(context);
141                 ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
142                 try {
143                     dc.set((T)f.apply(Tuple0.INSTANCE));
144                 } finally {
145                     context.put(GRAPH, oldGraph);
146                     SCLContext.pop();
147                 }
148             }
149         };
150         
151         Object graph = context.get(GRAPH);
152         if (graph != null) {
153             if (graph instanceof WriteGraph) {
154                 ((WriteGraph)graph).syncRequest(request);
155             } else {
156                 throw new DatabaseException("Caller is inside a read transaction.");
157             }
158         } else {
159             Simantics.getSession().syncRequest(request);
160         }
161         return dc.get();
162     }
163
164     public static <T> T virtualSyncWriteMem(WriteGraph graph, String virtualGraphId, final Function f) throws DatabaseException {
165         final SCLContext context = SCLContext.getCurrent();
166         VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class);
167         VirtualGraph vg = vgs.getMemoryPersistent(virtualGraphId);
168         return graph.syncRequest(new WriteResultRequest<T>(vg) {
169             @Override
170             public T perform(WriteGraph graph) throws DatabaseException {
171                 SCLContext.push(context);
172                 ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
173                 try {
174                     return (T)f.apply(Tuple0.INSTANCE);
175                 } finally {
176                     context.put(GRAPH, oldGraph);
177                     SCLContext.pop();
178                 }
179             }
180         });
181     }
182     
183     public static <T> T virtualSyncWriteWS(WriteGraph graph, String virtualGraphId, final Function f) throws DatabaseException {
184         final SCLContext context = SCLContext.getCurrent();
185         VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class);
186         VirtualGraph vg = vgs.getWorkspacePersistent(virtualGraphId);
187         return graph.syncRequest(new WriteResultRequest<T>(vg) {
188             @Override
189             public T perform(WriteGraph graph) throws DatabaseException {
190                 SCLContext.push(context);
191                 ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
192                 try {
193                     return (T)f.apply(Tuple0.INSTANCE);
194                 } finally {
195                     context.put(GRAPH, oldGraph);
196                     SCLContext.pop();
197                 }
198             }
199         });
200     }
201     
202     public static <T> T readValue(final String uri) throws DatabaseException {
203         return Simantics.getSession().syncRequest(new Read<T>() {
204             @Override
205             public T perform(ReadGraph graph) throws DatabaseException {
206                 return Variables.getVariable(graph, uri).getValue(graph);
207             }            
208         });
209     }
210     
211     public static <T> void writeValue(final String uri, final T value) throws DatabaseException {
212         Simantics.getSession().syncRequest(new WriteRequest() {
213             @Override
214             public void perform(WriteGraph graph) throws DatabaseException {
215                 Variables.getVariable(graph, uri).setValue(graph, value);
216             }            
217         });
218     }
219     
220     public static void activateOnce(Resource r) {
221         Simantics.getSession().getService(IActivationManager.class).activateOnce(r);
222     }
223     
224     public static void syncActivateOnce(WriteGraph graph, Resource r) throws DatabaseException {
225         graph.getService(IActivationManager.class).activateOnce(graph, r);
226     }
227
228     public static Resource resourceFromId(ReadGraph graph, long id) throws DatabaseException, IOException {
229         SerialisationSupport ss = graph.getService(SerialisationSupport.class);
230         return ss.getResource(id);
231     }
232     
233     public static void disableDependencies(WriteGraph graph) {
234         Layer0Utils.setDependenciesIndexingDisabled(graph, true);       
235     }
236     
237     public static void enableDependencies(WriteGraph graph) {
238         Layer0Utils.setDependenciesIndexingDisabled(graph, false);       
239     }
240     
241     public static void collectClusters() {
242         Simantics.getSession().getService(ClusterControl.class).collectClusters(Integer.MAX_VALUE);
243     }
244     
245     public static class SCLUnaryRead extends BinaryRead<Function1<Object,Object>, Object, Object> {
246
247                 public SCLUnaryRead(Function1<Object, Object> parameter1, Object parameter2) {
248                         super(parameter1, parameter2);
249                 }
250
251                 @Override
252                 public Object perform(ReadGraph graph) throws DatabaseException {
253                         return Simantics.applySCLRead(graph, parameter, parameter2);
254                 }
255         
256     }
257     
258     public static Object unaryQuery(ReadGraph graph, Function1<Object,Object> fn, Object value) throws DatabaseException {
259         return graph.syncRequest(new SCLUnaryRead(fn, value));
260     }
261
262     public static Object unaryQueryCached(ReadGraph graph, Function1<Object,Object> fn, Object value) throws DatabaseException {
263         return graph.syncRequest(new SCLUnaryRead(fn, value), TransientCacheAsyncListener.<Object>instance());
264     }
265     
266
267     private static class Subquery extends UnaryRead<Function, Object> {
268
269         public Subquery(Function q) {
270             super(q);
271         }
272
273         @Override
274         public Object perform(ReadGraph graph) throws DatabaseException {
275             return Simantics.applySCLRead(graph, parameter, Tuple0.INSTANCE);
276         }
277
278     }
279
280     public static Object subquery(ReadGraph graph, Function q) throws DatabaseException {
281         return graph.syncRequest(new Subquery(q));
282     }
283
284     public static Object subqueryC(ReadGraph graph, Function q) throws DatabaseException {
285         return graph.syncRequest(new Subquery(q), TransientCacheAsyncListener.<Object>instance());
286     }
287     
288     public static void subqueryL(ReadGraph graph, Function query, Function executeCallback, Function1<Throwable, Tuple> exceptionCallback, Function1<Tuple0, Boolean> isDisposedCallback) throws DatabaseException {
289         graph.asyncRequest(new Subquery(query), new SyncListenerAdapter<Object>() {
290             @Override
291             public void execute(ReadGraph graph, Object result) throws DatabaseException {
292                 Simantics.applySCLRead(graph, executeCallback, result);
293             }
294             
295             @Override
296             public void exception(ReadGraph graph, Throwable t) throws DatabaseException {
297                 Simantics.applySCLRead(graph, exceptionCallback, t);
298             }
299             
300             @Override
301             public boolean isDisposed() {
302                 return isDisposedCallback.apply(Tuple0.INSTANCE);
303             }
304         });
305     }
306
307     public static Object possibleFromDynamic(Type expectedType, String moduleName, Object value) {
308         
309         try {
310
311                 
312             Failable<Module> failable = SCLOsgi.MODULE_REPOSITORY.getModule(moduleName);
313             Module module = failable.getResult();
314             
315                 RuntimeEnvironment env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(
316                                 EnvironmentSpecification.of(moduleName, ""), module.getParentClassLoader());
317
318             JavaTypeTranslator tr = new JavaTypeTranslator(env.getEnvironment());
319             TypeDesc desc = tr.toTypeDesc(expectedType);
320             String className = desc.getFullName();
321             Class<?> clazz = env.getMutableClassLoader().loadClass(className);
322             if (!clazz.isAssignableFrom(value.getClass()))
323                 return null;
324             
325         } catch (ImportFailureException | ClassNotFoundException e) {
326         }
327         return value;
328     }
329
330 }