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