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