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.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.simantics.databoard.Bindings;
32 import org.simantics.db.ReadGraph;
33 import org.simantics.db.Resource;
34 import org.simantics.db.Session;
35 import org.simantics.db.Statement;
36 import org.simantics.db.common.request.ReadRequest;
37 import org.simantics.db.common.utils.NameUtils;
38 import org.simantics.db.exception.DatabaseException;
39 import org.simantics.db.request.Read;
40 import org.simantics.interop.test.GraphChanges.Modification;
41 import org.simantics.layer0.Layer0;
42 import org.simantics.utils.datastructures.BijectionMap;
43 import org.simantics.utils.datastructures.MapList;
44 import org.simantics.utils.datastructures.Pair;
47 * Compares two subgraphs and reports differences.
49 * Assumes that subgraphs (defined using traverse relations) are not cyclic.
51 * Assumes that properties can be used to identify objects, if relation type is not enough.
55 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
58 public class GraphComparator {
60 private static final boolean DEBUG = false;
64 private Set<Resource> strong = new HashSet<>(); // List of relations that identify object, if subject is already identified.
65 private List<Resource> traversed = new ArrayList<>(); // list of relations that are traversed (and tested)
66 private List<Resource> tested = new ArrayList<>(); // list of relations that are tested, but not traversed
67 private List<Resource> nonTraversed = new ArrayList<>(); // list of relations that are not traversed
68 private List<Resource> nonTested = new ArrayList<>(); // list of relations that are not tested
70 private List<Statement> changes1 = new ArrayList<>();
71 private List<Statement> changes2 = new ArrayList<>();
72 private List<Modification> modifications = new ArrayList<>();
73 private Set<Statement> changes1Set = new HashSet<>();
74 private Set<Statement> changes2Set = new HashSet<>();
75 private Set<Modification> modificationsSet = new HashSet<>();
77 private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<>();
78 private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<>();
80 private Set<Resource> processedResources = new HashSet<Resource>();
82 private ResourceComparator comparator;
84 private Comparator<Statement> scomp = new PredicateComparator();
85 private Comparator<Resource> rcomp = new ResComparator();
87 private Set<Resource> nonMatchedLeft = new HashSet<Resource>();
88 private Set<Resource> nonMatchedRight = new HashSet<Resource>();
90 private long iter = 0;
91 private long maxIter = -1;
98 private boolean mapLiterals = true;
100 public GraphComparator(Resource r1, Resource r2) {
103 comparator = new TypeComparator();
106 public GraphComparator(Resource r1, Resource r2, ResourceComparator comparator) {
109 this.comparator = comparator;
113 public Comparator<Resource> getResourceComparator() {
117 public Comparator<Statement> getStatementComparator() {
121 public Resource getR1() {
125 public Resource getR2() {
129 public void addTraversed(Resource rel) {
133 public void addTraversed(Collection<Resource> rels) {
134 traversed.addAll(rels);
137 public void addNonTraversed(Resource rel) {
138 nonTraversed.add(rel);
141 public void addNonTraversed(Collection<Resource> rels) {
142 nonTraversed.addAll(rels);
145 public void addTested(Resource rel) {
149 public void addTested(Collection<Resource> rels) {
153 public void addNonTested(Resource rel) {
157 public void addNonTested(Collection<Resource> rels) {
158 nonTested.addAll(rels);
161 public void addComparableResources(Resource r1, Resource r2) {
163 System.out.println("Preset " + r1 + " = " + r2);
164 comparableResources.map(r1, r2);
167 public void addComparableResources(BijectionMap<Resource, Resource> matching) {
169 for (Entry<Resource, Resource> entry : matching.getEntries())
170 System.out.println("Preset " + entry.getKey() + " = " + entry.getValue());
172 comparableResources.addAll(matching);
175 public void addStrong(Resource r) {
179 public void addStrong(Collection<Resource> rels) {
183 public void addNonMatchedLeft(Resource r) {
184 nonMatchedLeft.add(r);
187 public void addNonMatchedRight(Resource r) {
188 nonMatchedRight.add(r);
191 public long getMaxIter() {
196 * Sets maximum iteration done on a single DB transaction. Affects only test(Session) methods.
197 * Default value is -1, which disables iteration limit.
198 * Note that using iteration limit causes comparison to repeat some work, thus total execution time will increase.
202 public void setMaxIter(long maxIter) {
203 this.maxIter = maxIter;
206 public boolean isMapLiterals() {
210 public void setMapLiterals(boolean mapLiterals) {
211 this.mapLiterals = mapLiterals;
214 private void clear() {
219 comparableResources.clear();
220 comparableStatements.clear();
221 modifications.clear();
222 modificationsSet.clear();
223 processedResources.clear();
226 public void dispose() {
231 comparableResources = null;
232 comparableStatements = null;
234 modifications = null;
235 modificationsSet = null;
236 processedResources = null;
237 nonMatchedLeft = null;
238 nonMatchedRight = null;
246 public void test(ReadGraph g) throws DatabaseException {
250 public void test(ReadGraph g, IProgressMonitor monitor) throws DatabaseException {
252 this.b = Layer0.getInstance(g);
253 comparator.setComparator(this);
254 comparator.initialize(g, r1, r2);
257 monitor = new NullProgressMonitor();
259 Stack<Resource> objectsLeft = new Stack<Resource>();
260 Stack<Resource> objectsRight = new Stack<Resource>();
261 objectsLeft.push(r1);
262 objectsRight.push(r2);
264 Set<Statement> unreliableLeft = new HashSet<Statement>();
265 Set<Statement> unreliableRight = new HashSet<Statement>();
267 boolean changed = false;
269 if (objectsLeft.isEmpty() && !changed)
271 if (monitor.isCanceled()) {
275 monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight));
278 // process compares objects that are identified and searches for more resources to process.
279 changed = compareIter(g, objectsLeft, objectsRight, unreliableLeft, unreliableRight);
283 for (Statement s : unreliableLeft) {
284 if (!comparableStatements.containsLeft(s)) {
285 if (DEBUG) System.out.println("Unreliable Object deletion " + printStatement(g,s));
289 for (Statement s : unreliableRight) {
290 if (!comparableStatements.containsRight(s)) {
291 if (DEBUG) System.out.println("Unreliable Object addition " + printStatement(g,s));
295 monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight) + " done.");
299 public void test(Session session) throws DatabaseException {
300 test(session, r1, r2, null);
303 public void test(Session session, IProgressMonitor monitor) throws DatabaseException {
304 test(session, r1, r2, monitor);
307 public void test(Session session, Resource r1, Resource r2) throws DatabaseException {
308 test(session, r1, r2, null);
311 public void test(Session session, Resource r1, Resource r2, IProgressMonitor monitor) throws DatabaseException {
313 comparator.setComparator(this);
316 monitor = new NullProgressMonitor();
318 session.syncRequest(new ReadRequest() {
321 public void run(ReadGraph graph) throws DatabaseException {
322 comparator.initialize(graph, r1, r2);
326 addComparable(r1, r2);
328 final Stack<Resource> objectsLeft = new Stack<Resource>();
329 final Stack<Resource> objectsRight = new Stack<Resource>();
330 objectsLeft.push(r1);
331 objectsRight.push(r2);
333 final Set<Statement> unreliableLeft = new HashSet<Statement>();
334 final Set<Statement> unreliableRight = new HashSet<Statement>();
336 boolean changed = false;
338 if (objectsLeft.isEmpty() && !changed)
340 if (monitor.isCanceled()) {
344 monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight));
345 changed = session.syncRequest(new Read<Boolean>() {
348 public Boolean perform(ReadGraph graph) throws DatabaseException {
349 //System.out.println("Iter " + monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight));
351 b = Layer0.getInstance(graph);
352 return compareIter(graph, objectsLeft, objectsRight, unreliableLeft, unreliableRight);
359 for (Statement s : unreliableLeft) {
360 if (!comparableStatements.containsLeft(s))
363 for (Statement s : unreliableRight) {
364 if (!comparableStatements.containsRight(s))
367 unreliableLeft.clear();
368 unreliableRight.clear();
370 monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight) + " done.");
374 private boolean compareIter(ReadGraph graph, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Set<Statement> unreliableLeft, Set<Statement> unreliableRight) throws DatabaseException {
375 // process compares objects that are identified and searches for more resources to process.
377 boolean c = process(objectsLeft, objectsRight, unreliableLeft, unreliableRight,false);
378 if (objectsLeft.isEmpty()) {
379 // process unreliable handles cases where unidentified statements subject and object have been identified
380 c |= processUnreliable(unreliableLeft, unreliableRight);
381 // process unreliable handles cases where unidentified resources have path of length one to identified resource
383 c |= processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight,false);
384 if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
385 c |= processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight,true);
387 if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
388 c |= processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight,false);
390 if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
391 c |= processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight,true);
393 if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
394 // comparison is ending, but we have still unprocessed unidentified resources left.
395 // These cases have longer path than one to identified objects.
396 c |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);
398 if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {
399 // comparison is ending, but we have still unprocessed unidentified resources left.
400 // These cases have longer path than one to identified objects.
401 c |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);
406 process(objectsLeft, objectsRight, unreliableLeft, unreliableRight,true);
411 private String monitorTaskName(Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Set<Statement> unreliableLeft, Set<Statement> unreliableRight) {
412 int cr = comparableResources.size();
413 int ch = Math.max(changes1.size(), changes2.size());
414 return "Graph compare " + (cr + ch) + " / " + (cr+ch+(Math.max(objectsLeft.size(), objectsRight.size())+Math.max(unreliableLeft.size(), unreliableRight.size())));
417 private boolean process(Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Set<Statement> unreliableLeft, Set<Statement> unreliableRight, boolean useBest) throws DatabaseException {
418 List<Statement> ss1 = new ArrayList<Statement>();
419 List<Statement> ss2 = new ArrayList<Statement>();
420 boolean didSomething = false;
421 while (!objectsLeft.isEmpty()&& (maxIter < 0 || iter < maxIter)) {
422 Resource r1 = objectsLeft.pop();
423 Resource r2 = objectsRight.pop();
427 if (processedResources.contains(r1))
429 processedResources.add(r1);
432 if((comparableResources.containsLeft(r1)||comparableResources.containsRight(r2)) && !comparableResources.contains(r1, r2)) {
433 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.");
435 addComparable(r1, r2);
437 //System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));
438 compareProps(r1, r2);
440 for (Resource rel : tested) {
441 ss1.addAll(g.getStatements(r1, rel));
442 ss2.addAll(g.getStatements(r2, rel));
443 ss1 = filterAsserted(r1, ss1);
444 ss2 = filterAsserted(r2, ss2);
445 ss1 = filterTraversed(ss1);
446 ss2 = filterTraversed(ss2);
447 ss1 = filterNonTested(ss1);
448 ss2 = filterNonTested(ss2);
449 ss1 = filter(Collections.singletonList(b.HasProperty), ss1);
450 ss2 = filter(Collections.singletonList(b.HasProperty), ss2);
452 compareStatements(ss1, ss2, null, null,null,null, useBest);
457 for (Resource rel : traversed) {
458 ss1.addAll(g.getStatements(r1, rel));
459 ss2.addAll(g.getStatements(r2, rel));
460 ss1 = filterAsserted(r1, ss1);
461 ss2 = filterAsserted(r2, ss2);
462 ss1 = filterNonTraversed(ss1);
463 ss2 = filterNonTraversed(ss2);
464 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight, useBest);
474 private boolean processUnreliable(Set<Statement> unreliableLeft, Set<Statement> unreliableRight) throws DatabaseException {
475 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
476 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
477 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
478 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
479 boolean didSomething = false;
480 for (Statement s : unreliableLeft) {
481 subjectLeft.add(s.getSubject(),s);
482 objectLeft.add(s.getObject(),s);
484 for (Statement s : unreliableRight) {
485 subjectRight.add(s.getSubject(),s);
486 objectRight.add(s.getObject(),s);
489 for (Resource left : subjectLeft.getKeys()) {
490 if (maxIter > 0 && iter > maxIter)
492 Resource right = comparableResources.getRight(left);
495 for (Statement leftS : subjectLeft.getValues(left)) {
496 Resource leftO = leftS.getObject();
497 if (!unreliableLeft.contains(leftS))
499 Resource rightO = comparableResources.getRight(leftO);
502 for (Statement rightS : subjectRight.getValues(right)) {
503 if (!rightS.getObject().equals(rightO))
505 if (!unreliableRight.contains(rightS))
507 if (leftS.getPredicate().equals(rightS.getPredicate()) ||
508 comparableResources.contains(leftS.getPredicate(), rightS.getPredicate())) {
509 unreliableLeft.remove(leftS);
510 unreliableRight.remove(rightS);
511 addComparable(leftS, rightS);
521 private boolean processUnreliable(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, boolean useBest) throws DatabaseException {
522 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
523 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
524 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
525 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
526 boolean didSomething = false;
527 for (Statement s : unreliableLeft) {
528 subjectLeft.add(s.getSubject(),s);
529 objectLeft.add(s.getObject(),s);
531 for (Statement s : unreliableRight) {
532 subjectRight.add(s.getSubject(),s);
533 objectRight.add(s.getObject(),s);
535 for (Resource ol : objectLeft.getKeys()) {
536 if (maxIter > 0 && iter > maxIter)
538 // all statements to the left side object
539 List<Statement> left = objectLeft.getValues(ol);
540 // all subjects that have statements to the left side object (ol)
541 Set<Resource> sLeft = new HashSet<Resource>();
542 // all matching subjects on the right side
543 Set<Resource> sRight = new HashSet<Resource>();
544 for (Statement s : left) {
545 sLeft.add(s.getSubject());
546 sRight.add(comparableResources.getRight(s.getSubject()));
549 // check if object left can be reliably identified by available statements
550 // if there are any objects on the left side with similar statements, object left cannot be mapped.
551 boolean hasSimilar = false;
552 MapList<Resource, Statement> comparableOLeft = new MapList<Resource, Statement>();
553 for (Resource sl : sLeft) {
554 for (Statement s : subjectLeft.getValues(sl)) {
555 if (!s.getObject().equals(ol)) {
556 comparableOLeft.add(s.getObject(),s);
561 for (Resource similarOl : comparableOLeft.getKeys()) {
562 List<Statement> similarLeft = comparableOLeft.getValues(similarOl);
563 if (similarLeft.size() == left.size()) {
564 boolean useL[] = new boolean[left.size()];
565 boolean useSL[] = new boolean[left.size()];
566 for (int i = 0; i < left.size(); i++) {
570 for (int i = 0; i < left.size(); i++) {
571 for (int j = 0; j < left.size(); j++) {
574 // compare predicates
575 Resource pl = left.get(i).getPredicate();
576 Resource psl = similarLeft.get(j).getPredicate();
577 if (pl.equals(psl)) {
578 // compare objects (unreliable result is interpreted as positive match)
580 int comp = comparator.compare(g, left.get(i).getObject(), similarLeft.get(j).getObject(), true);
581 if (comp >= 0 && comp < ResourceComparator.NO_MATCH) {
589 boolean diff = false;
590 for (int i = 0; i < left.size(); i++) {
591 if (!useL[i] || !useSL[i]) {
606 // all objects that subjects on the right side point to. Object left has its matching resource among these, if it has matching resource
607 MapList<Resource,Statement> possibleOR = new MapList<Resource, Statement>();
608 for (Resource sr : sRight) {
609 for (Statement s : subjectRight.getValues(sr))
610 possibleOR.add(s.getObject(),s);
613 // filter possible right side objects to those that have same amount of statements as the left side object
614 for (Resource or : possibleOR.getKeys().toArray(new Resource[possibleOR.getKeys().size()])) {
615 List<Statement> right = possibleOR.getValues(or);
616 if (right.size() != left.size())
617 possibleOR.remove(or);
621 // check for matching statements (comparable subjects, matching predicates)
622 MapList<Resource,Statement> matchingOR = new MapList<Resource, Statement>(); // list of objects that have matching statements
623 Map<Resource,Pair<int[], int[]>> matchingStatements = new HashMap<Resource, Pair<int[], int[]>>(); // matching statements
624 for (Resource or : possibleOR.getKeys()) {
625 List<Statement> right = possibleOR.getValues(or);
626 int iLeft[] = new int[left.size()];
627 int iRight[] = new int[right.size()];
629 for (int i = 0; i < left.size(); i++) {
634 for (int l = 0; l < left.size(); l++) {
635 Statement ls = left.get(l);
636 for (int r = 0; r < right.size(); r++) {
639 Statement rs = right.get(r);
640 if (!comparableResources.contains(ls.getSubject(), rs.getSubject()))
642 if ((comparableResources.containsLeft(ls.getObject()) || comparableResources.containsRight(rs.getObject())) && !comparableResources.contains(ls.getObject(), rs.getObject()))
644 if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) {
645 // compare objects (unreliable result is not accepted)
646 int comp = comparator.compare(g, ls.getObject(), rs.getObject());
647 if (comp > 0 && comp < Integer.MAX_VALUE) {
657 boolean success = true;
658 for (int i = 0; i < left.size(); i++) {
670 for (Statement s : right)
671 matchingOR.add(or,s);
672 matchingStatements.put(or, new Pair<int[], int[]>(iLeft, iRight));
675 // if there is only one matching right side object, we have found a match
676 if (matchingOR.getKeySize() == 1) {
677 Resource or = matchingOR.getKeys().iterator().next();
678 List<Statement> right = matchingOR.getValues(or);
679 Pair<int[], int[]> indices = matchingStatements.get(or);
682 objectsRight.add(or);
683 addComparable(ol, or);
685 for (int l = 0; l < left.size(); l++) {
686 int r = indices.first[l];
687 Statement sl = left.get(l);
688 Statement sr = right.get(r);
689 addComparable(sl, sr);
690 unreliableLeft.remove(sl);
691 unreliableRight.remove(sr);
705 private boolean processUnreliable2(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, boolean useBest) throws DatabaseException {
706 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
707 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
708 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
709 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
710 boolean didSomething = false;
711 for (Statement s : unreliableLeft) {
712 subjectLeft.add(s.getSubject(),s);
713 objectLeft.add(s.getObject(),s);
715 for (Statement s : unreliableRight) {
716 subjectRight.add(s.getSubject(),s);
717 objectRight.add(s.getObject(),s);
719 Set<Pair<Resource, Resource>> processed = new HashSet<Pair<Resource,Resource>>();
720 for (Resource ol : objectLeft.getKeys()) {
721 if (maxIter > 0 && iter > maxIter)
723 // all statements to the left side object
724 List<Statement> left = objectLeft.getValues(ol);
725 // all subjects that have statements to the left side object (ol)
726 Set<Resource> sLeft = new HashSet<Resource>();
727 // all matching subjects on the right side
728 Set<Resource> sRight = new HashSet<Resource>();
729 for (Statement s : left) {
730 sLeft.add(s.getSubject());
731 sRight.add(comparableResources.getRight(s.getSubject()));
734 if (sLeft.size() == 1 && sRight.size() == 1) {
735 Resource sl = sLeft.iterator().next();
736 Resource sr = sRight.iterator().next();
737 Pair<Resource, Resource> p = new Pair<Resource, Resource>(sl, sr);
738 if (processed.contains(p))
741 List<Statement> ss1 = new ArrayList<Statement>(subjectLeft.getValuesSnapshot(sl));
742 List<Statement> ss2 = new ArrayList<Statement>(subjectRight.getValuesSnapshot(sr));
743 for (int i = ss1.size() -1; i >= 0; i--) {
744 if (!unreliableLeft.contains(ss1.get(i)))
747 for (int i = ss2.size() -1; i >= 0; i--) {
748 if (!unreliableRight.contains(ss2.get(i)))
752 int ccount = comparableStatements.size();
753 int lcount = changes1.size();
754 int rcount = changes2.size();
756 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight, useBest);
757 if (comparableStatements.size() > ccount) {
759 for (Entry<Statement, Statement> entry : comparableStatements.getEntries()) {
760 unreliableLeft.remove(entry.getKey());
761 unreliableRight.remove(entry.getValue());
765 if (changes1.size() > lcount) {
767 for (Statement stm : changes1) {
768 unreliableLeft.remove(stm);
772 if (changes2.size() > rcount) {
774 for (Statement stm : changes2) {
775 unreliableRight.remove(stm);
784 private boolean processUnreliableDeep(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {
785 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
786 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
787 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
788 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
789 boolean didSomething = false;
790 for (Statement s : unreliableLeft) {
791 subjectLeft.add(s.getSubject(),s);
792 objectLeft.add(s.getObject(),s);
794 for (Statement s : unreliableRight) {
795 subjectRight.add(s.getSubject(),s);
796 objectRight.add(s.getObject(),s);
798 for (Resource ol : objectLeft.getKeys()) {
799 if (maxIter > 0 && iter > maxIter)
801 Set<Path> pathsLeft = new HashSet<Path>();
802 for (Resource rel : traversed) {
803 pathsLeft.addAll(Path.create(g.getStatements(ol, rel)));
807 if (pathsLeft.size() == 0)
809 Collection<Path> endPaths = new ArrayList<Path>(1);
810 for (Path p : pathsLeft) {
811 if (comparableResources.containsLeft(p.getEnd())) {
815 if (endPaths.size() > 0) {
817 pathsLeft.addAll(endPaths);
821 if (pathsLeft.size() > 0) {
822 Resource sl = objectLeft.getValues(ol).get(0).getSubject();
823 Resource sr = comparableResources.getRight(sl);
824 Collection<Resource> possibleOR = new ArrayList<Resource>();
825 for (Statement s : subjectRight.getValues(sr)) {
826 possibleOR.add(s.getObject());
828 Map<Resource,Set<Path>> matchingPaths = new HashMap<Resource, Set<Path>>();
829 for (Resource or : possibleOR) {
830 Set<Path> possiblePathsRight = new HashSet<Path>();
831 for (Path leftPath : pathsLeft) {
832 possiblePathsRight.addAll(findComparableRight(leftPath, or));
834 if (hasMatchingPaths(pathsLeft, possiblePathsRight)) {
835 matchingPaths.put(or, possiblePathsRight);
838 if (matchingPaths.size() > 0) {
839 if (matchingPaths.size() == 1) {
840 Resource or = matchingPaths.keySet().iterator().next();
841 BijectionMap<Path,Path> map = getMatchingPaths(pathsLeft, matchingPaths.get(or));
842 BijectionMap<Resource,Resource> toMap = new BijectionMap<Resource, Resource>();
845 // Path matching may create conflicting results, prevent selecting them.
846 for (Path left : map.getLeftSet()) {
847 Path right = map.getRight(left);
848 for (int i = 0; i < left.getLength(); i++) {
849 Resource l = left.getStatements().get(i).getObject();
850 Resource r = right.getStatements().get(i).getObject();
851 if (comparableResources.contains(l, r))
853 if (comparableResources.containsLeft(l)) {
857 if (comparableResources.containsRight(r)) {
861 if (toMap.contains(l,r))
863 if (toMap.containsLeft(l)) {
867 if (toMap.containsRight(r)) {
879 objectsRight.add(or);
880 addComparable(ol, or);
881 Collection<Statement> statementsLeft = objectLeft.getValues(ol);
882 Collection<Statement> statementsRight = objectRight.getValues(or);
883 unreliableLeft.removeAll(statementsLeft);
884 unreliableRight.removeAll(statementsRight);
885 for (Path left : map.getLeftSet()) {
886 Path right = map.getRight(left);
887 for (int i = 0; i < left.getLength(); i++) {
888 addComparable(left.getStatements().get(i),right.getStatements().get(i));
905 private boolean hasMatchingPaths(Set<Path> leftPaths, Set<Path> rightPaths) throws DatabaseException {
906 if (leftPaths.size() != rightPaths.size())
908 BijectionMap<Path,Path> map = getMatchingPaths(leftPaths, rightPaths);
909 return map.size() == leftPaths.size();
912 private BijectionMap<Path,Path> getMatchingPaths(Set<Path> leftPaths, Set<Path> rightPaths) throws DatabaseException {
913 BijectionMap<Path,Path> map = new BijectionMap<Path, Path>();
914 for (Path leftPath : leftPaths) {
915 for (Path rightPath : rightPaths) {
916 if (map.containsRight(rightPath))
918 if (leftPath.getLength() != rightPath.getLength())
920 if (comparableResources.contains(leftPath.getEnd(), rightPath.getEnd())) {
921 boolean match = true;
922 for (int i = 0; i < leftPath.getLength(); i++) {
923 Statement sl = leftPath.getStatements().get(i);
924 Statement sr = rightPath.getStatements().get(i);
925 if (!sl.getPredicate().equals(sr.getPredicate()) && !comparableResources.contains(sl.getPredicate(), sr.getPredicate())) {
929 if ((getComparableResources().containsLeft(sl.getObject()) || getComparableResources().containsRight(sr.getObject())) && !getComparableResources().contains(sl.getObject(), sr.getObject())) {
933 if (comparator.compare(g, sl.getObject(), sr.getObject()) == ResourceComparator.NO_MATCH) {
939 map.map(leftPath, rightPath);
948 private void expand(Set<Path> paths) throws DatabaseException {
949 Set<Path> stepPathsLeft = new HashSet<Path>();
950 if (paths.size() == 0)
952 int length = paths.iterator().next().getLength() + 1;
953 for (Path p : paths) {
954 for (Resource rel : traversed) {
955 stepPathsLeft.addAll(Path.expand(p,g.getStatements(p.getEnd(), rel)));
959 for (Path p : stepPathsLeft) {
960 if (p.getLength() == length)
965 private Collection<Path> findComparableRight(Path leftPath, Resource beginRight) throws DatabaseException {
966 Set<Path> rightPaths = new HashSet<Path>();
967 rightPaths.addAll(Path.create(g.getStatements(beginRight, getRight(leftPath.getStatements().get(0).getPredicate()))));
968 for (int i = 1; i < leftPath.getLength(); i++) {
969 if (rightPaths.size() == 0)
971 Set<Path> stepPaths = new HashSet<Path>();
972 for (Path p : rightPaths) {
973 stepPaths.addAll(Path.expand(p, g.getStatements(p.getEnd(), getRight(leftPath.getStatements().get(i).getPredicate()))));
976 for (Path p : stepPaths)
977 if (p.getLength() == i+1)
984 private Resource getRight(Resource r) {
985 if (comparableResources.containsLeft(r))
986 return comparableResources.getRight(r);
992 public BijectionMap<Statement, Statement> getComparableStatements() {
993 return comparableStatements;
996 public BijectionMap<Resource, Resource> getComparableResources() {
997 return comparableResources;
1000 public GraphChanges getChanges() {
1001 return new GraphChanges(r1,r2,changes1,changes2,modifications,comparableResources);
1004 public List<Statement> getChanges1() {
1008 public List<Statement> getChanges2() {
1012 private void addComparable(Statement left, Statement right) throws DatabaseException {
1013 addComparable(left.getObject(), right.getObject());
1014 comparableStatements.map(left, right);
1017 private void addComparable(Resource left, Resource right) throws DatabaseException {
1018 if(!comparableResources.contains(left, right)) {
1019 if (comparableResources.containsLeft(left)||comparableResources.containsRight(right)) {
1020 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.");
1022 if (DEBUG) System.out.println(left + " = " + right);
1023 comparableResources.map(left, right);
1025 // if (comparableResources.size() % 1000 == 0)
1032 public void printStats() {
1033 System.out.println("Comp " + comparableResources.size() + " L " + changes1.size() + " R " + changes2.size() + " M " + modifications.size() + " P " + processedResources.size());
1036 public List<Statement> filterAsserted(Resource r, Collection<Statement> in) throws DatabaseException {
1037 List<Statement> out = new ArrayList<Statement>();
1038 for (Statement s : in) {
1039 if (!s.isAsserted(r))
1046 public List<Statement> filterAssertedDuplicates(Resource r, List<Statement> in) throws DatabaseException {
1047 List<Statement> out = new ArrayList<Statement>();
1048 for (int i = 0; i < in.size(); i++) {
1049 Statement s = in.get(i);
1050 if (!s.isAsserted(r))
1053 boolean has = false;
1054 if (i > 0 && in.get(i-1).getPredicate().equals(s.getPredicate()))
1056 else if (i < in.size()-1 && in.get(i+1).getPredicate().equals(s.getPredicate()))
1068 private String printStatement(ReadGraph graph, Statement s) throws DatabaseException {
1069 return NameUtils.getSafeName(graph, s.getSubject()) + " " + NameUtils.getSafeName(graph, s.getPredicate()) + " " + NameUtils.getSafeName(graph, s.getObject());
1072 private List<Statement> filterTraversed(List<Statement> in) throws DatabaseException {
1073 return filter(traversed, in);
1076 private List<Statement> filterNonTested(List<Statement> in) throws DatabaseException {
1077 return filter(nonTested, in);
1080 private List<Statement> filterNonTraversed(List<Statement> in) throws DatabaseException {
1081 return filter(nonTraversed, in);
1084 private List<Statement> filter(Collection<Resource> toFilter, List<Statement> in) throws DatabaseException {
1085 if (toFilter.size() == 0)
1087 List<Statement> out = new ArrayList<Statement>();
1088 for (Statement s : in) {
1089 boolean usable = true;
1090 for (Resource r : toFilter) {
1091 if (g.isSubrelationOf(s.getPredicate(),r)) {
1105 private void addDeletion(Statement s) {
1106 if (!changes1Set.contains(s)) {
1107 if (DEBUG) System.out.println("- " +s.getSubject() + " " + s.getPredicate() + " " + s.getObject()) ;
1113 private void addAddition(Statement s) {
1114 if (!changes2Set.contains(s)) {
1116 if (DEBUG) System.out.println("+ " +s.getSubject() + " " + s.getPredicate() + " " + s.getObject()) ;
1121 private void addModification(Resource left, Statement leftstm, Resource right, Statement rightstm) throws DatabaseException {
1122 Modification mod = new Modification(left, right, leftstm, rightstm);
1123 if (!modificationsSet.contains(mod)) {
1124 modificationsSet.add(mod);
1125 modifications.add(mod);
1126 if (mapLiterals && leftstm != null && rightstm != null)
1127 addComparable(leftstm, rightstm);
1131 public void sortStatement(List<Statement> list1, List<Statement> list2) {
1132 sortStatement(list1, list2, scomp);
1135 public void sortStatement(List<Statement> list1, List<Statement> list2, Comparator<Statement> scomp) {
1136 Collections.sort(list1,scomp);
1137 Collections.sort(list2,scomp);
1139 List<Statement> sorted1 = new ArrayList<Statement>(list1.size());
1140 List<Statement> sorted2 = new ArrayList<Statement>(list2.size());
1141 sorted1.addAll(list1);
1142 sorted2.addAll(list2);
1146 for (int i = 0; i < list1.size(); ) {
1147 Statement s1 = list1.get(i);
1148 int same1 = sameRel(list1, i);
1149 for (int j = 0; j < list2.size(); j++) {
1150 Statement s2 = list2.get(j);
1151 if (scomp.compare(s1, s2) == 0) {
1152 int same2 = sameRel(list2, j);
1153 copy(sorted1,ss1,list1,i,same1);
1155 copy(sorted2,ss2,list2,j,same2);
1162 if (ss1 < sorted1.size()) {
1163 for (Statement s : list1) {
1164 if (!sorted1.contains(s)) {
1170 if (ss2 < sorted2.size()) {
1171 for (Statement s : list2) {
1172 if (!sorted2.contains(s)) {
1181 list1.addAll(sorted1);
1182 list2.addAll(sorted2);
1185 public <T> void copy(List<T> to, int toIndex, List<T> from, int fromIndex, int amount) {
1186 for (int i = 0; i < amount; i++) {
1187 to.set(toIndex + i, from.get(fromIndex+ i));
1191 public void sortResource(List<Resource> list1, List<Resource> list2) {
1192 Collections.sort(list1,rcomp);
1194 for (int i = 0; i < list1.size(); i++) {
1195 Resource s1 = list1.get(i);
1196 for (int j = js; j < list2.size(); j++) {
1197 Resource s2 = list2.get(j);
1198 if (rcomp.compare(s1, s2) == 0) {
1199 Resource t = list2.get(js);
1209 private void compareStatements(List<Statement> ss1, List<Statement> ss2, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Collection<Statement> unreliableLeft, Collection<Statement> unreliableRight, boolean useBest) throws DatabaseException {
1210 sortStatement(ss1, ss2);
1216 if (i1 >= ss1.size()) {
1217 if (i2 >= ss2.size()) {
1220 while (i2 < ss2.size()) {
1221 if (DEBUG) System.out.println("Compare Statements addition " + printStatement(g,ss2.get(i2)));
1223 addAddition(ss2.get(i2));
1228 } else if (i2 >= ss2.size()) {
1229 while (i1 < ss1.size()) {
1230 if (DEBUG) System.out.println("Compare Statements deletion " + printStatement(g,ss1.get(i1)));
1231 addDeletion(ss1.get(i1));
1236 int same1 = sameRel(ss1, i1);
1237 int same2 = sameRel(ss2, i2);
1238 int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate());
1240 compareStatements(ss1, i1, same1, ss2, i2, same2,objectsLeft,objectsRight,unreliableLeft,unreliableRight, useBest);
1244 for (int i = 0; i < same1; i++) {
1245 if (DEBUG) System.out.println("Compare Statements deletion " + printStatement(g,ss1.get(i+i1)));
1246 addDeletion(ss1.get(i+i1));
1250 for (int i = 0; i < same2; i++) {
1251 if (DEBUG) System.out.println("Compare Statements addition " + printStatement(g,ss2.get(i+i2)));
1252 addAddition(ss2.get(i+i2));
1262 private int sameRel(List<Statement> statements, int off) {
1263 if (statements.size() <= off)
1266 long id = statements.get(off).getPredicate().getResourceId();
1267 for (int i = off+1; i <statements.size(); i++) {
1268 if (statements.get(i).getPredicate().getResourceId() == id)
1277 private int compareObject(Resource o1, Resource o2) throws DatabaseException {
1280 if (comparableResources.contains(o1, o2))
1282 if (comparableResources.containsLeft(o1))
1283 return Integer.MAX_VALUE;
1284 if (comparableResources.containsRight(o2))
1285 return Integer.MAX_VALUE;
1286 if (nonMatchedLeft.contains(o1))
1287 return Integer.MAX_VALUE;
1288 if (nonMatchedRight.contains(o2))
1289 return Integer.MAX_VALUE;
1290 return comparator.compare(g, o1, o2);
1293 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, boolean useBest) throws DatabaseException {
1294 boolean[] used1 = new boolean[len1];
1295 for (int i = 0; i < used1.length; i++) {
1299 boolean[] used2 = new boolean[len2];
1300 for (int i = 0; i < used2.length; i++) {
1304 // left, right, difference
1305 List<List<Integer>> differences = new ArrayList<List<Integer>>();
1306 for (int i1 = off1; i1 < off1 + len1; i1++) {
1307 Statement s1 = ss1.get(i1);
1308 List<Integer> diff = new ArrayList<Integer>();
1309 for (int i2 = off2; i2 < off2 + len2; i2++) {
1310 Statement s2 = ss2.get(i2);
1311 int d = compareObject(s1.getObject(), s2.getObject());
1313 for (Resource t : strong) {
1314 if (s1.getPredicate().equals(t) || g.isSubrelationOf(s1.getPredicate(), t)) {
1322 differences.add(diff);
1325 MapList<Integer, Integer> priorities = new MapList<Integer, Integer>();
1326 for (int i = 0; i < differences.size(); i++) {
1327 List<Integer> list = differences.get(i);
1328 for (int j = 0; j < list.size(); j++) {
1329 priorities.add(list.get(j), i);
1333 Integer[] pris = priorities.getKeys(new Integer[]{});
1335 boolean matchFail = priorityMatching(ss1, off1, len1, ss2, off2, len2, pris, differences, priorities, used1, used2, objectsLeft, objectsRight, false);
1336 if (matchFail && objectsLeft == null)
1337 matchFail = priorityMatching(ss1, off1, len1, ss2, off2, len2, pris, differences, priorities, used1, used2, objectsLeft, objectsRight,true);
1339 if (unreliableLeft != null) {
1342 bestMatching(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, objectsLeft, objectsRight);
1343 // With match failure, statement matching was aborted. We must move all unmatched statements to unreliable.
1344 for (Integer pri : pris) {
1345 if (pri == 0 || pri == Integer.MAX_VALUE)
1347 priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, pri);
1350 // Zero means unreliable comparison result, move all unmatched to unreliable.
1351 if (org.simantics.utils.datastructures.Arrays.contains(pris, 0)) {
1352 priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, 0);
1355 // Previous version processed 0 priority statements, even when unreliableLeft collection was null.
1356 // The problem was that property relations were not filtered in process() from "tested" statements.
1358 // if (org.simantics.utils.datastructures.Arrays.contains(pris, 0)) {
1359 // priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, 0);
1362 // Report unmatched statements as changes.
1363 for (int i1 = off1; i1 < off1 + len1; i1++) {
1364 if (!used1[i1-off1]) {
1365 if (DEBUG) System.out.println("Compare Object deletion " + printStatement(g,ss1.get(i1)));
1366 addDeletion(ss1.get(i1));
1369 for (int i2 = off2; i2 < off2 + len2; i2++) {
1370 if (!used2[i2-off2]) {
1371 if (DEBUG) System.out.println("Compare Object addition " + printStatement(g,ss2.get(i2)));
1372 addAddition(ss2.get(i2));
1378 * Moves unmatched statements to unreliable collections.
1385 * @param differences
1389 * @param unreliableLeft
1390 * @param unreliableRight
1393 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) {
1394 Set<Statement> s1s = new HashSet<Statement>();
1395 Set<Statement> s2s = new HashSet<Statement>();
1396 Set<Integer> s1i = new HashSet<Integer>();
1397 Set<Integer> s2i = new HashSet<Integer>();
1398 List<Integer> i1s = priorities.getValues(pri);
1399 for (Integer i1 : i1s) {
1402 List<Integer> i2diff = differences.get(i1);
1403 for (int i2 = 0; i2 < i2diff.size(); i2++) {
1404 if (i2diff.get(i2) == pri) {
1407 Statement s1 = ss1.get(i1+off1);
1408 Statement s2 = ss2.get(i2+off2);
1416 if (unreliableLeft != null) {
1417 unreliableLeft.addAll(s1s);
1418 unreliableRight.addAll(s2s);
1420 for (Integer i : s1i)
1422 for (Integer i : s2i)
1426 * Matches left and right side statements.
1428 * When there are two or more equally good matching objects, the behaviour depends on force flag.
1429 * False: Matching is aborted and matchFail is returned (method return true).
1430 * True: equally good matches will be paired randomly. Method always returns false.
1438 * @param differences
1442 * @param objectsLeft
1443 * @param objectsRight
1446 * @throws DatabaseException
1448 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 {
1449 boolean matchFail = false;
1450 for (Integer pri : pris) {
1451 if (pri == Integer.MAX_VALUE) {
1453 } else if (pri == 0) {
1456 List<Integer> i1s = priorities.getValues(pri);
1458 for (Integer i1 : i1s) {
1461 List<Integer> i2diff = differences.get(i1);
1462 List<Integer> matches = new ArrayList<Integer>();
1463 for (int i2 = 0; i2 < i2diff.size(); i2++) {
1464 if (i2diff.get(i2) == pri) {
1470 if (matches.size() == 1 || (force && matches.size() > 1)) {
1471 int i2 = matches.get(0);
1474 Statement s1 = ss1.get(i1+off1);
1475 Statement s2 = ss2.get(i2+off2);
1477 if (objectsLeft != null) {
1478 objectsLeft.add(s1.getObject());
1479 objectsRight.add(s2.getObject());
1481 addComparable(s1, s2);
1482 } else if (matches.size() > 1) {
1494 * priority matching has a flaw, if lowest priority produces conflicting results, it is not able to match anything.
1495 * This matching logic looks for a best match, and if it is non conflicting applies the match.
1497 * TODO: now this applies all unique lowest priority matches for each object. Should this pick only the object with global lowest priority,
1498 * so that new matches improve situation with conflicting (non unique) matches?
1506 * @param differences
1510 * @param objectsLeft
1511 * @param objectsRight
1512 * @throws DatabaseException
1514 private void bestMatching(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<Resource> objectsLeft, Collection<Resource> objectsRight) throws DatabaseException {
1515 for (int i1 = 0; i1 < differences.size(); i1++) {
1518 List<Integer> diffs = differences.get(i1);
1519 int min = Integer.MAX_VALUE;
1521 for (int j = 0; j < diffs.size(); j++) {
1522 int p = diffs.get(j);
1528 } else if (p == min) {
1532 if (minIndex >= 0 && min > 0) {
1537 Statement s1 = ss1.get(i1+off1);
1538 Statement s2 = ss2.get(i2+off2);
1540 if (objectsLeft != null) {
1541 objectsLeft.add(s1.getObject());
1542 objectsRight.add(s2.getObject());
1544 addComparable(s1, s2);
1552 * compares properties, assumes functional relations
1555 * @throws DatabaseException
1557 private void compareProps(Resource r1, Resource r2) throws DatabaseException {
1558 if (DEBUG) System.out.println("compareProps " + r1 + " " + NameUtils.getSafeName(g, r1) + " " + r2 + " " + NameUtils.getSafeName(g, r2));
1559 List<Statement> ss1 = new ArrayList<Statement>();
1560 List<Statement> ss2 = new ArrayList<Statement>();
1561 ss1.addAll(g.getStatements(r1, b.HasProperty));
1562 ss2.addAll(g.getStatements(r2, b.HasProperty));
1563 ss1 = filterNonTested(ss1);
1564 ss2 = filterNonTested(ss2);
1565 sortStatement(ss1, ss2);
1566 // getStatements(r1, b.HasProperty) returns both instance and asserted statements for the same property relation.
1567 ss1 = filterAssertedDuplicates(r1, ss1);
1568 ss2 = filterAssertedDuplicates(r2, ss2);
1574 if (i1 >= ss1.size()) {
1575 if (i2 >= ss2.size())
1578 while (i2 < ss2.size()) {
1579 Statement s = ss2.get(i2);
1580 if (DEBUG) System.out.println("Compare Prop diff2 " + printStatement(g,s));
1581 if (!s.isAsserted(r2))
1587 } else if (i2 >= ss2.size()) {
1588 while (i1 < ss1.size()) {
1589 Statement s = ss1.get(i1);
1590 if (DEBUG) System.out.println("Compare Prop diff1 " + printStatement(g,s));
1591 if (!s.isAsserted(r1))
1597 Statement s1 = ss1.get(i1);
1598 Statement s2 = ss2.get(i2);
1599 if (s1.isAsserted(r1) && s2.isAsserted(r2)) {
1604 int c = scomp.compare(s1, s2);
1607 boolean b1 = g.hasValue(s1.getObject());
1608 boolean b2 = g.hasValue(s2.getObject());
1609 boolean a1 = s1.isAsserted(r1);
1610 boolean a2 = s2.isAsserted(r2);
1614 boolean eq = compareValue(g,b,s1.getObject(), s2.getObject());
1616 addModification(r1,s1,r2,s2);
1618 if (mapLiterals && !a1 && !a2)
1619 addComparable(s1, s2);
1621 // Non literal properties.
1622 int comp = comparator.compare(g, s1.getObject(), s2.getObject());
1623 if (comp == ResourceComparator.NO_MATCH) {
1624 addModification(r1,s1,r2,s2);
1625 } else if (comp != ResourceComparator.EXACT_MATCH) {
1626 if (!s1.getObject().equals(s1.getSubject()) && !s2.getObject().equals(s2.getSubject())) {
1628 // compare props matches objects, so we can call that only for non asserted statements
1629 compareProps(s1.getObject(), s2.getObject());
1630 } else if (a1 && a2) {
1631 // TODO : compare asserted statements?
1633 addModification(r1,s1,r2,s2);
1636 addModification(r1,s1,r2,s2);
1639 // Exact match, nothing to do.
1641 addComparable(s1, s2);
1645 addModification(r1,s1,r2,s2);
1652 if (DEBUG) System.out.println("Compare Prop diff1s " + printStatement(g,s1));
1653 // Use modification, since deletions do not support asserted statements
1654 addModification(r1,s1,r2,null);
1661 if (DEBUG) System.out.println("Compare Prop diff2s " + printStatement(g,s2));
1662 // Use modification, since additions do not support asserted statements
1663 addModification(r1,null,r2,s2);
1677 public static boolean compareValue(ReadGraph g, Layer0 b, Resource r1, Resource r2) throws DatabaseException {
1678 Resource t1 = g.getSingleType(r1);
1679 Resource t2 = g.getSingleType(r2);
1682 if (t1.equals(b.Integer)) {
1683 int v1 = g.getValue(r1, Bindings.INTEGER);
1684 int v2 = g.getValue(r2, Bindings.INTEGER);
1686 } else if (t1.equals(b.Float)) {
1687 float v1 = g.getValue(r1, Bindings.FLOAT);
1688 float v2 = g.getValue(r2, Bindings.FLOAT);
1690 } else if (t1.equals(b.Double)) {
1691 double v1 = g.getValue(r1, Bindings.DOUBLE);
1692 double v2 = g.getValue(r2, Bindings.DOUBLE);
1694 } else if (t1.equals(b.String)) {
1695 String v1 = g.getValue(r1, Bindings.STRING);
1696 String v2 = g.getValue(r2, Bindings.STRING);
1697 return v1.equals(v2);
1698 } else if (t1.equals(b.Boolean)) {
1699 boolean v1 = g.getValue(r1, Bindings.BOOLEAN);
1700 boolean v2 = g.getValue(r2, Bindings.BOOLEAN);
1702 } else if (t1.equals(b.Byte)) {
1703 byte v1 = g.getValue(r1, Bindings.BYTE);
1704 byte v2 = g.getValue(r2, Bindings.BYTE);
1706 } else if (t1.equals(b.Long)) {
1707 long v1 = g.getValue(r1, Bindings.LONG);
1708 long v2 = g.getValue(r2, Bindings.LONG);
1710 } else if (t1.equals(b.IntegerArray)) {
1711 int[] v1 = g.getValue(r1, Bindings.INT_ARRAY);
1712 int[] v2 = g.getValue(r2, Bindings.INT_ARRAY);
1713 return Arrays.equals(v1,v2);
1714 } else if (t1.equals(b.FloatArray)) {
1715 float[] v1 = g.getValue(r1, Bindings.FLOAT_ARRAY);
1716 float[] v2 = g.getValue(r2, Bindings.FLOAT_ARRAY);
1717 return Arrays.equals(v1,v2);
1718 } else if (t1.equals(b.DoubleArray)) {
1719 double[] v1 = g.getValue(r1, Bindings.DOUBLE_ARRAY);
1720 double[] v2 = g.getValue(r2, Bindings.DOUBLE_ARRAY);
1721 return Arrays.equals(v1,v2);
1722 } else if (t1.equals(b.StringArray)) {
1723 String[] v1 = g.getValue(r1, Bindings.STRING_ARRAY);
1724 String[] v2 = g.getValue(r2, Bindings.STRING_ARRAY);
1725 return Arrays.equals(v1,v2);
1726 } else if (t1.equals(b.BooleanArray)) {
1727 boolean[] v1 = g.getValue(r1, Bindings.BOOLEAN_ARRAY);
1728 boolean[] v2 = g.getValue(r2, Bindings.BOOLEAN_ARRAY);
1729 return Arrays.equals(v1,v2);
1730 } else if (t1.equals(b.ByteArray)) {
1731 byte[] v1 = g.getValue(r1, Bindings.BYTE_ARRAY);
1732 byte[] v2 = g.getValue(r2, Bindings.BYTE_ARRAY);
1733 return Arrays.equals(v1,v2);
1734 } else if (t1.equals(b.LongArray)) {
1735 long[] v1 = g.getValue(r1, Bindings.LONG_ARRAY);
1736 long[] v2 = g.getValue(r2, Bindings.LONG_ARRAY);
1737 return Arrays.equals(v1,v2);
1739 Object v1 = g.getValue(r1);
1740 Object v2 = g.getValue(r2);
1741 return compareValue(v1, v2);
1746 public static boolean compareValue(Object v1, Object v2) {
1747 if (v1 instanceof Object[] && v2 instanceof Object[])
1748 return Arrays.deepEquals((Object[])v1, (Object[])v2);
1749 else if (v1 instanceof int[] && v2 instanceof int[])
1750 return Arrays.equals((int[])v1, (int[])v2);
1751 else if (v1 instanceof float[] && v2 instanceof float[])
1752 return Arrays.equals((float[])v1, (float[])v2);
1753 else if (v1 instanceof double[] && v2 instanceof double[])
1754 return Arrays.equals((double[])v1, (double[])v2);
1755 else if (v1 instanceof long[] && v2 instanceof long[])
1756 return Arrays.equals((long[])v1, (long[])v2);
1757 else if (v1 instanceof byte[] && v2 instanceof byte[])
1758 return Arrays.equals((byte[])v1, (byte[])v2);
1759 else if (v1 instanceof boolean[] && v2 instanceof boolean[])
1760 return Arrays.equals((boolean[])v1, (boolean[])v2);
1762 return v1.equals(v2);
1766 public class PredicateComparator implements Comparator<Statement> {
1768 public int compare(Statement o1, Statement o2) {
1769 if (comparableResources.contains(o1.getPredicate(), o2.getPredicate()))
1771 if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())
1773 if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())
1779 public class SubjectComparator implements Comparator<Statement> {
1781 public int compare(Statement o1, Statement o2) {
1782 if (comparableResources.contains(o1.getSubject(), o2.getSubject()))
1784 if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())
1786 if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())
1792 public class ObjectComparator implements Comparator<Statement> {
1794 public int compare(Statement o1, Statement o2) {
1795 if (comparableResources.contains(o1.getObject(), o2.getObject()))
1797 if (o1.getObject().getResourceId() < o2.getObject().getResourceId())
1799 if (o1.getObject().getResourceId() > o2.getObject().getResourceId())
1805 public static class FullStatementComparator implements Comparator<Statement> {
1807 public int compare(Statement o1, Statement o2) {
1808 if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())
1810 if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())
1812 if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())
1814 if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())
1816 if (o1.getObject().getResourceId() < o2.getObject().getResourceId())
1818 if (o1.getObject().getResourceId() > o2.getObject().getResourceId())
1824 public class ResComparator implements Comparator<Resource> {
1826 public int compare(Resource o1, Resource o2) {
1827 if (comparableResources.contains(o1, o2))
1829 if (o1.getResourceId() < o2.getResourceId())
1831 if (o1.getResourceId() > o2.getResourceId())