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