X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.interop%2Fsrc%2Forg%2Fsimantics%2Finterop%2Ftest%2FGraphComparator.java;h=52a8bab650c401d8288be76e7fbcba93455a84f4;hb=212801c71a012172929a33ffd9643e107eec4950;hp=11b3d1a3849e0309ab59d6ad271aa2187ce409d2;hpb=cbc22e9a30434bca2d197a3b6cbbdbced19aed4e;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 11b3d1a..52a8bab 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,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.Stack; +import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; @@ -31,6 +34,8 @@ 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; import org.simantics.utils.datastructures.MapList; @@ -54,21 +59,21 @@ public class GraphComparator { private Resource r1; private Resource r2; - private Set strong = new HashSet(); // List of relations that identify object, if subject is already identified. - private List traversed = new ArrayList(); // list of relations that are traversed (and tested) - private List tested = new ArrayList(); // list of relations that are tested, but not traversed - private List nonTraversed = new ArrayList(); // list of relations that are not traversed - private List nonTested = new ArrayList(); // list of relations that are not tested - - private List changes1 = new ArrayList(); - private List changes2 = new ArrayList(); - private List> modifications = new ArrayList>(); - private Set changes1Set = new HashSet(); - private Set changes2Set = new HashSet(); - private Set> modificationsSet = new HashSet>(); + private Set strong = new HashSet<>(); // List of relations that identify object, if subject is already identified. + private List traversed = new ArrayList<>(); // list of relations that are traversed (and tested) + private List tested = new ArrayList<>(); // list of relations that are tested, but not traversed + private List nonTraversed = new ArrayList<>(); // list of relations that are not traversed + private List nonTested = new ArrayList<>(); // list of relations that are not tested + + private List changes1 = new ArrayList<>(); + private List changes2 = new ArrayList<>(); + private List modifications = new ArrayList<>(); + private Set changes1Set = new HashSet<>(); + private Set changes2Set = new HashSet<>(); + private Set modificationsSet = new HashSet<>(); - private BijectionMap comparableStatements = new BijectionMap(); - private BijectionMap comparableResources = new BijectionMap(); + private BijectionMap comparableStatements = new BijectionMap<>(); + private BijectionMap comparableResources = new BijectionMap<>(); private Set processedResources = new HashSet(); @@ -150,10 +155,16 @@ public class GraphComparator { } public void addComparableResources(Resource r1, Resource r2) { + if (DEBUG) + System.out.println("Preset " + r1 + " = " + r2); comparableResources.map(r1, r2); } public void addComparableResources(BijectionMap matching) { + if (DEBUG) { + for (Entry entry : matching.getEntries()) + System.out.println("Preset " + entry.getKey() + " = " + entry.getValue()); + } comparableResources.addAll(matching); } @@ -177,6 +188,7 @@ public class GraphComparator { this.g = g; this.b = Layer0.getInstance(g); comparator.setComparator(this); + comparator.initialize(g, r1, r2); Stack objectsLeft = new Stack(); Stack objectsRight = new Stack(); @@ -186,34 +198,39 @@ public class GraphComparator { Set unreliableLeft = new HashSet(); Set unreliableRight = new HashSet(); + boolean changed = false; while (true) { - if (objectsLeft.isEmpty()) + if (objectsLeft.isEmpty() && !changed) break; - + changed = false; // process compares objects that are identified and searches for more resources to process. - process(objectsLeft, objectsRight, unreliableLeft, unreliableRight); + changed |= process(objectsLeft, objectsRight, unreliableLeft, unreliableRight); // process unreliable handles cases where unidentified statements subject and object have been identified - processUnreliable(unreliableLeft, unreliableRight); + changed |= processUnreliable(unreliableLeft, unreliableRight); // process unreliable handles cases where unidentified resources have path of length one to identified resource - processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight); + changed |= processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight); if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { - processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight); + changed |= 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 |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight); } } 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); + } } } @@ -225,6 +242,14 @@ public class GraphComparator { comparator.setComparator(this); + session.syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + comparator.initialize(graph, r1, r2); + } + }); + addComparable(r1, r2); final Stack objectsLeft = new Stack(); @@ -235,29 +260,36 @@ 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() { + changed = session.syncRequest(new Read() { @Override - public void run(ReadGraph graph) throws DatabaseException { + public Boolean perform(ReadGraph graph) throws DatabaseException { g = graph; b = Layer0.getInstance(graph); // process compares objects that are identified and searches for more resources to process. - process(objectsLeft, objectsRight, unreliableLeft, unreliableRight); + boolean c = process(objectsLeft, objectsRight, unreliableLeft, unreliableRight); // process unreliable handles cases where unidentified statements subject and object have been identified - processUnreliable(unreliableLeft, unreliableRight); + c |= processUnreliable(unreliableLeft, unreliableRight); // process unreliable handles cases where unidentified resources have path of length one to identified resource - processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight); + c |= processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight); if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) { - processUnreliable2(unreliableLeft, unreliableRight,objectsLeft,objectsRight); + c |= 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); + c |= 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. + c |= processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight); + } + return c; } }); @@ -266,8 +298,6 @@ public class GraphComparator { } for (Statement s : unreliableLeft) { if (!comparableStatements.containsLeft(s)) - if (s.getObject().getResourceId() == 303248) - System.out.println(); addDeletion(s); } for (Statement s : unreliableRight) { @@ -278,17 +308,16 @@ public class GraphComparator { } - private void process(Stack objectsLeft, Stack objectsRight, Set unreliableLeft, Set unreliableRight) throws DatabaseException { + private boolean process(Stack objectsLeft, Stack objectsRight, Set unreliableLeft, Set unreliableRight) throws DatabaseException { List ss1 = new ArrayList(); List ss2 = new ArrayList(); - + boolean didSomething = false; while (!objectsLeft.isEmpty()) { Resource r1 = objectsLeft.pop(); Resource r2 = objectsRight.pop(); if (r1.equals(r2)) continue; - if (processedResources.contains(r1)) continue; processedResources.add(r1); @@ -298,7 +327,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); @@ -311,7 +340,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(); @@ -331,14 +361,15 @@ public class GraphComparator { } } + 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); @@ -369,18 +400,20 @@ public class GraphComparator { unreliableLeft.remove(leftS); unreliableRight.remove(rightS); addComparable(leftS, rightS); + didSomething = true; } } } } + 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); @@ -436,7 +469,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; @@ -497,6 +530,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()); @@ -537,6 +572,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); @@ -551,16 +587,17 @@ public class GraphComparator { } } + 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); @@ -589,6 +626,7 @@ 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()); @@ -596,14 +634,15 @@ public class GraphComparator { } } } + 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); @@ -652,6 +691,7 @@ public class GraphComparator { } if (matchingPaths.size() > 0) { if (matchingPaths.size() == 1) { + didSomething = true; Resource or = matchingPaths.keySet().iterator().next(); objectsLeft.add(ol); @@ -673,17 +713,18 @@ public class GraphComparator { } } + 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) { @@ -692,8 +733,27 @@ public class GraphComparator { if (leftPath.getLength() != rightPath.getLength()) continue; if (comparableResources.contains(leftPath.getEnd(), rightPath.getEnd())) { - map.map(leftPath, rightPath); - break; + boolean match = true; + for (int i = 0; i < leftPath.getLength(); i++) { + Statement sl = leftPath.getStatements().get(i); + Statement sr = rightPath.getStatements().get(i); + if (!sl.getPredicate().equals(sr.getPredicate()) && !comparableResources.contains(sl.getPredicate(), sr.getPredicate())) { + match = false; + break; + } + if ((getComparableResources().containsLeft(sl.getObject()) || getComparableResources().containsRight(sr.getObject())) && !getComparableResources().contains(sl.getObject(), sr.getObject())) { + match = false; + break; + } + if (comparator.compare(g, sl.getObject(), sr.getObject()) == ResourceComparator.NO_MATCH) { + match = false; + break; + } + } + if (match) { + map.map(leftPath, rightPath); + break; + } } } } @@ -756,10 +816,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 { @@ -768,10 +835,7 @@ public class GraphComparator { 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."); } else { if (DEBUG) System.out.println(left + " = " + right); - comparableResources.map(left, right); - //if (left.getResourceId() == 313071 && right.getResourceId() == 325324) - if (left.getResourceId() == 313231 && right.getResourceId() == 337775) - System.out.println(); + comparableResources.map(left, right); } } @@ -787,6 +851,26 @@ public class GraphComparator { return out; } + public List filterAssertedDuplicates(Resource r, List in) throws DatabaseException { + List out = new ArrayList(); + for (int i = 0; i < in.size(); i++) { + Statement s = in.get(i); + if (!s.isAsserted(r)) + out.add(s); + else { + boolean has = false; + 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; + if (!has) + out.add(s); + } + + } + return out; + } + private String printStatement(ReadGraph graph, Statement s) throws DatabaseException { @@ -828,6 +912,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); } @@ -836,12 +921,13 @@ 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); } } - private void addModification(Statement s1, Statement s2) { - Pair mod = new Pair(s1,s2); + private void addModification(Resource left, Statement leftstm, Resource right, Statement rightstm) { + Modification mod = new Modification(left, right, leftstm, rightstm); if (!modificationsSet.contains(mod)) { modificationsSet.add(mod); modifications.add(mod); @@ -1020,7 +1106,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++) { @@ -1052,7 +1138,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) { @@ -1060,89 +1257,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)); @@ -1153,6 +1309,9 @@ public class GraphComparator { ss1 = filterNonTested(ss1); ss2 = filterNonTested(ss2); sortStatement(ss1, ss2); + // getStatements(r1, b.HasProperty) returns both instance and asserted statements for the same property relation. + ss1 = filterAssertedDuplicates(r1, ss1); + ss2 = filterAssertedDuplicates(r2, ss2); int i1 = 0; int i2 = 0; @@ -1163,16 +1322,20 @@ public class GraphComparator { break; else { while (i2 < ss2.size()) { - if (DEBUG) System.out.println("Compare Prop diff2 " + printStatement(g,ss2.get(i2))); - addAddition(ss2.get(i2)); + Statement s = ss2.get(i2); + if (DEBUG) System.out.println("Compare Prop diff2 " + printStatement(g,s)); + if (!s.isAsserted(r2)) + addAddition(s); i2++; } break; } } else if (i2 >= ss2.size()) { while (i1 < ss1.size()) { - if (DEBUG) System.out.println("Compare Prop diff1 " + printStatement(g,ss1.get(i1))); - addDeletion(ss1.get(i1)); + Statement s = ss1.get(i1); + if (DEBUG) System.out.println("Compare Prop diff1 " + printStatement(g,s)); + if (!s.isAsserted(r1)) + addDeletion(s); i1++; } break; @@ -1189,22 +1352,43 @@ public class GraphComparator { case 0:{ boolean b1 = g.hasValue(s1.getObject()); boolean b2 = g.hasValue(s2.getObject()); + boolean a1 = s1.isAsserted(r1); + boolean a2 = s2.isAsserted(r2); if (b1 == b2) { if (b1) { - Object v1 = g.getValue(s1.getObject()); - Object v2 = g.getValue(s2.getObject()); - boolean eq = compareValue(v1, v2); + // Literals + boolean eq = compareValue(g,b,s1.getObject(), s2.getObject()); if (!eq) { - addModification(s1, s2); - addComparable(s1, s2); + addModification(r1,s1,r2,s2); + if (!a1 && !a2) + addComparable(s1, s2); } } else { - if (!s1.getObject().equals(s1.getSubject()) && !s2.getObject().equals(s2.getSubject())) - compareProps(s1.getObject(), s2.getObject()); + // Non literal properties. + int comp = comparator.compare(g, s1.getObject(), s2.getObject()); + if (comp == ResourceComparator.NO_MATCH) { + addModification(r1,s1,r2,s2); + } else if (comp != ResourceComparator.EXACT_MATCH) { + if (!s1.getObject().equals(s1.getSubject()) && !s2.getObject().equals(s2.getSubject())) { + if (!a1 && !a2) { + // compare props matches objects, so we can call that only for non asserted statements + compareProps(s1.getObject(), s2.getObject()); + } else if (a1 && a2) { + // TODO : compare asserted statements? + } else { + addModification(r1,s1,r2,s2); + } + } else { + addModification(r1,s1,r2,s2); + } + } else { + // Exact match, nothing to do. + if (!a1 && !a2) + addComparable(s1, s2); + } } } else { - addModification(s1, s2); - addComparable(s1, s2); + addModification(r1,s1,r2,s2); } i1++; i2++; @@ -1212,14 +1396,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; } @@ -1232,6 +1420,75 @@ public class GraphComparator { } + public static boolean compareValue(ReadGraph g, Layer0 b, Resource r1, Resource r2) throws DatabaseException { + Resource t1 = g.getSingleType(r1); + Resource t2 = g.getSingleType(r2); + if (!t1.equals(t2)) + return false; + if (t1.equals(b.Integer)) { + int v1 = g.getValue(r1, Bindings.INTEGER); + int v2 = g.getValue(r2, Bindings.INTEGER); + return v1 == v2; + } else if (t1.equals(b.Float)) { + float v1 = g.getValue(r1, Bindings.FLOAT); + float v2 = g.getValue(r2, Bindings.FLOAT); + return v1 == v2; + } else if (t1.equals(b.Double)) { + double v1 = g.getValue(r1, Bindings.DOUBLE); + double v2 = g.getValue(r2, Bindings.DOUBLE); + return v1 == v2; + } else if (t1.equals(b.String)) { + String v1 = g.getValue(r1, Bindings.STRING); + String v2 = g.getValue(r2, Bindings.STRING); + return v1.equals(v2); + } else if (t1.equals(b.Boolean)) { + boolean v1 = g.getValue(r1, Bindings.BOOLEAN); + boolean v2 = g.getValue(r2, Bindings.BOOLEAN); + return v1 == v2; + } else if (t1.equals(b.Byte)) { + byte v1 = g.getValue(r1, Bindings.BYTE); + byte v2 = g.getValue(r2, Bindings.BYTE); + return v1 == v2; + } else if (t1.equals(b.Long)) { + long v1 = g.getValue(r1, Bindings.LONG); + long v2 = g.getValue(r2, Bindings.LONG); + return v1 == v2; + } else if (t1.equals(b.IntegerArray)) { + int[] v1 = g.getValue(r1, Bindings.INT_ARRAY); + int[] v2 = g.getValue(r2, Bindings.INT_ARRAY); + return Arrays.equals(v1,v2); + } else if (t1.equals(b.FloatArray)) { + float[] v1 = g.getValue(r1, Bindings.FLOAT_ARRAY); + float[] v2 = g.getValue(r2, Bindings.FLOAT_ARRAY); + return Arrays.equals(v1,v2); + } else if (t1.equals(b.DoubleArray)) { + double[] v1 = g.getValue(r1, Bindings.DOUBLE_ARRAY); + double[] v2 = g.getValue(r2, Bindings.DOUBLE_ARRAY); + return Arrays.equals(v1,v2); + } else if (t1.equals(b.StringArray)) { + String[] v1 = g.getValue(r1, Bindings.STRING_ARRAY); + String[] v2 = g.getValue(r2, Bindings.STRING_ARRAY); + return Arrays.equals(v1,v2); + } else if (t1.equals(b.BooleanArray)) { + boolean[] v1 = g.getValue(r1, Bindings.BOOLEAN_ARRAY); + boolean[] v2 = g.getValue(r2, Bindings.BOOLEAN_ARRAY); + return Arrays.equals(v1,v2); + } else if (t1.equals(b.ByteArray)) { + byte[] v1 = g.getValue(r1, Bindings.BYTE_ARRAY); + byte[] v2 = g.getValue(r2, Bindings.BYTE_ARRAY); + return Arrays.equals(v1,v2); + } else if (t1.equals(b.LongArray)) { + long[] v1 = g.getValue(r1, Bindings.LONG_ARRAY); + long[] v2 = g.getValue(r2, Bindings.LONG_ARRAY); + return Arrays.equals(v1,v2); + } else { + Object v1 = g.getValue(r1); + Object v2 = g.getValue(r2); + return compareValue(v1, v2); + } + + } + public static boolean compareValue(Object v1, Object v2) { if (v1 instanceof Object[] && v2 instanceof Object[]) return Arrays.deepEquals((Object[])v1, (Object[])v2);