]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java
Comparator fixes
[simantics/interop.git] / org.simantics.interop / src / org / simantics / interop / test / GraphComparator.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     Foster Wheeler Energia Oy - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.interop.test;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Arrays;\r
16 import java.util.Collection;\r
17 import java.util.Collections;\r
18 import java.util.Comparator;\r
19 import java.util.HashSet;\r
20 import java.util.List;\r
21 import java.util.Set;\r
22 import java.util.Stack;\r
23 \r
24 import org.simantics.db.ReadGraph;\r
25 import org.simantics.db.Resource;\r
26 import org.simantics.db.Statement;\r
27 import org.simantics.db.common.utils.NameUtils;\r
28 import org.simantics.db.exception.DoesNotContainValueException;\r
29 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
30 import org.simantics.db.exception.ServiceException;\r
31 import org.simantics.db.exception.ValidationException;\r
32 import org.simantics.layer0.Layer0;\r
33 import org.simantics.utils.datastructures.BijectionMap;\r
34 import org.simantics.utils.datastructures.MapList;\r
35 import org.simantics.utils.datastructures.Pair;\r
36 \r
37 /**\r
38  * Compares two subgraphs and reports differences.\r
39  * \r
40  * Assumes that subgraphs (defined using traverse relations) are not cyclic.\r
41  * \r
42  * Assumes that properties can be used to identify objects, if relation type is not enough.\r
43  * \r
44  * \r
45  * \r
46  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
47  *\r
48  */\r
49 public class GraphComparator {\r
50 \r
51         \r
52         private List<Resource> traversed = new ArrayList<Resource>(); // list of relations that are traversed (and tested)\r
53         private List<Resource> tested = new ArrayList<Resource>();    // list of relations that are tested, but not traversed\r
54         private List<Resource> nonTraversed = new ArrayList<Resource>(); // list of relations that are not traversed\r
55         private List<Resource> nonTested = new ArrayList<Resource>(); // list of relations that are not tested\r
56         \r
57         private List<Statement> changes1 = new ArrayList<Statement>();\r
58         private List<Statement> changes2 = new ArrayList<Statement>();\r
59         private List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();\r
60         private Set<Statement> changes1Set = new HashSet<Statement>();\r
61         private Set<Statement> changes2Set = new HashSet<Statement>();\r
62         private Set<Pair<Statement,Statement>> modificationsSet = new HashSet<Pair<Statement,Statement>>();\r
63 \r
64         private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<Statement, Statement>();\r
65         private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<Resource, Resource>();\r
66         \r
67         \r
68         // runtime attributes\r
69         \r
70         private ReadGraph g;\r
71         private Layer0 b;\r
72         \r
73         ArrayList<Resource> rs1 = new ArrayList<Resource>();\r
74         ArrayList<Resource> rs2 = new ArrayList<Resource>();\r
75         ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
76         ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
77         Comparator<Statement> scomp = new PredicateComparator();\r
78         Comparator<Resource> rcomp = new ResourceComparator();\r
79 \r
80         \r
81         public void addTraversed(Resource rel) {\r
82                 traversed.add(rel);\r
83         }\r
84         \r
85         public void addTraversed(Collection<Resource> rels) {\r
86                 traversed.addAll(rels);\r
87         }\r
88         \r
89         public void addNonTraversed(Resource rel) {\r
90                 nonTraversed.add(rel);\r
91         }\r
92         \r
93         public void addNonTraversed(Collection<Resource> rels) {\r
94                 nonTraversed.addAll(rels);\r
95         }\r
96         \r
97         public void addTested(Resource rel) {\r
98                 tested.add(rel);\r
99         }\r
100         \r
101         public void addTested(Collection<Resource> rels) {\r
102                 tested.addAll(rels);\r
103         }\r
104         \r
105         public void addNonTested(Resource rel) {\r
106                 nonTested.add(rel);\r
107         }\r
108         \r
109         public void addNonTested(Collection<Resource> rels) {\r
110                 nonTested.addAll(rels);\r
111         }\r
112         \r
113         public void clearRels() {\r
114                 traversed.clear();\r
115                 tested.clear();\r
116         }\r
117         \r
118         public void test(ReadGraph g, Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
119                 this.g = g;\r
120                 this.b = Layer0.getInstance(g);\r
121                 \r
122                 changes1Set.clear();\r
123                 changes2Set.clear();\r
124                 modificationsSet.clear();\r
125                 changes1.clear();\r
126                 changes2.clear();\r
127                 modifications.clear();\r
128                 comparableResources.clear();\r
129                 \r
130                 Stack<Resource> stack1 = new Stack<Resource>();\r
131                 Stack<Resource> stack2 = new Stack<Resource>();\r
132                 stack1.push(r1);\r
133                 stack2.push(r2);\r
134                 \r
135                 \r
136                 List<Statement> ss1 = new ArrayList<Statement>();\r
137                 List<Statement> ss2 = new ArrayList<Statement>();\r
138                 \r
139                 while (!stack1.isEmpty()) {\r
140                         r1 = stack1.pop();\r
141                         r2 = stack2.pop();\r
142                 \r
143                         if (comparableResources.contains(r1, r2)) {\r
144                                 System.out.println("already tested " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
145                                 continue;\r
146                         }\r
147                         comparableResources.map(r1, r2);\r
148                         \r
149                         System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
150                         compareProps(r1, r2);\r
151                         \r
152                         for (Resource rel : tested) {\r
153                                 ss1.addAll(g.getStatements(r1, rel));\r
154                                 ss2.addAll(g.getStatements(r2, rel));\r
155                                 ss1 = filterAsserted(r1, ss1);\r
156                                 ss2 = filterAsserted(r2, ss2);\r
157                                 ss1 = filterTraversed(ss1);\r
158                                 ss2 = filterTraversed(ss2);\r
159                                 ss1 = filterNonTested(ss1);\r
160                                 ss2 = filterNonTested(ss2);\r
161                                 \r
162                                 compareStatement(ss1, ss2, null, null);\r
163                                 ss1.clear();\r
164                                 ss2.clear();\r
165                         }\r
166                         \r
167                         for (Resource rel : traversed) {\r
168                                 ss1.addAll(g.getStatements(r1, rel));\r
169                                 ss2.addAll(g.getStatements(r2, rel));\r
170                                 ss1 = filterAsserted(r1, ss1);\r
171                                 ss2 = filterAsserted(r2, ss2);\r
172                                 compareStatement(ss1, ss2, stack1, stack2);\r
173                                 ss1.clear();\r
174                                 ss2.clear();\r
175                         }\r
176                 }\r
177         }\r
178         \r
179         \r
180         \r
181         public BijectionMap<Statement, Statement> getComparableStatements() {\r
182                 return comparableStatements;\r
183         }\r
184         \r
185         public GraphChanges getChanges() {\r
186 //              List<Statement> deletions = new ArrayList<Statement>();\r
187 //              List<Statement> additions = new ArrayList<Statement>();\r
188 //              deletions.addAll(changes1);\r
189 //              additions.addAll(changes2);\r
190 //              Collections.sort(deletions, new FullStatementComparator());\r
191 //              Collections.sort(additions, new FullStatementComparator());\r
192 //              return new GraphChanges(deletions, additions, modifications);\r
193                 return new GraphChanges(changes1,changes2,modifications);\r
194         }\r
195         \r
196         private List<Statement> filterAsserted(Resource r, Collection<Statement> in) throws ServiceException {\r
197                 List<Statement> out = new ArrayList<Statement>();\r
198                 for (Statement s : in) {\r
199                         if (!s.isAsserted(r))\r
200                                 out.add(s);\r
201                         \r
202                 }\r
203                 return out;\r
204         }\r
205         \r
206         private String printStatement(ReadGraph graph, Statement s) throws ValidationException, ServiceException {\r
207                 return NameUtils.getSafeName(graph, s.getSubject()) + " " + NameUtils.getSafeName(graph, s.getPredicate()) + " " + NameUtils.getSafeName(graph, s.getObject());\r
208         }\r
209         \r
210         private List<Statement> filterTraversed(List<Statement> in) throws ServiceException {\r
211                 return filter(traversed, in);\r
212         }\r
213         \r
214         private List<Statement> filterNonTested(List<Statement> in) throws ServiceException {\r
215                 return filter(nonTested, in);\r
216         }\r
217         \r
218         private List<Statement> filter(Collection<Resource> toFilter, List<Statement> in) throws ServiceException {\r
219                 if (toFilter.size() == 0)\r
220                         return in;\r
221                 List<Statement> out = new ArrayList<Statement>();\r
222                 for (Statement s : in) {\r
223                         boolean usable = true;\r
224                         for (Resource r : toFilter) {\r
225                                 if (g.isSubrelationOf(s.getPredicate(),r)) {\r
226                                         usable = false;\r
227                                         break;\r
228                                 }\r
229                         }\r
230                         if (usable) {\r
231                                 out.add(s);\r
232                         }\r
233                         \r
234                 }\r
235                 return out;\r
236         }\r
237         \r
238         \r
239         private void addDeletion(Statement s) {\r
240                 if (!changes1Set.contains(s)) {\r
241                         changes1Set.add(s);\r
242                         changes1.add(s);\r
243                 }\r
244         }\r
245         \r
246         private void addAddition(Statement s) {\r
247                 if (!changes2Set.contains(s)) {\r
248                         changes2Set.add(s);\r
249                         changes2.add(s);\r
250                 }\r
251         }\r
252         \r
253         private void addModification(Statement s1, Statement s2) {\r
254                 Pair<Statement, Statement> mod = new Pair<Statement, Statement>(s1,s2);\r
255                 if (!modificationsSet.contains(mod)) {\r
256                         modificationsSet.add(mod);\r
257                         modifications.add(mod);\r
258                 }\r
259         }\r
260         \r
261         private void compareStatement(List<Statement> ss1, List<Statement> ss2, Stack<Resource> stack1, Stack<Resource> stack2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
262                 Collections.sort(ss1, scomp);\r
263                 Collections.sort(ss2, scomp);\r
264                 \r
265                 int i1 = 0;\r
266                 int i2 = 0;\r
267                 \r
268                 while (true) {\r
269                         if (i1 >= ss1.size()) {\r
270                                 if (i2 >= ss2.size()) {\r
271                                         break;\r
272                                 } else {\r
273                                         while (i2 < ss2.size()) {\r
274                                                 System.out.println("Compare Statement diff2 " + printStatement(g,ss2.get(i2)));\r
275                                                 \r
276                                                 addAddition(ss2.get(i2));\r
277                                                 i2++;\r
278                                         }\r
279                                         break;\r
280                                 }\r
281                         } else if (i2 >= ss2.size()) {\r
282                                 while (i1 < ss1.size()) {\r
283                                         System.out.println("Compare Statement diff1 " + printStatement(g,ss1.get(i1)));\r
284                                         addDeletion(ss1.get(i1));\r
285                                         i1++;\r
286                                 }\r
287                                 break;\r
288                         }\r
289                         int same1 = sameRel(ss1, i1);\r
290                         int same2 = sameRel(ss2, i2);\r
291                         int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate());\r
292                         if (c == 0) {\r
293                                 compareObject(ss1, i1, same1, ss2, i2, same2,stack1,stack2);\r
294                                 i1+=same1;\r
295                                 i2+=same2;\r
296                         } else if (c < 0) {\r
297                                 for (int i = 0; i < same1; i++) {\r
298                                         System.out.println("Compare Statement diff1 " + printStatement(g,ss1.get(i+i1)));\r
299                                         addDeletion(ss1.get(i+i1));\r
300                                 }\r
301                                 i1 += same1;\r
302                         } else {\r
303                                 for (int i = 0; i < same2; i++) {\r
304                                         System.out.println("Compare Statement diff2 " + printStatement(g,ss2.get(i+i2)));\r
305                                         addAddition(ss2.get(i+i2));\r
306                                 }\r
307                                 \r
308                                 i2 += same2;\r
309                         }\r
310                         \r
311                 }\r
312         }\r
313         \r
314         private int sameRel(List<Statement> statements, int off) {\r
315                 if (statements.size() <= off)\r
316                         return 0;\r
317                 int same = 1;\r
318                 long id = statements.get(off).getPredicate().getResourceId();\r
319                 for (int i = off+1; i <statements.size(); i++) {\r
320                         if (statements.get(i).getPredicate().getResourceId() == id)\r
321                                 same++;\r
322                         else \r
323                                 break;\r
324                 }\r
325                 return same;\r
326                 \r
327         }\r
328 \r
329         \r
330         private void compareObject(List<Statement> ss1, int off1, int len1, List<Statement> ss2, int off2, int len2, Stack<Resource> stack1, Stack<Resource> stack2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
331                 boolean[] used1 = new boolean[len1];\r
332                 for (int i = 0; i < used1.length; i++) {\r
333                         used1[i] = false;\r
334                 }\r
335                 \r
336                 boolean[] used2 = new boolean[len2];\r
337                 for (int i = 0; i < used2.length; i++) {\r
338                         used2[i] = false;\r
339                 }\r
340                 \r
341                 // left, right, difference\r
342                 List<List<Integer>> differences = new ArrayList<List<Integer>>();\r
343                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
344                         Statement s1 = ss1.get(i1);\r
345                         //Map<Integer,Integer> differences = new HashMap<Integer, Integer>();\r
346                         List<Integer> diff = new ArrayList<Integer>();\r
347                         for (int i2 = off2; i2 < off2 + len2; i2++) {\r
348                                 Statement s2 = ss2.get(i2);\r
349                                 if (!compareType(s1.getObject(), s2.getObject())) {\r
350                                         diff.add(Integer.MAX_VALUE);\r
351                                         continue;\r
352                                 }\r
353                                 if (comparableResources.contains(s1.getObject(), s2.getObject()))\r
354                                         diff.add(-1);\r
355                                 else\r
356                                         diff.add(propsDiffCount(s1.getObject(), s2.getObject()));\r
357                         }\r
358                         differences.add(diff);\r
359                 }\r
360                 // difference, left\r
361                 MapList<Integer, Integer> priorities = new MapList<Integer, Integer>();\r
362                 for (int i = 0; i < differences.size(); i++) {\r
363                         List<Integer> list = differences.get(i);\r
364                         for (int j = 0; j < list.size(); j++) {\r
365                                 priorities.add(list.get(j), i);\r
366                         }\r
367                 }\r
368                 \r
369                 Integer[] pris = priorities.getKeys(new Integer[]{});\r
370                 Arrays.sort(pris);\r
371                 \r
372                 for (Integer pri : pris) {\r
373                         if (pri == Integer.MAX_VALUE)\r
374                                 continue;\r
375                         List<Integer> i1s = priorities.getValues(pri);\r
376                         for (Integer i1 : i1s) {\r
377                                 if (used1[i1])\r
378                                         continue;\r
379                                 List<Integer> i2diff = differences.get(i1);\r
380                                 for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
381                                         if (i2diff.get(i2) == pri) {\r
382                                                 if (used2[i2])\r
383                                                         continue;\r
384                                                 used1[i1] = true;\r
385                                                 used2[i2] = true;\r
386                                                 Statement s1  = ss1.get(i1+off1);\r
387                                                 Statement s2  = ss2.get(i2+off2);\r
388                                                 \r
389                                                 if (stack1 != null) {\r
390                                                         \r
391                                                                 stack1.add(s1.getObject());\r
392                                                                 stack2.add(s2.getObject());\r
393                                                         \r
394                                                 } else {\r
395                                                         // TODO : how should we report non traversed differences\r
396                                                         // using compareProps assumes that referenced objects are the same (references are not different)\r
397                                                         // using propsDiffCount assumes that objects are different, and cannot report changes in referred object.\r
398                                                         \r
399                                                         \r
400 //                                                      int diff = propsDiffCount(ss1.get(i1+off1).getObject(), ss2.get(i2+off2).getObject());\r
401 //                                                      if (diff != 0) {\r
402 //                                                              //changes1.add(ss1.get(i1+off1));\r
403 //                                                              //changes2.add(ss2.get(i2+off2));\r
404 //                                                              modifies.add(new Pair<Statement, Statement>(ss1.get(i1+off1), ss2.get(i2+off2)));\r
405 //                                                      }\r
406                                                 }\r
407                                                 comparableStatements.map(s1, s2);\r
408                                                 //comparableResources.map(s1.getObject(), s2.getObject());\r
409                                                 break;\r
410                                         }\r
411                                 }\r
412                         }\r
413                 }\r
414                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
415                         if (!used1[i1-off1]) {\r
416                                 System.out.println("Compare Object diff1 " + printStatement(g,ss1.get(i1)));\r
417                                 addDeletion(ss1.get(i1));\r
418                         }\r
419                 }\r
420                 for (int i2 = off2; i2 < off2 + len2; i2++) {\r
421                         if (!used2[i2-off2]) {\r
422                                 System.out.println("Compare Object diff2 " + printStatement(g,ss2.get(i2)));\r
423                                 addAddition(ss2.get(i2));\r
424                         }\r
425                 }\r
426         }\r
427         \r
428         private boolean compareType(Resource r1, Resource r2) throws ServiceException, ManyObjectsForFunctionalRelationException {\r
429                 rs1.addAll(g.getObjects(r1, b.InstanceOf));\r
430                 rs2.addAll(g.getObjects(r2, b.InstanceOf));\r
431                 if (rs1.size() != rs2.size()) {\r
432                         rs1.clear();\r
433                         rs2.clear();\r
434                         return false;\r
435                 }\r
436                 Collections.sort(rs1, rcomp);\r
437                 Collections.sort(rs2, rcomp);\r
438                 for (int i = 0; i < rs1.size(); i++) {\r
439                         int c = rcomp.compare(rs1.get(i), rs2.get(i));\r
440                         if (c != 0) {\r
441                                 rs1.clear();\r
442                                 rs2.clear();\r
443                                 return false;\r
444                         }\r
445                 }\r
446                 \r
447                 rs1.clear();\r
448                 rs2.clear();\r
449                 \r
450                 return true;\r
451         }\r
452         \r
453         /**\r
454          * compares properties, assumes functional relations\r
455          * @param r1\r
456          * @param r2\r
457          * @throws ServiceException\r
458          * @throws DoesNotContainValueException\r
459          * @throws ValidationException \r
460          */\r
461         private void compareProps(Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
462                 ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
463                 ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
464                 ss1.addAll(g.getStatements(r1, b.HasProperty));\r
465                 ss2.addAll(g.getStatements(r2, b.HasProperty));\r
466                 Collections.sort(ss1, scomp);\r
467                 Collections.sort(ss2, scomp);\r
468                 \r
469                 int i1 = 0; \r
470                 int i2 = 0;\r
471                 \r
472                 while (true) {\r
473                         if (i1 >= ss1.size()) {\r
474                                 if (i2 >= ss2.size())\r
475                                         break;\r
476                                 else {\r
477                                         while (i2 < ss2.size()) {\r
478                                                 System.out.println("Compare Prop diff2 " + printStatement(g,ss2.get(i2)));\r
479                                                 addAddition(ss2.get(i2));\r
480                                                 i2++;\r
481                                         }\r
482                                         break;\r
483                                 }\r
484                         } else if (i2 >= ss2.size()) {\r
485                                 while (i1 < ss1.size()) {\r
486                                         System.out.println("Compare Prop diff1 " + printStatement(g,ss1.get(i1)));\r
487                                         addDeletion(ss1.get(i1));\r
488                                         i1++;\r
489                                 }\r
490                                 break;\r
491                         }\r
492                         Statement s1 = ss1.get(i1);\r
493                         Statement s2 = ss2.get(i2);\r
494                         int c = scomp.compare(s1, s2);\r
495                         switch (c) {\r
496                         case 0:{\r
497                                 boolean b1 = g.hasValue(s1.getObject());\r
498                                 boolean b2 = g.hasValue(s2.getObject());\r
499                                 if (b1 == b2) {\r
500                                         if (b1) {\r
501                                                 Object v1 = g.getValue(s1.getObject());\r
502                                                 Object v2 = g.getValue(s2.getObject());\r
503                                                 boolean eq = false;\r
504                                                 if (v1 instanceof Object[] && v2 instanceof Object[])\r
505                                                         eq = Arrays.deepEquals((Object[])v1, (Object[])v2);\r
506                                                 else if (v1 instanceof int[] && v2 instanceof int[]) \r
507                                                         eq = Arrays.equals((int[])v1, (int[])v2);\r
508                                                 else if (v1 instanceof float[] && v2 instanceof float[]) \r
509                                                         eq = Arrays.equals((float[])v1, (float[])v2);\r
510                                                 else if (v1 instanceof double[] && v2 instanceof double[]) \r
511                                                         eq = Arrays.equals((double[])v1, (double[])v2);\r
512                                                 else if (v1 instanceof long[] && v2 instanceof long[]) \r
513                                                         eq = Arrays.equals((long[])v1, (long[])v2);\r
514                                                 else if (v1 instanceof byte[] && v2 instanceof byte[]) \r
515                                                         eq = Arrays.equals((byte[])v1, (byte[])v2);\r
516                                                 else if (v1 instanceof boolean[] && v2 instanceof boolean[]) \r
517                                                         eq = Arrays.equals((boolean[])v1, (boolean[])v2);\r
518                                                 else\r
519                                                         eq = v1.equals(v2);\r
520                                                 if (!eq) {\r
521                                                         //changes1.add(s1);\r
522                                                         //changes2.add(s2);\r
523                                                         addModification(s1, s2);\r
524                                                         comparableStatements.map(s1, s2);\r
525                                                         comparableResources.map(s1.getObject(),s2.getObject());\r
526                                                 }\r
527                                         } else {\r
528                                                 compareProps(s1.getObject(), s2.getObject());\r
529                                         }\r
530                                 } else {\r
531                                         //changes1.add(s1);\r
532                                         //changes2.add(s2);\r
533                                         addModification(s1, s2);\r
534                                         comparableStatements.map(s1, s2);\r
535                                         comparableResources.map(s1.getObject(),s2.getObject());\r
536                                 }\r
537                                 i1++;\r
538                                 i2++;\r
539                                 break;\r
540                         }\r
541                         case -1:{\r
542                                 System.out.println("Compare Prop diff1s " + printStatement(g,s1));\r
543                                 addDeletion(s1);\r
544                                 i1++;\r
545                                 break;\r
546                         }\r
547                                 \r
548                         case 1:{\r
549                                 System.out.println("Compare Prop diff2s " + printStatement(g,s2));\r
550                                 addAddition(s2);\r
551                                 i2++;\r
552                                 break;\r
553                         }\r
554                         }\r
555                         \r
556                         \r
557                 }\r
558                 \r
559                 ss1.clear();\r
560                 ss2.clear();\r
561                 \r
562         }\r
563         \r
564         private int propsDiffCount(Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
565                 ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
566                 ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
567                 ss1.addAll(g.getStatements(r1, b.HasProperty));\r
568                 ss2.addAll(g.getStatements(r2, b.HasProperty));\r
569                 //System.out.println("Props count " + GraphUtils.getReadableName(g, r1) + " " + GraphUtils.getReadableName(g, r2));\r
570                 Collections.sort(ss1, scomp);\r
571                 Collections.sort(ss2, scomp);\r
572                 \r
573                 int count = 0;\r
574                 \r
575                 int i1 = 0; \r
576                 int i2 = 0;\r
577                 \r
578                 while (true) {\r
579                         if (i1 >= ss1.size()) {\r
580                                 if (i2 >= ss2.size())\r
581                                         break;\r
582                                 else {\r
583                                         while (i2 < ss2.size()) {\r
584                                                 count++;\r
585                                                 i2++;\r
586                                         }\r
587                                         break;\r
588                                 }\r
589                         } else if (i2 >= ss2.size()) {\r
590                                 while (i1 < ss1.size()) {\r
591                                         count++;\r
592                                         i1++;\r
593                                 }\r
594                                 break;\r
595                         }\r
596                         Statement s1 = ss1.get(i1);\r
597                         Statement s2 = ss2.get(i2);\r
598                         int c = scomp.compare(s1, s2);\r
599                         switch (c) {\r
600                                 case 0:{\r
601                                         boolean b1 = g.hasValue(s1.getObject());\r
602                                         boolean b2 = g.hasValue(s2.getObject());\r
603                                         if (b1 == b2) {\r
604                                                 if (b1) {\r
605                                                         Object v1 = g.getValue(s1.getObject());\r
606                                                         Object v2 = g.getValue(s2.getObject());\r
607                                                         boolean eq = false;\r
608                                                         if (v1 instanceof Object[] && v2 instanceof Object[])\r
609                                                                 eq = Arrays.deepEquals((Object[])v1, (Object[])v2);\r
610                                                         else if (v1 instanceof int[] && v2 instanceof int[]) \r
611                                                                 eq = Arrays.equals((int[])v1, (int[])v2);\r
612                                                         else if (v1 instanceof float[] && v2 instanceof float[]) \r
613                                                                 eq = Arrays.equals((float[])v1, (float[])v2);\r
614                                                         else if (v1 instanceof double[] && v2 instanceof double[]) \r
615                                                                 eq = Arrays.equals((double[])v1, (double[])v2);\r
616                                                         else if (v1 instanceof long[] && v2 instanceof long[]) \r
617                                                                 eq = Arrays.equals((long[])v1, (long[])v2);\r
618                                                         else if (v1 instanceof byte[] && v2 instanceof byte[]) \r
619                                                                 eq = Arrays.equals((byte[])v1, (byte[])v2);\r
620                                                         else if (v1 instanceof boolean[] && v2 instanceof boolean[]) \r
621                                                                 eq = Arrays.equals((boolean[])v1, (boolean[])v2);\r
622                                                         else\r
623                                                                 eq = v1.equals(v2);\r
624                                                         if (!eq) {\r
625                                                                 count++;\r
626                                                         }\r
627                                                         //System.out.println("Prop count values " + v1 + " " + v2);\r
628                                                 } else {\r
629                                                         count += propsDiffCount(s1.getObject(), s2.getObject());\r
630                                                 }\r
631                                         } else {\r
632                                                 //System.out.println("Props count structural vs literal");\r
633                                                 count++;\r
634                                         }\r
635                                         i1++;\r
636                                         i2++;\r
637                                         break;\r
638                                 }\r
639                                 case -1:{\r
640                                         count++;\r
641                                         i1++;\r
642                                         break;\r
643                                 }\r
644                                         \r
645                                 case 1:{\r
646                                         count++;\r
647                                         i2++;\r
648                                         break;\r
649                                 }\r
650                         }\r
651 \r
652                 }\r
653                 \r
654                 ss1.clear();\r
655                 ss2.clear();\r
656                 return count;\r
657         }\r
658 \r
659         \r
660         \r
661         public class PredicateComparator implements Comparator<Statement> {\r
662                 @Override\r
663                 public int compare(Statement o1, Statement o2) {\r
664                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
665                                 return -1;\r
666                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
667                                 return 1;\r
668                         return 0;\r
669                 }\r
670         }\r
671         \r
672         public class FullStatementComparator implements Comparator<Statement> {\r
673                 @Override\r
674                 public int compare(Statement o1, Statement o2) {\r
675                         if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
676                                 return -1;\r
677                         if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
678                                 return 1;\r
679                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
680                                 return -1;\r
681                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
682                                 return 1;\r
683                         if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
684                                 return -1;\r
685                         if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
686                                 return 1;\r
687                         return 0;\r
688                 }\r
689         }\r
690         \r
691 \r
692         \r
693         public class ResourceComparator implements Comparator<Resource> {\r
694                 @Override\r
695                 public int compare(Resource o1, Resource o2) {\r
696                         if (o1.getResourceId() < o2.getResourceId())\r
697                                 return -1;\r
698                         if (o1.getResourceId() > o2.getResourceId())\r
699                                 return 1;\r
700                         return 0;\r
701                 }\r
702         }\r
703 }\r