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