]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graph/src/org/simantics/graph/diff/Diff.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / diff / Diff.java
diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/diff/Diff.java b/bundles/org.simantics.graph/src/org/simantics/graph/diff/Diff.java
new file mode 100644 (file)
index 0000000..6f2add8
--- /dev/null
@@ -0,0 +1,206 @@
+package org.simantics.graph.diff;\r
+\r
+import gnu.trove.map.hash.TIntObjectHashMap;\r
+import gnu.trove.procedure.TIntObjectProcedure;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.graph.matching.GraphMatching;\r
+import org.simantics.graph.representation.External;\r
+import org.simantics.graph.representation.Identity;\r
+import org.simantics.graph.representation.IdentityDefinition;\r
+import org.simantics.graph.representation.Internal;\r
+import org.simantics.graph.representation.Optional;\r
+import org.simantics.graph.representation.Root;\r
+import org.simantics.graph.representation.TransferableGraph1;\r
+import org.simantics.graph.representation.Value;\r
+\r
+public class Diff extends GraphMatching {\r
+\r
+       TransferableGraph1 a;\r
+       TransferableGraph1 b;\r
+       \r
+       public Diff(TransferableGraph1 a, TransferableGraph1 b) {\r
+               super(a, b);\r
+               this.a = a;\r
+               this.b = b;\r
+       }       \r
+       \r
+       static THashSet<Statement> createStatementSet(int[] statements) {\r
+               THashSet<Statement> result = new THashSet<Statement>();\r
+               for(int i=0;i<statements.length;i+=4)\r
+                       result.add(new Statement(\r
+                                       statements[i],\r
+                                       statements[i+1],\r
+                                       statements[i+2],\r
+                                       statements[i+3]\r
+                       ));\r
+               return result;\r
+       }\r
+       \r
+       public TransferableGraphDelta1 diff() {\r
+               match();\r
+               \r
+               long begin = System.nanoTime();\r
+               \r
+               // Statement diff;\r
+               THashSet<Statement> aStatements = createStatementSet(a.statements);\r
+               ArrayList<Statement> bStatements = new ArrayList<Statement>();\r
+               \r
+               int[] statements = b.statements;\r
+               for(int i=0;i<statements.length;i+=4) {\r
+                       Statement statement = new Statement(\r
+                                       statements[i],\r
+                                       statements[i+1],\r
+                                       statements[i+2],\r
+                                       statements[i+3]\r
+                       );\r
+                       Statement mappedStatement = statement.map(bToA);\r
+                       if(mappedStatement == null || !aStatements.remove(mappedStatement))\r
+                               bStatements.add(statement);\r
+               }               \r
+       \r
+               // Identity diff\r
+               TIntObjectHashMap<IdentityDefinition> aIdentities = new TIntObjectHashMap<IdentityDefinition>();\r
+               ArrayList<Identity> bIdentities = new ArrayList<Identity>();\r
+               for(Identity id : a.identities)\r
+                       aIdentities.put(id.resource, id.definition);\r
+               for(Identity id : b.identities) {\r
+                       int a = bToA[id.resource];\r
+                       IdentityDefinition def = aIdentities.get(a);\r
+                       if(def != null && identityDefinitionEquals(bToA, def, id.definition))\r
+                               aIdentities.remove(a);\r
+                       else\r
+                               bIdentities.add(id);\r
+               }\r
+               \r
+               // Value diff\r
+               TIntObjectHashMap<Variant> aValues = new TIntObjectHashMap<Variant>();\r
+               ArrayList<Value> bValues = new ArrayList<Value>();\r
+               for(Value value : a.values)\r
+                       aValues.put(value.resource, value.value);\r
+               \r
+               for(Value value : b.values) {\r
+                       int a = bToA[value.resource]; // a may be -1\r
+                       Variant aValue = aValues.get(a);\r
+                       if(aValue != null && aValue.equals(value.value))\r
+                               aValues.remove(a);\r
+                       else\r
+                               bValues.add(value);\r
+               }\r
+                               \r
+               // Create result\r
+               TransferableGraphDelta1 result = new TransferableGraphDelta1(\r
+                               aToB,\r
+                               new TransferableGraph1(\r
+                                       a.resourceCount,\r
+                                       toIdentityArray(aIdentities),\r
+                                       toStatementArray(aStatements),\r
+                                       toValueArray(aValues)\r
+                               ),\r
+                               new TransferableGraph1(\r
+                                       b.resourceCount,\r
+                                       bIdentities.toArray(new Identity[bIdentities.size()]),\r
+                                       toStatementArray(bStatements),\r
+                                       bValues.toArray(new Value[bValues.size()])\r
+                               )\r
+                       );\r
+               if(GraphMatching.TIMING) {\r
+                       long end = System.nanoTime();\r
+                       System.out.println("Diffing: " + (end-begin)*1e-6 + "ms");\r
+               }\r
+               return result;\r
+       }\r
+       \r
+       private static boolean identityDefinitionEquals(int[] bToA,\r
+                       IdentityDefinition a, IdentityDefinition b) {           \r
+               if(a instanceof Root)\r
+                       return b instanceof Root && ((Root)a).name.equals(((Root)b).name);\r
+               if(b instanceof Root)\r
+                       return false;\r
+               int aParent, bParent;\r
+               String aName, bName;\r
+               \r
+               if(b instanceof External) {\r
+                       External def = (External)b;\r
+                       bParent = def.parent;\r
+                       bName = def.name;\r
+               }\r
+               else if(b instanceof Internal) {\r
+                       Internal def = (Internal)b;\r
+                       bParent = def.parent;\r
+                       bName = def.name;\r
+               }\r
+               else if(b instanceof Optional) {\r
+                       Optional def = (Optional)b;\r
+                       bParent = def.parent;\r
+                       bName = def.name;\r
+               }\r
+               else\r
+                       return false;\r
+               bParent = bToA[bParent];\r
+               if(bParent < 0)\r
+                       return false;\r
+               \r
+               if(a instanceof External) {\r
+                       External def = (External)a;\r
+                       aParent = def.parent;\r
+                       aName = def.name;\r
+               }\r
+               else if(a instanceof Internal) {\r
+                       Internal def = (Internal)a;\r
+                       aParent = def.parent;\r
+                       aName = def.name;\r
+               }\r
+               else if(a instanceof Optional) {\r
+                       Optional def = (Optional)a;\r
+                       aParent = def.parent;\r
+                       aName = def.name;\r
+               }\r
+               else\r
+                       return false;\r
+               return aParent == bParent && aName.equals(bName);\r
+       }\r
+\r
+       static int[] toStatementArray(Collection<Statement> statements) {\r
+               int[] result = new int[4*statements.size()];\r
+               int i=0;\r
+               for(Statement statement : statements) {\r
+                       result[i++] = statement.subject;\r
+                       result[i++] = statement.predicate;\r
+                       result[i++] = statement.inverse;\r
+                       result[i++] = statement.object;\r
+               }\r
+               return result;\r
+       }\r
+       \r
+       static Value[] toValueArray(TIntObjectHashMap<Variant> values) {\r
+               final Value[] result = new Value[values.size()];\r
+               values.forEachEntry(new TIntObjectProcedure<Variant>() {\r
+                       int i=0;\r
+                       @Override\r
+                       public boolean execute(int a, Variant b) {\r
+                               result[i++] = new Value(a, b);\r
+                               return true;\r
+                       }\r
+               });\r
+               return result;\r
+       }\r
+       \r
+       static Identity[] toIdentityArray(TIntObjectHashMap<IdentityDefinition> identities) {\r
+               final Identity[] result = new Identity[identities.size()];\r
+               identities.forEachEntry(new TIntObjectProcedure<IdentityDefinition>() {\r
+                       int i=0;\r
+                       @Override\r
+                       public boolean execute(int a, IdentityDefinition b) {\r
+                               result[i++] = new Identity(a, b);\r
+                               return true;\r
+                       }\r
+               });\r
+               return result;\r
+       }\r
+       \r
+}
\ No newline at end of file