1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * Foster Wheeler Energia Oy - initial API and implementation
11 * VTT Technical Research Centre of Finland - Improvements to comparison.
12 * Semantum Oy - Improvements to comparison, various bug fixes.
13 *******************************************************************************/
14 package org.simantics.interop.test;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
25 import java.util.Map.Entry;
27 import java.util.Stack;
29 import org.simantics.databoard.Bindings;
30 import org.simantics.db.ReadGraph;
31 import org.simantics.db.Resource;
32 import org.simantics.db.Session;
33 import org.simantics.db.Statement;
34 import org.simantics.db.common.request.ReadRequest;
35 import org.simantics.db.common.utils.NameUtils;
36 import org.simantics.db.exception.DatabaseException;
37 import org.simantics.db.request.Read;
38 import org.simantics.interop.test.GraphChanges.Modification;
39 import org.simantics.layer0.Layer0;
40 import org.simantics.utils.datastructures.BijectionMap;
41 import org.simantics.utils.datastructures.MapList;
42 import org.simantics.utils.datastructures.Pair;
45 * Compares two subgraphs and reports differences.
47 * Assumes that subgraphs (defined using traverse relations) are not cyclic.
49 * Assumes that properties can be used to identify objects, if relation type is not enough.
53 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
56 public class GraphComparator {
58 private static final boolean DEBUG = false;
62 private Set<Resource> strong = new HashSet<>(); // List of relations that identify object, if subject is already identified.
63 private List<Resource> traversed = new ArrayList<>(); // list of relations that are traversed (and tested)
64 private List<Resource> tested = new ArrayList<>(); // list of relations that are tested, but not traversed
65 private List<Resource> nonTraversed = new ArrayList<>(); // list of relations that are not traversed
66 private List<Resource> nonTested = new ArrayList<>(); // list of relations that are not tested
68 private List<Statement> changes1 = new ArrayList<>();
69 private List<Statement> changes2 = new ArrayList<>();
70 private List<Modification> modifications = new ArrayList<>();
71 private Set<Statement> changes1Set = new HashSet<>();
72 private Set<Statement> changes2Set = new HashSet<>();
73 private Set<Modification> modificationsSet = new HashSet<>();
75 private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<>();
76 private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<>();
78 private Set<Resource> processedResources = new HashSet<Resource>();
80 private ResourceComparator comparator;
82 private Comparator<Statement> scomp = new PredicateComparator();
83 private Comparator<Resource> rcomp = new ResComparator();
85 private Set<Resource> nonMatchedLeft = new HashSet<Resource>();
86 private Set<Resource> nonMatchedRight = new HashSet<Resource>();
93 public GraphComparator(Resource r1, Resource r2) {
96 comparator = new TypeComparator();
99 public GraphComparator(Resource r1, Resource r2, ResourceComparator comparator) {
102 this.comparator = comparator;
105 ArrayList<Statement> ss1 = new ArrayList<Statement>();
106 ArrayList<Statement> ss2 = new ArrayList<Statement>();
109 public Comparator<Resource> getResourceComparator() {
113 public Comparator<Statement> getStatementComparator() {
117 public Resource getR1() {
121 public Resource getR2() {
125 public void addTraversed(Resource rel) {
129 public void addTraversed(Collection<Resource> rels) {
130 traversed.addAll(rels);
133 public void addNonTraversed(Resource rel) {
134 nonTraversed.add(rel);
137 public void addNonTraversed(Collection<Resource> rels) {
138 nonTraversed.addAll(rels);
141 public void addTested(Resource rel) {
145 public void addTested(Collection<Resource> rels) {
149 public void addNonTested(Resource rel) {
153 public void addNonTested(Collection<Resource> rels) {
154 nonTested.addAll(rels);
157 public void addComparableResources(Resource r1, Resource r2) {
159 System.out.println("Preset " + r1 + " = " + r2);
160 comparableResources.map(r1, r2);
163 public void addComparableResources(BijectionMap<Resource, Resource> matching) {
165 for (Entry<Resource, Resource> entry : matching.getEntries())
166 System.out.println("Preset " + entry.getKey() + " = " + entry.getValue());
168 comparableResources.addAll(matching);
171 public void addStrong(Resource r) {
175 public void addStrong(Collection<Resource> rels) {
179 public void addNonMatchedLeft(Resource r) {
180 nonMatchedLeft.add(r);
183 public void addNonMatchedRight(Resource r) {
184 nonMatchedRight.add(r);
187 public void test(ReadGraph g) throws DatabaseException {
189 this.b = Layer0.getInstance(g);
190 comparator.setComparator(this);
191 comparator.initialize(g, r1, r2);
193 Stack<Resource> objectsLeft = new Stack<Resource>();
194 Stack<Resource> objectsRight = new Stack<Resource>();
195 objectsLeft.push(r1);
196 objectsRight.push(r2);
198 Set<Statement> unreliableLeft = new HashSet<Statement>();
199 Set<Statement> unreliableRight = new HashSet<Statement>();
201 boolean changed = false;
203 if (objectsLeft.isEmpty() && !changed)
207 // process compares objects that are identified and searches for more resources to process.
208 changed |= process(objectsLeft, objectsRight, unreliableLeft, unreliableRight);
209 // process unreliable handles cases where unidentified statements subject and object have been identified
210 changed |= processUnreliable(unreliableLeft, unreliableRight);
211 // process unreliable handles cases where unidentified resources have path of length one to identified resource
212 changed |= processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight);
213 if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
214 changed |= processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight);
216 if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
217 // comparison is ending, but we have still unprocessed unidentified resources left.
218 // These cases have longer path than one to identified objects.
219 changed |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);
223 for (Statement s : unreliableLeft) {
224 if (!comparableStatements.containsLeft(s)) {
225 if (DEBUG) System.out.println("Unreliable Object deletion " + printStatement(g,s));
229 for (Statement s : unreliableRight) {
230 if (!comparableStatements.containsRight(s)) {
231 if (DEBUG) System.out.println("Unreliable Object addition " + printStatement(g,s));
237 public void test(Session session) throws DatabaseException {
238 test(session, r1, r2);
241 public void test(Session session, Resource r1, Resource r2) throws DatabaseException {
243 comparator.setComparator(this);
245 session.syncRequest(new ReadRequest() {
248 public void run(ReadGraph graph) throws DatabaseException {
249 comparator.initialize(graph, r1, r2);
253 addComparable(r1, r2);
255 final Stack<Resource> objectsLeft = new Stack<Resource>();
256 final Stack<Resource> objectsRight = new Stack<Resource>();
257 objectsLeft.push(r1);
258 objectsRight.push(r2);
260 final Set<Statement> unreliableLeft = new HashSet<Statement>();
261 final Set<Statement> unreliableRight = new HashSet<Statement>();
263 boolean changed = false;
265 if (objectsLeft.isEmpty() && !changed)
267 changed = session.syncRequest(new Read<Boolean>() {
270 public Boolean perform(ReadGraph graph) throws DatabaseException {
272 b = Layer0.getInstance(graph);
273 // process compares objects that are identified and searches for more resources to process.
274 boolean c = process(objectsLeft, objectsRight, unreliableLeft, unreliableRight);
275 // process unreliable handles cases where unidentified statements subject and object have been identified
276 c |= processUnreliable(unreliableLeft, unreliableRight);
277 // process unreliable handles cases where unidentified resources have path of length one to identified resource
278 c |= processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight);
279 if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
280 c |= processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight);
282 if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
283 // comparison is ending, but we have still unprocessed unidentified resources left.
284 // These cases have longer path than one to identified objects.
285 c |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);
287 if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
288 // comparison is ending, but we have still unprocessed unidentified resources left.
289 // These cases have longer path than one to identified objects.
290 c |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);
299 for (Statement s : unreliableLeft) {
300 if (!comparableStatements.containsLeft(s))
303 for (Statement s : unreliableRight) {
304 if (!comparableStatements.containsRight(s))
311 private boolean process(Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Set<Statement> unreliableLeft, Set<Statement> unreliableRight) throws DatabaseException {
312 List<Statement> ss1 = new ArrayList<Statement>();
313 List<Statement> ss2 = new ArrayList<Statement>();
314 boolean didSomething = false;
315 while (!objectsLeft.isEmpty()) {
316 Resource r1 = objectsLeft.pop();
317 Resource r2 = objectsRight.pop();
321 if (processedResources.contains(r1))
323 processedResources.add(r1);
326 if((comparableResources.containsLeft(r1)||comparableResources.containsRight(r2)) && !comparableResources.contains(r1, r2)) {
327 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.");
329 addComparable(r1, r2);
331 //System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));
332 compareProps(r1, r2);
334 for (Resource rel : tested) {
335 ss1.addAll(g.getStatements(r1, rel));
336 ss2.addAll(g.getStatements(r2, rel));
337 ss1 = filterAsserted(r1, ss1);
338 ss2 = filterAsserted(r2, ss2);
339 ss1 = filterTraversed(ss1);
340 ss2 = filterTraversed(ss2);
341 ss1 = filterNonTested(ss1);
342 ss2 = filterNonTested(ss2);
343 ss1 = filter(Collections.singletonList(b.HasProperty), ss1);
344 ss2 = filter(Collections.singletonList(b.HasProperty), ss2);
346 compareStatements(ss1, ss2, null, null,null,null);
351 for (Resource rel : traversed) {
352 ss1.addAll(g.getStatements(r1, rel));
353 ss2.addAll(g.getStatements(r2, rel));
354 ss1 = filterAsserted(r1, ss1);
355 ss2 = filterAsserted(r2, ss2);
356 ss1 = filterNonTraversed(ss1);
357 ss2 = filterNonTraversed(ss2);
358 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);
367 private boolean processUnreliable(Set<Statement> unreliableLeft, Set<Statement> unreliableRight) throws DatabaseException {
368 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
369 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
370 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
371 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
372 boolean didSomething = false;
373 for (Statement s : unreliableLeft) {
374 subjectLeft.add(s.getSubject(),s);
375 objectLeft.add(s.getObject(),s);
377 for (Statement s : unreliableRight) {
378 subjectRight.add(s.getSubject(),s);
379 objectRight.add(s.getObject(),s);
382 for (Resource left : subjectLeft.getKeys()) {
383 Resource right = comparableResources.getRight(left);
386 for (Statement leftS : subjectLeft.getValues(left)) {
387 Resource leftO = leftS.getObject();
388 if (!unreliableLeft.contains(leftS))
390 Resource rightO = comparableResources.getRight(leftO);
393 for (Statement rightS : subjectRight.getValues(right)) {
394 if (!rightS.getObject().equals(rightO))
396 if (!unreliableRight.contains(rightS))
398 if (leftS.getPredicate().equals(rightS.getPredicate()) ||
399 comparableResources.contains(leftS.getPredicate(), rightS.getPredicate())) {
400 unreliableLeft.remove(leftS);
401 unreliableRight.remove(rightS);
402 addComparable(leftS, rightS);
411 private boolean processUnreliable(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {
412 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
413 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
414 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
415 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
416 boolean didSomething = false;
417 for (Statement s : unreliableLeft) {
418 subjectLeft.add(s.getSubject(),s);
419 objectLeft.add(s.getObject(),s);
421 for (Statement s : unreliableRight) {
422 subjectRight.add(s.getSubject(),s);
423 objectRight.add(s.getObject(),s);
426 for (Resource ol : objectLeft.getKeys()) {
427 // all statements to the left side object
428 List<Statement> left = objectLeft.getValues(ol);
429 // all subjects that have statements to the left side object (ol)
430 Set<Resource> sLeft = new HashSet<Resource>();
431 // all matching subjects on the right side
432 Set<Resource> sRight = new HashSet<Resource>();
433 for (Statement s : left) {
434 sLeft.add(s.getSubject());
435 sRight.add(comparableResources.getRight(s.getSubject()));
438 // check if object left can be reliably identified by available statements
439 // if there are any objects on the left side with similar statements, object left cannot be mapped.
440 boolean hasSimilar = false;
441 MapList<Resource, Statement> comparableOLeft = new MapList<Resource, Statement>();
442 for (Resource sl : sLeft) {
443 for (Statement s : subjectLeft.getValues(sl)) {
444 if (!s.getObject().equals(ol)) {
445 comparableOLeft.add(s.getObject(),s);
450 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);
452 for (Resource similarOl : comparableOLeft.getKeys()) {
453 List<Statement> similarLeft = comparableOLeft.getValues(similarOl);
454 if (similarLeft.size() == left.size()) {
455 boolean useL[] = new boolean[left.size()];
456 boolean useSL[] = new boolean[left.size()];
457 for (int i = 0; i < left.size(); i++) {
461 for (int i = 0; i < left.size(); i++) {
462 for (int j = 0; j < left.size(); j++) {
465 // compare predicates
466 Resource pl = left.get(i).getPredicate();
467 Resource psl = similarLeft.get(j).getPredicate();
468 if (pl.equals(psl)) {
469 // compare objects (unreliable result is interpreted as positive match)
471 int comp = comparator.compare(g, left.get(i).getObject(), similarLeft.get(j).getObject(), true);
472 if (comp >= 0 && comp < ResourceComparator.NO_MATCH) {
480 boolean diff = false;
481 for (int i = 0; i < left.size(); i++) {
482 if (!useL[i] || !useSL[i]) {
497 // all objects that subjects on the right side point to. Object left has its matching resource among these, if it has matching resource
498 MapList<Resource,Statement> possibleOR = new MapList<Resource, Statement>();
499 for (Resource sr : sRight) {
500 for (Statement s : subjectRight.getValues(sr))
501 possibleOR.add(s.getObject(),s);
504 // filter possible right side objects to those that have same amount of statements as the left side object
505 for (Resource or : possibleOR.getKeys().toArray(new Resource[possibleOR.getKeys().size()])) {
506 List<Statement> right = possibleOR.getValues(or);
507 if (right.size() != left.size())
508 possibleOR.remove(or);
512 // check for matching statements (comparable subjects, matching predicates)
513 MapList<Resource,Statement> matchingOR = new MapList<Resource, Statement>(); // list of objects that have matching statements
514 Map<Resource,Pair<int[], int[]>> matchingStatements = new HashMap<Resource, Pair<int[], int[]>>(); // matching statements
515 for (Resource or : possibleOR.getKeys()) {
516 List<Statement> right = possibleOR.getValues(or);
517 int iLeft[] = new int[left.size()];
518 int iRight[] = new int[right.size()];
520 for (int i = 0; i < left.size(); i++) {
525 for (int l = 0; l < left.size(); l++) {
526 Statement ls = left.get(l);
527 for (int r = 0; r < right.size(); r++) {
530 Statement rs = right.get(r);
531 if (!comparableResources.contains(ls.getSubject(), rs.getSubject()))
533 if ((comparableResources.containsLeft(ls.getObject()) || comparableResources.containsRight(rs.getObject())) && !comparableResources.contains(ls.getObject(), rs.getObject()))
535 if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) {
536 // compare objects (unreliable result is not accepted)
537 int comp = comparator.compare(g, ls.getObject(), rs.getObject());
538 if (comp > 0 && comp < Integer.MAX_VALUE) {
548 boolean success = true;
549 for (int i = 0; i < left.size(); i++) {
561 for (Statement s : right)
562 matchingOR.add(or,s);
563 matchingStatements.put(or, new Pair<int[], int[]>(iLeft, iRight));
566 // if there is only one matching right side object, we have found a match
567 if (matchingOR.getKeySize() == 1) {
568 Resource or = matchingOR.getKeys().iterator().next();
569 List<Statement> right = matchingOR.getValues(or);
570 Pair<int[], int[]> indices = matchingStatements.get(or);
573 objectsRight.add(or);
574 addComparable(ol, or);
576 for (int l = 0; l < left.size(); l++) {
577 int r = indices.first[l];
578 Statement sl = left.get(l);
579 Statement sr = right.get(r);
580 addComparable(sl, sr);
581 unreliableLeft.remove(sl);
582 unreliableRight.remove(sr);
595 private boolean processUnreliable2(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {
596 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
597 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
598 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
599 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
600 boolean didSomething = false;
601 for (Statement s : unreliableLeft) {
602 subjectLeft.add(s.getSubject(),s);
603 objectLeft.add(s.getObject(),s);
605 for (Statement s : unreliableRight) {
606 subjectRight.add(s.getSubject(),s);
607 objectRight.add(s.getObject(),s);
610 for (Resource ol : objectLeft.getKeys()) {
611 // all statements to the left side object
612 List<Statement> left = objectLeft.getValues(ol);
613 // all subjects that have statements to the left side object (ol)
614 Set<Resource> sLeft = new HashSet<Resource>();
615 // all matching subjects on the right side
616 Set<Resource> sRight = new HashSet<Resource>();
617 for (Statement s : left) {
618 sLeft.add(s.getSubject());
619 sRight.add(comparableResources.getRight(s.getSubject()));
622 if (sLeft.size() == 1 && sRight.size() == 1) {
623 List<Statement> ss1 = new ArrayList<Statement>(subjectLeft.getValues(sLeft.iterator().next()));
624 List<Statement> ss2 = new ArrayList<Statement>(subjectRight.getValues(sRight.iterator().next()));
626 int count = comparableStatements.size();
627 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);
628 if (comparableStatements.size() > count) {
630 for (Entry<Statement, Statement> entry : comparableStatements.getEntries()) {
631 unreliableLeft.remove(entry.getKey());
632 unreliableRight.remove(entry.getValue());
640 private boolean processUnreliableDeep(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {
641 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
642 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
643 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
644 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
645 boolean didSomething = false;
646 for (Statement s : unreliableLeft) {
647 subjectLeft.add(s.getSubject(),s);
648 objectLeft.add(s.getObject(),s);
650 for (Statement s : unreliableRight) {
651 subjectRight.add(s.getSubject(),s);
652 objectRight.add(s.getObject(),s);
654 for (Resource ol : objectLeft.getKeys()) {
655 Set<Path> pathsLeft = new HashSet<Path>();
656 for (Resource rel : traversed) {
657 pathsLeft.addAll(Path.create(g.getStatements(ol, rel)));
661 if (pathsLeft.size() == 0)
663 Collection<Path> endPaths = new ArrayList<Path>(1);
664 for (Path p : pathsLeft) {
665 if (comparableResources.containsLeft(p.getEnd())) {
669 if (endPaths.size() > 0) {
671 pathsLeft.addAll(endPaths);
675 if (pathsLeft.size() > 0) {
676 Resource sl = objectLeft.getValues(ol).get(0).getSubject();
677 Resource sr = comparableResources.getRight(sl);
678 Collection<Resource> possibleOR = new ArrayList<Resource>();
679 for (Statement s : subjectRight.getValues(sr)) {
680 possibleOR.add(s.getObject());
682 Map<Resource,Set<Path>> matchingPaths = new HashMap<Resource, Set<Path>>();
683 for (Resource or : possibleOR) {
684 Set<Path> possiblePathsRight = new HashSet<Path>();
685 for (Path leftPath : pathsLeft) {
686 possiblePathsRight.addAll(findComparableRight(leftPath, or));
688 if (hasMatchingPaths(pathsLeft, possiblePathsRight)) {
689 matchingPaths.put(or, possiblePathsRight);
692 if (matchingPaths.size() > 0) {
693 if (matchingPaths.size() == 1) {
695 Resource or = matchingPaths.keySet().iterator().next();
698 objectsRight.add(or);
699 addComparable(ol, or);
700 Collection<Statement> statementsLeft = objectLeft.getValues(ol);
701 Collection<Statement> statementsRight = objectRight.getValues(or);
702 unreliableLeft.removeAll(statementsLeft);
703 unreliableRight.removeAll(statementsRight);
704 BijectionMap<Path,Path> map = getMatchingPaths(pathsLeft, matchingPaths.get(or));
705 for (Path left : map.getLeftSet()) {
706 Path right = map.getRight(left);
707 for (int i = 0; i < left.getLength(); i++) {
708 addComparable(left.getStatements().get(i),right.getStatements().get(i));
720 private boolean hasMatchingPaths(Set<Path> leftPaths, Set<Path> rightPaths) throws DatabaseException {
721 if (leftPaths.size() != rightPaths.size())
723 BijectionMap<Path,Path> map = getMatchingPaths(leftPaths, rightPaths);
724 return map.size() == leftPaths.size();
727 private BijectionMap<Path,Path> getMatchingPaths(Set<Path> leftPaths, Set<Path> rightPaths) throws DatabaseException {
728 BijectionMap<Path,Path> map = new BijectionMap<Path, Path>();
729 for (Path leftPath : leftPaths) {
730 for (Path rightPath : rightPaths) {
731 if (map.containsRight(rightPath))
733 if (leftPath.getLength() != rightPath.getLength())
735 if (comparableResources.contains(leftPath.getEnd(), rightPath.getEnd())) {
736 boolean match = true;
737 for (int i = 0; i < leftPath.getLength(); i++) {
738 Statement sl = leftPath.getStatements().get(i);
739 Statement sr = rightPath.getStatements().get(i);
740 if (!sl.getPredicate().equals(sr.getPredicate()) && !comparableResources.contains(sl.getPredicate(), sr.getPredicate())) {
744 if ((getComparableResources().containsLeft(sl.getObject()) || getComparableResources().containsRight(sr.getObject())) && !getComparableResources().contains(sl.getObject(), sr.getObject())) {
748 if (comparator.compare(g, sl.getObject(), sr.getObject()) == ResourceComparator.NO_MATCH) {
754 map.map(leftPath, rightPath);
763 private void expand(Set<Path> paths) throws DatabaseException {
764 Set<Path> stepPathsLeft = new HashSet<Path>();
765 if (paths.size() == 0)
767 int length = paths.iterator().next().getLength() + 1;
768 for (Path p : paths) {
769 for (Resource rel : traversed) {
770 stepPathsLeft.addAll(Path.expand(p,g.getStatements(p.getEnd(), rel)));
774 for (Path p : stepPathsLeft) {
775 if (p.getLength() == length)
780 private Collection<Path> findComparableRight(Path leftPath, Resource beginRight) throws DatabaseException {
781 Set<Path> rightPaths = new HashSet<Path>();
782 rightPaths.addAll(Path.create(g.getStatements(beginRight, getRight(leftPath.getStatements().get(0).getPredicate()))));
783 for (int i = 1; i < leftPath.getLength(); i++) {
784 if (rightPaths.size() == 0)
786 Set<Path> stepPaths = new HashSet<Path>();
787 for (Path p : rightPaths) {
788 stepPaths.addAll(Path.expand(p, g.getStatements(p.getEnd(), getRight(leftPath.getStatements().get(i).getPredicate()))));
791 for (Path p : stepPaths)
792 if (p.getLength() == i+1)
799 private Resource getRight(Resource r) {
800 if (comparableResources.containsLeft(r))
801 return comparableResources.getRight(r);
807 public BijectionMap<Statement, Statement> getComparableStatements() {
808 return comparableStatements;
811 public BijectionMap<Resource, Resource> getComparableResources() {
812 return comparableResources;
815 public GraphChanges getChanges() {
816 return new GraphChanges(r1,r2,changes1,changes2,modifications,comparableResources);
819 public List<Statement> getChanges1() {
823 public List<Statement> getChanges2() {
827 private void addComparable(Statement left, Statement right) throws DatabaseException {
828 addComparable(left.getObject(), right.getObject());
829 comparableStatements.map(left, right);
832 private void addComparable(Resource left, Resource right) throws DatabaseException {
833 if(!comparableResources.contains(left, right)) {
834 if (comparableResources.containsLeft(left)||comparableResources.containsRight(right)) {
835 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.");
837 if (DEBUG) System.out.println(left + " = " + right);
838 comparableResources.map(left, right);
844 public List<Statement> filterAsserted(Resource r, Collection<Statement> in) throws DatabaseException {
845 List<Statement> out = new ArrayList<Statement>();
846 for (Statement s : in) {
847 if (!s.isAsserted(r))
854 public List<Statement> filterAssertedDuplicates(Resource r, List<Statement> in) throws DatabaseException {
855 List<Statement> out = new ArrayList<Statement>();
856 for (int i = 0; i < in.size(); i++) {
857 Statement s = in.get(i);
858 if (!s.isAsserted(r))
862 if (i > 0 && in.get(i-1).getPredicate().equals(s.getPredicate()))
864 else if (i < in.size()-1 && in.get(i+1).getPredicate().equals(s.getPredicate()))
876 private String printStatement(ReadGraph graph, Statement s) throws DatabaseException {
877 return NameUtils.getSafeName(graph, s.getSubject()) + " " + NameUtils.getSafeName(graph, s.getPredicate()) + " " + NameUtils.getSafeName(graph, s.getObject());
880 private List<Statement> filterTraversed(List<Statement> in) throws DatabaseException {
881 return filter(traversed, in);
884 private List<Statement> filterNonTested(List<Statement> in) throws DatabaseException {
885 return filter(nonTested, in);
888 private List<Statement> filterNonTraversed(List<Statement> in) throws DatabaseException {
889 return filter(nonTraversed, in);
892 private List<Statement> filter(Collection<Resource> toFilter, List<Statement> in) throws DatabaseException {
893 if (toFilter.size() == 0)
895 List<Statement> out = new ArrayList<Statement>();
896 for (Statement s : in) {
897 boolean usable = true;
898 for (Resource r : toFilter) {
899 if (g.isSubrelationOf(s.getPredicate(),r)) {
913 private void addDeletion(Statement s) {
914 if (!changes1Set.contains(s)) {
915 if (DEBUG) System.out.println("- " +s.getSubject() + " " + s.getPredicate() + " " + s.getObject()) ;
921 private void addAddition(Statement s) {
922 if (!changes2Set.contains(s)) {
924 if (DEBUG) System.out.println("+ " +s.getSubject() + " " + s.getPredicate() + " " + s.getObject()) ;
929 private void addModification(Resource left, Statement leftstm, Resource right, Statement rightstm) {
930 Modification mod = new Modification(left, right, leftstm, rightstm);
931 if (!modificationsSet.contains(mod)) {
932 modificationsSet.add(mod);
933 modifications.add(mod);
937 public void sortStatement(List<Statement> list1, List<Statement> list2) {
938 sortStatement(list1, list2, scomp);
941 public void sortStatement(List<Statement> list1, List<Statement> list2, Comparator<Statement> scomp) {
942 Collections.sort(list1,scomp);
943 Collections.sort(list2,scomp);
945 List<Statement> sorted1 = new ArrayList<Statement>(list1.size());
946 List<Statement> sorted2 = new ArrayList<Statement>(list2.size());
947 sorted1.addAll(list1);
948 sorted2.addAll(list2);
952 for (int i = 0; i < list1.size(); ) {
953 Statement s1 = list1.get(i);
954 int same1 = sameRel(list1, i);
955 for (int j = 0; j < list2.size(); j++) {
956 Statement s2 = list2.get(j);
957 if (scomp.compare(s1, s2) == 0) {
958 int same2 = sameRel(list2, j);
959 copy(sorted1,ss1,list1,i,same1);
961 copy(sorted2,ss2,list2,j,same2);
968 if (ss1 < sorted1.size()) {
969 for (Statement s : list1) {
970 if (!sorted1.contains(s)) {
976 if (ss2 < sorted2.size()) {
977 for (Statement s : list2) {
978 if (!sorted2.contains(s)) {
987 list1.addAll(sorted1);
988 list2.addAll(sorted2);
991 public <T> void copy(List<T> to, int toIndex, List<T> from, int fromIndex, int amount) {
992 for (int i = 0; i < amount; i++) {
993 to.set(toIndex + i, from.get(fromIndex+ i));
997 public void sortResource(List<Resource> list1, List<Resource> list2) {
998 Collections.sort(list1,rcomp);
1000 for (int i = 0; i < list1.size(); i++) {
1001 Resource s1 = list1.get(i);
1002 for (int j = js; j < list2.size(); j++) {
1003 Resource s2 = list2.get(j);
1004 if (rcomp.compare(s1, s2) == 0) {
1005 Resource t = list2.get(js);
1015 private void compareStatements(List<Statement> ss1, List<Statement> ss2, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Collection<Statement> unreliableLeft, Collection<Statement> unreliableRight) throws DatabaseException {
1016 sortStatement(ss1, ss2);
1022 if (i1 >= ss1.size()) {
1023 if (i2 >= ss2.size()) {
1026 while (i2 < ss2.size()) {
1027 if (DEBUG) System.out.println("Compare Statements addition " + printStatement(g,ss2.get(i2)));
1029 addAddition(ss2.get(i2));
1034 } else if (i2 >= ss2.size()) {
1035 while (i1 < ss1.size()) {
1036 if (DEBUG) System.out.println("Compare Statements deletion " + printStatement(g,ss1.get(i1)));
1037 addDeletion(ss1.get(i1));
1042 int same1 = sameRel(ss1, i1);
1043 int same2 = sameRel(ss2, i2);
1044 int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate());
1046 compareStatements(ss1, i1, same1, ss2, i2, same2,objectsLeft,objectsRight,unreliableLeft,unreliableRight);
1050 for (int i = 0; i < same1; i++) {
1051 if (DEBUG) System.out.println("Compare Statements deletion " + printStatement(g,ss1.get(i+i1)));
1052 addDeletion(ss1.get(i+i1));
1056 for (int i = 0; i < same2; i++) {
1057 if (DEBUG) System.out.println("Compare Statements addition " + printStatement(g,ss2.get(i+i2)));
1058 addAddition(ss2.get(i+i2));
1068 private int sameRel(List<Statement> statements, int off) {
1069 if (statements.size() <= off)
1072 long id = statements.get(off).getPredicate().getResourceId();
1073 for (int i = off+1; i <statements.size(); i++) {
1074 if (statements.get(i).getPredicate().getResourceId() == id)
1083 private int compareObject(Resource o1, Resource o2) throws DatabaseException {
1086 if (comparableResources.contains(o1, o2))
1088 if (comparableResources.containsLeft(o1))
1089 return Integer.MAX_VALUE;
1090 if (comparableResources.containsRight(o2))
1091 return Integer.MAX_VALUE;
1092 if (nonMatchedLeft.contains(o1))
1093 return Integer.MAX_VALUE;
1094 if (nonMatchedRight.contains(o2))
1095 return Integer.MAX_VALUE;
1096 return comparator.compare(g, o1, o2);
1099 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 {
1100 boolean[] used1 = new boolean[len1];
1101 for (int i = 0; i < used1.length; i++) {
1105 boolean[] used2 = new boolean[len2];
1106 for (int i = 0; i < used2.length; i++) {
1110 // left, right, difference
1111 List<List<Integer>> differences = new ArrayList<List<Integer>>();
1112 for (int i1 = off1; i1 < off1 + len1; i1++) {
1113 Statement s1 = ss1.get(i1);
1114 List<Integer> diff = new ArrayList<Integer>();
1115 for (int i2 = off2; i2 < off2 + len2; i2++) {
1116 Statement s2 = ss2.get(i2);
1117 int d = compareObject(s1.getObject(), s2.getObject());
1119 for (Resource t : strong) {
1120 if (s1.getPredicate().equals(t) || g.isSubrelationOf(s1.getPredicate(), t)) {
1128 differences.add(diff);
1131 MapList<Integer, Integer> priorities = new MapList<Integer, Integer>();
1132 for (int i = 0; i < differences.size(); i++) {
1133 List<Integer> list = differences.get(i);
1134 for (int j = 0; j < list.size(); j++) {
1135 priorities.add(list.get(j), i);
1139 Integer[] pris = priorities.getKeys(new Integer[]{});
1141 boolean matchFail = priorityMatching(ss1, off1, len1, ss2, off2, len2, pris, differences, priorities, used1, used2, objectsLeft, objectsRight, false);
1143 matchFail = priorityMatching(ss1, off1, len1, ss2, off2, len2, pris, differences, priorities, used1, used2, objectsLeft, objectsRight, objectsLeft == null);
1144 if (unreliableLeft != null) {
1146 // With match failure, statement matching was aborted. We must move all unmatched statements to unreliable.
1147 for (Integer pri : pris) {
1148 if (pri == 0 || pri == Integer.MAX_VALUE)
1150 priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, pri);
1153 // Zero means unreliable comparison result, move all unmatched to unreliable.
1154 if (org.simantics.utils.datastructures.Arrays.contains(pris, 0)) {
1155 priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, 0);
1158 // Previous version processed 0 priority statements, even when unreliableLeft collection was null.
1159 // The problem was that property relations were not filtered in process() from "tested" statements.
1161 // if (org.simantics.utils.datastructures.Arrays.contains(pris, 0)) {
1162 // priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, 0);
1165 // Report unmatched statements as changes.
1166 for (int i1 = off1; i1 < off1 + len1; i1++) {
1167 if (!used1[i1-off1]) {
1168 if (DEBUG) System.out.println("Compare Object deletion " + printStatement(g,ss1.get(i1)));
1169 addDeletion(ss1.get(i1));
1172 for (int i2 = off2; i2 < off2 + len2; i2++) {
1173 if (!used2[i2-off2]) {
1174 if (DEBUG) System.out.println("Compare Object addition " + printStatement(g,ss2.get(i2)));
1175 addAddition(ss2.get(i2));
1181 * Moves unmatched statements to unreliable collections.
1188 * @param differences
1192 * @param unreliableLeft
1193 * @param unreliableRight
1196 private void priorityProcessUnmatched(List<Statement> ss1, int off1, int len1, List<Statement> ss2, int off2, int len2,List<List<Integer>> differences,MapList<Integer, Integer> priorities,boolean used1[],boolean used2[], Collection<Statement> unreliableLeft, Collection<Statement> unreliableRight, int pri) {
1197 Set<Statement> s1s = new HashSet<Statement>();
1198 Set<Statement> s2s = new HashSet<Statement>();
1199 Set<Integer> s1i = new HashSet<Integer>();
1200 Set<Integer> s2i = new HashSet<Integer>();
1201 List<Integer> i1s = priorities.getValues(pri);
1202 for (Integer i1 : i1s) {
1205 List<Integer> i2diff = differences.get(i1);
1206 for (int i2 = 0; i2 < i2diff.size(); i2++) {
1207 if (i2diff.get(i2) == pri) {
1210 Statement s1 = ss1.get(i1+off1);
1211 Statement s2 = ss2.get(i2+off2);
1219 if (unreliableLeft != null) {
1220 unreliableLeft.addAll(s1s);
1221 unreliableRight.addAll(s2s);
1223 for (Integer i : s1i)
1225 for (Integer i : s2i)
1229 * Matches left and right side statements.
1231 * When there are two or more equally good matching objects, the behaviour depends on force flag.
1232 * False: Matching is aborted and matchFail is returned (method return true).
1233 * True: equally good matches will be paired randomly. Method always returns false.
1241 * @param differences
1245 * @param objectsLeft
1246 * @param objectsRight
1249 * @throws DatabaseException
1251 private boolean priorityMatching(List<Statement> ss1, int off1, int len1, List<Statement> ss2, int off2, int len2, Integer[] pris, List<List<Integer>> differences, MapList<Integer, Integer> priorities, boolean used1[],boolean used2[], Collection<Resource> objectsLeft, Collection<Resource> objectsRight, boolean force) throws DatabaseException {
1252 boolean matchFail = false;
1253 for (Integer pri : pris) {
1254 if (pri == Integer.MAX_VALUE) {
1256 } else if (pri == 0) {
1259 List<Integer> i1s = priorities.getValues(pri);
1261 for (Integer i1 : i1s) {
1264 List<Integer> i2diff = differences.get(i1);
1265 List<Integer> matches = new ArrayList<Integer>();
1266 for (int i2 = 0; i2 < i2diff.size(); i2++) {
1267 if (i2diff.get(i2) == pri) {
1273 if (matches.size() == 1 || (force && matches.size() > 1)) {
1274 int i2 = matches.get(0);
1277 Statement s1 = ss1.get(i1+off1);
1278 Statement s2 = ss2.get(i2+off2);
1280 if (objectsLeft != null) {
1281 objectsLeft.add(s1.getObject());
1282 objectsRight.add(s2.getObject());
1284 addComparable(s1, s2);
1285 } else if (matches.size() > 1) {
1298 * compares properties, assumes functional relations
1301 * @throws DatabaseException
1303 private void compareProps(Resource r1, Resource r2) throws DatabaseException {
1304 if (DEBUG) System.out.println("compareProps " + r1 + " " + NameUtils.getSafeName(g, r1) + " " + r2 + " " + NameUtils.getSafeName(g, r2));
1305 List<Statement> ss1 = new ArrayList<Statement>();
1306 List<Statement> ss2 = new ArrayList<Statement>();
1307 ss1.addAll(g.getStatements(r1, b.HasProperty));
1308 ss2.addAll(g.getStatements(r2, b.HasProperty));
1309 ss1 = filterNonTested(ss1);
1310 ss2 = filterNonTested(ss2);
1311 sortStatement(ss1, ss2);
1312 // getStatements(r1, b.HasProperty) returns both instance and asserted statements for the same property relation.
1313 ss1 = filterAssertedDuplicates(r1, ss1);
1314 ss2 = filterAssertedDuplicates(r2, ss2);
1320 if (i1 >= ss1.size()) {
1321 if (i2 >= ss2.size())
1324 while (i2 < ss2.size()) {
1325 Statement s = ss2.get(i2);
1326 if (DEBUG) System.out.println("Compare Prop diff2 " + printStatement(g,s));
1327 if (!s.isAsserted(r2))
1333 } else if (i2 >= ss2.size()) {
1334 while (i1 < ss1.size()) {
1335 Statement s = ss1.get(i1);
1336 if (DEBUG) System.out.println("Compare Prop diff1 " + printStatement(g,s));
1337 if (!s.isAsserted(r1))
1343 Statement s1 = ss1.get(i1);
1344 Statement s2 = ss2.get(i2);
1345 if (s1.isAsserted(r1) && s2.isAsserted(r2)) {
1350 int c = scomp.compare(s1, s2);
1353 boolean b1 = g.hasValue(s1.getObject());
1354 boolean b2 = g.hasValue(s2.getObject());
1355 boolean a1 = s1.isAsserted(r1);
1356 boolean a2 = s2.isAsserted(r2);
1360 boolean eq = compareValue(g,b,s1.getObject(), s2.getObject());
1362 addModification(r1,s1,r2,s2);
1364 addComparable(s1, s2);
1367 // Non literal properties.
1368 int comp = comparator.compare(g, s1.getObject(), s2.getObject());
1369 if (comp == ResourceComparator.NO_MATCH) {
1370 addModification(r1,s1,r2,s2);
1371 } else if (comp != ResourceComparator.EXACT_MATCH) {
1372 if (!s1.getObject().equals(s1.getSubject()) && !s2.getObject().equals(s2.getSubject())) {
1374 // compare props matches objects, so we can call that only for non asserted statements
1375 compareProps(s1.getObject(), s2.getObject());
1376 } else if (a1 && a2) {
1377 // TODO : compare asserted statements?
1379 addModification(r1,s1,r2,s2);
1382 addModification(r1,s1,r2,s2);
1385 // Exact match, nothing to do.
1387 addComparable(s1, s2);
1391 addModification(r1,s1,r2,s2);
1398 if (DEBUG) System.out.println("Compare Prop diff1s " + printStatement(g,s1));
1399 // Use modification, since deletions do not support asserted statements
1400 addModification(r1,s1,r2,null);
1407 if (DEBUG) System.out.println("Compare Prop diff2s " + printStatement(g,s2));
1408 // Use modification, since additions do not support asserted statements
1409 addModification(r1,null,r2,s2);
1423 public static boolean compareValue(ReadGraph g, Layer0 b, Resource r1, Resource r2) throws DatabaseException {
1424 Resource t1 = g.getSingleType(r1);
1425 Resource t2 = g.getSingleType(r2);
1428 if (t1.equals(b.Integer)) {
1429 int v1 = g.getValue(r1, Bindings.INTEGER);
1430 int v2 = g.getValue(r2, Bindings.INTEGER);
1432 } else if (t1.equals(b.Float)) {
1433 float v1 = g.getValue(r1, Bindings.FLOAT);
1434 float v2 = g.getValue(r2, Bindings.FLOAT);
1436 } else if (t1.equals(b.Double)) {
1437 double v1 = g.getValue(r1, Bindings.DOUBLE);
1438 double v2 = g.getValue(r2, Bindings.DOUBLE);
1440 } else if (t1.equals(b.String)) {
1441 String v1 = g.getValue(r1, Bindings.STRING);
1442 String v2 = g.getValue(r2, Bindings.STRING);
1443 return v1.equals(v2);
1444 } else if (t1.equals(b.Boolean)) {
1445 boolean v1 = g.getValue(r1, Bindings.BOOLEAN);
1446 boolean v2 = g.getValue(r2, Bindings.BOOLEAN);
1448 } else if (t1.equals(b.Byte)) {
1449 byte v1 = g.getValue(r1, Bindings.BYTE);
1450 byte v2 = g.getValue(r2, Bindings.BYTE);
1452 } else if (t1.equals(b.Long)) {
1453 long v1 = g.getValue(r1, Bindings.LONG);
1454 long v2 = g.getValue(r2, Bindings.LONG);
1456 } else if (t1.equals(b.IntegerArray)) {
1457 int[] v1 = g.getValue(r1, Bindings.INT_ARRAY);
1458 int[] v2 = g.getValue(r2, Bindings.INT_ARRAY);
1459 return Arrays.equals(v1,v2);
1460 } else if (t1.equals(b.FloatArray)) {
1461 float[] v1 = g.getValue(r1, Bindings.FLOAT_ARRAY);
1462 float[] v2 = g.getValue(r2, Bindings.FLOAT_ARRAY);
1463 return Arrays.equals(v1,v2);
1464 } else if (t1.equals(b.DoubleArray)) {
1465 double[] v1 = g.getValue(r1, Bindings.DOUBLE_ARRAY);
1466 double[] v2 = g.getValue(r2, Bindings.DOUBLE_ARRAY);
1467 return Arrays.equals(v1,v2);
1468 } else if (t1.equals(b.StringArray)) {
1469 String[] v1 = g.getValue(r1, Bindings.STRING_ARRAY);
1470 String[] v2 = g.getValue(r2, Bindings.STRING_ARRAY);
1471 return Arrays.equals(v1,v2);
1472 } else if (t1.equals(b.BooleanArray)) {
1473 boolean[] v1 = g.getValue(r1, Bindings.BOOLEAN_ARRAY);
1474 boolean[] v2 = g.getValue(r2, Bindings.BOOLEAN_ARRAY);
1475 return Arrays.equals(v1,v2);
1476 } else if (t1.equals(b.ByteArray)) {
1477 byte[] v1 = g.getValue(r1, Bindings.BYTE_ARRAY);
1478 byte[] v2 = g.getValue(r2, Bindings.BYTE_ARRAY);
1479 return Arrays.equals(v1,v2);
1480 } else if (t1.equals(b.LongArray)) {
1481 long[] v1 = g.getValue(r1, Bindings.LONG_ARRAY);
1482 long[] v2 = g.getValue(r2, Bindings.LONG_ARRAY);
1483 return Arrays.equals(v1,v2);
1485 Object v1 = g.getValue(r1);
1486 Object v2 = g.getValue(r2);
1487 return compareValue(v1, v2);
1492 public static boolean compareValue(Object v1, Object v2) {
1493 if (v1 instanceof Object[] && v2 instanceof Object[])
1494 return Arrays.deepEquals((Object[])v1, (Object[])v2);
1495 else if (v1 instanceof int[] && v2 instanceof int[])
1496 return Arrays.equals((int[])v1, (int[])v2);
1497 else if (v1 instanceof float[] && v2 instanceof float[])
1498 return Arrays.equals((float[])v1, (float[])v2);
1499 else if (v1 instanceof double[] && v2 instanceof double[])
1500 return Arrays.equals((double[])v1, (double[])v2);
1501 else if (v1 instanceof long[] && v2 instanceof long[])
1502 return Arrays.equals((long[])v1, (long[])v2);
1503 else if (v1 instanceof byte[] && v2 instanceof byte[])
1504 return Arrays.equals((byte[])v1, (byte[])v2);
1505 else if (v1 instanceof boolean[] && v2 instanceof boolean[])
1506 return Arrays.equals((boolean[])v1, (boolean[])v2);
1508 return v1.equals(v2);
1512 public class PredicateComparator implements Comparator<Statement> {
1514 public int compare(Statement o1, Statement o2) {
1515 if (comparableResources.contains(o1.getPredicate(), o2.getPredicate()))
1517 if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())
1519 if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())
1525 public class SubjectComparator implements Comparator<Statement> {
1527 public int compare(Statement o1, Statement o2) {
1528 if (comparableResources.contains(o1.getSubject(), o2.getSubject()))
1530 if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())
1532 if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())
1538 public class ObjectComparator implements Comparator<Statement> {
1540 public int compare(Statement o1, Statement o2) {
1541 if (comparableResources.contains(o1.getObject(), o2.getObject()))
1543 if (o1.getObject().getResourceId() < o2.getObject().getResourceId())
1545 if (o1.getObject().getResourceId() > o2.getObject().getResourceId())
1551 public static class FullStatementComparator implements Comparator<Statement> {
1553 public int compare(Statement o1, Statement o2) {
1554 if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())
1556 if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())
1558 if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())
1560 if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())
1562 if (o1.getObject().getResourceId() < o2.getObject().getResourceId())
1564 if (o1.getObject().getResourceId() > o2.getObject().getResourceId())
1570 public class ResComparator implements Comparator<Resource> {
1572 public int compare(Resource o1, Resource o2) {
1573 if (comparableResources.contains(o1, o2))
1575 if (o1.getResourceId() < o2.getResourceId())
1577 if (o1.getResourceId() > o2.getResourceId())