]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.issues.common/src/org/simantics/issues/common/DependencyIssueSource2.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.issues.common / src / org / simantics / issues / common / DependencyIssueSource2.java
1 package org.simantics.issues.common;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.HashSet;\r
5 import java.util.List;\r
6 import java.util.Set;\r
7 import java.util.concurrent.ConcurrentHashMap;\r
8 import java.util.concurrent.ConcurrentMap;\r
9 import java.util.concurrent.CopyOnWriteArraySet;\r
10 \r
11 import org.simantics.Simantics;\r
12 import org.simantics.db.MetadataI;\r
13 import org.simantics.db.ReadGraph;\r
14 import org.simantics.db.Resource;\r
15 import org.simantics.db.WriteGraph;\r
16 import org.simantics.db.common.Indexing;\r
17 import org.simantics.db.common.changeset.GenericChangeListener;\r
18 import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
19 import org.simantics.db.common.request.PossibleTypedParent;\r
20 import org.simantics.db.common.utils.Functions;\r
21 import org.simantics.db.common.utils.NameUtils;\r
22 import org.simantics.db.event.ChangeListener;\r
23 import org.simantics.db.exception.DatabaseException;\r
24 import org.simantics.db.layer0.genericrelation.DependenciesRelation.DependencyChangesRequest;\r
25 import org.simantics.db.layer0.genericrelation.DependencyChanges;\r
26 import org.simantics.db.service.GraphChangeListenerSupport;\r
27 import org.simantics.issues.ontology.IssueResource;\r
28 import org.simantics.layer0.Layer0;\r
29 import org.simantics.scl.runtime.function.Function2;\r
30 import org.simantics.simulation.ontology.SimulationResource;\r
31 \r
32 public class DependencyIssueSource2 implements IssueSource {\r
33 \r
34         public static final boolean DEBUG = false;\r
35         \r
36         private Resource source;\r
37         private Resource model;\r
38         private Resource type;\r
39         private Set<Resource> searchTypes;\r
40         private Resource base;\r
41         private Resource extensionFunction;\r
42 \r
43         private CopyOnWriteArraySet<Function2<ReadGraph, List<Resource>, Boolean>> listeners = new CopyOnWriteArraySet<>();\r
44         private ConcurrentMap<Function2<ReadGraph, List<Resource>, Boolean>, ChangeListener> listenerMap = new ConcurrentHashMap<>();\r
45 \r
46         public DependencyIssueSource2(ReadGraph graph, Resource source) throws DatabaseException {\r
47             Layer0 L0 = Layer0.getInstance(graph);\r
48                 IssueResource IR = IssueResource.getInstance(graph);\r
49                 this.source = source;\r
50                 this.model = graph.syncRequest(new PossibleTypedParent(source, SimulationResource.getInstance(graph).Model));\r
51                 this.extensionFunction = graph.getPossibleObject(source, IR.Sources_DependencyTracker_HasExtension); \r
52                 this.type = graph.getSingleObject(source, IR.Sources_DependencyTracker_HasType);\r
53                 HashSet<Resource> _searchTypes = new HashSet<>();\r
54                 _searchTypes.addAll(graph.getObjects(source, IR.Sources_DependencyTracker_HasSearchType));\r
55                 _searchTypes.add(type);\r
56                 this.searchTypes = new HashSet<>(_searchTypes);\r
57                 Resource baseFunction = graph.getSingleObject(source, IR.Sources_DependencyTracker_HasBaseFunction);\r
58                 this.base = Functions.exec(graph, baseFunction, graph, graph.getSingleObject(source, L0.PartOf));\r
59         }\r
60 \r
61         private List<Resource> resourcesToCheck(ReadGraph graph, DependencyChanges event) throws DatabaseException {\r
62 \r
63                 HashSet<Resource> depSet = new HashSet<>();\r
64 \r
65                 if(DEBUG) {\r
66                         System.err.println("resourcesToCheck[" + NameUtils.getSafeName(graph, source) + "] - component changes for type " + NameUtils.getSafeName(graph, searchTypes));\r
67                 }\r
68 \r
69                 depSet.addAll(IssueSourceUtils.getChangedDependencies(graph, model, base, searchTypes, event));\r
70                 depSet.addAll(IssueSourceUtils.getChangedDependencies(graph, source, model, base, searchTypes));\r
71                 \r
72                 List<Resource> deps = new ArrayList<>(depSet);\r
73                 \r
74                 if(DEBUG) {\r
75                         System.err.println("resourcesToCheck[" + NameUtils.getSafeName(graph, source) + "] " + deps);\r
76                         for(Resource r : deps) {\r
77                                 System.err.println("dep " + NameUtils.getSafeName(graph, r));\r
78                         }\r
79                 }\r
80                 \r
81                 if(extensionFunction != null) {\r
82                         try {\r
83                                 deps = Functions.exec(graph, extensionFunction, graph, deps);\r
84                         } catch (Throwable t) {\r
85                                 t.printStackTrace();\r
86                         }\r
87                 }\r
88 \r
89                 if(DEBUG) {\r
90                         for(Resource r : deps) {\r
91                                 System.err.println("dep extension " + NameUtils.getSafeName(graph, r));\r
92                         }\r
93                 }\r
94                 \r
95                 ArrayList<Resource> result = new ArrayList<>();\r
96                 for(Resource dep : deps) {\r
97                     // TODO: still not complete - e.g. someone can replace the InstanceOf\r
98                     Set<Resource> types = graph.getTypes(dep);\r
99                     if(types.isEmpty() || types.contains(type)) result.add(dep);\r
100                 }\r
101                 return result;\r
102                 \r
103         }\r
104 \r
105     class DependencyChangeListener extends GenericChangeListener<DependencyChangesRequest, DependencyChanges> {\r
106 \r
107         private boolean isValid(ReadGraph graph, List<Resource> toCheck) throws DatabaseException {\r
108             for(Resource resource : toCheck) {\r
109                 if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.<Boolean>instance())) {\r
110                     return false;\r
111                 }\r
112             }\r
113             return true;\r
114         }\r
115 \r
116         @Override\r
117         public boolean preEventRequest() {\r
118             return !Indexing.isDependenciesIndexingDisabled();\r
119         }\r
120 \r
121         @Override\r
122         public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException {\r
123 \r
124             List<Resource> toCheck = resourcesToCheck(graph, event);\r
125             if(!isValid(graph, toCheck)) {\r
126                 for(Function2<ReadGraph, List<Resource>, Boolean> r : listeners) {\r
127                     r.apply(graph, toCheck);\r
128                 }\r
129             }\r
130 \r
131             if(graph instanceof WriteGraph) {\r
132                 IssueSourceUtils.update((WriteGraph)graph, source);\r
133             }\r
134         }\r
135 \r
136     }\r
137 \r
138     @Override\r
139     public void addDirtyListener(Function2<ReadGraph, List<Resource>, Boolean> runnable) {\r
140         boolean added = listeners.add(runnable);\r
141         if (added) {\r
142             GraphChangeListenerSupport changeSupport = Simantics.getSession().getService(GraphChangeListenerSupport.class);\r
143             ChangeListener metadataListener = new DependencyChangeListener();\r
144             listenerMap.put(runnable, metadataListener);\r
145             changeSupport.addMetadataListener(metadataListener);\r
146         }\r
147     }\r
148 \r
149     @Override\r
150     public void removeDirtyListener(Function2<ReadGraph, List<Resource>, Boolean> runnable) {\r
151         boolean removed = listeners.remove(runnable);\r
152         ChangeListener metadataListener = listenerMap.remove(runnable);\r
153         if (removed && metadataListener != null) {\r
154             GraphChangeListenerSupport changeSupport = Simantics.getSession().getService(GraphChangeListenerSupport.class);\r
155             changeSupport.removeMetadataListener(metadataListener);\r
156         }\r
157     }\r
158 \r
159         @Override\r
160         public void update(WriteGraph graph, List<Resource> resources) throws DatabaseException {\r
161 \r
162                 for(Resource resource : resources) {\r
163                         if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.<Boolean>instance())) {\r
164                                 new DependencyIssueSynchronizer2(resource, source).perform(graph);\r
165                         }\r
166                 }\r
167 \r
168                 IssueSourceUtils.update(graph, source);\r
169 \r
170         }\r
171 \r
172         @Override\r
173         public boolean needUpdate(ReadGraph graph, List<Resource> resources) throws DatabaseException {\r
174 \r
175                 for(Resource resource : resources) {\r
176                         if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.<Boolean>instance())) return true;\r
177                 }\r
178 \r
179                 return false;\r
180 \r
181         }\r
182 \r
183 }\r