]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java
Improve Proteus property comparison
[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.Session;\r
29 import org.simantics.db.Statement;\r
30 import org.simantics.db.common.request.ReadRequest;\r
31 import org.simantics.db.common.utils.NameUtils;\r
32 import org.simantics.db.exception.DatabaseException;\r
33 import org.simantics.layer0.Layer0;\r
34 import org.simantics.utils.datastructures.BijectionMap;\r
35 import org.simantics.utils.datastructures.MapList;\r
36 import org.simantics.utils.datastructures.Pair;\r
37 \r
38 /**\r
39  * Compares two subgraphs and reports differences.\r
40  * \r
41  * Assumes that subgraphs (defined using traverse relations) are not cyclic.\r
42  * \r
43  * Assumes that properties can be used to identify objects, if relation type is not enough.\r
44  * \r
45  * \r
46  * \r
47  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
48  *\r
49  */\r
50 public class GraphComparator {\r
51         \r
52         private static final boolean DEBUG = false;\r
53 \r
54         private Resource r1;\r
55         private Resource r2;\r
56         private Set<Resource> strong = new HashSet<Resource>();       // List of relations that identify object, if subject is already identified. \r
57         private List<Resource> traversed = new ArrayList<Resource>(); // list of relations that are traversed (and tested)\r
58         private List<Resource> tested = new ArrayList<Resource>();    // list of relations that are tested, but not traversed\r
59         private List<Resource> nonTraversed = new ArrayList<Resource>(); // list of relations that are not traversed\r
60         private List<Resource> nonTested = new ArrayList<Resource>(); // list of relations that are not tested\r
61         \r
62         private List<Statement> changes1 = new ArrayList<Statement>();\r
63         private List<Statement> changes2 = new ArrayList<Statement>();\r
64         private List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();\r
65         private Set<Statement> changes1Set = new HashSet<Statement>();\r
66         private Set<Statement> changes2Set = new HashSet<Statement>();\r
67         private Set<Pair<Statement,Statement>> modificationsSet = new HashSet<Pair<Statement,Statement>>();\r
68 \r
69         private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<Statement, Statement>();\r
70         private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<Resource, Resource>();\r
71         private Set<Resource> processedResources = new HashSet<Resource>();\r
72         \r
73         private ResourceComparator comparator;\r
74         \r
75         private Comparator<Statement> scomp = new PredicateComparator();\r
76         private Comparator<Resource> rcomp = new ResComparator();\r
77         \r
78         // runtime attributes\r
79         \r
80         private ReadGraph g;\r
81         private Layer0 b;\r
82         \r
83         public GraphComparator(Resource r1, Resource r2) {\r
84                 this.r1 = r1;\r
85                 this.r2 = r2;\r
86                 comparator = new TypeComparator();\r
87         }\r
88         \r
89         public GraphComparator(Resource r1, Resource r2, ResourceComparator comparator) {\r
90                 this.r1 = r1;\r
91                 this.r2 = r2;\r
92                 this.comparator = comparator;\r
93         }\r
94         \r
95         ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
96         ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
97         \r
98         \r
99         public Comparator<Resource> getResourceComparator() {\r
100                 return rcomp;\r
101         }\r
102         \r
103         public Comparator<Statement> getStatementComparator() {\r
104                 return scomp;\r
105         }\r
106         \r
107         public Resource getR1() {\r
108                 return r1;\r
109         }\r
110         \r
111         public Resource getR2() {\r
112                 return r2;\r
113         }\r
114         \r
115         public void addTraversed(Resource rel) {\r
116                 traversed.add(rel);\r
117         }\r
118         \r
119         public void addTraversed(Collection<Resource> rels) {\r
120                 traversed.addAll(rels);\r
121         }\r
122         \r
123         public void addNonTraversed(Resource rel) {\r
124                 nonTraversed.add(rel);\r
125         }\r
126         \r
127         public void addNonTraversed(Collection<Resource> rels) {\r
128                 nonTraversed.addAll(rels);\r
129         }\r
130         \r
131         public void addTested(Resource rel) {\r
132                 tested.add(rel);\r
133         }\r
134         \r
135         public void addTested(Collection<Resource> rels) {\r
136                 tested.addAll(rels);\r
137         }\r
138         \r
139         public void addNonTested(Resource rel) {\r
140                 nonTested.add(rel);\r
141         }\r
142         \r
143         public void addNonTested(Collection<Resource> rels) {\r
144                 nonTested.addAll(rels);\r
145         }\r
146         \r
147         public void addComparableResources(Resource r1, Resource r2) {\r
148                 comparableResources.map(r1, r2);\r
149         }\r
150         \r
151         public void addComparableResources(BijectionMap<Resource, Resource> matching) {\r
152                 comparableResources.addAll(matching);\r
153         }\r
154         \r
155         public void addStrong(Resource r) {\r
156                 strong.add(r);\r
157         }\r
158         \r
159         public void addStrong(Collection<Resource> rels) {\r
160                 strong.addAll(rels);\r
161         }\r
162         \r
163         \r
164         public void test(ReadGraph g) throws DatabaseException {\r
165                 this.g = g;\r
166                 this.b = Layer0.getInstance(g);\r
167                 comparator.setComparator(this);\r
168                 \r
169                 Stack<Resource> objectsLeft = new Stack<Resource>();\r
170                 Stack<Resource> objectsRight = new Stack<Resource>();\r
171                 objectsLeft.push(r1);\r
172                 objectsRight.push(r2);\r
173                 \r
174                 Set<Statement> unreliableLeft = new HashSet<Statement>();\r
175                 Set<Statement> unreliableRight = new HashSet<Statement>();\r
176                 \r
177                 while (true) {\r
178                         if (objectsLeft.isEmpty())\r
179                                 break;\r
180                         \r
181                         \r
182                         // process compares objects that are identified and searches for more resources to process. \r
183                         process(objectsLeft, objectsRight, unreliableLeft, unreliableRight);\r
184                         // process unreliable handles cases where unidentified statements subject and object have been identified \r
185                         processUnreliable(unreliableLeft, unreliableRight);\r
186                         // process unreliable handles cases where unidentified resources have path of length one to identified resource\r
187                         processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight);\r
188                         if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {\r
189                                 // comparison is ending, but we have still unprocessed unidentified resources left.\r
190                                 // These cases have longer path than one to identified objects.\r
191                                 processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);\r
192                         }\r
193                         \r
194                 }\r
195                 for (Statement s : unreliableLeft) {\r
196                         if (!comparableStatements.containsLeft(s))\r
197                                 addDeletion(s);\r
198                 }\r
199                 for (Statement s : unreliableRight) {\r
200                         if (!comparableStatements.containsRight(s))\r
201                                 addAddition(s);\r
202                 }\r
203                 \r
204                 \r
205         }\r
206         \r
207         public void test(Session session) throws DatabaseException {\r
208                 test(session, r1, r2);\r
209         }\r
210         \r
211         public void test(Session session, Resource r1, Resource r2) throws DatabaseException {\r
212                 \r
213                 comparator.setComparator(this);\r
214                 \r
215                 addComparable(r1, r2, false);\r
216                 \r
217                 final Stack<Resource> objectsLeft = new Stack<Resource>();\r
218                 final Stack<Resource> objectsRight = new Stack<Resource>();\r
219                 objectsLeft.push(r1);\r
220                 objectsRight.push(r2);\r
221                 \r
222                 final Set<Statement> unreliableLeft = new HashSet<Statement>();\r
223                 final Set<Statement> unreliableRight = new HashSet<Statement>();\r
224                 \r
225                 while (true) {\r
226                         if (objectsLeft.isEmpty())\r
227                                 break;\r
228                         session.syncRequest(new ReadRequest() {\r
229                                 \r
230                                 @Override\r
231                                 public void run(ReadGraph graph) throws DatabaseException {\r
232                                         g = graph;\r
233                                         b = Layer0.getInstance(graph);\r
234                                         // process compares objects that are identified and searches for more resources to process. \r
235                                         process(objectsLeft, objectsRight, unreliableLeft, unreliableRight);\r
236                                         // process unreliable handles cases where unidentified statements subject and object have been identified \r
237                                         processUnreliable(unreliableLeft, unreliableRight);\r
238                                         // process unreliable handles cases where unidentified resources have path of length one to identified resource\r
239                                         processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight);\r
240                                         if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {\r
241                                                 // comparison is ending, but we have still unprocessed unidentified resources left.\r
242                                                 // These cases have longer path than one to identified objects.\r
243                                                 processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);\r
244                                         }\r
245                                 }\r
246                         });\r
247                         \r
248                         \r
249                         \r
250                 }\r
251                 for (Statement s : unreliableLeft) {\r
252                         if (!comparableStatements.containsLeft(s))\r
253                                 addDeletion(s);\r
254                 }\r
255                 for (Statement s : unreliableRight) {\r
256                         if (!comparableStatements.containsRight(s))\r
257                                 addAddition(s);\r
258                 }\r
259                 \r
260                 \r
261         }\r
262         \r
263         private void process(Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Set<Statement> unreliableLeft, Set<Statement> unreliableRight) throws DatabaseException {\r
264                 List<Statement> ss1 = new ArrayList<Statement>();\r
265                 List<Statement> ss2 = new ArrayList<Statement>();\r
266                 \r
267                 while (!objectsLeft.isEmpty()) {\r
268                         Resource r1 = objectsLeft.pop();\r
269                         Resource r2 = objectsRight.pop();\r
270                         \r
271                         if (r1.equals(r2))\r
272                                 continue;\r
273                         \r
274                         if (processedResources.contains(r1))\r
275                                 continue;\r
276                         processedResources.add(r1);\r
277                         \r
278                 \r
279                         if((comparableResources.containsLeft(r1)||comparableResources.containsRight(r2)) && !comparableResources.contains(r1, r2)) {\r
280                                 throw new DatabaseException("Comparator error: Trying to map " + r1 + " to " + r2 + " while mappings " + r1 + " to " + comparableResources.getRight(r1) + " and " + comparableResources.getLeft(r2) + " to " + r2 + " exist.");\r
281                         }\r
282                         addComparable(r1, r2, false);\r
283                         \r
284                         //System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
285                         compareProps(r1, r2);\r
286                         \r
287                         for (Resource rel : tested) {\r
288                                 ss1.addAll(g.getStatements(r1, rel));\r
289                                 ss2.addAll(g.getStatements(r2, rel));\r
290                                 ss1 = filterAsserted(r1, ss1);\r
291                                 ss2 = filterAsserted(r2, ss2);\r
292                                 ss1 = filterTraversed(ss1);\r
293                                 ss2 = filterTraversed(ss2);\r
294                                 ss1 = filterNonTested(ss1);\r
295                                 ss2 = filterNonTested(ss2);\r
296                                 \r
297                                 \r
298                                 compareStatements(ss1, ss2, null, null,null,null);\r
299                                 ss1.clear();\r
300                                 ss2.clear();\r
301                         }\r
302                         \r
303                         for (Resource rel : traversed) {\r
304                                 ss1.addAll(g.getStatements(r1, rel));\r
305                                 ss2.addAll(g.getStatements(r2, rel));\r
306                                 ss1 = filterAsserted(r1, ss1);\r
307                                 ss2 = filterAsserted(r2, ss2);\r
308                                 ss1 = filterNonTraversed(ss1);\r
309                                 ss2 = filterNonTraversed(ss2);\r
310                                 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);\r
311                                 ss1.clear();\r
312                                 ss2.clear();\r
313                                 \r
314                         }\r
315                 }\r
316         }\r
317         \r
318         private void processUnreliable(Set<Statement> unreliableLeft, Set<Statement> unreliableRight) throws DatabaseException {\r
319                 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();\r
320                 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();\r
321                 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();\r
322                 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();\r
323                 \r
324                 for (Statement s : unreliableLeft) {\r
325                         subjectLeft.add(s.getSubject(),s);\r
326                         objectLeft.add(s.getObject(),s);\r
327                 }\r
328                 for (Statement s : unreliableRight) {\r
329                         subjectRight.add(s.getSubject(),s);\r
330                         objectRight.add(s.getObject(),s);\r
331                 }\r
332                 \r
333                 for (Resource left : subjectLeft.getKeys()) {\r
334                         if (!comparableResources.containsLeft(left))\r
335                                 continue;\r
336                         Resource right = comparableResources.getRight(left);\r
337                         for (Statement leftS : subjectLeft.getValues(left)) {\r
338                                 Resource leftO = leftS.getObject();\r
339                                 if (!comparableResources.containsLeft(leftO)) \r
340                                         continue;\r
341                                 if (!unreliableLeft.contains(leftS))\r
342                                         continue;\r
343                                 Resource rightO = comparableResources.getRight(leftO);\r
344                                 for (Statement rightS : subjectRight.getValues(right)) {\r
345                                         if (!rightS.getObject().equals(rightO))\r
346                                                 continue;\r
347                                         if (!unreliableRight.contains(rightS))\r
348                                                 continue;\r
349                                         if (leftS.getPredicate().equals(rightS.getPredicate()) ||\r
350                                                 comparableResources.contains(leftS.getPredicate(), rightS.getPredicate())) {\r
351                                                 unreliableLeft.remove(leftS);\r
352                                                 unreliableRight.remove(rightS);\r
353                                                 addComparable(leftS, rightS, false);\r
354                                         }\r
355                                 }\r
356                         }               \r
357                 }\r
358         }\r
359         \r
360         private void processUnreliable(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {\r
361                 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();\r
362                 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();\r
363                 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();\r
364                 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();\r
365                 \r
366                 for (Statement s : unreliableLeft) {\r
367                         subjectLeft.add(s.getSubject(),s);\r
368                         objectLeft.add(s.getObject(),s);\r
369                 }\r
370                 for (Statement s : unreliableRight) {\r
371                         subjectRight.add(s.getSubject(),s);\r
372                         objectRight.add(s.getObject(),s);\r
373                 }\r
374                 \r
375                 for (Resource ol : objectLeft.getKeys()) {\r
376                         // all statements to the left side object\r
377                         List<Statement> left = objectLeft.getValues(ol);\r
378                         // all subjects that have statements to the left side object (ol)\r
379                         Set<Resource> sLeft = new HashSet<Resource>();\r
380                         // all matching subjects on the right side\r
381                         Set<Resource> sRight = new HashSet<Resource>();\r
382                         for (Statement s : left) {\r
383                                 sLeft.add(s.getSubject());\r
384                                 sRight.add(comparableResources.getRight(s.getSubject()));\r
385                         }\r
386                         \r
387                         // check if object left can be reliably identified by available statements\r
388                         // if there are any objects on the left side with similar statements, object left cannot be mapped.\r
389                         boolean hasSimilar = false;\r
390                         MapList<Resource, Statement> comparableOLeft = new MapList<Resource, Statement>();\r
391                         for (Resource sl : sLeft) {\r
392                                 for (Statement s : subjectLeft.getValues(sl)) {\r
393                                         if (!s.getObject().equals(ol)) {\r
394                                                 comparableOLeft.add(s.getObject(),s);\r
395                                         }\r
396                                 }\r
397                         }\r
398                         \r
399                         for (Resource similarOl : comparableOLeft.getKeys()) {\r
400                                 List<Statement> similarLeft = comparableOLeft.getValues(similarOl);\r
401                                 if (similarLeft.size() == left.size()) {\r
402                                         boolean useL[] = new boolean[left.size()];\r
403                                         boolean useSL[] = new boolean[left.size()];\r
404                                         for (int i = 0; i < left.size(); i++) {\r
405                                                 useL[i] = false;\r
406                                                 useSL[i] = false;\r
407                                         }\r
408                                         for (int i = 0; i < left.size(); i++) {\r
409                                                 for (int j = 0; j < left.size(); j++) {\r
410                                                         if (useSL[j])\r
411                                                                 continue;\r
412                                                         Resource pl = left.get(i).getPredicate();\r
413                                                         Resource psl = similarLeft.get(j).getPredicate();\r
414                                                         if (pl.equals(psl)) {\r
415                                                                 useL[i] = true;\r
416                                                                 useSL[j] = true;\r
417                                                                 break;\r
418                                                         }\r
419                                                 }\r
420                                         }\r
421                                         boolean diff = false;\r
422                                         for (int i = 0; i < left.size(); i++) {\r
423                                                 if (!useL[i] || !useSL[i]) {\r
424                                                         diff = true;\r
425                                                 }\r
426                                         }\r
427                                         if (!diff) {\r
428                                                 hasSimilar = true;\r
429                                                 break;\r
430                                         }\r
431                                 }\r
432                         }\r
433                         \r
434                         if (hasSimilar)\r
435                                 continue;\r
436                                 \r
437                         \r
438                         // all objects that subjects on the right side point to. Object left has its matching resource among these, if it has matching resource\r
439                         MapList<Resource,Statement> possibleOR = new MapList<Resource, Statement>();\r
440                         for (Resource sr : sRight) {\r
441                                 for (Statement s : subjectRight.getValues(sr))\r
442                                         possibleOR.add(s.getObject(),s);\r
443                         }\r
444                         \r
445                         // filter possible right side objects to those that have same amount of statements as the left side object\r
446                         for (Resource or : possibleOR.getKeys().toArray(new Resource[possibleOR.getKeys().size()])) {\r
447                                 List<Statement> right = possibleOR.getValues(or);\r
448                                 if (right.size() != left.size())\r
449                                         possibleOR.remove(or);\r
450                                         \r
451                         }\r
452                         \r
453                         // check for matching statements (comparable subjects, matching predicates)\r
454                         MapList<Resource,Statement> matchingOR = new MapList<Resource, Statement>(); // list of objects that have matching statements\r
455                         Map<Resource,Pair<int[], int[]>> matchingStatements = new HashMap<Resource, Pair<int[], int[]>>(); // matching statements\r
456                         for (Resource or : possibleOR.getKeys()) {\r
457                                 List<Statement> right = possibleOR.getValues(or);\r
458                                 int iLeft[] = new int[left.size()];\r
459                                 int iRight[] = new int[right.size()];\r
460                                 \r
461                                 for (int i = 0; i < left.size(); i++) {\r
462                                         iLeft[i] = -1;\r
463                                         iRight[i] = -1;\r
464                                 }\r
465                                 \r
466                                 for (int l = 0; l < left.size(); l++) {\r
467                                         Statement ls = left.get(l);\r
468                                         for (int r = 0; r < right.size(); r++) {\r
469                                                 if (iRight[r] >= 0)\r
470                                                         continue;\r
471                                                 Statement rs = right.get(r);\r
472                                                 if (!comparableResources.contains(ls.getSubject(), rs.getSubject()))\r
473                                                         continue;\r
474                                                 if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) {\r
475                                                         iLeft[l] = r;\r
476                                                         iRight[r] = l;\r
477                                                         break;\r
478                                                 }\r
479                                         }\r
480                                         \r
481                                 }\r
482                                 boolean success = true;\r
483                                 for (int i = 0; i < left.size(); i++) {\r
484                                         if (iLeft[i] < 0) {\r
485                                                 success = false;\r
486                                                 break;\r
487                                         }\r
488                                         if (iRight[i] < 0) {\r
489                                                 success = false;\r
490                                                 break;\r
491                                         }\r
492                                                 \r
493                                 }\r
494                                 if (success) {\r
495                                         for (Statement s : right) \r
496                                                 matchingOR.add(or,s);\r
497                                         matchingStatements.put(or, new Pair<int[], int[]>(iLeft, iRight));\r
498                                 }\r
499                         }\r
500                         // if there is only one matching right side object, we have found a match \r
501                         if (matchingOR.getKeySize() == 1) {\r
502                                 Resource or = matchingOR.getKeys().iterator().next();\r
503                                 List<Statement> right = matchingOR.getValues(or);\r
504                                 Pair<int[], int[]> indices = matchingStatements.get(or);\r
505                                 \r
506                                 objectsLeft.add(ol);\r
507                                 objectsRight.add(or);\r
508                                 addComparable(ol, or, false);\r
509                                 for (int l = 0; l < left.size(); l++) {\r
510                                         int r = indices.first[l];\r
511                                         Statement sl = left.get(l);\r
512                                         Statement sr = right.get(r);\r
513                                         addComparable(sl, sr, true);\r
514                                         unreliableLeft.remove(sl);\r
515                                         unreliableRight.remove(sr);\r
516                                 }\r
517                                 \r
518                         }\r
519 \r
520                 }\r
521                 \r
522                 \r
523         }\r
524         \r
525         private void processUnreliableDeep(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {\r
526                 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();\r
527                 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();\r
528                 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();\r
529                 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();\r
530                 \r
531                 for (Statement s : unreliableLeft) {\r
532                         subjectLeft.add(s.getSubject(),s);\r
533                         objectLeft.add(s.getObject(),s);\r
534                 }\r
535                 for (Statement s : unreliableRight) {\r
536                         subjectRight.add(s.getSubject(),s);\r
537                         objectRight.add(s.getObject(),s);\r
538                 }\r
539                 for (Resource ol : objectLeft.getKeys()) {\r
540                         Set<Path> pathsLeft = new HashSet<Path>();\r
541                         for (Resource rel : traversed) {\r
542                                 pathsLeft.addAll(Path.create(g.getStatements(ol, rel)));\r
543                         }\r
544                         while (true) {\r
545                                 expand(pathsLeft);\r
546                                 if (pathsLeft.size() == 0)\r
547                                         break;\r
548                                 Collection<Path> endPaths = new ArrayList<Path>(1);\r
549                                 for (Path p : pathsLeft) {\r
550                                         if (comparableResources.containsLeft(p.getEnd())) {\r
551                                                 endPaths.add(p);\r
552                                         }\r
553                                 }\r
554                                 if (endPaths.size() > 0) {\r
555                                         pathsLeft.clear();\r
556                                         pathsLeft.addAll(endPaths);\r
557                                         break;\r
558                                 }       \r
559                         }\r
560                         if (pathsLeft.size() > 0) {\r
561                                 Resource sl = objectLeft.getValues(ol).get(0).getSubject();\r
562                                 Resource sr = comparableResources.getRight(sl);\r
563                                 Collection<Resource> possibleOR = new ArrayList<Resource>();\r
564                                 for (Statement s : subjectRight.getValues(sr)) {\r
565                                         possibleOR.add(s.getObject());\r
566                                 }\r
567                                 Map<Resource,Set<Path>> matchingPaths = new HashMap<Resource, Set<Path>>();\r
568                                 for (Resource or : possibleOR) {\r
569                                         Set<Path> possiblePathsRight = new HashSet<Path>();\r
570                                         for (Path leftPath : pathsLeft) {\r
571                                                 possiblePathsRight.addAll(findComparableRight(leftPath, or));\r
572                                         }\r
573                                         if (hasMatchingPaths(pathsLeft, possiblePathsRight)) {\r
574                                                 matchingPaths.put(or, possiblePathsRight);\r
575                                         }\r
576                                 }\r
577                                 if (matchingPaths.size() > 0) {\r
578                                         if (matchingPaths.size() == 1) {\r
579                                                 Resource or = matchingPaths.keySet().iterator().next();\r
580                                                 \r
581                                                 objectsLeft.add(ol);\r
582                                                 objectsRight.add(or);\r
583                                                 addComparable(ol, or, false);\r
584                                                 Collection<Statement> statementsLeft = objectLeft.getValues(ol);\r
585                                                 Collection<Statement> statementsRight = objectRight.getValues(or);\r
586                                                 unreliableLeft.removeAll(statementsLeft);\r
587                                                 unreliableRight.removeAll(statementsRight);\r
588                                                 BijectionMap<Path,Path> map = getMatchingPaths(pathsLeft, matchingPaths.get(or));\r
589                                                 for (Path left : map.getLeftSet()) {\r
590                                                         Path right = map.getRight(left);\r
591                                                         for (int i = 0; i < left.getLength(); i++) {\r
592                                                                 addComparable(left.getStatements().get(i),right.getStatements().get(i),false);\r
593                                                         }\r
594                                                 }\r
595                                         } \r
596                                 }\r
597                         }\r
598                         \r
599                 }\r
600                 \r
601         }\r
602         \r
603         private boolean hasMatchingPaths(Set<Path> leftPaths, Set<Path> rightPaths) {\r
604                 if (leftPaths.size() != rightPaths.size())\r
605                         return false;\r
606                 BijectionMap<Path,Path> map = getMatchingPaths(leftPaths, rightPaths);\r
607                 return map.size() == leftPaths.size();\r
608         }\r
609         \r
610         private BijectionMap<Path,Path> getMatchingPaths(Set<Path> leftPaths, Set<Path> rightPaths) {\r
611                 BijectionMap<Path,Path> map = new BijectionMap<Path, Path>();\r
612                 for (Path leftPath : leftPaths) {\r
613                         for (Path rightPath : rightPaths) {\r
614                                 if (map.containsRight(rightPath))\r
615                                         continue;\r
616                                 if (leftPath.getLength() != rightPath.getLength())\r
617                                         continue;\r
618                                 if (comparableResources.contains(leftPath.getEnd(), rightPath.getEnd())) {\r
619                                         map.map(leftPath, rightPath);\r
620                                         break;\r
621                                 }\r
622                         }\r
623                 }\r
624                 return map;\r
625         }\r
626         \r
627         private void expand(Set<Path> paths) throws DatabaseException {\r
628                 Set<Path> stepPathsLeft = new HashSet<Path>();\r
629                 if (paths.size() == 0)\r
630                         return;\r
631                 int length = paths.iterator().next().getLength() + 1;\r
632                 for (Path p : paths) {\r
633                         for (Resource rel : traversed) {\r
634                                 stepPathsLeft.addAll(Path.expand(p,g.getStatements(p.getEnd(), rel)));\r
635                         }\r
636                 }\r
637                 paths.clear();\r
638                 for (Path p : stepPathsLeft) {\r
639                         if (p.getLength() == length)\r
640                                 paths.add(p);\r
641                 }\r
642         }\r
643         \r
644         private Collection<Path> findComparableRight(Path leftPath, Resource beginRight) throws DatabaseException {\r
645                 Set<Path> rightPaths = new HashSet<Path>();\r
646                 rightPaths.addAll(Path.create(g.getStatements(beginRight, getRight(leftPath.getStatements().get(0).getPredicate()))));\r
647                 for (int i = 1; i < leftPath.getLength(); i++) {\r
648                         if (rightPaths.size() == 0)\r
649                                 return rightPaths;\r
650                         Set<Path> stepPaths = new HashSet<Path>();\r
651                         for (Path p : rightPaths) {\r
652                                 stepPaths.addAll(Path.expand(p, g.getStatements(p.getEnd(), getRight(leftPath.getStatements().get(i).getPredicate()))));\r
653                         }\r
654                         rightPaths.clear();\r
655                         for (Path p : stepPaths)\r
656                                 if (p.getLength() == i+1) \r
657                                         rightPaths.add(p);\r
658                 }\r
659                 return rightPaths;\r
660                 \r
661         }\r
662         \r
663         private Resource getRight(Resource r) {\r
664                 if (comparableResources.containsLeft(r))\r
665                         return comparableResources.getRight(r);\r
666                 return r;\r
667         }\r
668         \r
669 \r
670         \r
671         public BijectionMap<Statement, Statement> getComparableStatements() {\r
672                 return comparableStatements;\r
673         }\r
674         \r
675         public BijectionMap<Resource, Resource> getComparableResources() {\r
676                 return comparableResources;\r
677         }\r
678         \r
679         public GraphChanges getChanges() {\r
680                 return new GraphChanges(r1,r2,changes1,changes2,modifications,comparableResources);\r
681         }\r
682         \r
683         private void addComparable(Statement left, Statement right, boolean process) throws DatabaseException {\r
684                 addComparable(left.getObject(), right.getObject(), process);\r
685                 comparableStatements.map(left, right);\r
686                 //comparableResources.map(left.getObject(), right.getObject());\r
687         }\r
688         \r
689         private void addComparable(Resource left, Resource right, boolean process) throws DatabaseException {\r
690                 if(!comparableResources.contains(left, right)) {\r
691                         if (comparableResources.containsLeft(left)||comparableResources.containsRight(right)) {\r
692                                 throw new DatabaseException("Comparator error: Trying to map " + left + " to " + right + " while mappings " + left + " to " + comparableResources.getRight(left) + " and " + comparableResources.getLeft(right) + " to " + right + " exist.");\r
693                         } else {\r
694                                 if (DEBUG) System.out.println(left + " = " + right);\r
695                                 comparableResources.map(left, right);           \r
696                         }\r
697                 }\r
698                 \r
699         }\r
700         \r
701         public List<Statement> filterAsserted(Resource r, Collection<Statement> in) throws DatabaseException {\r
702                 List<Statement> out = new ArrayList<Statement>();\r
703                 for (Statement s : in) {\r
704                         if (!s.isAsserted(r))\r
705                                 out.add(s);\r
706                         \r
707                 }\r
708                 return out;\r
709         }\r
710         \r
711         \r
712 \r
713         private String printStatement(ReadGraph graph, Statement s) throws DatabaseException {\r
714                 return NameUtils.getSafeName(graph, s.getSubject()) + " " + NameUtils.getSafeName(graph, s.getPredicate()) + " " + NameUtils.getSafeName(graph, s.getObject());\r
715         }\r
716         \r
717         private List<Statement> filterTraversed(List<Statement> in) throws DatabaseException {\r
718                 return filter(traversed, in);\r
719         }\r
720         \r
721         private List<Statement> filterNonTested(List<Statement> in) throws DatabaseException {\r
722                 return filter(nonTested, in);\r
723         }\r
724         \r
725         private List<Statement> filterNonTraversed(List<Statement> in) throws DatabaseException {\r
726                 return filter(nonTraversed, in);\r
727         }\r
728         \r
729         private List<Statement> filter(Collection<Resource> toFilter, List<Statement> in) throws DatabaseException {\r
730                 if (toFilter.size() == 0)\r
731                         return in;\r
732                 List<Statement> out = new ArrayList<Statement>();\r
733                 for (Statement s : in) {\r
734                         boolean usable = true;\r
735                         for (Resource r : toFilter) {\r
736                                 if (g.isSubrelationOf(s.getPredicate(),r)) {\r
737                                         usable = false;\r
738                                         break;\r
739                                 }\r
740                         }\r
741                         if (usable) {\r
742                                 out.add(s);\r
743                         }\r
744                         \r
745                 }\r
746                 return out;\r
747         }\r
748         \r
749         \r
750         private void addDeletion(Statement s) {\r
751                 if (!changes1Set.contains(s)) {\r
752                         changes1Set.add(s);\r
753                         changes1.add(s);\r
754                 }\r
755         }\r
756         \r
757         private void addAddition(Statement s) {\r
758                 if (!changes2Set.contains(s)) {\r
759                         changes2Set.add(s);\r
760                         changes2.add(s);\r
761                 }\r
762         }\r
763         \r
764         private void addModification(Statement s1, Statement s2) {\r
765                 Pair<Statement, Statement> mod = new Pair<Statement, Statement>(s1,s2);\r
766                 if (!modificationsSet.contains(mod)) {\r
767                         modificationsSet.add(mod);\r
768                         modifications.add(mod);\r
769                 }\r
770         }\r
771         \r
772         public void sortStatement(List<Statement> list1, List<Statement> list2) {\r
773                 sortStatement(list1, list2, scomp);\r
774         }\r
775         \r
776         public void sortStatement(List<Statement> list1, List<Statement> list2, Comparator<Statement> scomp) {\r
777                 Collections.sort(list1,scomp);\r
778                 Collections.sort(list2,scomp);\r
779                 \r
780                 List<Statement> sorted1 = new ArrayList<Statement>(list1.size());\r
781                 List<Statement> sorted2 = new ArrayList<Statement>(list2.size());\r
782                 sorted1.addAll(list1);\r
783                 sorted2.addAll(list2);\r
784                 \r
785                 int ss1 = 0;\r
786                 int ss2 = 0;\r
787                 for (int i = 0; i < list1.size(); ) {\r
788                         Statement s1 = list1.get(i);\r
789                         int same1 = sameRel(list1, i);  \r
790                         for (int j = 0; j < list2.size(); j++) {\r
791                                 Statement s2 = list2.get(j);\r
792                                 if (scomp.compare(s1, s2) == 0) {\r
793                                         int same2 = sameRel(list2, j);\r
794                                         copy(sorted1,ss1,list1,i,same1);\r
795                                         ss1 += same1;\r
796                                         copy(sorted2,ss2,list2,j,same2);\r
797                                         ss2 += same2;\r
798                                         break;\r
799                                 }\r
800                         }\r
801                         i+= same1;\r
802                 }\r
803                 if (ss1 < sorted1.size()) {\r
804                         for (Statement s : list1) {\r
805                                 if (!sorted1.contains(s)) {\r
806                                         sorted1.set(ss1,s);\r
807                                         ss1++;\r
808                                 }\r
809                         }\r
810                 }\r
811                 if (ss2 < sorted2.size()) {\r
812                         for (Statement s : list2) {\r
813                                 if (!sorted2.contains(s)) {\r
814                                         sorted2.set(ss2,s);\r
815                                         ss2++;\r
816                                 }\r
817                         }\r
818                 }\r
819                 \r
820                 list1.clear();\r
821                 list2.clear();\r
822                 list1.addAll(sorted1);\r
823                 list2.addAll(sorted2);\r
824         }\r
825         \r
826         public <T> void copy(List<T> to, int toIndex, List<T> from, int fromIndex, int amount) {\r
827                 for (int i = 0; i <  amount; i++) {\r
828                         to.set(toIndex + i, from.get(fromIndex+ i));\r
829                 }\r
830         }\r
831         \r
832         public void sortResource(List<Resource> list1, List<Resource> list2) {\r
833                 Collections.sort(list1,rcomp);\r
834                 int js = 0;\r
835                 for (int i = 0; i < list1.size(); i++) {\r
836                         Resource s1 = list1.get(i);\r
837                         for (int j = js; j < list2.size(); j++) {\r
838                                 Resource s2 = list2.get(j);\r
839                                 if (rcomp.compare(s1, s2) == 0) {\r
840                                         Resource t = list2.get(js);\r
841                                         list2.set(js, s2);\r
842                                         list2.set(j, t);\r
843                                         break;\r
844                                 }\r
845                         }\r
846                         js++;\r
847                 }\r
848         }\r
849         \r
850         private void compareStatements(List<Statement> ss1, List<Statement> ss2, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Collection<Statement> unreliableLeft, Collection<Statement> unreliableRight) throws DatabaseException {\r
851                 sortStatement(ss1, ss2);\r
852                 \r
853                 int i1 = 0;\r
854                 int i2 = 0;\r
855                 \r
856                 while (true) {\r
857                         if (i1 >= ss1.size()) {\r
858                                 if (i2 >= ss2.size()) {\r
859                                         break;\r
860                                 } else {\r
861                                         while (i2 < ss2.size()) {\r
862                                                 if (DEBUG) System.out.println("Compare Statements addition " + printStatement(g,ss2.get(i2)));\r
863                                                 \r
864                                                 addAddition(ss2.get(i2));\r
865                                                 i2++;\r
866                                         }\r
867                                         break;\r
868                                 }\r
869                         } else if (i2 >= ss2.size()) {\r
870                                 while (i1 < ss1.size()) {\r
871                                         if (DEBUG) System.out.println("Compare Statements deletion " + printStatement(g,ss1.get(i1)));\r
872                                         addDeletion(ss1.get(i1));\r
873                                         i1++;\r
874                                 }\r
875                                 break;\r
876                         }\r
877                         int same1 = sameRel(ss1, i1);\r
878                         int same2 = sameRel(ss2, i2);\r
879                         int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate());\r
880                         if (c == 0) {\r
881                                 compareStatements(ss1, i1, same1, ss2, i2, same2,objectsLeft,objectsRight,unreliableLeft,unreliableRight);\r
882                                 i1+=same1;\r
883                                 i2+=same2;\r
884                         } else if (c < 0) {\r
885                                 for (int i = 0; i < same1; i++) {\r
886                                         if (DEBUG) System.out.println("Compare Statements deletion " + printStatement(g,ss1.get(i+i1)));\r
887                                         addDeletion(ss1.get(i+i1));\r
888                                 }\r
889                                 i1 += same1;\r
890                         } else {\r
891                                 for (int i = 0; i < same2; i++) {\r
892                                         if (DEBUG) System.out.println("Compare Statements addition " + printStatement(g,ss2.get(i+i2)));\r
893                                         addAddition(ss2.get(i+i2));\r
894                                 }\r
895                                 \r
896                                 i2 += same2;\r
897                         }\r
898                 }\r
899         }\r
900         \r
901 \r
902         \r
903         private int sameRel(List<Statement> statements, int off) {\r
904                 if (statements.size() <= off)\r
905                         return 0;\r
906                 int same = 1;\r
907                 long id = statements.get(off).getPredicate().getResourceId();\r
908                 for (int i = off+1; i <statements.size(); i++) {\r
909                         if (statements.get(i).getPredicate().getResourceId() == id)\r
910                                 same++;\r
911                         else \r
912                                 break;\r
913                 }\r
914                 return same;\r
915                 \r
916         }\r
917 \r
918         private int compareObject(Resource o1, Resource o2) throws DatabaseException {\r
919                 if (o1.equals(o2))\r
920                         return -1;\r
921                 if (comparableResources.contains(o1, o2))\r
922                         return (-1);\r
923                 if (comparableResources.containsLeft(o1))\r
924                         return Integer.MAX_VALUE;\r
925                 if (comparableResources.containsRight(o2))\r
926                         return Integer.MAX_VALUE;\r
927                 return comparator.compare(g, o1, o2);\r
928         }\r
929         \r
930         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
931                 boolean[] used1 = new boolean[len1];\r
932                 for (int i = 0; i < used1.length; i++) {\r
933                         used1[i] = false;\r
934                 }\r
935                 \r
936                 boolean[] used2 = new boolean[len2];\r
937                 for (int i = 0; i < used2.length; i++) {\r
938                         used2[i] = false;\r
939                 }\r
940                 \r
941                 // left, right, difference\r
942                 List<List<Integer>> differences = new ArrayList<List<Integer>>();\r
943                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
944                         Statement s1 = ss1.get(i1);\r
945                         List<Integer> diff = new ArrayList<Integer>();\r
946                         for (int i2 = off2; i2 < off2 + len2; i2++) {\r
947                                 Statement s2 = ss2.get(i2);\r
948                                 int d = compareObject(s1.getObject(), s2.getObject());\r
949                                 if (d == 0) {\r
950                                         for (Resource t : strong) {\r
951                                                  if (s1.getPredicate().equals(t) || g.isSubrelationOf(s1.getPredicate(), t)) {\r
952                                                          d = 1;\r
953                                                          break;\r
954                                                  }\r
955                                         }\r
956                                 }\r
957                                 diff.add(d);\r
958                         }\r
959                         differences.add(diff);\r
960                 }\r
961                 // difference, left\r
962                 MapList<Integer, Integer> priorities = new MapList<Integer, Integer>();\r
963                 for (int i = 0; i < differences.size(); i++) {\r
964                         List<Integer> list = differences.get(i);\r
965                         for (int j = 0; j < list.size(); j++) {\r
966                                 priorities.add(list.get(j), i);\r
967                         }\r
968                 }\r
969                 \r
970                 Integer[] pris = priorities.getKeys(new Integer[]{});\r
971                 Arrays.sort(pris);\r
972                 \r
973                 for (Integer pri : pris) {\r
974                         if (pri == Integer.MAX_VALUE) {\r
975 \r
976                         } else if (pri == 0) {\r
977                                 \r
978                         } else {\r
979                                 List<Integer> i1s = priorities.getValues(pri);\r
980                                 for (Integer i1 : i1s) {\r
981                                         if (used1[i1])\r
982                                                 continue;\r
983                                         List<Integer> i2diff = differences.get(i1);\r
984                                         for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
985                                                 if (i2diff.get(i2) == pri) {\r
986                                                         if (used2[i2])\r
987                                                                 continue;\r
988                                                         used1[i1] = true;\r
989                                                         used2[i2] = true;\r
990                                                         Statement s1  = ss1.get(i1+off1);\r
991                                                         Statement s2  = ss2.get(i2+off2);\r
992                                                         \r
993                                                         if (objectsLeft != null) {\r
994                                                                 objectsLeft.add(s1.getObject());\r
995                                                                 objectsRight.add(s2.getObject());\r
996                                                         } \r
997                                                         addComparable(s1, s2, true);\r
998                                                         break;\r
999                                                 }\r
1000                                         }\r
1001                                 }\r
1002                         }\r
1003                 }\r
1004                 \r
1005                 for (Integer pri : pris) {\r
1006                         if (pri != 0)\r
1007                                 continue;\r
1008                         Set<Statement> s1s = new HashSet<Statement>();\r
1009                         Set<Statement> s2s = new HashSet<Statement>();\r
1010                         Set<Integer> s1i = new HashSet<Integer>();\r
1011                         Set<Integer> s2i = new HashSet<Integer>();\r
1012                         List<Integer> i1s = priorities.getValues(pri);\r
1013                         for (Integer i1 : i1s) {\r
1014                                 if (used1[i1])\r
1015                                         continue;\r
1016                                 List<Integer> i2diff = differences.get(i1);\r
1017                                 for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
1018                                         if (i2diff.get(i2) == pri) {\r
1019                                                 if (used2[i2])\r
1020                                                         continue;\r
1021                                                 Statement s1  = ss1.get(i1+off1);\r
1022                                                 Statement s2  = ss2.get(i2+off2);\r
1023                                                 s1s.add(s1);\r
1024                                                 s2s.add(s2);\r
1025                                                 s1i.add(i1);\r
1026                                                 s2i.add(i2);\r
1027                                         }\r
1028                                 }\r
1029                         }\r
1030                         if (unreliableLeft != null) {\r
1031                                 unreliableLeft.addAll(s1s);\r
1032                                 unreliableRight.addAll(s2s);\r
1033                         }\r
1034                         for (Integer i : s1i)\r
1035                                 used1[i] = true;\r
1036                         for (Integer i : s2i)\r
1037                                 used2[i] = true;\r
1038 \r
1039                 }\r
1040                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
1041                         if (!used1[i1-off1]) {\r
1042                                 if (DEBUG) System.out.println("Compare Object deletion " + printStatement(g,ss1.get(i1)));\r
1043                                 addDeletion(ss1.get(i1));\r
1044                         }\r
1045                 }\r
1046                 for (int i2 = off2; i2 < off2 + len2; i2++) {\r
1047                         if (!used2[i2-off2]) {\r
1048                                 if (DEBUG) System.out.println("Compare Object addition " + printStatement(g,ss2.get(i2)));\r
1049                                 addAddition(ss2.get(i2));\r
1050                         }\r
1051                 }\r
1052         }\r
1053         \r
1054         \r
1055         \r
1056         /**\r
1057          * compares properties, assumes functional relations\r
1058          * @param r1\r
1059          * @param r2\r
1060          * @throws ServiceException\r
1061          * @throws DoesNotContainValueException\r
1062          * @throws ValidationException \r
1063          */\r
1064         private void compareProps(Resource r1, Resource r2) throws DatabaseException {\r
1065                 if (DEBUG) System.out.println("compareProps " + r1 + " " + NameUtils.getSafeName(g, r1) + " " + r2 + " " + NameUtils.getSafeName(g, r2));\r
1066                 ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
1067                 ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
1068                 ss1.addAll(g.getStatements(r1, b.HasProperty));\r
1069                 ss2.addAll(g.getStatements(r2, b.HasProperty));\r
1070                 sortStatement(ss1, ss2);\r
1071                 \r
1072                 int i1 = 0; \r
1073                 int i2 = 0;\r
1074                 \r
1075                 while (true) {\r
1076                         if (i1 >= ss1.size()) {\r
1077                                 if (i2 >= ss2.size())\r
1078                                         break;\r
1079                                 else {\r
1080                                         while (i2 < ss2.size()) {\r
1081                                                 if (DEBUG) System.out.println("Compare Prop diff2 " + printStatement(g,ss2.get(i2)));\r
1082                                                 addAddition(ss2.get(i2));\r
1083                                                 i2++;\r
1084                                         }\r
1085                                         break;\r
1086                                 }\r
1087                         } else if (i2 >= ss2.size()) {\r
1088                                 while (i1 < ss1.size()) {\r
1089                                         if (DEBUG) System.out.println("Compare Prop diff1 " + printStatement(g,ss1.get(i1)));\r
1090                                         addDeletion(ss1.get(i1));\r
1091                                         i1++;\r
1092                                 }\r
1093                                 break;\r
1094                         }\r
1095                         Statement s1 = ss1.get(i1);\r
1096                         Statement s2 = ss2.get(i2);\r
1097                         if (s1.isAsserted(r1) && s2.isAsserted(r2)) {\r
1098                                 i1++;\r
1099                                 i2++;\r
1100                                 continue;\r
1101                         }\r
1102                         int c = scomp.compare(s1, s2);\r
1103                         switch (c) {\r
1104                                 case 0:{\r
1105                                         boolean b1 = g.hasValue(s1.getObject());\r
1106                                         boolean b2 = g.hasValue(s2.getObject());\r
1107                                         if (b1 == b2) {\r
1108                                                 if (b1) {\r
1109                                                         Object v1 = g.getValue(s1.getObject());\r
1110                                                         Object v2 = g.getValue(s2.getObject());\r
1111                                                         boolean eq = compareValue(v1, v2);\r
1112                                                         if (!eq) {\r
1113                                                                 addModification(s1, s2);\r
1114                                                                 addComparable(s1, s2, false);\r
1115                                                         }\r
1116                                                 } else {\r
1117                                                         if (!s1.getObject().equals(s1.getSubject()) && !s2.getObject().equals(s2.getSubject()))\r
1118                                                                 compareProps(s1.getObject(), s2.getObject());\r
1119                                                 }\r
1120                                         } else {\r
1121                                                 addModification(s1, s2);\r
1122                                                 addComparable(s1, s2, false);\r
1123                                         }\r
1124                                         i1++;\r
1125                                         i2++;\r
1126                                         break;\r
1127                                 }\r
1128                                 case -1:{\r
1129                                         if (DEBUG) System.out.println("Compare Prop diff1s " + printStatement(g,s1));\r
1130                                         addDeletion(s1);\r
1131                                         i1++;\r
1132                                         break;\r
1133                                 }\r
1134                                         \r
1135                                 case 1:{\r
1136                                         if (DEBUG) System.out.println("Compare Prop diff2s " + printStatement(g,s2));\r
1137                                         addAddition(s2);\r
1138                                         i2++;\r
1139                                         break;\r
1140                                 }\r
1141                         }\r
1142 \r
1143                 }\r
1144                 \r
1145                 ss1.clear();\r
1146                 ss2.clear();\r
1147                 \r
1148         }\r
1149         \r
1150         public static boolean compareValue(Object v1, Object v2) {\r
1151                 if (v1 instanceof Object[] && v2 instanceof Object[])\r
1152                         return Arrays.deepEquals((Object[])v1, (Object[])v2);\r
1153                 else if (v1 instanceof int[] && v2 instanceof int[]) \r
1154                         return Arrays.equals((int[])v1, (int[])v2);\r
1155                 else if (v1 instanceof float[] && v2 instanceof float[]) \r
1156                         return Arrays.equals((float[])v1, (float[])v2);\r
1157                 else if (v1 instanceof double[] && v2 instanceof double[]) \r
1158                         return Arrays.equals((double[])v1, (double[])v2);\r
1159                 else if (v1 instanceof long[] && v2 instanceof long[]) \r
1160                         return  Arrays.equals((long[])v1, (long[])v2);\r
1161                 else if (v1 instanceof byte[] && v2 instanceof byte[]) \r
1162                         return Arrays.equals((byte[])v1, (byte[])v2);\r
1163                 else if (v1 instanceof boolean[] && v2 instanceof boolean[]) \r
1164                         return Arrays.equals((boolean[])v1, (boolean[])v2);\r
1165                 else\r
1166                         return v1.equals(v2);\r
1167         }\r
1168 \r
1169         \r
1170         public class PredicateComparator implements Comparator<Statement> {\r
1171                 @Override\r
1172                 public int compare(Statement o1, Statement o2) {\r
1173                         if (comparableResources.contains(o1.getPredicate(), o2.getPredicate()))\r
1174                                 return 0;\r
1175                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
1176                                 return -1;\r
1177                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
1178                                 return 1;\r
1179                         return 0;\r
1180                 }\r
1181         }\r
1182         \r
1183         public class SubjectComparator implements Comparator<Statement> {\r
1184                 @Override\r
1185                 public int compare(Statement o1, Statement o2) {\r
1186                         if (comparableResources.contains(o1.getSubject(), o2.getSubject()))\r
1187                                 return 0;\r
1188                         if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
1189                                 return -1;\r
1190                         if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
1191                                 return 1;\r
1192                         return 0;\r
1193                 }\r
1194         }\r
1195         \r
1196         public class ObjectComparator implements Comparator<Statement> {\r
1197                 @Override\r
1198                 public int compare(Statement o1, Statement o2) {\r
1199                         if (comparableResources.contains(o1.getObject(), o2.getObject()))\r
1200                                 return 0;\r
1201                         if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
1202                                 return -1;\r
1203                         if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
1204                                 return 1;\r
1205                         return 0;\r
1206                 }\r
1207         }\r
1208         \r
1209         public static class FullStatementComparator implements Comparator<Statement> {\r
1210                 @Override\r
1211                 public int compare(Statement o1, Statement o2) {\r
1212                         if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
1213                                 return -1;\r
1214                         if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
1215                                 return 1;\r
1216                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
1217                                 return -1;\r
1218                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
1219                                 return 1;\r
1220                         if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
1221                                 return -1;\r
1222                         if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
1223                                 return 1;\r
1224                         return 0;\r
1225                 }\r
1226         }\r
1227         \r
1228         public class ResComparator implements Comparator<Resource> {\r
1229                 @Override\r
1230                 public int compare(Resource o1, Resource o2) {\r
1231                         if (comparableResources.contains(o1, o2))\r
1232                                 return 0;\r
1233                         if (o1.getResourceId() < o2.getResourceId())\r
1234                                 return -1;\r
1235                         if (o1.getResourceId() > o2.getResourceId())\r
1236                                 return 1;\r
1237                         return 0;\r
1238                 }\r
1239         }\r
1240 \r
1241 }\r