]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java
Fixing a deadlock. Some improvements to ModuleSourceRepository API
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / scl / GraphModuleSourceRepository.java
1 package org.simantics.modeling.scl;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5
6 import org.simantics.Simantics;
7 import org.simantics.db.ReadGraph;
8 import org.simantics.db.RequestProcessorSpecific;
9 import org.simantics.db.Resource;
10 import org.simantics.db.WriteGraph;
11 import org.simantics.db.common.request.UnaryRead;
12 import org.simantics.db.common.request.WriteRequest;
13 import org.simantics.db.exception.DatabaseException;
14 import org.simantics.db.procedure.SyncListener;
15 import org.simantics.db.request.Read;
16 import org.simantics.layer0.Layer0;
17 import org.simantics.modeling.ModelingUtils;
18 import org.simantics.scl.compiler.module.repository.UpdateListener;
19 import org.simantics.scl.compiler.source.ModuleSource;
20 import org.simantics.scl.compiler.source.StringModuleSource;
21 import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
22 import org.simantics.scl.runtime.SCLContext;
23 import org.simantics.structural2.utils.StructuralUtils;
24 import org.simantics.scl.runtime.tuple.Tuple0;
25
26 import gnu.trove.procedure.TObjectProcedure;
27 import gnu.trove.set.hash.THashSet;
28
29 public enum GraphModuleSourceRepository implements ModuleSourceRepository {
30     INSTANCE;
31
32     @Override
33     public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) {
34         if(!moduleName.startsWith("http://"))
35             return null;
36
37         Object graph = SCLContext.getCurrent().get("graph");
38         RequestProcessorSpecific requestProcessor;
39         if(graph instanceof ReadGraph)
40             requestProcessor = (ReadGraph)graph;
41         else
42             requestProcessor = Simantics.getSession();
43
44         Read<ModuleSource> request = new ReadModuleSource(moduleName);
45
46         try {
47             if(listener != null)
48                 return requestProcessor.syncRequest(request, new ModuleListener(listener, moduleName));
49             else
50                 return requestProcessor.syncRequest(request);
51         } catch (DatabaseException e) {
52             e.printStackTrace();
53             return null;
54         }
55     }
56
57     static class ModuleListener implements SyncListener<ModuleSource> {
58         UpdateListener listener;
59         boolean alreadyExecutedOnce;
60         final String moduleName;
61         public ModuleListener(UpdateListener listener, String moduleName) {
62             this.listener = listener;
63             this.moduleName = moduleName;
64         }
65         @Override
66         public boolean isDisposed() {
67             return listener == null;
68         }
69         private void fireUpdate(ReadGraph graph) {
70             if(listener != null) {
71                 SCLContext context = SCLContext.getCurrent();
72                 Object oldGraph = context.put("graph", graph);
73                 try {
74                     listener.notifyAboutUpdate();
75                 } finally {
76                     listener = null;
77                     context.put("graph", oldGraph);
78                 }
79             }
80         }
81         @Override
82         public void execute(ReadGraph graph, ModuleSource result)
83                 throws DatabaseException {
84             if(alreadyExecutedOnce)
85                 fireUpdate(graph);
86             else
87                 alreadyExecutedOnce = true;
88         }
89         @Override
90         public void exception(ReadGraph graph, Throwable t)
91                 throws DatabaseException {
92             t.printStackTrace();
93             if(alreadyExecutedOnce && listener != null)
94                 fireUpdate(graph);
95         }
96     };
97     
98     public static class GraphModuleSource extends StringModuleSource {
99
100         private final boolean immutable;
101
102         public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText, boolean immutable) {
103             super(moduleName, classLoader, moduleText);
104             this.immutable = immutable;
105         }
106         
107         @Override
108         public boolean isUpdateable() {
109             return !immutable;
110         }
111         
112         @Override
113         public void update(String newSourceText) {
114             try {
115                 Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText));
116             } catch (DatabaseException e) {
117                 e.printStackTrace();
118             }
119         }
120     }
121
122     static class ReadModuleSource extends UnaryRead<String, ModuleSource> {
123         public ReadModuleSource(String moduleName) {
124             super(moduleName);
125         }
126
127         @Override
128         public ModuleSource perform(ReadGraph graph) throws DatabaseException {
129             Resource moduleResource = graph.getPossibleResource(parameter);
130             if(moduleResource == null)
131                 return null;
132             Layer0 L0 = Layer0.getInstance(graph);
133             if(!graph.isInstanceOf(moduleResource, L0.SCLModule))
134                 return null;
135             String text = graph.getRelatedValue(moduleResource, L0.SCLModule_definition);
136             boolean immutable = StructuralUtils.isImmutable(graph, moduleResource);
137             return new GraphModuleSource(parameter, getClass().getClassLoader(), text, immutable);
138         }
139     }
140     
141     static class WriteModuleSource extends WriteRequest {
142         private final String moduleURI;
143         private final String sourceText;
144         
145         public WriteModuleSource(String moduleURI, String sourceText) {
146             this.moduleURI = moduleURI;
147             this.sourceText = sourceText;
148         }
149
150         @Override
151         public void perform(WriteGraph graph) throws DatabaseException {
152             Resource moduleResource = graph.getPossibleResource(moduleURI);
153             if(moduleResource == null)
154                 return;
155             Layer0 L0 = Layer0.getInstance(graph);
156             if(!graph.isInstanceOf(moduleResource, L0.SCLModule))
157                 return;
158             graph.claimLiteral(moduleResource, L0.SCLModule_definition, sourceText);
159         }
160     }
161
162     @Override
163     public void forAllModules(TObjectProcedure<String> procedure) {
164         THashSet<String> moduleURIs;
165         try {
166             moduleURIs = Simantics.getSession().syncRequest(new Read<THashSet<String>>() {
167                 @Override
168                 public THashSet<String> perform(ReadGraph graph)
169                         throws DatabaseException {
170                     THashSet<String> result = new THashSet<String>(); 
171                     Resource projectResource = Simantics.getProjectResource();
172                     Layer0 L0 = Layer0.getInstance(graph);
173                     for(Resource model : graph.getObjects(projectResource, L0.ConsistsOf)) {
174                         if(graph.isInstanceOf(model, L0.IndexRoot)) {
175                             for(Resource module : ModelingUtils.searchByType(graph, model, L0.SCLModule))
176                                 result.add(graph.getURI(module));
177                         }
178                     }
179                     
180                     Collection<Resource> ontologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE);
181                     for (Resource ontology : ontologies) {
182                         for(Resource module : ModelingUtils.searchByType(graph, ontology, L0.SCLModule))
183                             result.add(graph.getURI(module));
184                     }
185                     
186                     return result;
187                 }
188             });
189             moduleURIs.forEach(procedure);
190         } catch (DatabaseException e) {
191             e.printStackTrace();
192         }
193     }
194     
195     @Override
196     public Collection<String> getModuleNames() {
197         ArrayList<String> result = new ArrayList<>();
198         forAllModules((String name) -> {
199             result.add(name);
200             return true;
201         });
202         return result;
203     }
204 }