]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.graph.diff;\r
2 \r
3 import gnu.trove.map.hash.TIntObjectHashMap;\r
4 import gnu.trove.procedure.TIntObjectProcedure;\r
5 import gnu.trove.set.hash.THashSet;\r
6 \r
7 import java.util.ArrayList;\r
8 import java.util.Collection;\r
9 \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
20 \r
21 public class Diff extends GraphMatching {\r
22 \r
23         TransferableGraph1 a;\r
24         TransferableGraph1 b;\r
25         \r
26         public Diff(TransferableGraph1 a, TransferableGraph1 b) {\r
27                 super(a, b);\r
28                 this.a = a;\r
29                 this.b = b;\r
30         }       \r
31         \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
36                                         statements[i],\r
37                                         statements[i+1],\r
38                                         statements[i+2],\r
39                                         statements[i+3]\r
40                         ));\r
41                 return result;\r
42         }\r
43         \r
44         public TransferableGraphDelta1 diff() {\r
45                 match();\r
46                 \r
47                 long begin = System.nanoTime();\r
48                 \r
49                 // Statement diff;\r
50                 THashSet<Statement> aStatements = createStatementSet(a.statements);\r
51                 ArrayList<Statement> bStatements = new ArrayList<Statement>();\r
52                 \r
53                 int[] statements = b.statements;\r
54                 for(int i=0;i<statements.length;i+=4) {\r
55                         Statement statement = new Statement(\r
56                                         statements[i],\r
57                                         statements[i+1],\r
58                                         statements[i+2],\r
59                                         statements[i+3]\r
60                         );\r
61                         Statement mappedStatement = statement.map(bToA);\r
62                         if(mappedStatement == null || !aStatements.remove(mappedStatement))\r
63                                 bStatements.add(statement);\r
64                 }               \r
65         \r
66                 // Identity diff\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
76                         else\r
77                                 bIdentities.add(id);\r
78                 }\r
79                 \r
80                 // Value diff\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
85                 \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
90                                 aValues.remove(a);\r
91                         else\r
92                                 bValues.add(value);\r
93                 }\r
94                                 \r
95                 // Create result\r
96                 TransferableGraphDelta1 result = new TransferableGraphDelta1(\r
97                                 aToB,\r
98                                 new TransferableGraph1(\r
99                                         a.resourceCount,\r
100                                         toIdentityArray(aIdentities),\r
101                                         toStatementArray(aStatements),\r
102                                         toValueArray(aValues)\r
103                                 ),\r
104                                 new TransferableGraph1(\r
105                                         b.resourceCount,\r
106                                         bIdentities.toArray(new Identity[bIdentities.size()]),\r
107                                         toStatementArray(bStatements),\r
108                                         bValues.toArray(new Value[bValues.size()])\r
109                                 )\r
110                         );\r
111                 if(GraphMatching.TIMING) {\r
112                         long end = System.nanoTime();\r
113                         System.out.println("Diffing: " + (end-begin)*1e-6 + "ms");\r
114                 }\r
115                 return result;\r
116         }\r
117         \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
123                         return false;\r
124                 int aParent, bParent;\r
125                 String aName, bName;\r
126                 \r
127                 if(b instanceof External) {\r
128                         External def = (External)b;\r
129                         bParent = def.parent;\r
130                         bName = def.name;\r
131                 }\r
132                 else if(b instanceof Internal) {\r
133                         Internal def = (Internal)b;\r
134                         bParent = def.parent;\r
135                         bName = def.name;\r
136                 }\r
137                 else if(b instanceof Optional) {\r
138                         Optional def = (Optional)b;\r
139                         bParent = def.parent;\r
140                         bName = def.name;\r
141                 }\r
142                 else\r
143                         return false;\r
144                 bParent = bToA[bParent];\r
145                 if(bParent < 0)\r
146                         return false;\r
147                 \r
148                 if(a instanceof External) {\r
149                         External def = (External)a;\r
150                         aParent = def.parent;\r
151                         aName = def.name;\r
152                 }\r
153                 else if(a instanceof Internal) {\r
154                         Internal def = (Internal)a;\r
155                         aParent = def.parent;\r
156                         aName = def.name;\r
157                 }\r
158                 else if(a instanceof Optional) {\r
159                         Optional def = (Optional)a;\r
160                         aParent = def.parent;\r
161                         aName = def.name;\r
162                 }\r
163                 else\r
164                         return false;\r
165                 return aParent == bParent && aName.equals(bName);\r
166         }\r
167 \r
168         static int[] toStatementArray(Collection<Statement> statements) {\r
169                 int[] result = new int[4*statements.size()];\r
170                 int i=0;\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
176                 }\r
177                 return result;\r
178         }\r
179         \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
183                         int i=0;\r
184                         @Override\r
185                         public boolean execute(int a, Variant b) {\r
186                                 result[i++] = new Value(a, b);\r
187                                 return true;\r
188                         }\r
189                 });\r
190                 return result;\r
191         }\r
192         \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
196                         int i=0;\r
197                         @Override\r
198                         public boolean execute(int a, IdentityDefinition b) {\r
199                                 result[i++] = new Identity(a, b);\r
200                                 return true;\r
201                         }\r
202                 });\r
203                 return result;\r
204         }\r
205         \r
206 }