X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.interop%2Fsrc%2Forg%2Fsimantics%2Finterop%2Ftest%2FGraphComparator.java;h=9ad20611277dd84427e39896c3521c7c31873bf5;hb=92b414c8ba889933a493d10b3c609edbb8aab95e;hp=82320753c7a8eb81e8e1473b1b95954838e6d475;hpb=752a36aca7c905ac07f65799509925e4cb252ab1;p=simantics%2Finterop.git diff --git a/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java b/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java index 8232075..9ad2061 100644 --- a/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java +++ b/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java @@ -8,6 +8,8 @@ * * Contributors: * Foster Wheeler Energia Oy - initial API and implementation + * VTT Technical Research Centre of Finland - Improvements to comparison. + * Semantum Oy - Improvements to comparison, various bug fixes. *******************************************************************************/ package org.simantics.interop.test; @@ -24,6 +26,8 @@ import java.util.Map.Entry; import java.util.Set; import java.util.Stack; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; @@ -32,6 +36,7 @@ import org.simantics.db.Statement; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; import org.simantics.interop.test.GraphChanges.Modification; import org.simantics.layer0.Layer0; import org.simantics.utils.datastructures.BijectionMap; @@ -82,6 +87,9 @@ public class GraphComparator { private Set nonMatchedLeft = new HashSet(); private Set nonMatchedRight = new HashSet(); + private long iter = 0; + private long maxIter = -1; + // runtime attributes private ReadGraph g; @@ -181,12 +189,46 @@ public class GraphComparator { nonMatchedRight.add(r); } + public long getMaxIter() { + return maxIter; + } + + /** + * Sets maximum iteration done on a single DB transaction. Affects only test(Session) methods. + * Default value is -1, which disables iteration limit. + * Note that using iteration limit causes comparison to repeat some work, thus total execution time will increase. + * + * @param maxIter + */ + public void setMaxIter(long maxIter) { + this.maxIter = maxIter; + } + + public void clear() { + changes1.clear(); + changes1Set.clear(); + changes2.clear(); + changes2Set.clear(); + comparableResources.clear(); + comparableStatements.clear(); + modifications.clear(); + modificationsSet.clear(); + processedResources.clear(); + } + public void test(ReadGraph g) throws DatabaseException { + test(g,null); + } + + public void test(ReadGraph g, IProgressMonitor monitor) throws DatabaseException { this.g = g; this.b = Layer0.getInstance(g); comparator.setComparator(this); comparator.initialize(g, r1, r2); + if (monitor == null) + monitor = new NullProgressMonitor(); + Stack objectsLeft = new Stack(); Stack objectsRight = new Stack(); objectsLeft.push(r1); @@ -195,45 +237,57 @@ public class GraphComparator { Set unreliableLeft = new HashSet(); Set unreliableRight = new HashSet(); + boolean changed = false; while (true) { - if (objectsLeft.isEmpty()) + if (objectsLeft.isEmpty() && !changed) break; - + if (monitor.isCanceled()) { + clear(); + return; + } + monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight)); + changed = false; // process compares objects that are identified and searches for more resources to process. - process(objectsLeft, objectsRight, unreliableLeft, unreliableRight); - // process unreliable handles cases where unidentified statements subject and object have been identified - processUnreliable(unreliableLeft, unreliableRight); - // process unreliable handles cases where unidentified resources have path of length one to identified resource - processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight); - if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { - processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight); - } - if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { - // comparison is ending, but we have still unprocessed unidentified resources left. - // These cases have longer path than one to identified objects. - processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight); - } + changed = compareIter(g, objectsLeft, objectsRight, unreliableLeft, unreliableRight); + monitor.worked(1); } for (Statement s : unreliableLeft) { - if (!comparableStatements.containsLeft(s)) + if (!comparableStatements.containsLeft(s)) { + if (DEBUG) System.out.println("Unreliable Object deletion " + printStatement(g,s)); addDeletion(s); + } } for (Statement s : unreliableRight) { - if (!comparableStatements.containsRight(s)) + if (!comparableStatements.containsRight(s)) { + if (DEBUG) System.out.println("Unreliable Object addition " + printStatement(g,s)); addAddition(s); + } } + monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight) + " done."); + //printStats(); } public void test(Session session) throws DatabaseException { - test(session, r1, r2); + test(session, r1, r2, null); + } + + public void test(Session session, IProgressMonitor monitor) throws DatabaseException { + test(session, r1, r2, monitor); } public void test(Session session, Resource r1, Resource r2) throws DatabaseException { + test(session, r1, r2, null); + } + + public void test(Session session, Resource r1, Resource r2, IProgressMonitor monitor) throws DatabaseException { comparator.setComparator(this); + if (monitor == null) + monitor = new NullProgressMonitor(); + session.syncRequest(new ReadRequest() { @Override @@ -252,37 +306,26 @@ public class GraphComparator { final Set unreliableLeft = new HashSet(); final Set unreliableRight = new HashSet(); + boolean changed = false; while (true) { - if (objectsLeft.isEmpty()) + if (objectsLeft.isEmpty() && !changed) break; - session.syncRequest(new ReadRequest() { + if (monitor.isCanceled()) { + clear(); + return; + } + monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight)); + changed = session.syncRequest(new Read() { @Override - public void run(ReadGraph graph) throws DatabaseException { + public Boolean perform(ReadGraph graph) throws DatabaseException { + //System.out.println("Iter " + monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight)); g = graph; b = Layer0.getInstance(graph); - // process compares objects that are identified and searches for more resources to process. - process(objectsLeft, objectsRight, unreliableLeft, unreliableRight); - // process unreliable handles cases where unidentified statements subject and object have been identified - processUnreliable(unreliableLeft, unreliableRight); - // process unreliable handles cases where unidentified resources have path of length one to identified resource - processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight); - if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { - processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight); - } - if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { - // comparison is ending, but we have still unprocessed unidentified resources left. - // These cases have longer path than one to identified objects. - processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight); - } - if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { - // comparison is ending, but we have still unprocessed unidentified resources left. - // These cases have longer path than one to identified objects. - processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight); - } + return compareIter(graph, objectsLeft, objectsRight, unreliableLeft, unreliableRight); } }); - + monitor.worked(1); } @@ -294,15 +337,53 @@ public class GraphComparator { if (!comparableStatements.containsRight(s)) addAddition(s); } + unreliableLeft.clear(); + unreliableRight.clear(); - + monitor.subTask(monitorTaskName(objectsLeft, objectsRight, unreliableLeft, unreliableRight) + " done."); + //printStats(); } - private void process(Stack objectsLeft, Stack objectsRight, Set unreliableLeft, Set unreliableRight) throws DatabaseException { + private boolean compareIter(ReadGraph graph, Stack objectsLeft, Stack objectsRight, Set unreliableLeft, Set unreliableRight) throws DatabaseException { + // process compares objects that are identified and searches for more resources to process. + iter = 0; + boolean c = process(objectsLeft, objectsRight, unreliableLeft, unreliableRight); + if (objectsLeft.isEmpty()) { + // process unreliable handles cases where unidentified statements subject and object have been identified + c |= processUnreliable(unreliableLeft, unreliableRight); + // process unreliable handles cases where unidentified resources have path of length one to identified resource + if (!c) { + c |= processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight); + if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { + c |= processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight); + } + if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { + // comparison is ending, but we have still unprocessed unidentified resources left. + // These cases have longer path than one to identified objects. + c |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight); + } + if (!c && objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { + // comparison is ending, but we have still unprocessed unidentified resources left. + // These cases have longer path than one to identified objects. + c |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight); + } + } + } + return c; + + } + + private String monitorTaskName(Stack objectsLeft, Stack objectsRight, Set unreliableLeft, Set unreliableRight) { + int cr = comparableResources.size(); + int ch = Math.max(changes1.size(), changes2.size()); + return "Graph compare " + (cr + ch) + " / " + (cr+ch+(Math.max(objectsLeft.size(), objectsRight.size())+Math.max(unreliableLeft.size(), unreliableRight.size()))); + } + + private boolean process(Stack objectsLeft, Stack objectsRight, Set unreliableLeft, Set unreliableRight) throws DatabaseException { List ss1 = new ArrayList(); List ss2 = new ArrayList(); - - while (!objectsLeft.isEmpty()) { + boolean didSomething = false; + while (!objectsLeft.isEmpty()&& (maxIter < 0 || iter < maxIter)) { Resource r1 = objectsLeft.pop(); Resource r2 = objectsRight.pop(); @@ -317,7 +398,7 @@ public class GraphComparator { 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."); } addComparable(r1, r2); - + didSomething = true; //System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2)); compareProps(r1, r2); @@ -330,7 +411,8 @@ public class GraphComparator { ss2 = filterTraversed(ss2); ss1 = filterNonTested(ss1); ss2 = filterNonTested(ss2); - + ss1 = filter(Collections.singletonList(b.HasProperty), ss1); + ss2 = filter(Collections.singletonList(b.HasProperty), ss2); compareStatements(ss1, ss2, null, null,null,null); ss1.clear(); @@ -349,15 +431,17 @@ public class GraphComparator { ss2.clear(); } + iter++; } + return didSomething; } - private void processUnreliable(Set unreliableLeft, Set unreliableRight) throws DatabaseException { + private boolean processUnreliable(Set unreliableLeft, Set unreliableRight) throws DatabaseException { MapList subjectLeft = new MapList(); MapList subjectRight = new MapList(); MapList objectLeft = new MapList(); MapList objectRight = new MapList(); - + boolean didSomething = false; for (Statement s : unreliableLeft) { subjectLeft.add(s.getSubject(),s); objectLeft.add(s.getObject(),s); @@ -368,6 +452,8 @@ public class GraphComparator { } for (Resource left : subjectLeft.getKeys()) { + if (maxIter > 0 && iter > maxIter) + break; Resource right = comparableResources.getRight(left); if (right == null) continue; @@ -388,18 +474,21 @@ public class GraphComparator { unreliableLeft.remove(leftS); unreliableRight.remove(rightS); addComparable(leftS, rightS); + didSomething = true; + iter++; } } } } + return didSomething; } - private void processUnreliable(Set unreliableLeft, Set unreliableRight, Stack objectsLeft, Stack objectsRight) throws DatabaseException { + private boolean processUnreliable(Set unreliableLeft, Set unreliableRight, Stack objectsLeft, Stack objectsRight) throws DatabaseException { MapList subjectLeft = new MapList(); MapList subjectRight = new MapList(); MapList objectLeft = new MapList(); MapList objectRight = new MapList(); - + boolean didSomething = false; for (Statement s : unreliableLeft) { subjectLeft.add(s.getSubject(),s); objectLeft.add(s.getObject(),s); @@ -408,8 +497,9 @@ public class GraphComparator { subjectRight.add(s.getSubject(),s); objectRight.add(s.getObject(),s); } - for (Resource ol : objectLeft.getKeys()) { + if (maxIter > 0 && iter > maxIter) + break; // all statements to the left side object List left = objectLeft.getValues(ol); // all subjects that have statements to the left side object (ol) @@ -455,7 +545,7 @@ public class GraphComparator { // compare objects (unreliable result is interpreted as positive match) int comp = comparator.compare(g, left.get(i).getObject(), similarLeft.get(j).getObject(), true); - if (comp >= 0 && comp < Integer.MAX_VALUE) { + if (comp >= 0 && comp < ResourceComparator.NO_MATCH) { useL[i] = true; useSL[j] = true; break; @@ -516,6 +606,8 @@ public class GraphComparator { Statement rs = right.get(r); if (!comparableResources.contains(ls.getSubject(), rs.getSubject())) continue; + if ((comparableResources.containsLeft(ls.getObject()) || comparableResources.containsRight(rs.getObject())) && !comparableResources.contains(ls.getObject(), rs.getObject())) + continue; if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) { // compare objects (unreliable result is not accepted) int comp = comparator.compare(g, ls.getObject(), rs.getObject()); @@ -556,6 +648,7 @@ public class GraphComparator { objectsLeft.add(ol); objectsRight.add(or); addComparable(ol, or); + didSomething = true; for (int l = 0; l < left.size(); l++) { int r = indices.first[l]; Statement sl = left.get(l); @@ -564,22 +657,24 @@ public class GraphComparator { unreliableLeft.remove(sl); unreliableRight.remove(sr); } + iter++; } else { } } + return didSomething; } - private void processUnreliable2(Set unreliableLeft, Set unreliableRight, Stack objectsLeft, Stack objectsRight) throws DatabaseException { + private boolean processUnreliable2(Set unreliableLeft, Set unreliableRight, Stack objectsLeft, Stack objectsRight) throws DatabaseException { MapList subjectLeft = new MapList(); MapList subjectRight = new MapList(); MapList objectLeft = new MapList(); MapList objectRight = new MapList(); - + boolean didSomething = false; for (Statement s : unreliableLeft) { subjectLeft.add(s.getSubject(),s); objectLeft.add(s.getObject(),s); @@ -588,8 +683,9 @@ public class GraphComparator { subjectRight.add(s.getSubject(),s); objectRight.add(s.getObject(),s); } - for (Resource ol : objectLeft.getKeys()) { + if (maxIter > 0 && iter > maxIter) + break; // all statements to the left side object List left = objectLeft.getValues(ol); // all subjects that have statements to the left side object (ol) @@ -608,21 +704,24 @@ public class GraphComparator { int count = comparableStatements.size(); compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight); if (comparableStatements.size() > count) { + didSomething = true; for (Entry entry : comparableStatements.getEntries()) { unreliableLeft.remove(entry.getKey()); unreliableRight.remove(entry.getValue()); + iter++; } } } } + return didSomething; } - private void processUnreliableDeep(Set unreliableLeft, Set unreliableRight, Stack objectsLeft, Stack objectsRight) throws DatabaseException { + private boolean processUnreliableDeep(Set unreliableLeft, Set unreliableRight, Stack objectsLeft, Stack objectsRight) throws DatabaseException { MapList subjectLeft = new MapList(); MapList subjectRight = new MapList(); MapList objectLeft = new MapList(); MapList objectRight = new MapList(); - + boolean didSomething = false; for (Statement s : unreliableLeft) { subjectLeft.add(s.getSubject(),s); objectLeft.add(s.getObject(),s); @@ -632,6 +731,8 @@ public class GraphComparator { objectRight.add(s.getObject(),s); } for (Resource ol : objectLeft.getKeys()) { + if (maxIter > 0 && iter > maxIter) + break; Set pathsLeft = new HashSet(); for (Resource rel : traversed) { pathsLeft.addAll(Path.create(g.getStatements(ol, rel))); @@ -671,6 +772,7 @@ public class GraphComparator { } if (matchingPaths.size() > 0) { if (matchingPaths.size() == 1) { + didSomething = true; Resource or = matchingPaths.keySet().iterator().next(); objectsLeft.add(ol); @@ -685,24 +787,27 @@ public class GraphComparator { Path right = map.getRight(left); for (int i = 0; i < left.getLength(); i++) { addComparable(left.getStatements().get(i),right.getStatements().get(i)); + iter++; } } + iter++; } } } } + return didSomething; } - private boolean hasMatchingPaths(Set leftPaths, Set rightPaths) { + private boolean hasMatchingPaths(Set leftPaths, Set rightPaths) throws DatabaseException { if (leftPaths.size() != rightPaths.size()) return false; BijectionMap map = getMatchingPaths(leftPaths, rightPaths); return map.size() == leftPaths.size(); } - private BijectionMap getMatchingPaths(Set leftPaths, Set rightPaths) { + private BijectionMap getMatchingPaths(Set leftPaths, Set rightPaths) throws DatabaseException { BijectionMap map = new BijectionMap(); for (Path leftPath : leftPaths) { for (Path rightPath : rightPaths) { @@ -723,6 +828,10 @@ public class GraphComparator { match = false; break; } + if (comparator.compare(g, sl.getObject(), sr.getObject()) == ResourceComparator.NO_MATCH) { + match = false; + break; + } } if (match) { map.map(leftPath, rightPath); @@ -790,10 +899,17 @@ public class GraphComparator { return new GraphChanges(r1,r2,changes1,changes2,modifications,comparableResources); } + public List getChanges1() { + return changes1; + } + + public List getChanges2() { + return changes2; + } + private void addComparable(Statement left, Statement right) throws DatabaseException { addComparable(left.getObject(), right.getObject()); comparableStatements.map(left, right); - //comparableResources.map(left.getObject(), right.getObject()); } private void addComparable(Resource left, Resource right) throws DatabaseException { @@ -803,11 +919,18 @@ public class GraphComparator { } else { if (DEBUG) System.out.println(left + " = " + right); comparableResources.map(left, right); + +// if (comparableResources.size() % 1000 == 0) +// printStats(); } } } + public void printStats() { + System.out.println("Comp " + comparableResources.size() + " L " + changes1.size() + " R " + changes2.size() + " M " + modifications.size() + " P " + processedResources.size()); + } + public List filterAsserted(Resource r, Collection in) throws DatabaseException { List out = new ArrayList(); for (Statement s : in) { @@ -826,7 +949,7 @@ public class GraphComparator { out.add(s); else { boolean has = false; - if (i > 1 && in.get(i-1).getPredicate().equals(s.getPredicate())) + if (i > 0 && in.get(i-1).getPredicate().equals(s.getPredicate())) has = true; else if (i < in.size()-1 && in.get(i+1).getPredicate().equals(s.getPredicate())) has = true; @@ -834,11 +957,6 @@ public class GraphComparator { out.add(s); } - } - for (Statement s : in) { - if (!s.isAsserted(r)) - out.add(s); - } return out; } @@ -884,6 +1002,7 @@ public class GraphComparator { private void addDeletion(Statement s) { if (!changes1Set.contains(s)) { + if (DEBUG) System.out.println("- " +s.getSubject() + " " + s.getPredicate() + " " + s.getObject()) ; changes1Set.add(s); changes1.add(s); } @@ -892,6 +1011,7 @@ public class GraphComparator { private void addAddition(Statement s) { if (!changes2Set.contains(s)) { changes2Set.add(s); + if (DEBUG) System.out.println("+ " +s.getSubject() + " " + s.getPredicate() + " " + s.getObject()) ; changes2.add(s); } } @@ -1076,7 +1196,7 @@ public class GraphComparator { for (int i = 0; i < used2.length; i++) { used2[i] = false; } - + // left, right, difference List> differences = new ArrayList>(); for (int i1 = off1; i1 < off1 + len1; i1++) { @@ -1108,7 +1228,118 @@ public class GraphComparator { Integer[] pris = priorities.getKeys(new Integer[]{}); Arrays.sort(pris); - + boolean matchFail = priorityMatching(ss1, off1, len1, ss2, off2, len2, pris, differences, priorities, used1, used2, objectsLeft, objectsRight, false); + if (matchFail) + matchFail = priorityMatching(ss1, off1, len1, ss2, off2, len2, pris, differences, priorities, used1, used2, objectsLeft, objectsRight, objectsLeft == null); + if (unreliableLeft != null) { + if (matchFail) { + // With match failure, statement matching was aborted. We must move all unmatched statements to unreliable. + for (Integer pri : pris) { + if (pri == 0 || pri == Integer.MAX_VALUE) + continue; + priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, pri); + } + } + // Zero means unreliable comparison result, move all unmatched to unreliable. + if (org.simantics.utils.datastructures.Arrays.contains(pris, 0)) { + priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, 0); + } + } +// Previous version processed 0 priority statements, even when unreliableLeft collection was null. +// The problem was that property relations were not filtered in process() from "tested" statements. +// else { +// if (org.simantics.utils.datastructures.Arrays.contains(pris, 0)) { +// priorityProcessUnmatched(ss1, off1, len1, ss2, off2, len2, differences, priorities, used1, used2, unreliableLeft, unreliableRight, 0); +// } +// } + // Report unmatched statements as changes. + for (int i1 = off1; i1 < off1 + len1; i1++) { + if (!used1[i1-off1]) { + if (DEBUG) System.out.println("Compare Object deletion " + printStatement(g,ss1.get(i1))); + addDeletion(ss1.get(i1)); + } + } + for (int i2 = off2; i2 < off2 + len2; i2++) { + if (!used2[i2-off2]) { + if (DEBUG) System.out.println("Compare Object addition " + printStatement(g,ss2.get(i2))); + addAddition(ss2.get(i2)); + } + } + } + + /** + * Moves unmatched statements to unreliable collections. + * @param ss1 + * @param off1 + * @param len1 + * @param ss2 + * @param off2 + * @param len2 + * @param differences + * @param priorities + * @param used1 + * @param used2 + * @param unreliableLeft + * @param unreliableRight + * @param pri + */ + private void priorityProcessUnmatched(List ss1, int off1, int len1, List ss2, int off2, int len2,List> differences,MapList priorities,boolean used1[],boolean used2[], Collection unreliableLeft, Collection unreliableRight, int pri) { + Set s1s = new HashSet(); + Set s2s = new HashSet(); + Set s1i = new HashSet(); + Set s2i = new HashSet(); + List i1s = priorities.getValues(pri); + for (Integer i1 : i1s) { + if (used1[i1]) + continue; + List i2diff = differences.get(i1); + for (int i2 = 0; i2 < i2diff.size(); i2++) { + if (i2diff.get(i2) == pri) { + if (used2[i2]) + continue; + Statement s1 = ss1.get(i1+off1); + Statement s2 = ss2.get(i2+off2); + s1s.add(s1); + s2s.add(s2); + s1i.add(i1); + s2i.add(i2); + } + } + } + if (unreliableLeft != null) { + unreliableLeft.addAll(s1s); + unreliableRight.addAll(s2s); + } + for (Integer i : s1i) + used1[i] = true; + for (Integer i : s2i) + used2[i] = true; + } + /** + * Matches left and right side statements. + * + * When there are two or more equally good matching objects, the behaviour depends on force flag. + * False: Matching is aborted and matchFail is returned (method return true). + * True: equally good matches will be paired randomly. Method always returns false. + * @param ss1 + * @param off1 + * @param len1 + * @param ss2 + * @param off2 + * @param len2 + * @param pris + * @param differences + * @param priorities + * @param used1 + * @param used2 + * @param objectsLeft + * @param objectsRight + * @param force + * @return + * @throws DatabaseException + */ + private boolean priorityMatching(List ss1, int off1, int len1, List ss2, int off2, int len2, Integer[] pris, List> differences, MapList priorities, boolean used1[],boolean used2[], Collection objectsLeft, Collection objectsRight, boolean force) throws DatabaseException { + boolean matchFail = false; for (Integer pri : pris) { if (pri == Integer.MAX_VALUE) { @@ -1116,89 +1347,48 @@ public class GraphComparator { } else { List i1s = priorities.getValues(pri); + for (Integer i1 : i1s) { if (used1[i1]) continue; List i2diff = differences.get(i1); + List matches = new ArrayList(); for (int i2 = 0; i2 < i2diff.size(); i2++) { - if (i2diff.get(i2) == pri) { + if (i2diff.get(i2) == pri) { if (used2[i2]) continue; - used1[i1] = true; - used2[i2] = true; - Statement s1 = ss1.get(i1+off1); - Statement s2 = ss2.get(i2+off2); - - if (objectsLeft != null) { - objectsLeft.add(s1.getObject()); - objectsRight.add(s2.getObject()); - } - addComparable(s1, s2); - break; + matches.add(i2); } } - } - } - } - - for (Integer pri : pris) { - if (pri != 0) - continue; - Set s1s = new HashSet(); - Set s2s = new HashSet(); - Set s1i = new HashSet(); - Set s2i = new HashSet(); - List i1s = priorities.getValues(pri); - for (Integer i1 : i1s) { - if (used1[i1]) - continue; - List i2diff = differences.get(i1); - for (int i2 = 0; i2 < i2diff.size(); i2++) { - if (i2diff.get(i2) == pri) { - if (used2[i2]) - continue; + if (matches.size() == 1 || (force && matches.size() > 1)) { + int i2 = matches.get(0); + used1[i1] = true; + used2[i2] = true; Statement s1 = ss1.get(i1+off1); Statement s2 = ss2.get(i2+off2); - s1s.add(s1); - s2s.add(s2); - s1i.add(i1); - s2i.add(i2); + + if (objectsLeft != null) { + objectsLeft.add(s1.getObject()); + objectsRight.add(s2.getObject()); + } + addComparable(s1, s2); + } else if (matches.size() > 1) { + matchFail = true; } } - } - if (unreliableLeft != null) { - unreliableLeft.addAll(s1s); - unreliableRight.addAll(s2s); - } - for (Integer i : s1i) - used1[i] = true; - for (Integer i : s2i) - used2[i] = true; - - } - for (int i1 = off1; i1 < off1 + len1; i1++) { - if (!used1[i1-off1]) { - if (DEBUG) System.out.println("Compare Object deletion " + printStatement(g,ss1.get(i1))); - addDeletion(ss1.get(i1)); - } - } - for (int i2 = off2; i2 < off2 + len2; i2++) { - if (!used2[i2-off2]) { - if (DEBUG) System.out.println("Compare Object addition " + printStatement(g,ss2.get(i2))); - addAddition(ss2.get(i2)); + if (matchFail) + break; } } + return matchFail; } - - + /** * compares properties, assumes functional relations * @param r1 * @param r2 - * @throws ServiceException - * @throws DoesNotContainValueException - * @throws ValidationException + * @throws DatabaseException */ private void compareProps(Resource r1, Resource r2) throws DatabaseException { if (DEBUG) System.out.println("compareProps " + r1 + " " + NameUtils.getSafeName(g, r1) + " " + r2 + " " + NameUtils.getSafeName(g, r2)); @@ -1283,6 +1473,8 @@ public class GraphComparator { } } else { // Exact match, nothing to do. + if (!a1 && !a2) + addComparable(s1, s2); } } } else { @@ -1294,14 +1486,18 @@ public class GraphComparator { } case -1:{ if (DEBUG) System.out.println("Compare Prop diff1s " + printStatement(g,s1)); - addDeletion(s1); + // Use modification, since deletions do not support asserted statements + addModification(r1,s1,r2,null); + //addDeletion(s1); i1++; break; } case 1:{ if (DEBUG) System.out.println("Compare Prop diff2s " + printStatement(g,s2)); - addAddition(s2); + // Use modification, since additions do not support asserted statements + addModification(r1,null,r2,s2); + //addAddition(s2); i2++; break; }