]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics/src/org/simantics/Simantics.java
Merge commit '728147df5d63a3333daff3d8c0e9bfd4f5597e3a'
[simantics/platform.git] / bundles / org.simantics / src / org / simantics / Simantics.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics;\r
13 \r
14 import java.io.File;\r
15 import java.util.UUID;\r
16 import java.util.concurrent.ScheduledFuture;\r
17 import java.util.concurrent.TimeUnit;\r
18 \r
19 import org.eclipse.core.runtime.IProgressMonitor;\r
20 import org.eclipse.core.runtime.NullProgressMonitor;\r
21 import org.eclipse.core.runtime.Platform;\r
22 import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;\r
23 import org.simantics.SimanticsPlatform.RecoveryPolicy;\r
24 import org.simantics.application.arguments.IArguments;\r
25 import org.simantics.application.arguments.SimanticsArguments;\r
26 import org.simantics.db.ReadGraph;\r
27 import org.simantics.db.Resource;\r
28 import org.simantics.db.Session;\r
29 import org.simantics.db.WriteGraph;\r
30 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;\r
31 import org.simantics.db.exception.DatabaseException;\r
32 import org.simantics.db.exception.RuntimeDatabaseException;\r
33 import org.simantics.db.indexing.IndexUtils;\r
34 import org.simantics.db.layer0.util.SimanticsClipboard;\r
35 import org.simantics.db.layer0.util.SimanticsKeys;\r
36 import org.simantics.db.layer0.variable.Variable;\r
37 import org.simantics.db.layer0.variable.Variables;\r
38 import org.simantics.db.management.ISessionContext;\r
39 import org.simantics.db.management.ISessionContextProvider;\r
40 import org.simantics.db.management.ISessionContextProviderSource;\r
41 import org.simantics.db.management.SessionContextProvider;\r
42 import org.simantics.db.management.SingleSessionContextProviderSource;\r
43 import org.simantics.db.request.ReadInterface;\r
44 import org.simantics.db.request.WriteInterface;\r
45 import org.simantics.internal.FileServiceImpl;\r
46 import org.simantics.layer0.Layer0;\r
47 import org.simantics.project.IProject;\r
48 import org.simantics.project.ProjectKeys;\r
49 import org.simantics.scl.compiler.top.ValueNotFound;\r
50 import org.simantics.scl.osgi.SCLOsgi;\r
51 import org.simantics.scl.runtime.SCLContext;\r
52 import org.simantics.scl.runtime.function.Function;\r
53 import org.simantics.scl.runtime.function.Function1;\r
54 import org.simantics.scl.runtime.function.Function2;\r
55 import org.simantics.utils.FileService;\r
56 import org.simantics.utils.FileUtils;\r
57 import org.simantics.utils.TempFiles;\r
58 import org.simantics.utils.threads.ThreadUtils;\r
59 \r
60 /**\r
61  * A facade for accessing basic Simantics platform services. Usable without a\r
62  * graphical UI, i.e. in headless contexts.\r
63  *\r
64  * TODO: in time, move headless functionality of SimanticsUI into this class but\r
65  * originals as delegates in SimanticsUI.\r
66  *\r
67  * TODO: duplicate of org.simantics.db.layer0.util.Simantics, do something about this!!\r
68  */\r
69 public class Simantics {\r
70 \r
71     /**\r
72      * Default database driver ID\r
73      */\r
74     private static final String DEFAULT_DATABASE_DRIVER_ID = "procore";\r
75 \r
76     private static String defaultDatabaseDriverId = DEFAULT_DATABASE_DRIVER_ID;\r
77 \r
78     private static ISessionContextProviderSource providerSource = null;\r
79     private static volatile FileServiceImpl fileService = null;\r
80 \r
81     /**\r
82      * Sets the database driver to be used by the platform. To have any effect,\r
83      * this must be set before platform startup.\r
84      * \r
85      * @param id driver id\r
86      */\r
87     public static void setDefaultDatabaseDriver(String id) {\r
88         defaultDatabaseDriverId = id;\r
89     }\r
90 \r
91     /**\r
92      * Returns currently set default database driver id.\r
93      */\r
94     public static String getDefaultDatabaseDriver() {\r
95         return defaultDatabaseDriverId;\r
96     }\r
97 \r
98     /**\r
99      * @param args\r
100      * @param progress\r
101      * @return\r
102      * @throws PlatformException\r
103      */\r
104     public static ISessionContext startUpHeadless(IArguments args, IProgressMonitor progress) throws PlatformException {\r
105         if (SimanticsPlatform.INSTANCE.sessionContext != null) {\r
106             throw new RuntimeDatabaseException("Simantics is already up and running.");\r
107         }\r
108 \r
109         RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;\r
110         OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;\r
111 \r
112         if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {\r
113             workspacePolicy = RecoveryPolicy.FixError;\r
114             ontologyPolicy = OntologyRecoveryPolicy.Merge;\r
115         }\r
116 \r
117         if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {\r
118             ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;\r
119         }\r
120 \r
121         if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {\r
122             ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;\r
123         }\r
124 \r
125         int localPort = 0;\r
126         if (args.contains(SimanticsArguments.LOCAL_SERVER_PORT)) {\r
127             try {\r
128                 localPort = args.get(SimanticsArguments.LOCAL_SERVER_PORT);\r
129             } catch (IllegalArgumentException e) {\r
130                 throw new PlatformException("Failed to open database session", e);\r
131             }\r
132         }\r
133 \r
134 //        ServerAddress remoteDatabase = null;\r
135 //        if (args.contains(SimanticsArguments.SERVER)) {\r
136 //            String serverAddress = args.get(SimanticsArguments.SERVER);\r
137 //            try {\r
138 //                remoteDatabase = new ServerAddress(serverAddress);\r
139 //            } catch (IllegalArgumentException e) {\r
140 //                throw new PlatformException("Failed to open database session", e);\r
141 //            }\r
142 //        }\r
143 \r
144         return startUpHeadless(progress, workspacePolicy, ontologyPolicy, localPort /*, remoteDatabase*/);\r
145     }\r
146 \r
147     /**\r
148      * @param progress\r
149      * @param workspacePolicy\r
150      * @param ontologyPolicy\r
151      * @param localPort\r
152      * @param remoteDatabase\r
153      * @return\r
154      * @throws PlatformException\r
155      */\r
156     public static ISessionContext startUpHeadless(IProgressMonitor progress, RecoveryPolicy workspacePolicy, OntologyRecoveryPolicy ontologyPolicy, int localPort) throws PlatformException {\r
157         if (SimanticsPlatform.INSTANCE.sessionContext != null) {\r
158             throw new RuntimeDatabaseException("Simantics is already up and running.");\r
159         }\r
160 \r
161         // Set session context provider.\r
162         final ISessionContextProvider provider = new SessionContextProvider(null);\r
163         ISessionContextProviderSource source = new SingleSessionContextProviderSource(provider);\r
164         setSessionContextProviderSource(source);\r
165         org.simantics.db.layer0.internal.SimanticsInternal.setSessionContextProviderSource(source);\r
166 \r
167         if (progress == null)\r
168             progress = new NullProgressMonitor();\r
169         return SimanticsPlatform.INSTANCE.startUp(defaultDatabaseDriverId, progress, workspacePolicy, ontologyPolicy, true, new ConsoleUserAgent());\r
170     }\r
171 \r
172     /**\r
173      * @param progress\r
174      * @throws PlatformException\r
175      */\r
176     public static void shutdown(IProgressMonitor progress) throws PlatformException {\r
177         SimanticsPlatform.INSTANCE.shutdown(progress);\r
178     }\r
179 \r
180     /**\r
181      * Queue execution of a runnable.\r
182      *\r
183      * @param runnable\r
184      */\r
185     public static void async(Runnable runnable) {\r
186         ThreadUtils.getBlockingWorkExecutor().execute(runnable);\r
187     }\r
188 \r
189     public static void async(Runnable runnable, int delay, TimeUnit unit) {\r
190         ThreadUtils.getTimer().schedule(runnable, delay, unit);\r
191     }\r
192 \r
193     public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, int initialDelay, int period, TimeUnit unit) {\r
194         return ThreadUtils.getTimer().scheduleAtFixedRate(runnable, initialDelay, period, unit);\r
195     }\r
196 \r
197     /**\r
198      * Queue execution of a non-blocking runnable. Use this method with caution.\r
199      * A non-blocking runnable nevers locks anything, No Locks, No semaphores,\r
200      * No Object.wait(), No synchronized() {} blocks.\r
201      *\r
202      * @param runnable a non-blocking runnable\r
203      */\r
204     public static void asyncNonblocking(Runnable runnable) {\r
205         ThreadUtils.getNonBlockingWorkExecutor().execute(runnable);\r
206     }\r
207 \r
208     /**\r
209      * Schedule execution of a non-blocking runnable. Use this method with caution.\r
210      * A non-blocking runnable never locks anything, No Locks, No semaphores,\r
211      * No Object,wait(), No synchronized() {} blocks.\r
212      *\r
213      * @param runnable a non-blocking runnable\r
214      * @param initialDelay\r
215      * @param period\r
216      */\r
217     public static void asyncNonblocking(Runnable runnable, int initialDelay, int period) {\r
218         ThreadUtils.getNonBlockingWorkExecutor().scheduleAtFixedRate(runnable, initialDelay, period, TimeUnit.MILLISECONDS);\r
219     }\r
220 \r
221     public static synchronized ISessionContext setSessionContext(ISessionContext ctx) {\r
222         return getSessionContextProvider().setSessionContext(ctx);\r
223     }\r
224 \r
225     public static void setSessionContextProviderSource(ISessionContextProviderSource source) {\r
226         if (source == null)\r
227             throw new IllegalArgumentException("null provider source");\r
228         providerSource = source;\r
229     }\r
230 \r
231     public static ISessionContextProviderSource getProviderSource() {\r
232         if (providerSource == null)\r
233             throw new IllegalStateException(\r
234             "providerSource must be initialized by the application before using class Simantics");\r
235         return providerSource;\r
236     }\r
237 \r
238     public static ISessionContextProvider getSessionContextProvider() {\r
239         return getProviderSource().getActive();\r
240     }\r
241 \r
242     /**\r
243      * Returns the database session context associated with the currently active\r
244      * context. This method should be used to retrieve session contexts only\r
245      * when the client is sure that the correct context is active.\r
246      *\r
247      * @return the session context associated with the currently active context\r
248      *         or <code>null</code> if the context has no session context\r
249      */\r
250     public static ISessionContext getSessionContext() {\r
251         ISessionContextProvider provider = getSessionContextProvider();\r
252         return provider != null ? provider.getSessionContext() : null;\r
253     }\r
254 \r
255     /**\r
256      * Returns the database Session bound to the currently active context.\r
257      *\r
258      * <p>\r
259      * The method always returns a non-null Session or produces an\r
260      * IllegalStateException if a Session was not attainable.\r
261      * </p>\r
262      *\r
263      * @return the Session bound to the currently active workbench window\r
264      * @throws IllegalStateException if no Session was available\r
265      */\r
266     public static Session getSession() {\r
267         ISessionContext ctx = getSessionContext();\r
268         if (ctx == null)\r
269             throw new IllegalStateException("Session unavailable, no database session open");\r
270         return ctx.getSession();\r
271     }\r
272 \r
273     /**\r
274      * Returns the database Session bound to the currently active context.\r
275      * Differently from {@link #getSession()}, this method returns\r
276      * <code>null</code> if there is no current Session available.\r
277      *\r
278      * @see #getSession()\r
279      * @return the Session bound to the currently active context or\r
280      *         <code>null</code>\r
281      */\r
282     public static Session peekSession() {\r
283         ISessionContext ctx = getSessionContext();\r
284         return ctx == null ? null : ctx.peekSession();\r
285     }\r
286 \r
287     /**\r
288      * @return the currently open and active project as a Resource\r
289      * @throws IllegalStateException if there is no currently active database\r
290      *         session, which also means there is no active project at the\r
291      *         moment\r
292      */\r
293     public static Resource getProjectResource() {\r
294         ISessionContext ctx = getSessionContext();\r
295         if (ctx == null)\r
296             throw new IllegalStateException("No current database session");\r
297         Resource project = ctx.getHint(SimanticsKeys.KEY_PROJECT);\r
298         if (project == null)\r
299             throw new IllegalStateException("No current project resource in session context " + ctx);\r
300         return project;\r
301     }\r
302 \r
303     /**\r
304      * @return the currently open and active project as a {@link Resource}\r
305      */\r
306     public static Resource peekProjectResource() {\r
307         ISessionContext ctx = getSessionContext();\r
308         return ctx != null ? ctx.<Resource>getHint(SimanticsKeys.KEY_PROJECT) : null;\r
309     }\r
310 \r
311     /**\r
312      * @return the currently open and active project as an {@link IProject}\r
313      * @throws IllegalStateException if there is no currently active database\r
314      *         session, which also means there is no active project at the\r
315      *         moment\r
316      */\r
317     public static IProject getProject() {\r
318         ISessionContext ctx = getSessionContext();\r
319         if (ctx == null)\r
320             throw new IllegalStateException("No current database session");\r
321         IProject project = ctx.getHint(ProjectKeys.KEY_PROJECT);\r
322         if (project == null)\r
323             throw new IllegalStateException("No current project in session context " + ctx);\r
324         return project;\r
325     }\r
326 \r
327     /**\r
328      * @return the currently open and active project as an {@link IProject} or\r
329      *         <code>null</code> if there is no active session or project\r
330      */\r
331     public static IProject peekProject() {\r
332         ISessionContext ctx = getSessionContext();\r
333         return ctx == null ? null : ctx.<IProject>getHint(ProjectKeys.KEY_PROJECT);\r
334     }\r
335 \r
336     // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this\r
337 //    private static SimanticsClipboard clipboard = SimanticsClipboard.EMPTY;\r
338 \r
339     /**\r
340      * @param content\r
341      */\r
342     public static void setClipboard(SimanticsClipboard content) {\r
343         // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this\r
344 //        if (content == null)\r
345 //            throw new NullPointerException("null clipboard content");\r
346 //        clipboard = content;\r
347         org.simantics.db.layer0.internal.SimanticsInternal.setClipboard(content);\r
348     }\r
349 \r
350     public static SimanticsClipboard getClipboard() {\r
351         // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this\r
352         //return clipboard;\r
353         return org.simantics.db.layer0.internal.SimanticsInternal.getClipboard();\r
354     }\r
355 \r
356     public static Layer0 getLayer0() throws DatabaseException {\r
357         return Layer0.getInstance(getSession());\r
358     }\r
359 \r
360     public static <T> T sync(ReadInterface<T> r) throws DatabaseException {\r
361         return getSession().sync(r);\r
362     }\r
363 \r
364     public static <T> T sync(WriteInterface<T> r) throws DatabaseException {\r
365         return getSession().sync(r);\r
366     }\r
367 \r
368     public static <T> void async(ReadInterface<T> r) {\r
369         getSession().async(r, new ProcedureAdapter<T>());\r
370     }\r
371 \r
372     public static <T> void async(WriteInterface<T> r) {\r
373         getSession().async(r);\r
374     }\r
375 \r
376     public static void clearTemporaryDirectory() {\r
377         FileUtils.deleteDir(getTemporaryDirectory());\r
378     }\r
379 \r
380     public static File getTempfile(String directory, String suffix) {\r
381         File dir = getTemporaryDirectory(directory);\r
382         return new File(dir, UUID.randomUUID().toString() + "." + suffix);\r
383     }\r
384 \r
385     public static File getTemporaryDirectory(String directory) {\r
386         File sub = new File(getTemporaryDirectory(), directory);\r
387         sub.mkdirs();\r
388         return sub;\r
389     }\r
390 \r
391     public static File getTemporaryDirectory() {\r
392         File workspace = Platform.getLocation().toFile();\r
393         File temp = new File(workspace, "tempFiles");\r
394         temp.mkdirs();\r
395         return temp;\r
396     }\r
397 \r
398     public static TempFiles getTempFiles() {\r
399         return TEMP_FILES;\r
400     }\r
401 \r
402     private static class TempFilesImpl implements TempFiles {\r
403         private final TempFilesImpl parent;\r
404         private final String prefix;\r
405         private final String fullPrefix;\r
406 \r
407         private TempFilesImpl(TempFilesImpl parent, String directory) {\r
408             this.parent = parent;\r
409             this.prefix = directory;\r
410             this.fullPrefix = getPrefix(new StringBuilder()).toString();\r
411         }\r
412 \r
413         private StringBuilder getPrefix(StringBuilder sb) {\r
414             if (parent != null)\r
415                 parent.getPrefix(sb);\r
416             if (prefix != null && !prefix.isEmpty())\r
417                 sb.append(prefix).append(File.separatorChar);\r
418             return sb;\r
419         }\r
420 \r
421         @Override\r
422         public File getRoot() {\r
423             return Simantics.getTemporaryDirectory(fullPrefix);\r
424         }\r
425 \r
426         @Override\r
427         public File getTempfile(String directory, String suffix) {\r
428             return Simantics.getTempfile(fullPrefix.isEmpty() ? directory : fullPrefix + directory, suffix);\r
429         }\r
430 \r
431         @Override\r
432         public TempFiles subdirectory(String directory) {\r
433             return new TempFilesImpl(this, directory);\r
434         }\r
435     }\r
436 \r
437     public static TempFiles TEMP_FILES = new TempFilesImpl(null, null);\r
438 \r
439     public static void flushIndexCaches(IProgressMonitor progress, Session session) {\r
440         try {\r
441             IndexUtils.flushIndexCaches(progress, session);\r
442         } catch (Exception e) {\r
443             Logger.defaultLogError(e);\r
444         }\r
445     }\r
446 \r
447 \r
448     @SuppressWarnings({ "unchecked", "rawtypes" })\r
449         public static <T> T applySCL(String module, String function, ReadGraph graph, Object ... args) throws DatabaseException {\r
450         SCLContext sclContext = SCLContext.getCurrent();\r
451             Object oldGraph = sclContext.put("graph", graph);\r
452                 try {\r
453                         T t = (T)((Function)SCLOsgi.MODULE_REPOSITORY.getValue(module, function)).applyArray(args);\r
454                         return t;\r
455                 } catch (ValueNotFound e) {\r
456                         throw new DatabaseException("SCL Value not found: " + e.name);\r
457                 } catch (Throwable t) {\r
458                         throw new DatabaseException(t);\r
459                 } finally {\r
460                         sclContext.put("graph", oldGraph);\r
461                 }\r
462 \r
463     }\r
464 \r
465     @SuppressWarnings("unchecked")\r
466     public static <T> T applySCLWrite(WriteGraph graph, @SuppressWarnings("rawtypes") Function f, Object ... args) throws DatabaseException {\r
467         SCLContext sclContext = SCLContext.getCurrent();\r
468         Object oldGraph = sclContext.put("graph", graph);\r
469         try {\r
470             return (T)f.applyArray(args);\r
471         } catch (Throwable t) {\r
472             throw new DatabaseException(t);\r
473         } finally {\r
474             sclContext.put("graph", oldGraph);\r
475         }\r
476     }\r
477 \r
478     @SuppressWarnings("unchecked")\r
479     public static <T> T applySCLRead(ReadGraph graph, @SuppressWarnings("rawtypes") Function f, Object ... args) throws DatabaseException {\r
480         SCLContext sclContext = SCLContext.getCurrent();\r
481         Object oldGraph = sclContext.put("graph", graph);\r
482         try {\r
483             return (T)f.applyArray(args);\r
484         } catch (Throwable t) {\r
485             throw new DatabaseException(t);\r
486         } finally {\r
487             sclContext.put("graph", oldGraph);\r
488         }\r
489     }\r
490     \r
491     public static <P0,R> R applySCLWrite(WriteGraph graph, Function1<P0,R> function, P0 p0) throws DatabaseException {\r
492         SCLContext sclContext = SCLContext.getCurrent();\r
493         Object oldGraph = sclContext.put("graph", graph);\r
494         try {\r
495             return function.apply(p0);\r
496         } catch (Throwable t) {\r
497             throw new DatabaseException(t);\r
498         } finally {\r
499             sclContext.put("graph", oldGraph);\r
500         }\r
501     }\r
502 \r
503     public static <P0,R> R applySCLRead(ReadGraph graph, Function1<P0,R> function, P0 p0) throws DatabaseException {\r
504         SCLContext sclContext = SCLContext.getCurrent();\r
505         Object oldGraph = sclContext.put("graph", graph);\r
506         try {\r
507             return function.apply(p0);\r
508         } catch (Throwable t) {\r
509             throw new DatabaseException(t);\r
510         } finally {\r
511             sclContext.put("graph", oldGraph);\r
512         }\r
513     }\r
514 \r
515     public static <P0,P1,R> R applySCLRead(ReadGraph graph, Function2<P0,P1,R> function, P0 p0, P1 p1) throws DatabaseException {\r
516         SCLContext sclContext = SCLContext.getCurrent();\r
517         Object oldGraph = sclContext.put("graph", graph);\r
518         try {\r
519             return function.apply(p0, p1);\r
520         } catch (Throwable t) {\r
521             throw new DatabaseException(t);\r
522         } finally {\r
523             sclContext.put("graph", oldGraph);\r
524         }\r
525     }\r
526 \r
527     public static <P0,R> R invokeSCLWrite(WriteGraph graph, Variable property, P0 p0) throws DatabaseException {\r
528         Function1<P0,R> fn = property.getPossibleValue(graph);\r
529         if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));\r
530         return Simantics.applySCLWrite(graph, fn, p0);\r
531     }\r
532 \r
533     public static <P0,R> R invokeSCL(ReadGraph graph, Variable property, P0 p0) throws DatabaseException {\r
534         Function1<P0,R> fn = property.getPossibleValue(graph);\r
535         if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));\r
536         return Simantics.applySCLRead(graph, fn, p0);\r
537     }\r
538 \r
539     public static <P0,P1,R> R invokeSCL(ReadGraph graph, Variable property, P0 p0, P1 p1) throws DatabaseException {\r
540         Function2<P0,P1,R> fn = property.getPossibleValue(graph);\r
541         if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));\r
542         return Simantics.applySCLRead(graph, fn, p0, p1);\r
543     }\r
544 \r
545     public static <P0,R> R invokeSCLWrite(WriteGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {\r
546         return invokeSCLWrite(graph, getProperty(graph, entity, property), p0);\r
547     }\r
548 \r
549     public static <P0,R> R invokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {\r
550         return invokeSCL(graph, getProperty(graph, entity, property), p0);\r
551     }\r
552 \r
553     public static <P0,P1,R> R invokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0, P1 p1) throws DatabaseException {\r
554         return invokeSCL(graph, getProperty(graph, entity, property), p0, p1);\r
555     }\r
556 \r
557         public static <P0,R> R tryInvokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {\r
558         Variable p = Variables.tryGetProperty(graph, entity, property);\r
559         if (p == null)\r
560                 return null;\r
561         return invokeSCL(graph, p, p0);\r
562     }\r
563 \r
564         public static <P0,P1,R> R tryInvokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0, P1 p1) throws DatabaseException {\r
565         Variable p = Variables.tryGetProperty(graph, entity, property);\r
566         if (p == null)\r
567                 return null;\r
568         return invokeSCL(graph, p, p0, p1);\r
569     }\r
570 \r
571         private static Variable getProperty(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {\r
572         return Variables.getVariable(graph, entity).getProperty(graph, property);\r
573     }\r
574 \r
575     public static boolean ensureMemoryBytes(long bytes) {\r
576 \r
577         Runtime runtime = Runtime.getRuntime();\r
578         long consumedMemory = runtime.totalMemory() - runtime.freeMemory();\r
579         long available = runtime.maxMemory() - consumedMemory;\r
580 \r
581         return available > bytes;\r
582 \r
583     }\r
584 \r
585     public static long getDiskBytes() {\r
586 \r
587         File ws = new File(Platform.getInstanceLocation().getURL().getFile());\r
588         return ws.getUsableSpace();\r
589 \r
590     }\r
591 \r
592     /**\r
593      * @return a service for dealing with recurring file system handling cases\r
594      */\r
595     public static FileService getFileService() {\r
596         FileService fs = fileService;\r
597         if (fs == null) {\r
598             synchronized (Simantics.class) {\r
599                 fs = fileService;\r
600                 if (fs == null)\r
601                     fs = fileService = new FileServiceImpl();\r
602             }\r
603         }\r
604         return fs;\r
605     }\r
606 \r
607 }\r