Automatically import also SCLMain modules of dependent index roots
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / request / RuntimeEnvironmentRequest.java
1 package org.simantics.db.common.request;
2
3 import org.simantics.db.ReadGraph;
4 import org.simantics.db.Resource;
5 import org.simantics.db.common.SimanticsInternal;
6 import org.simantics.db.common.utils.CommonDBUtils;
7 import org.simantics.db.exception.DatabaseException;
8 import org.simantics.db.procedure.Listener;
9 import org.simantics.db.request.Read;
10 import org.simantics.layer0.Layer0;
11 import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
12 import org.simantics.scl.compiler.module.repository.ImportFailureException;
13 import org.simantics.scl.compiler.module.repository.UpdateListener;
14 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
15 import org.simantics.scl.osgi.SCLOsgi;
16 import org.simantics.scl.runtime.SCLContext;
17
18 /**
19  * Finds the runtime environment of a model or other index root.
20  * 
21  * @author Hannu Niemistö
22  * @author Antti Villberg
23  */
24 public class RuntimeEnvironmentRequest extends UnaryRead<Resource, RuntimeEnvironment> {
25
26     public RuntimeEnvironmentRequest(Resource parameter) {
27         super(parameter);
28     }
29
30     protected void fillEnvironmentSpecification(EnvironmentSpecification environmentSpecification) {
31     }
32
33     static class UpdateListenerImpl extends UpdateListener {
34
35         final EnvironmentSpecification environmentSpecification;
36         final Listener<RuntimeEnvironment> callback;
37
38         UpdateListenerImpl(EnvironmentSpecification environmentSpecification, Listener<RuntimeEnvironment> callback) {
39             this.environmentSpecification = environmentSpecification;
40             this.callback = callback;
41         }
42
43         @Override
44         public void notifyAboutUpdate() {
45             if(callback.isDisposed()) {
46                 stopListening();
47                 return;
48             }
49             getRuntimeEnvironment(environmentSpecification, callback, this);
50         }
51     };
52
53     public static void getRuntimeEnvironment(EnvironmentSpecification environmentSpecification, Listener<RuntimeEnvironment> callback, UpdateListenerImpl listener) {
54
55         try {
56
57             SCLContext context = SCLContext.getCurrent();
58
59             RuntimeEnvironment env;
60             Object graph = context.get("graph");
61             if(graph == null)
62                 try {
63                     env = SimanticsInternal.getSession().syncRequest(new Read<RuntimeEnvironment>() {
64                         @Override
65                         public RuntimeEnvironment perform(ReadGraph graph) throws DatabaseException {
66
67                             SCLContext sclContext = SCLContext.getCurrent();
68                             Object oldGraph = sclContext.get("graph");
69                             try {
70                                 sclContext.put("graph", graph);
71                                 return SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(
72                                         environmentSpecification,
73                                         callback.getClass().getClassLoader(), listener);
74                             } catch (ImportFailureException e) {
75                                 throw new DatabaseException(e);
76                             } catch (Throwable t) {
77                                 throw new DatabaseException(t);
78                             } finally {
79                                 sclContext.put("graph", oldGraph);
80                             }
81                         }
82                     });
83                 } catch (DatabaseException e) {
84                     callback.exception(e);
85                     return;
86                 }
87             else 
88                 env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(
89                         environmentSpecification,
90                         callback.getClass().getClassLoader(), listener);
91             callback.execute(env);
92         } catch (ImportFailureException e) {
93             callback.exception(new DatabaseException(e));
94         }
95
96     }
97
98     @Override
99     public RuntimeEnvironment perform(ReadGraph graph)
100             throws DatabaseException {
101         final EnvironmentSpecification environmentSpecification = EnvironmentSpecification.of(
102                 "Builtin", "",
103                 "StandardLibrary", "",
104                 "Simantics/All", "");
105         fillEnvironmentSpecification(environmentSpecification);
106
107         Resource mainModule = CommonDBUtils.getPossibleChild(graph, parameter, "SCLMain");
108         String mainModuleUri;
109         if(mainModule != null) {
110             mainModuleUri = graph.getURI(mainModule);
111             environmentSpecification.importModule(mainModuleUri, "");
112             Layer0 L0 = Layer0.getInstance(graph);
113             for(Resource l : graph.getObjects(parameter, L0.IsLinkedTo)) {
114                 mainModule = CommonDBUtils.getPossibleChild(graph, l, "SCLMain");
115                 if(mainModule != null)
116                     environmentSpecification.importModule(graph.getURI(mainModule), "");
117             }
118         }
119         else
120             mainModuleUri = graph.getURI(parameter) + "/#"; // Add something dummy to the model uri that cannot be in a real URI
121
122         return graph.syncRequest(new ParametrizedPrimitiveRead<String, RuntimeEnvironment>(mainModuleUri) {
123
124             UpdateListenerImpl sclListener;
125
126             @Override
127             public void register(ReadGraph graph, Listener<RuntimeEnvironment> procedure) {
128
129                 SCLContext context = SCLContext.getCurrent();
130                 Object oldGraph = context.put("graph", graph);
131                 try {
132
133                     if(procedure.isDisposed()) {
134                         getRuntimeEnvironment(environmentSpecification, procedure, null);
135                     } else {
136                         sclListener = new UpdateListenerImpl(environmentSpecification, procedure);
137                         sclListener.notifyAboutUpdate();
138                     }
139
140                 } finally {
141                     context.put("graph", oldGraph);
142                 }
143
144             }
145
146             @Override
147             public void unregistered() {
148                 if(sclListener != null)
149                     sclListener.stopListening();
150             }
151
152         });
153     }
154
155     @Override
156     public int hashCode() {
157         return 31*getClass().hashCode() + super.hashCode();
158     }
159
160 }