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