]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/StructuralChangeFlattener.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.structural.synchronization.client / src / org / simantics / structural / synchronization / StructuralChangeFlattener.java
diff --git a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/StructuralChangeFlattener.java b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/StructuralChangeFlattener.java
new file mode 100644 (file)
index 0000000..7a1fbdc
--- /dev/null
@@ -0,0 +1,128 @@
+package org.simantics.structural.synchronization;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Map;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.genericrelation.DependencyChanges;\r
+import org.simantics.db.layer0.request.ModelInstances;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.Variables;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.structural2.utils.StructuralChangeVisitor;\r
+import org.simantics.structural2.utils.StructuralMetadataUtils;\r
+\r
+/**\r
+ * Browses change metadata from the requested revision and\r
+ * marks the components in a flat structural configuration\r
+ * where changes have been occured.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public class StructuralChangeFlattener {\r
+    \r
+    private static Variable[] EMPTY_VARIABLE_ARRAY = new Variable[0];\r
+    \r
+    public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,\r
+            Variable rootVariable, long fromRevision) throws DatabaseException {\r
+        Visitor visitor = new Visitor(graph, rootVariable);\r
+        StructuralMetadataUtils.visitStructuralChangesFrom(graph,\r
+                Variables.getModel(graph, rootVariable),\r
+                fromRevision, visitor);\r
+        return visitor.modifiedComponents;\r
+    }\r
+\r
+    public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,\r
+            Variable rootVariable, DependencyChanges.Change[] changes) throws DatabaseException {\r
+        Visitor visitor = new Visitor(graph, rootVariable);\r
+        StructuralMetadataUtils.visitStructuralChangesFrom(graph,\r
+                Variables.getModel(graph, rootVariable),\r
+                changes, visitor);\r
+        return visitor.modifiedComponents;\r
+    }\r
+\r
+    private static class Visitor implements StructuralChangeVisitor {\r
+\r
+        Variable rootVariable;\r
+        Resource rootResource;\r
+        Resource model;\r
+        THashMap<Resource, Variable[]> visitedVariables = new THashMap<Resource, Variable[]>();\r
+        Layer0 L0;\r
+        StructuralResource2 STR;\r
+        TObjectIntHashMap<Variable> modifiedComponents = new TObjectIntHashMap<Variable>(); \r
+        \r
+        public Visitor(ReadGraph graph, Variable rootVariable) throws DatabaseException {\r
+            this.rootVariable = rootVariable;\r
+            this.rootResource = rootVariable.getRepresents(graph);\r
+            this.model = Variables.getModel(graph, rootVariable);\r
+            this.L0 = Layer0.getInstance(graph);\r
+            this.STR = StructuralResource2.getInstance(graph);\r
+        }\r
+        \r
+        @Override\r
+        public void visitComponentChange(ReadGraph graph, Resource component, boolean componentItselfModified)\r
+                throws DatabaseException {\r
+            Variable[] variables = visitedVariables.get(component);\r
+            if(variables == null) {\r
+                variables = visitUnseenComponent(graph, component);\r
+                visitedVariables.put(component, variables);\r
+            }\r
+            if(componentItselfModified)\r
+                for(Variable variable : variables)\r
+                    modifiedComponents.put(variable, 2);\r
+            else\r
+                for(Variable variable : variables)\r
+                    modifiedComponents.putIfAbsent(variable, 1);\r
+        }\r
+        \r
+        private Variable[] visitUnseenComponent(ReadGraph graph, Resource component) throws DatabaseException {\r
+            // Is root?\r
+            if(component.equals(rootResource))\r
+                return new Variable[] { rootVariable };\r
+            \r
+            // Check if this a component type root\r
+            Resource componentType = graph.getPossibleObject(component, STR.Defines);\r
+            if(componentType != null) {\r
+                ArrayList<Variable> result = new ArrayList<Variable>();\r
+                Map<String,Resource> instances = graph.syncRequest(new ModelInstances(model, componentType), TransientCacheAsyncListener.<Map<String,Resource>>instance());\r
+                for(Resource instance : instances.values()) {\r
+                    visitComponentChange(graph, instance, false);\r
+                    for(Variable variable : visitedVariables.get(instance))\r
+                        result.add(variable);\r
+                }\r
+                if(result.isEmpty())\r
+                    return EMPTY_VARIABLE_ARRAY;\r
+                else\r
+                    return result.toArray(new Variable[result.size()]);\r
+            }\r
+            \r
+            // Check parent\r
+            Resource parent = graph.getPossibleObject(component, L0.PartOf);\r
+            String name = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING);\r
+            if(parent == null || name == null || !graph.isInstanceOf(component, STR.Component))\r
+                return EMPTY_VARIABLE_ARRAY;\r
+            \r
+            visitComponentChange(graph, parent, false);\r
+            Variable[] parentCorrespondences = visitedVariables.get(parent);\r
+            ArrayList<Variable> result = new ArrayList<Variable>(parentCorrespondences.length);\r
+            for(Variable parentCorrespondence : parentCorrespondences) {\r
+                Variable correspondence = parentCorrespondence.getPossibleChild(graph, name);\r
+                if(correspondence != null)\r
+                    result.add(correspondence);\r
+            }\r
+            if(result.isEmpty())\r
+                return EMPTY_VARIABLE_ARRAY;\r
+            else\r
+                return result.toArray(new Variable[result.size()]);\r
+        }\r
+        \r
+    }\r
+}\r