]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java
Better handling of unidentified resources (resources that have no name, or other...
[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.math.MathContext;\r
15 import java.util.ArrayList;\r
16 import java.util.Arrays;\r
17 import java.util.Collection;\r
18 import java.util.Collections;\r
19 import java.util.Comparator;\r
20 import java.util.HashMap;\r
21 import java.util.HashSet;\r
22 import java.util.List;\r
23 import java.util.Map;\r
24 import java.util.Set;\r
25 import java.util.Stack;\r
26 \r
27 import org.simantics.db.ReadGraph;\r
28 import org.simantics.db.Resource;\r
29 import org.simantics.db.Statement;\r
30 import org.simantics.db.common.utils.NameUtils;\r
31 import org.simantics.db.exception.DatabaseException;\r
32 import org.simantics.db.exception.DoesNotContainValueException;\r
33 import org.simantics.db.exception.ServiceException;\r
34 import org.simantics.db.exception.ValidationException;\r
35 import org.simantics.layer0.Layer0;\r
36 import org.simantics.utils.datastructures.BijectionMap;\r
37 import org.simantics.utils.datastructures.MapList;\r
38 import org.simantics.utils.datastructures.Pair;\r
39 \r
40 /**\r
41  * Compares two subgraphs and reports differences.\r
42  * \r
43  * Assumes that subgraphs (defined using traverse relations) are not cyclic.\r
44  * \r
45  * Assumes that properties can be used to identify objects, if relation type is not enough.\r
46  * \r
47  * \r
48  * \r
49  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
50  *\r
51  */\r
52 public class GraphComparator {\r
53 \r
54         private Resource r1;\r
55         private Resource r2;\r
56         private List<Resource> traversed = new ArrayList<Resource>(); // list of relations that are traversed (and tested)\r
57         private List<Resource> tested = new ArrayList<Resource>();    // list of relations that are tested, but not traversed\r
58         private List<Resource> nonTraversed = new ArrayList<Resource>(); // list of relations that are not traversed\r
59         private List<Resource> nonTested = new ArrayList<Resource>(); // list of relations that are not tested\r
60         \r
61         private List<Statement> changes1 = new ArrayList<Statement>();\r
62         private List<Statement> changes2 = new ArrayList<Statement>();\r
63         private List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();\r
64         private Set<Statement> changes1Set = new HashSet<Statement>();\r
65         private Set<Statement> changes2Set = new HashSet<Statement>();\r
66         private Set<Pair<Statement,Statement>> modificationsSet = new HashSet<Pair<Statement,Statement>>();\r
67 \r
68         private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<Statement, Statement>();\r
69         private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<Resource, Resource>();\r
70         \r
71         \r
72         private ResourceComparator comparator;\r
73         \r
74         private Comparator<Statement> scomp = new PredicateComparator();\r
75         private Comparator<Resource> rcomp = new ResComparator();\r
76         \r
77         // runtime attributes\r
78         \r
79         private ReadGraph g;\r
80         private Layer0 b;\r
81         \r
82         public GraphComparator(Resource r1, Resource r2) {\r
83                 this.r1 = r1;\r
84                 this.r2 = r2;\r
85                 comparator = new TypeComparator();\r
86         }\r
87         \r
88         public GraphComparator(Resource r1, Resource r2, ResourceComparator comparator) {\r
89                 this.r1 = r1;\r
90                 this.r2 = r2;\r
91                 this.comparator = comparator;\r
92         }\r
93         \r
94         ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
95         ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
96         \r
97         \r
98         public Comparator<Resource> getResourceComparator() {\r
99                 return rcomp;\r
100         }\r
101         \r
102         public Comparator<Statement> getStatementComparator() {\r
103                 return scomp;\r
104         }\r
105         \r
106         public Resource getR1() {\r
107                 return r1;\r
108         }\r
109         \r
110         public Resource getR2() {\r
111                 return r2;\r
112         }\r
113         \r
114         public void addTraversed(Resource rel) {\r
115                 traversed.add(rel);\r
116         }\r
117         \r
118         public void addTraversed(Collection<Resource> rels) {\r
119                 traversed.addAll(rels);\r
120         }\r
121         \r
122         public void addNonTraversed(Resource rel) {\r
123                 nonTraversed.add(rel);\r
124         }\r
125         \r
126         public void addNonTraversed(Collection<Resource> rels) {\r
127                 nonTraversed.addAll(rels);\r
128         }\r
129         \r
130         public void addTested(Resource rel) {\r
131                 tested.add(rel);\r
132         }\r
133         \r
134         public void addTested(Collection<Resource> rels) {\r
135                 tested.addAll(rels);\r
136         }\r
137         \r
138         public void addNonTested(Resource rel) {\r
139                 nonTested.add(rel);\r
140         }\r
141         \r
142         public void addNonTested(Collection<Resource> rels) {\r
143                 nonTested.addAll(rels);\r
144         }\r
145         \r
146         public void addComparableResources(Resource r1, Resource r2) {\r
147                 comparableResources.map(r1, r2);\r
148         }\r
149         \r
150         public void addComparableResources(BijectionMap<Resource, Resource> matching) {\r
151                 comparableResources.addAll(matching);\r
152         }\r
153         \r
154         public void clearRels() {\r
155                 traversed.clear();\r
156                 tested.clear();\r
157                 nonTraversed.clear();\r
158                 nonTested.clear();\r
159         }\r
160         \r
161         public void test(ReadGraph g) throws DatabaseException {\r
162                 this.g = g;\r
163                 this.b = Layer0.getInstance(g);\r
164                 comparator.setComparator(this);\r
165                 \r
166                 Stack<Resource> objectsLeft = new Stack<Resource>();\r
167                 Stack<Resource> objectsRight = new Stack<Resource>();\r
168                 objectsLeft.push(r1);\r
169                 objectsRight.push(r2);\r
170                 \r
171                 \r
172                 List<Statement> ss1 = new ArrayList<Statement>();\r
173                 List<Statement> ss2 = new ArrayList<Statement>();\r
174                 \r
175                 Stack<Statement> unreliableLeft = new Stack<Statement>();\r
176                 Stack<Statement> unreliableRight = new Stack<Statement>();\r
177                 \r
178                 while (!objectsLeft.isEmpty()) {\r
179                         Resource r1 = objectsLeft.pop();\r
180                         Resource r2 = objectsRight.pop();\r
181                 \r
182                         if (comparableResources.contains(r1, r2)) {\r
183                                 //System.out.println("already tested " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
184                                 continue;\r
185                         }\r
186                         comparableResources.map(r1, r2);\r
187                         \r
188                         //System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
189                         compareProps(r1, r2);\r
190                         \r
191                         for (Resource rel : tested) {\r
192                                 ss1.addAll(g.getStatements(r1, rel));\r
193                                 ss2.addAll(g.getStatements(r2, rel));\r
194                                 ss1 = filterAsserted(r1, ss1);\r
195                                 ss2 = filterAsserted(r2, ss2);\r
196                                 ss1 = filterTraversed(ss1);\r
197                                 ss2 = filterTraversed(ss2);\r
198                                 ss1 = filterNonTested(ss1);\r
199                                 ss2 = filterNonTested(ss2);\r
200                                 \r
201                                 compareStatements(ss1, ss2, null, null,null,null);\r
202                                 ss1.clear();\r
203                                 ss2.clear();\r
204                         }\r
205                         \r
206                         for (Resource rel : traversed) {\r
207                                 ss1.addAll(g.getStatements(r1, rel));\r
208                                 ss2.addAll(g.getStatements(r2, rel));\r
209                                 ss1 = filterAsserted(r1, ss1);\r
210                                 ss2 = filterAsserted(r2, ss2);\r
211                                 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);\r
212                                 ss1.clear();\r
213                                 ss2.clear();\r
214                                 \r
215                         }\r
216                 }\r
217                 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();\r
218                 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();\r
219                 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();\r
220                 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();\r
221                 \r
222                 for (Statement s : unreliableLeft) {\r
223                         subjectLeft.add(s.getSubject(),s);\r
224                         objectLeft.add(s.getObject(),s);\r
225                 }\r
226                 for (Statement s : unreliableRight) {\r
227                         subjectRight.add(s.getSubject(),s);\r
228                         objectRight.add(s.getObject(),s);\r
229                 }\r
230                 \r
231                 for (Resource ol : objectLeft.getKeys()) {\r
232 \r
233                         // all statements to the left side object\r
234                         List<Statement> left = objectLeft.getValues(ol);\r
235                         // all subjects that have statements to the left side object (ol)\r
236                         Set<Resource> sLeft = new HashSet<Resource>();\r
237                         // all matching subjects on the right side\r
238                         Set<Resource> sRight = new HashSet<Resource>();\r
239                         for (Statement s : left) {\r
240                                 sLeft.add(s.getSubject());\r
241                                 sRight.add(comparableResources.getRight(s.getSubject()));\r
242                         }\r
243                         // all objects that subjects on the right side point to. Object left has its matching resource among these, if it has matching resource\r
244                         MapList<Resource,Statement> possibleOR = new MapList<Resource, Statement>();\r
245                         for (Resource sr : sRight) {\r
246                                 for (Statement s : subjectRight.getValues(sr))\r
247                                         possibleOR.add(s.getObject(),s);\r
248                         }\r
249                         \r
250                         // filter possible right side objects to those that have same amount of statements as the left side object\r
251                         for (Resource or : possibleOR.getKeys().toArray(new Resource[possibleOR.getKeys().size()])) {\r
252                                 List<Statement> right = possibleOR.getValues(or);\r
253                                 if (right.size() != left.size())\r
254                                         possibleOR.remove(or);\r
255                                         \r
256                         }\r
257                         \r
258                         // check for matching statements (comparable subjects, matching predicates)\r
259                         MapList<Resource,Statement> matchingOR = new MapList<Resource, Statement>(); // list of objects that have matching statements\r
260                         Map<Resource,Pair<int[], int[]>> matchingStatements = new HashMap<Resource, Pair<int[], int[]>>(); // matching statements\r
261                         for (Resource or : possibleOR.getKeys()) {\r
262                                 List<Statement> right = possibleOR.getValues(or);\r
263                                 int iLeft[] = new int[left.size()];\r
264                                 int iRight[] = new int[right.size()];\r
265                                 \r
266                                 for (int i = 0; i < left.size(); i++) {\r
267                                         iLeft[i] = -1;\r
268                                         iRight[i] = -1;\r
269                                 }\r
270                                 \r
271                                 for (int l = 0; l < left.size(); l++) {\r
272                                         Statement ls = left.get(l);\r
273                                         for (int r = 0; r < right.size(); r++) {\r
274                                                 if (iRight[r] >= 0)\r
275                                                         continue;\r
276                                                 Statement rs = right.get(r);\r
277                                                 if (!comparableResources.contains(ls.getSubject(), rs.getSubject()))\r
278                                                         continue;\r
279                                                 if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) {\r
280                                                         iLeft[l] = r;\r
281                                                         iRight[r] = l;\r
282                                                         break;\r
283                                                 }\r
284                                         }\r
285                                         \r
286                                 }\r
287                                 boolean success = true;\r
288                                 for (int i = 0; i < left.size(); i++) {\r
289                                         if (iLeft[i] < 0) {\r
290                                                 success = false;\r
291                                                 break;\r
292                                         }\r
293                                         if (iRight[i] < 0) {\r
294                                                 success = false;\r
295                                                 break;\r
296                                         }\r
297                                                 \r
298                                 }\r
299                                 if (success) {\r
300                                         for (Statement s : right) \r
301                                                 matchingOR.add(or,s);\r
302                                         matchingStatements.put(or, new Pair<int[], int[]>(iLeft, iRight));\r
303                                 }\r
304                         }\r
305                         // if there is only one matching right side object, we have found a match \r
306                         if (matchingOR.getKeySize() == 1) {\r
307                                 Resource or = matchingOR.getKeys().iterator().next();\r
308                                 List<Statement> right = matchingOR.getValues(or);\r
309                                 Pair<int[], int[]> indices = matchingStatements.get(or);\r
310                                 \r
311                                 comparableResources.map(ol, or);\r
312                                 for (int l = 0; l < left.size(); l++) {\r
313                                         int r = indices.first[l];\r
314                                         comparableStatements.map(left.get(l), right.get(r));\r
315                                 }\r
316                                 \r
317                         }\r
318 \r
319                 }\r
320                 \r
321                 for (Statement s : unreliableLeft) {\r
322                         if (!comparableStatements.containsLeft(s))\r
323                                 addDeletion(s);\r
324                 }\r
325                 for (Statement s : unreliableRight) {\r
326                         if (!comparableStatements.containsRight(s))\r
327                                 addAddition(s);\r
328                 }\r
329                 \r
330                 \r
331         }\r
332         \r
333         \r
334         \r
335         public BijectionMap<Statement, Statement> getComparableStatements() {\r
336                 return comparableStatements;\r
337         }\r
338         \r
339         public GraphChanges getChanges() {\r
340                 return new GraphChanges(r1,r2,changes1,changes2,modifications,comparableResources);\r
341         }\r
342         \r
343         private List<Statement> filterAsserted(Resource r, Collection<Statement> in) throws ServiceException {\r
344                 List<Statement> out = new ArrayList<Statement>();\r
345                 for (Statement s : in) {\r
346                         if (!s.isAsserted(r))\r
347                                 out.add(s);\r
348                         \r
349                 }\r
350                 return out;\r
351         }\r
352         \r
353         private String printStatement(ReadGraph graph, Statement s) throws ValidationException, ServiceException {\r
354                 return NameUtils.getSafeName(graph, s.getSubject()) + " " + NameUtils.getSafeName(graph, s.getPredicate()) + " " + NameUtils.getSafeName(graph, s.getObject());\r
355         }\r
356         \r
357         private List<Statement> filterTraversed(List<Statement> in) throws ServiceException {\r
358                 return filter(traversed, in);\r
359         }\r
360         \r
361         private List<Statement> filterNonTested(List<Statement> in) throws ServiceException {\r
362                 return filter(nonTested, in);\r
363         }\r
364         \r
365         private List<Statement> filter(Collection<Resource> toFilter, List<Statement> in) throws ServiceException {\r
366                 if (toFilter.size() == 0)\r
367                         return in;\r
368                 List<Statement> out = new ArrayList<Statement>();\r
369                 for (Statement s : in) {\r
370                         boolean usable = true;\r
371                         for (Resource r : toFilter) {\r
372                                 if (g.isSubrelationOf(s.getPredicate(),r)) {\r
373                                         usable = false;\r
374                                         break;\r
375                                 }\r
376                         }\r
377                         if (usable) {\r
378                                 out.add(s);\r
379                         }\r
380                         \r
381                 }\r
382                 return out;\r
383         }\r
384         \r
385         \r
386         private void addDeletion(Statement s) {\r
387                 if (!changes1Set.contains(s)) {\r
388                         changes1Set.add(s);\r
389                         changes1.add(s);\r
390                 }\r
391         }\r
392         \r
393         private void addAddition(Statement s) {\r
394                 if (!changes2Set.contains(s)) {\r
395                         changes2Set.add(s);\r
396                         changes2.add(s);\r
397                 }\r
398         }\r
399         \r
400         private void addModification(Statement s1, Statement s2) {\r
401                 Pair<Statement, Statement> mod = new Pair<Statement, Statement>(s1,s2);\r
402                 if (!modificationsSet.contains(mod)) {\r
403                         modificationsSet.add(mod);\r
404                         modifications.add(mod);\r
405                 }\r
406         }\r
407         \r
408         public void sortStatement(List<Statement> list1, List<Statement> list2) {\r
409                 sortStatement(list1, list2, scomp);\r
410         }\r
411         \r
412         public void sortStatement(List<Statement> list1, List<Statement> list2, Comparator<Statement> scomp) {\r
413                 Collections.sort(list1,scomp);\r
414                 Collections.sort(list2,scomp);\r
415                 \r
416                 List<Statement> sorted1 = new ArrayList<Statement>(list1.size());\r
417                 List<Statement> sorted2 = new ArrayList<Statement>(list2.size());\r
418                 sorted1.addAll(list1);\r
419                 sorted2.addAll(list2);\r
420                 \r
421                 int ss1 = 0;\r
422                 int ss2 = 0;\r
423                 for (int i = 0; i < list1.size(); ) {\r
424                         Statement s1 = list1.get(i);\r
425                         int same1 = sameRel(list1, i);  \r
426                         for (int j = 0; j < list2.size(); j++) {\r
427                                 Statement s2 = list2.get(j);\r
428                                 if (scomp.compare(s1, s2) == 0) {\r
429                                         int same2 = sameRel(list2, j);\r
430                                         copy(sorted1,ss1,list1,i,same1);\r
431                                         ss1 += same1;\r
432                                         copy(sorted2,ss2,list2,j,same2);\r
433                                         ss2 += same2;\r
434                                         break;\r
435                                 }\r
436                         }\r
437                         i+= same1;\r
438                 }\r
439                 if (ss1 < sorted1.size()) {\r
440                         for (Statement s : list1) {\r
441                                 if (!sorted1.contains(s)) {\r
442                                         sorted1.set(ss1,s);\r
443                                         ss1++;\r
444                                 }\r
445                         }\r
446                 }\r
447                 if (ss2 < sorted2.size()) {\r
448                         for (Statement s : list2) {\r
449                                 if (!sorted2.contains(s)) {\r
450                                         sorted2.set(ss2,s);\r
451                                         ss2++;\r
452                                 }\r
453                         }\r
454                 }\r
455                 \r
456                 list1.clear();\r
457                 list2.clear();\r
458                 list1.addAll(sorted1);\r
459                 list2.addAll(sorted2);\r
460         }\r
461         \r
462         public <T> void copy(List<T> to, int toIndex, List<T> from, int fromIndex, int amount) {\r
463                 for (int i = 0; i <  amount; i++) {\r
464                         to.set(toIndex + i, from.get(fromIndex+ i));\r
465                 }\r
466         }\r
467         \r
468         public void sortResource(List<Resource> list1, List<Resource> list2) {\r
469                 Collections.sort(list1,rcomp);\r
470                 int js = 0;\r
471                 for (int i = 0; i < list1.size(); i++) {\r
472                         Resource s1 = list1.get(i);\r
473                         for (int j = js; j < list2.size(); j++) {\r
474                                 Resource s2 = list2.get(j);\r
475                                 if (rcomp.compare(s1, s2) == 0) {\r
476                                         Resource t = list2.get(js);\r
477                                         list2.set(js, s2);\r
478                                         list2.set(j, t);\r
479                                         break;\r
480                                 }\r
481                         }\r
482                         js++;\r
483                         \r
484                 }\r
485         }\r
486         \r
487         private void compareStatements(List<Statement> ss1, List<Statement> ss2, Stack<Resource> objectsLeft, Stack<Resource> objectsRight,Stack<Statement> unreliableLeft, Stack<Statement> unreliableRight) throws DatabaseException {\r
488                 sortStatement(ss1, ss2);\r
489                 \r
490                 int i1 = 0;\r
491                 int i2 = 0;\r
492                 \r
493                 while (true) {\r
494                         if (i1 >= ss1.size()) {\r
495                                 if (i2 >= ss2.size()) {\r
496                                         break;\r
497                                 } else {\r
498                                         while (i2 < ss2.size()) {\r
499                                                 System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i2)));\r
500                                                 \r
501                                                 addAddition(ss2.get(i2));\r
502                                                 i2++;\r
503                                         }\r
504                                         break;\r
505                                 }\r
506                         } else if (i2 >= ss2.size()) {\r
507                                 while (i1 < ss1.size()) {\r
508                                         System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i1)));\r
509                                         addDeletion(ss1.get(i1));\r
510                                         i1++;\r
511                                 }\r
512                                 break;\r
513                         }\r
514                         int same1 = sameRel(ss1, i1);\r
515                         int same2 = sameRel(ss2, i2);\r
516                         int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate());\r
517                         if (c == 0) {\r
518                                 compareStatements(ss1, i1, same1, ss2, i2, same2,objectsLeft,objectsRight,unreliableLeft,unreliableRight);\r
519                                 i1+=same1;\r
520                                 i2+=same2;\r
521                         } else if (c < 0) {\r
522                                 for (int i = 0; i < same1; i++) {\r
523                                         System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i+i1)));\r
524                                         addDeletion(ss1.get(i+i1));\r
525                                 }\r
526                                 i1 += same1;\r
527                         } else {\r
528                                 for (int i = 0; i < same2; i++) {\r
529                                         System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i+i2)));\r
530                                         addAddition(ss2.get(i+i2));\r
531                                 }\r
532                                 \r
533                                 i2 += same2;\r
534                         }\r
535                         \r
536                 }\r
537         }\r
538         \r
539         private void compareUnreliableStatements(List<Statement> ss1, List<Statement> ss2) throws DatabaseException {\r
540                 sortStatement(ss1, ss2);\r
541                 \r
542                 int i1 = 0;\r
543                 int i2 = 0;\r
544                 \r
545                 while (true) {\r
546                         if (i1 >= ss1.size()) {\r
547                                 if (i2 >= ss2.size()) {\r
548                                         break;\r
549                                 } else {\r
550                                         while (i2 < ss2.size()) {\r
551                                                 System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i2)));\r
552                                                 \r
553                                                 addAddition(ss2.get(i2));\r
554                                                 i2++;\r
555                                         }\r
556                                         break;\r
557                                 }\r
558                         } else if (i2 >= ss2.size()) {\r
559                                 while (i1 < ss1.size()) {\r
560                                         System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i1)));\r
561                                         addDeletion(ss1.get(i1));\r
562                                         i1++;\r
563                                 }\r
564                                 break;\r
565                         }\r
566                         int same1 = sameRel(ss1, i1);\r
567                         int same2 = sameRel(ss2, i2);\r
568                         int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate());\r
569                         if (c == 0) {\r
570                                 compareStatements(ss1, i1, same1, ss2, i2, same2,null, null, null, null);\r
571                                 i1+=same1;\r
572                                 i2+=same2;\r
573                         } else if (c < 0) {\r
574                                 for (int i = 0; i < same1; i++) {\r
575                                         System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i+i1)));\r
576                                         addDeletion(ss1.get(i+i1));\r
577                                 }\r
578                                 i1 += same1;\r
579                         } else {\r
580                                 for (int i = 0; i < same2; i++) {\r
581                                         System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i+i2)));\r
582                                         addAddition(ss2.get(i+i2));\r
583                                 }\r
584                                 \r
585                                 i2 += same2;\r
586                         }\r
587                         \r
588                 }\r
589         }\r
590         \r
591         private int sameRel(List<Statement> statements, int off) {\r
592                 if (statements.size() <= off)\r
593                         return 0;\r
594                 int same = 1;\r
595                 long id = statements.get(off).getPredicate().getResourceId();\r
596                 for (int i = off+1; i <statements.size(); i++) {\r
597                         if (statements.get(i).getPredicate().getResourceId() == id)\r
598                                 same++;\r
599                         else \r
600                                 break;\r
601                 }\r
602                 return same;\r
603                 \r
604         }\r
605 \r
606         private int compareObject(Resource o1, Resource o2) throws DatabaseException {\r
607                 if (comparableResources.contains(o1, o2))\r
608                         return (-1);\r
609                 if (comparableResources.containsLeft(o1))\r
610                         return Integer.MAX_VALUE;\r
611                 if (comparableResources.containsRight(o2))\r
612                         return Integer.MAX_VALUE;\r
613                 return comparator.compare(g, o1, o2);\r
614         }\r
615         \r
616         private void compareStatements(List<Statement> ss1, int off1, int len1, List<Statement> ss2, int off2, int len2, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Stack<Statement> unreliableLeft, Stack<Statement> unreliableRight) throws DatabaseException {\r
617                 boolean[] used1 = new boolean[len1];\r
618                 for (int i = 0; i < used1.length; i++) {\r
619                         used1[i] = false;\r
620                 }\r
621                 \r
622                 boolean[] used2 = new boolean[len2];\r
623                 for (int i = 0; i < used2.length; i++) {\r
624                         used2[i] = false;\r
625                 }\r
626                 \r
627                 // left, right, difference\r
628                 List<List<Integer>> differences = new ArrayList<List<Integer>>();\r
629                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
630                         Statement s1 = ss1.get(i1);\r
631                         List<Integer> diff = new ArrayList<Integer>();\r
632                         for (int i2 = off2; i2 < off2 + len2; i2++) {\r
633                                 Statement s2 = ss2.get(i2);\r
634                                 int d = compareObject(s1.getObject(), s2.getObject());\r
635                                 diff.add(d);\r
636                         }\r
637                         differences.add(diff);\r
638                 }\r
639                 // difference, left\r
640                 MapList<Integer, Integer> priorities = new MapList<Integer, Integer>();\r
641                 for (int i = 0; i < differences.size(); i++) {\r
642                         List<Integer> list = differences.get(i);\r
643                         for (int j = 0; j < list.size(); j++) {\r
644                                 priorities.add(list.get(j), i);\r
645                         }\r
646                 }\r
647                 \r
648                 Integer[] pris = priorities.getKeys(new Integer[]{});\r
649                 Arrays.sort(pris);\r
650                 \r
651                 for (Integer pri : pris) {\r
652                         if (pri == Integer.MAX_VALUE) {\r
653 \r
654                         } else if (pri == 0) {\r
655                                 Set<Statement> s1s = new HashSet<Statement>();\r
656                                 Set<Statement> s2s = new HashSet<Statement>();\r
657                                 List<Integer> i1s = priorities.getValues(pri);\r
658                                 for (Integer i1 : i1s) {\r
659 \r
660                                         List<Integer> i2diff = differences.get(i1);\r
661                                         for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
662                                                 if (i2diff.get(i2) == pri) {\r
663                                                         used1[i1] = true;\r
664                                                         used2[i2] = true;\r
665                                                         Statement s1  = ss1.get(i1+off1);\r
666                                                         Statement s2  = ss2.get(i2+off2);\r
667                                                         s1s.add(s1);\r
668                                                         s2s.add(s2);\r
669                                                 }\r
670                                         }\r
671                                 }\r
672                                 if (unreliableLeft != null) {\r
673                                         unreliableLeft.addAll(s1s);\r
674                                         unreliableRight.addAll(s2s);\r
675                                 }\r
676                                 continue;\r
677                         } else {\r
678                                 List<Integer> i1s = priorities.getValues(pri);\r
679                                 for (Integer i1 : i1s) {\r
680                                         if (used1[i1])\r
681                                                 continue;\r
682                                         List<Integer> i2diff = differences.get(i1);\r
683                                         for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
684                                                 if (i2diff.get(i2) == pri) {\r
685                                                         if (used2[i2])\r
686                                                                 continue;\r
687                                                         used1[i1] = true;\r
688                                                         used2[i2] = true;\r
689                                                         Statement s1  = ss1.get(i1+off1);\r
690                                                         Statement s2  = ss2.get(i2+off2);\r
691                                                         \r
692                                                         if (objectsLeft != null) {\r
693                                                                 \r
694                                                                         objectsLeft.add(s1.getObject());\r
695                                                                         objectsRight.add(s2.getObject());\r
696                                                                 \r
697                                                         } \r
698                                                         comparableStatements.map(s1, s2);\r
699                                                         //comparableResources.map(s1.getObject(), s2.getObject());\r
700                                                         break;\r
701                                                 }\r
702                                         }\r
703                                 }\r
704                         }\r
705                 }\r
706                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
707                         if (!used1[i1-off1]) {\r
708                                 System.out.println("Compare Object diff1 " + printStatement(g,ss1.get(i1)));\r
709                                 addDeletion(ss1.get(i1));\r
710                         }\r
711                 }\r
712                 for (int i2 = off2; i2 < off2 + len2; i2++) {\r
713                         if (!used2[i2-off2]) {\r
714                                 System.out.println("Compare Object diff2 " + printStatement(g,ss2.get(i2)));\r
715                                 addAddition(ss2.get(i2));\r
716                         }\r
717                 }\r
718         }\r
719         \r
720         \r
721         \r
722         /**\r
723          * compares properties, assumes functional relations\r
724          * @param r1\r
725          * @param r2\r
726          * @throws ServiceException\r
727          * @throws DoesNotContainValueException\r
728          * @throws ValidationException \r
729          */\r
730         private void compareProps(Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
731                 ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
732                 ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
733                 ss1.addAll(g.getStatements(r1, b.HasProperty));\r
734                 ss2.addAll(g.getStatements(r2, b.HasProperty));\r
735                 sortStatement(ss1, ss2);\r
736 //              Collections.sort(ss1, scomp);\r
737 //              Collections.sort(ss2, scomp);\r
738                 \r
739                 int i1 = 0; \r
740                 int i2 = 0;\r
741                 \r
742                 while (true) {\r
743                         if (i1 >= ss1.size()) {\r
744                                 if (i2 >= ss2.size())\r
745                                         break;\r
746                                 else {\r
747                                         while (i2 < ss2.size()) {\r
748                                                 System.out.println("Compare Prop diff2 " + printStatement(g,ss2.get(i2)));\r
749                                                 addAddition(ss2.get(i2));\r
750                                                 i2++;\r
751                                         }\r
752                                         break;\r
753                                 }\r
754                         } else if (i2 >= ss2.size()) {\r
755                                 while (i1 < ss1.size()) {\r
756                                         System.out.println("Compare Prop diff1 " + printStatement(g,ss1.get(i1)));\r
757                                         addDeletion(ss1.get(i1));\r
758                                         i1++;\r
759                                 }\r
760                                 break;\r
761                         }\r
762                         Statement s1 = ss1.get(i1);\r
763                         Statement s2 = ss2.get(i2);\r
764                         int c = scomp.compare(s1, s2);\r
765                         switch (c) {\r
766                         case 0:{\r
767                                 boolean b1 = g.hasValue(s1.getObject());\r
768                                 boolean b2 = g.hasValue(s2.getObject());\r
769                                 if (b1 == b2) {\r
770                                         if (b1) {\r
771                                                 Object v1 = g.getValue(s1.getObject());\r
772                                                 Object v2 = g.getValue(s2.getObject());\r
773                                                 boolean eq = compareValue(v1, v2);\r
774                                                 if (!eq) {\r
775                                                         addModification(s1, s2);\r
776                                                         comparableStatements.map(s1, s2);\r
777                                                         comparableResources.map(s1.getObject(),s2.getObject());\r
778                                                 }\r
779                                         } else {\r
780                                                 compareProps(s1.getObject(), s2.getObject());\r
781                                         }\r
782                                 } else {\r
783                                         addModification(s1, s2);\r
784                                         comparableStatements.map(s1, s2);\r
785                                         comparableResources.map(s1.getObject(),s2.getObject());\r
786                                 }\r
787                                 i1++;\r
788                                 i2++;\r
789                                 break;\r
790                         }\r
791                         case -1:{\r
792                                 System.out.println("Compare Prop diff1s " + printStatement(g,s1));\r
793                                 addDeletion(s1);\r
794                                 i1++;\r
795                                 break;\r
796                         }\r
797                                 \r
798                         case 1:{\r
799                                 System.out.println("Compare Prop diff2s " + printStatement(g,s2));\r
800                                 addAddition(s2);\r
801                                 i2++;\r
802                                 break;\r
803                         }\r
804                         }\r
805                         \r
806                         \r
807                 }\r
808                 \r
809                 ss1.clear();\r
810                 ss2.clear();\r
811                 \r
812         }\r
813         \r
814         \r
815         public static boolean compareValue(Object v1, Object v2) {\r
816                 if (v1 instanceof Object[] && v2 instanceof Object[])\r
817                         return Arrays.deepEquals((Object[])v1, (Object[])v2);\r
818                 else if (v1 instanceof int[] && v2 instanceof int[]) \r
819                         return Arrays.equals((int[])v1, (int[])v2);\r
820                 else if (v1 instanceof float[] && v2 instanceof float[]) \r
821                         return Arrays.equals((float[])v1, (float[])v2);\r
822                 else if (v1 instanceof double[] && v2 instanceof double[]) \r
823                         return Arrays.equals((double[])v1, (double[])v2);\r
824                 else if (v1 instanceof long[] && v2 instanceof long[]) \r
825                         return  Arrays.equals((long[])v1, (long[])v2);\r
826                 else if (v1 instanceof byte[] && v2 instanceof byte[]) \r
827                         return Arrays.equals((byte[])v1, (byte[])v2);\r
828                 else if (v1 instanceof boolean[] && v2 instanceof boolean[]) \r
829                         return Arrays.equals((boolean[])v1, (boolean[])v2);\r
830                 else\r
831                         return v1.equals(v2);\r
832         }\r
833 \r
834         \r
835         \r
836         public class PredicateComparator implements Comparator<Statement> {\r
837                 @Override\r
838                 public int compare(Statement o1, Statement o2) {\r
839                         if (comparableResources.contains(o1.getPredicate(), o2.getPredicate()))\r
840                                 return 0;\r
841                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
842                                 return -1;\r
843                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
844                                 return 1;\r
845                         return 0;\r
846                 }\r
847         }\r
848         \r
849         public class SubjectComparator implements Comparator<Statement> {\r
850                 @Override\r
851                 public int compare(Statement o1, Statement o2) {\r
852                         if (comparableResources.contains(o1.getSubject(), o2.getSubject()))\r
853                                 return 0;\r
854                         if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
855                                 return -1;\r
856                         if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
857                                 return 1;\r
858                         return 0;\r
859                 }\r
860         }\r
861         \r
862         public class ObjectComparator implements Comparator<Statement> {\r
863                 @Override\r
864                 public int compare(Statement o1, Statement o2) {\r
865                         if (comparableResources.contains(o1.getObject(), o2.getObject()))\r
866                                 return 0;\r
867                         if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
868                                 return -1;\r
869                         if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
870                                 return 1;\r
871                         return 0;\r
872                 }\r
873         }\r
874         \r
875         public static class FullStatementComparator implements Comparator<Statement> {\r
876                 @Override\r
877                 public int compare(Statement o1, Statement o2) {\r
878                         if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
879                                 return -1;\r
880                         if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
881                                 return 1;\r
882                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
883                                 return -1;\r
884                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
885                                 return 1;\r
886                         if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
887                                 return -1;\r
888                         if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
889                                 return 1;\r
890                         return 0;\r
891                 }\r
892         }\r
893         \r
894 \r
895         \r
896         public class ResComparator implements Comparator<Resource> {\r
897                 @Override\r
898                 public int compare(Resource o1, Resource o2) {\r
899                         if (comparableResources.contains(o1, o2))\r
900                                 return 0;\r
901                         if (o1.getResourceId() < o2.getResourceId())\r
902                                 return -1;\r
903                         if (o1.getResourceId() > o2.getResourceId())\r
904                                 return 1;\r
905                         return 0;\r
906                 }\r
907         }\r
908         \r
909         \r
910 }\r