1 package org.simantics.graph.diff;
3 import gnu.trove.map.hash.TIntObjectHashMap;
4 import gnu.trove.procedure.TIntObjectProcedure;
5 import gnu.trove.set.hash.THashSet;
7 import java.util.ArrayList;
8 import java.util.Collection;
10 import org.simantics.databoard.binding.mutable.Variant;
11 import org.simantics.graph.matching.GraphMatching;
12 import org.simantics.graph.representation.External;
13 import org.simantics.graph.representation.Identity;
14 import org.simantics.graph.representation.IdentityDefinition;
15 import org.simantics.graph.representation.Internal;
16 import org.simantics.graph.representation.Optional;
17 import org.simantics.graph.representation.Root;
18 import org.simantics.graph.representation.TransferableGraph1;
19 import org.simantics.graph.representation.Value;
21 public class Diff extends GraphMatching {
26 public Diff(TransferableGraph1 a, TransferableGraph1 b) {
32 static THashSet<Statement> createStatementSet(int[] statements) {
33 THashSet<Statement> result = new THashSet<Statement>();
34 for(int i=0;i<statements.length;i+=4)
35 result.add(new Statement(
44 public TransferableGraphDelta1 diff() {
47 long begin = System.nanoTime();
50 THashSet<Statement> aStatements = createStatementSet(a.statements);
51 ArrayList<Statement> bStatements = new ArrayList<Statement>();
53 int[] statements = b.statements;
54 for(int i=0;i<statements.length;i+=4) {
55 Statement statement = new Statement(
61 Statement mappedStatement = statement.map(bToA);
62 if(mappedStatement == null || !aStatements.remove(mappedStatement))
63 bStatements.add(statement);
67 TIntObjectHashMap<IdentityDefinition> aIdentities = new TIntObjectHashMap<IdentityDefinition>();
68 ArrayList<Identity> bIdentities = new ArrayList<Identity>();
69 for(Identity id : a.identities)
70 aIdentities.put(id.resource, id.definition);
71 for(Identity id : b.identities) {
72 int a = bToA[id.resource];
73 IdentityDefinition def = aIdentities.get(a);
74 if(def != null && identityDefinitionEquals(bToA, def, id.definition))
75 aIdentities.remove(a);
81 TIntObjectHashMap<Variant> aValues = new TIntObjectHashMap<Variant>();
82 ArrayList<Value> bValues = new ArrayList<Value>();
83 for(Value value : a.values)
84 aValues.put(value.resource, value.value);
86 for(Value value : b.values) {
87 int a = bToA[value.resource]; // a may be -1
88 Variant aValue = aValues.get(a);
89 if(aValue != null && aValue.equals(value.value))
96 TransferableGraphDelta1 result = new TransferableGraphDelta1(
98 new TransferableGraph1(
100 toIdentityArray(aIdentities),
101 toStatementArray(aStatements),
102 toValueArray(aValues)
104 new TransferableGraph1(
106 bIdentities.toArray(new Identity[bIdentities.size()]),
107 toStatementArray(bStatements),
108 bValues.toArray(new Value[bValues.size()])
111 if(GraphMatching.TIMING) {
112 long end = System.nanoTime();
113 System.out.println("Diffing: " + (end-begin)*1e-6 + "ms");
118 private static boolean identityDefinitionEquals(int[] bToA,
119 IdentityDefinition a, IdentityDefinition b) {
120 if(a instanceof Root)
121 return b instanceof Root && ((Root)a).name.equals(((Root)b).name);
122 if(b instanceof Root)
124 int aParent, bParent;
127 if(b instanceof External) {
128 External def = (External)b;
129 bParent = def.parent;
132 else if(b instanceof Internal) {
133 Internal def = (Internal)b;
134 bParent = def.parent;
137 else if(b instanceof Optional) {
138 Optional def = (Optional)b;
139 bParent = def.parent;
144 bParent = bToA[bParent];
148 if(a instanceof External) {
149 External def = (External)a;
150 aParent = def.parent;
153 else if(a instanceof Internal) {
154 Internal def = (Internal)a;
155 aParent = def.parent;
158 else if(a instanceof Optional) {
159 Optional def = (Optional)a;
160 aParent = def.parent;
165 return aParent == bParent && aName.equals(bName);
168 static int[] toStatementArray(Collection<Statement> statements) {
169 int[] result = new int[4*statements.size()];
171 for(Statement statement : statements) {
172 result[i++] = statement.subject;
173 result[i++] = statement.predicate;
174 result[i++] = statement.inverse;
175 result[i++] = statement.object;
180 static Value[] toValueArray(TIntObjectHashMap<Variant> values) {
181 final Value[] result = new Value[values.size()];
182 values.forEachEntry(new TIntObjectProcedure<Variant>() {
185 public boolean execute(int a, Variant b) {
186 result[i++] = new Value(a, b);
193 static Identity[] toIdentityArray(TIntObjectHashMap<IdentityDefinition> identities) {
194 final Identity[] result = new Identity[identities.size()];
195 identities.forEachEntry(new TIntObjectProcedure<IdentityDefinition>() {
198 public boolean execute(int a, IdentityDefinition b) {
199 result[i++] = new Identity(a, b);