]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.db/src/org/simantics/scl/db/SCLFunctions.java
(refs #7090) New functions subquery and subqueryC
[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.simantics.Simantics;
6 import org.simantics.db.ReadGraph;
7 import org.simantics.db.Resource;
8 import org.simantics.db.VirtualGraph;
9 import org.simantics.db.WriteGraph;
10 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
11 import org.simantics.db.common.request.BinaryRead;
12 import org.simantics.db.common.request.DelayedWriteRequest;
13 import org.simantics.db.common.request.ReadRequest;
14 import org.simantics.db.common.request.WriteRequest;
15 import org.simantics.db.common.request.WriteResultRequest;
16 import org.simantics.db.exception.DatabaseException;
17 import org.simantics.db.layer0.util.Layer0Utils;
18 import org.simantics.db.layer0.variable.Variables;
19 import org.simantics.db.request.Read;
20 import org.simantics.db.service.ClusterControl;
21 import org.simantics.db.service.SerialisationSupport;
22 import org.simantics.db.service.VirtualGraphSupport;
23 import org.simantics.layer0.utils.triggers.IActivationManager;
24 import org.simantics.scl.runtime.SCLContext;
25 import org.simantics.scl.runtime.function.Function;
26 import org.simantics.scl.runtime.function.Function1;
27 import org.simantics.scl.runtime.tuple.Tuple0;
28 import org.simantics.utils.DataContainer;
29
30 @SuppressWarnings({"rawtypes", "unchecked"})
31 public class SCLFunctions {
32
33     public static final String GRAPH = "graph";
34
35     public static <T> T safeExec(final Function f) {
36         try {
37             return (T)f.apply(Tuple0.INSTANCE);
38         } catch (Throwable t) {
39             t.printStackTrace();
40             return null;
41         }
42     }
43     
44     public static void asyncRead(final Function f) throws DatabaseException {
45         final SCLContext context = SCLContext.getCurrent();
46         Object graph = context.get(GRAPH);
47         if (graph != null) {
48             f.apply(Tuple0.INSTANCE);
49         } else {
50             Simantics.getSession().asyncRequest(new ReadRequest() {
51                 @Override
52                 public void run(ReadGraph graph) throws DatabaseException {
53                     SCLContext.push(context);
54                     ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
55                     try {
56                         f.apply(Tuple0.INSTANCE);
57                     } finally {
58                         context.put(GRAPH, oldGraph);
59                         SCLContext.pop();
60                     }
61                 }
62             });
63         }
64     }
65     
66     public static <T> T syncRead(final Function f) throws DatabaseException {
67         final SCLContext context = SCLContext.getCurrent();
68         Object graph = context.get(GRAPH);
69         if (graph != null) {
70             return (T)f.apply(Tuple0.INSTANCE);
71         } else {
72             return Simantics.getSession().syncRequest(new Read<T>() {
73                 @Override
74                 public T perform(ReadGraph graph) throws DatabaseException {
75                     SCLContext.push(context);
76                     ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
77                     try {
78                         return (T)f.apply(Tuple0.INSTANCE);
79                     } finally {
80                         context.put(GRAPH, oldGraph);
81                         SCLContext.pop();
82                     }
83                 }
84             });
85         }
86     }
87     
88     public static void asyncWrite(final Function f) throws DatabaseException {
89         final SCLContext context = SCLContext.getCurrent();
90         Object graph = context.get(GRAPH);
91         if (graph != null) {
92             f.apply(Tuple0.INSTANCE);
93         } else {
94             Simantics.getSession().asyncRequest(new WriteRequest() {
95                 @Override
96                 public void perform(WriteGraph graph) throws DatabaseException {
97                     SCLContext.push(context);
98                     ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
99                     try {
100                         f.apply(Tuple0.INSTANCE);
101                     } finally {
102                         context.put(GRAPH, oldGraph);
103                         SCLContext.pop();
104                     }
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 implements Read<Object> {
268         Function q;
269
270         public Subquery(Function q) {
271             this.q = q;
272         }
273
274         @Override
275         public Object perform(ReadGraph graph) throws DatabaseException {
276             SCLContext sclContext = SCLContext.getCurrent();
277             Object oldGraph = sclContext.put("graph", graph);
278             try {
279                 return q.apply(Tuple0.INSTANCE);
280             } catch (Throwable e) {
281                 if(e instanceof DatabaseException)
282                     throw (DatabaseException)e;
283                 else
284                     throw new DatabaseException(e);
285             } finally {
286                 sclContext.put("graph", oldGraph);
287             }
288         }
289
290         @Override
291         public int hashCode() {
292             return q.hashCode();
293         }
294         
295         @Override
296         public boolean equals(Object obj) {
297             if(this == obj)
298                 return true;
299             if(obj == null || obj.getClass() != getClass())
300                 return false;
301             Subquery other = (Subquery)obj;
302             return q.equals(other.q);
303         }
304     }
305
306     public static Object subquery(ReadGraph graph, Function q) throws DatabaseException {
307         return graph.syncRequest(new Subquery(q));
308     }
309
310     public static Object subqueryC(ReadGraph graph, Function q) throws DatabaseException {
311         return graph.syncRequest(new Subquery(q), TransientCacheAsyncListener.<Object>instance());
312     }
313 }