]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.issues.common/src/org/simantics/issues/common/DependencyIssueSource2.java b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/DependencyIssueSource2.java
new file mode 100644 (file)
index 0000000..37669ab
--- /dev/null
@@ -0,0 +1,183 @@
+package org.simantics.issues.common;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+import java.util.concurrent.ConcurrentHashMap;\r
+import java.util.concurrent.ConcurrentMap;\r
+import java.util.concurrent.CopyOnWriteArraySet;\r
+\r
+import org.simantics.Simantics;\r
+import org.simantics.db.MetadataI;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.Indexing;\r
+import org.simantics.db.common.changeset.GenericChangeListener;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.request.PossibleTypedParent;\r
+import org.simantics.db.common.utils.Functions;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.event.ChangeListener;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.genericrelation.DependenciesRelation.DependencyChangesRequest;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges;\r
+import org.simantics.db.service.GraphChangeListenerSupport;\r
+import org.simantics.issues.ontology.IssueResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.scl.runtime.function.Function2;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+\r
+public class DependencyIssueSource2 implements IssueSource {\r
+\r
+       public static final boolean DEBUG = false;\r
+       \r
+       private Resource source;\r
+       private Resource model;\r
+       private Resource type;\r
+       private Set<Resource> searchTypes;\r
+       private Resource base;\r
+       private Resource extensionFunction;\r
+\r
+       private CopyOnWriteArraySet<Function2<ReadGraph, List<Resource>, Boolean>> listeners = new CopyOnWriteArraySet<>();\r
+       private ConcurrentMap<Function2<ReadGraph, List<Resource>, Boolean>, ChangeListener> listenerMap = new ConcurrentHashMap<>();\r
+\r
+       public DependencyIssueSource2(ReadGraph graph, Resource source) throws DatabaseException {\r
+           Layer0 L0 = Layer0.getInstance(graph);\r
+               IssueResource IR = IssueResource.getInstance(graph);\r
+               this.source = source;\r
+               this.model = graph.syncRequest(new PossibleTypedParent(source, SimulationResource.getInstance(graph).Model));\r
+               this.extensionFunction = graph.getPossibleObject(source, IR.Sources_DependencyTracker_HasExtension); \r
+               this.type = graph.getSingleObject(source, IR.Sources_DependencyTracker_HasType);\r
+               HashSet<Resource> _searchTypes = new HashSet<>();\r
+               _searchTypes.addAll(graph.getObjects(source, IR.Sources_DependencyTracker_HasSearchType));\r
+               _searchTypes.add(type);\r
+               this.searchTypes = new HashSet<>(_searchTypes);\r
+               Resource baseFunction = graph.getSingleObject(source, IR.Sources_DependencyTracker_HasBaseFunction);\r
+               this.base = Functions.exec(graph, baseFunction, graph, graph.getSingleObject(source, L0.PartOf));\r
+       }\r
+\r
+       private List<Resource> resourcesToCheck(ReadGraph graph, DependencyChanges event) throws DatabaseException {\r
+\r
+               HashSet<Resource> depSet = new HashSet<>();\r
+\r
+               if(DEBUG) {\r
+                       System.err.println("resourcesToCheck[" + NameUtils.getSafeName(graph, source) + "] - component changes for type " + NameUtils.getSafeName(graph, searchTypes));\r
+               }\r
+\r
+               depSet.addAll(IssueSourceUtils.getChangedDependencies(graph, model, base, searchTypes, event));\r
+               depSet.addAll(IssueSourceUtils.getChangedDependencies(graph, source, model, base, searchTypes));\r
+               \r
+               List<Resource> deps = new ArrayList<>(depSet);\r
+               \r
+               if(DEBUG) {\r
+                       System.err.println("resourcesToCheck[" + NameUtils.getSafeName(graph, source) + "] " + deps);\r
+                       for(Resource r : deps) {\r
+                               System.err.println("dep " + NameUtils.getSafeName(graph, r));\r
+                       }\r
+               }\r
+               \r
+               if(extensionFunction != null) {\r
+                       try {\r
+                               deps = Functions.exec(graph, extensionFunction, graph, deps);\r
+                       } catch (Throwable t) {\r
+                               t.printStackTrace();\r
+                       }\r
+               }\r
+\r
+               if(DEBUG) {\r
+                       for(Resource r : deps) {\r
+                               System.err.println("dep extension " + NameUtils.getSafeName(graph, r));\r
+                       }\r
+               }\r
+               \r
+               ArrayList<Resource> result = new ArrayList<>();\r
+               for(Resource dep : deps) {\r
+                   // TODO: still not complete - e.g. someone can replace the InstanceOf\r
+                   Set<Resource> types = graph.getTypes(dep);\r
+                   if(types.isEmpty() || types.contains(type)) result.add(dep);\r
+               }\r
+               return result;\r
+               \r
+       }\r
+\r
+    class DependencyChangeListener extends GenericChangeListener<DependencyChangesRequest, DependencyChanges> {\r
+\r
+        private boolean isValid(ReadGraph graph, List<Resource> toCheck) throws DatabaseException {\r
+            for(Resource resource : toCheck) {\r
+                if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.<Boolean>instance())) {\r
+                    return false;\r
+                }\r
+            }\r
+            return true;\r
+        }\r
+\r
+        @Override\r
+        public boolean preEventRequest() {\r
+            return !Indexing.isDependenciesIndexingDisabled();\r
+        }\r
+\r
+        @Override\r
+        public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException {\r
+\r
+            List<Resource> toCheck = resourcesToCheck(graph, event);\r
+            if(!isValid(graph, toCheck)) {\r
+                for(Function2<ReadGraph, List<Resource>, Boolean> r : listeners) {\r
+                    r.apply(graph, toCheck);\r
+                }\r
+            }\r
+\r
+            if(graph instanceof WriteGraph) {\r
+                IssueSourceUtils.update((WriteGraph)graph, source);\r
+            }\r
+        }\r
+\r
+    }\r
+\r
+    @Override\r
+    public void addDirtyListener(Function2<ReadGraph, List<Resource>, Boolean> runnable) {\r
+        boolean added = listeners.add(runnable);\r
+        if (added) {\r
+            GraphChangeListenerSupport changeSupport = Simantics.getSession().getService(GraphChangeListenerSupport.class);\r
+            ChangeListener metadataListener = new DependencyChangeListener();\r
+            listenerMap.put(runnable, metadataListener);\r
+            changeSupport.addMetadataListener(metadataListener);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void removeDirtyListener(Function2<ReadGraph, List<Resource>, Boolean> runnable) {\r
+        boolean removed = listeners.remove(runnable);\r
+        ChangeListener metadataListener = listenerMap.remove(runnable);\r
+        if (removed && metadataListener != null) {\r
+            GraphChangeListenerSupport changeSupport = Simantics.getSession().getService(GraphChangeListenerSupport.class);\r
+            changeSupport.removeMetadataListener(metadataListener);\r
+        }\r
+    }\r
+\r
+       @Override\r
+       public void update(WriteGraph graph, List<Resource> resources) throws DatabaseException {\r
+\r
+               for(Resource resource : resources) {\r
+                       if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.<Boolean>instance())) {\r
+                               new DependencyIssueSynchronizer2(resource, source).perform(graph);\r
+                       }\r
+               }\r
+\r
+               IssueSourceUtils.update(graph, source);\r
+\r
+       }\r
+\r
+       @Override\r
+       public boolean needUpdate(ReadGraph graph, List<Resource> resources) throws DatabaseException {\r
+\r
+               for(Resource resource : resources) {\r
+                       if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.<Boolean>instance())) return true;\r
+               }\r
+\r
+               return false;\r
+\r
+       }\r
+\r
+}\r