]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyChangesWriter.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / genericrelation / DependencyChangesWriter.java
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyChangesWriter.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyChangesWriter.java
new file mode 100644 (file)
index 0000000..9e55ff5
--- /dev/null
@@ -0,0 +1,136 @@
+package org.simantics.db.layer0.genericrelation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.request.IndexRoots;\r
+import org.simantics.db.common.request.PossibleIndexRoot;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges.Change;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges.ChangeType;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentAddition;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentModification;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentRemoval;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges.LinkChange;\r
+import org.simantics.db.service.CollectionSupport;\r
+import org.simantics.layer0.Layer0;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+public class DependencyChangesWriter {\r
+    ReadGraph g;\r
+    Layer0 l0;\r
+\r
+    THashMap<Resource, Change> changesByResource = new THashMap<>();\r
+    ArrayList<ComponentRemoval> removals = new ArrayList<>();\r
+\r
+    public DependencyChangesWriter(ReadGraph g) {\r
+        this.g = g;\r
+        this.l0 = Layer0.getInstance(g);\r
+    }\r
+\r
+    public void addComponentModification(Resource component) throws DatabaseException {\r
+        if (!component.isPersistent())\r
+            return;\r
+        if(!changesByResource.contains(component))\r
+            changesByResource.put(component, new ComponentModification(component));\r
+    }\r
+\r
+    public void addLinkChange(Resource component) throws DatabaseException {\r
+        if (!component.isPersistent())\r
+            return;\r
+        //if(!changesByResource.contains(component))\r
+            changesByResource.put(component, new LinkChange(component));\r
+    }\r
+\r
+    public void addComponentAddition(Resource parent, Resource component) throws DatabaseException {\r
+        if (!component.isPersistent())\r
+            return;\r
+        changesByResource.put(component, new ComponentAddition(component, parent));\r
+    }\r
+\r
+    public void addComponentRemoval(Resource parent, Resource component) throws DatabaseException {\r
+//     System.err.println("addComponentRemoval " + component);\r
+        // NOTE: removals are registered by their parent resource because the\r
+        // (component, PartOf, parent) link no longer exists and the model cannot\r
+        // be found otherwise.\r
+//        changesByResource.put(parent, new ComponentRemoval(component, parent));\r
+        if (!component.isPersistent())\r
+            return;\r
+        removals.add(new ComponentRemoval(component, parent));\r
+    }\r
+\r
+    public DependencyChanges getResult() throws DatabaseException {\r
+        THashMap<Resource, ArrayList<Change>> changes = new THashMap<>();\r
+        CollectionSupport cs = g.getService(CollectionSupport.class);\r
+        List<Resource> keys = cs.asSortedList(changesByResource.keySet());\r
+        boolean hasUnresolved = false;\r
+        for(Resource key : keys) {\r
+            Change change = changesByResource.get(key);\r
+            // Default logic with simpler index root resolution.\r
+            Resource model = g.syncRequest(new PossibleIndexRoot(key), TransientCacheListener.<Resource>instance());\r
+            boolean modelFound = model != null;\r
+            if (model != null) {\r
+                addChange(model, change, changes);\r
+            } else {\r
+                // Very heavy fallback logic\r
+                Collection<Resource> models = g.syncRequest(new IndexRoots(key), TransientCacheListener.<Collection<Resource>>instance());\r
+                for(Resource m : models)\r
+                    addChange(m, change, changes);\r
+                modelFound = !models.isEmpty();\r
+            }\r
+            if (modelFound && change.getType() == ChangeType.COMPONENT_ADDITION) {\r
+                hasUnresolved = true;\r
+            }\r
+        }\r
+        if (!removals.isEmpty()) {\r
+            THashMap<Resource, ComponentRemoval> removedComponents = new THashMap<>(removals.size());\r
+            for(ComponentRemoval removal : removals)\r
+                removedComponents.put(removal.component, removal);\r
+            for(ComponentRemoval removal : removals) {\r
+                Resource parent = removal.parent;\r
+                Collection<Resource> models = getModelsForRemoved(g, parent, removedComponents); \r
+                for(Resource model : models) {\r
+                    ArrayList<Change> modelChanges = changes.get(model);\r
+                    if(modelChanges == null) {\r
+                        modelChanges = new ArrayList<>();\r
+                        changes.put(model, modelChanges);\r
+                    }\r
+                    modelChanges.add(removal);\r
+                }\r
+                if(models.isEmpty() && !removedComponents.contains(parent)) {\r
+                    hasUnresolved = true;\r
+                }\r
+            }\r
+        }\r
+\r
+        return new DependencyChanges(changes, hasUnresolved);\r
+    }\r
+\r
+    private void addChange(Resource model, Change change, Map<Resource, ArrayList<Change>> changes) {\r
+        ArrayList<Change> modelChanges = changes.get(model);\r
+        if(modelChanges == null) {\r
+            modelChanges = new ArrayList<>();\r
+            changes.put(model, modelChanges);\r
+        }\r
+        modelChanges.add(change);\r
+    }\r
+\r
+    private Collection<Resource> getModelsForRemoved(ReadGraph graph, Resource resource, THashMap<Resource, ComponentRemoval> removedComponents) throws DatabaseException {\r
+        ComponentRemoval removal = removedComponents.get(resource);\r
+        if(removal == null) {\r
+            Resource model = g.syncRequest(new PossibleIndexRoot(resource), TransientCacheListener.<Resource>instance());\r
+            if (model != null)\r
+                return Collections.singleton(model);\r
+            return graph.syncRequest(new IndexRoots(resource), TransientCacheListener.<Collection<Resource>>instance());\r
+        }\r
+        return getModelsForRemoved(graph, removal.parent, removedComponents);\r
+    }\r
+    \r
+}\r