From 7ec38c9ede219eeaf7b55d2d529fc66f098de5dc Mon Sep 17 00:00:00 2001 From: luukkainen Date: Tue, 27 Sep 2011 10:07:32 +0000 Subject: [PATCH] Better handling of unidentified resources (resources that have no name, or other properties). - This fixes connection synchronization git-svn-id: https://www.simantics.org/svn/simantics/interoperability/trunk@22426 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../interop/test/GraphComparator.java | 325 +++++++++++++++--- ...omparator.java => ResourceComparator.java} | 8 +- .../interop/test/TypeComparator.java | 7 +- 3 files changed, 283 insertions(+), 57 deletions(-) rename org.simantics.interop/src/org/simantics/interop/test/{ObjectComparator.java => ResourceComparator.java} (74%) 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 4fb9cf2..c84a8f9 100644 --- a/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java +++ b/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java @@ -11,13 +11,16 @@ *******************************************************************************/ package org.simantics.interop.test; +import java.math.MathContext; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; @@ -66,10 +69,10 @@ public class GraphComparator { private BijectionMap comparableResources = new BijectionMap(); - private ObjectComparator comparator; + private ResourceComparator comparator; private Comparator scomp = new PredicateComparator(); - private Comparator rcomp = new ResourceComparator(); + private Comparator rcomp = new ResComparator(); // runtime attributes @@ -82,7 +85,7 @@ public class GraphComparator { comparator = new TypeComparator(); } - public GraphComparator(Resource r1, Resource r2, ObjectComparator comparator) { + public GraphComparator(Resource r1, Resource r2, ResourceComparator comparator) { this.r1 = r1; this.r2 = r2; this.comparator = comparator; @@ -160,18 +163,21 @@ public class GraphComparator { this.b = Layer0.getInstance(g); comparator.setComparator(this); - Stack stack1 = new Stack(); - Stack stack2 = new Stack(); - stack1.push(r1); - stack2.push(r2); + Stack objectsLeft = new Stack(); + Stack objectsRight = new Stack(); + objectsLeft.push(r1); + objectsRight.push(r2); List ss1 = new ArrayList(); List ss2 = new ArrayList(); - while (!stack1.isEmpty()) { - Resource r1 = stack1.pop(); - Resource r2 = stack2.pop(); + Stack unreliableLeft = new Stack(); + Stack unreliableRight = new Stack(); + + while (!objectsLeft.isEmpty()) { + Resource r1 = objectsLeft.pop(); + Resource r2 = objectsRight.pop(); if (comparableResources.contains(r1, r2)) { //System.out.println("already tested " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2)); @@ -192,7 +198,7 @@ public class GraphComparator { ss1 = filterNonTested(ss1); ss2 = filterNonTested(ss2); - compareStatements(ss1, ss2, null, null); + compareStatements(ss1, ss2, null, null,null,null); ss1.clear(); ss2.clear(); } @@ -202,11 +208,126 @@ public class GraphComparator { ss2.addAll(g.getStatements(r2, rel)); ss1 = filterAsserted(r1, ss1); ss2 = filterAsserted(r2, ss2); - compareStatements(ss1, ss2, stack1, stack2); + compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight); ss1.clear(); ss2.clear(); + } } + MapList subjectLeft = new MapList(); + MapList subjectRight = new MapList(); + MapList objectLeft = new MapList(); + MapList objectRight = new MapList(); + + for (Statement s : unreliableLeft) { + subjectLeft.add(s.getSubject(),s); + objectLeft.add(s.getObject(),s); + } + for (Statement s : unreliableRight) { + subjectRight.add(s.getSubject(),s); + objectRight.add(s.getObject(),s); + } + + for (Resource ol : objectLeft.getKeys()) { + + // all statements to the left side object + List left = objectLeft.getValues(ol); + // all subjects that have statements to the left side object (ol) + Set sLeft = new HashSet(); + // all matching subjects on the right side + Set sRight = new HashSet(); + for (Statement s : left) { + sLeft.add(s.getSubject()); + sRight.add(comparableResources.getRight(s.getSubject())); + } + // all objects that subjects on the right side point to. Object left has its matching resource among these, if it has matching resource + MapList possibleOR = new MapList(); + for (Resource sr : sRight) { + for (Statement s : subjectRight.getValues(sr)) + possibleOR.add(s.getObject(),s); + } + + // filter possible right side objects to those that have same amount of statements as the left side object + for (Resource or : possibleOR.getKeys().toArray(new Resource[possibleOR.getKeys().size()])) { + List right = possibleOR.getValues(or); + if (right.size() != left.size()) + possibleOR.remove(or); + + } + + // check for matching statements (comparable subjects, matching predicates) + MapList matchingOR = new MapList(); // list of objects that have matching statements + Map> matchingStatements = new HashMap>(); // matching statements + for (Resource or : possibleOR.getKeys()) { + List right = possibleOR.getValues(or); + int iLeft[] = new int[left.size()]; + int iRight[] = new int[right.size()]; + + for (int i = 0; i < left.size(); i++) { + iLeft[i] = -1; + iRight[i] = -1; + } + + for (int l = 0; l < left.size(); l++) { + Statement ls = left.get(l); + for (int r = 0; r < right.size(); r++) { + if (iRight[r] >= 0) + continue; + Statement rs = right.get(r); + if (!comparableResources.contains(ls.getSubject(), rs.getSubject())) + continue; + if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) { + iLeft[l] = r; + iRight[r] = l; + break; + } + } + + } + boolean success = true; + for (int i = 0; i < left.size(); i++) { + if (iLeft[i] < 0) { + success = false; + break; + } + if (iRight[i] < 0) { + success = false; + break; + } + + } + if (success) { + for (Statement s : right) + matchingOR.add(or,s); + matchingStatements.put(or, new Pair(iLeft, iRight)); + } + } + // if there is only one matching right side object, we have found a match + if (matchingOR.getKeySize() == 1) { + Resource or = matchingOR.getKeys().iterator().next(); + List right = matchingOR.getValues(or); + Pair indices = matchingStatements.get(or); + + comparableResources.map(ol, or); + for (int l = 0; l < left.size(); l++) { + int r = indices.first[l]; + comparableStatements.map(left.get(l), right.get(r)); + } + + } + + } + + for (Statement s : unreliableLeft) { + if (!comparableStatements.containsLeft(s)) + addDeletion(s); + } + for (Statement s : unreliableRight) { + if (!comparableStatements.containsRight(s)) + addAddition(s); + } + + } @@ -285,6 +406,10 @@ public class GraphComparator { } public void sortStatement(List list1, List list2) { + sortStatement(list1, list2, scomp); + } + + public void sortStatement(List list1, List list2, Comparator scomp) { Collections.sort(list1,scomp); Collections.sort(list2,scomp); @@ -359,10 +484,8 @@ public class GraphComparator { } } - private void compareStatements(List ss1, List ss2, Stack stack1, Stack stack2) throws DatabaseException { + private void compareStatements(List ss1, List ss2, Stack objectsLeft, Stack objectsRight,Stack unreliableLeft, Stack unreliableRight) throws DatabaseException { sortStatement(ss1, ss2); -// Collections.sort(ss1, scomp); -// Collections.sort(ss2, scomp); int i1 = 0; int i2 = 0; @@ -392,7 +515,59 @@ public class GraphComparator { int same2 = sameRel(ss2, i2); int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate()); if (c == 0) { - compareStatements(ss1, i1, same1, ss2, i2, same2,stack1,stack2); + compareStatements(ss1, i1, same1, ss2, i2, same2,objectsLeft,objectsRight,unreliableLeft,unreliableRight); + i1+=same1; + i2+=same2; + } else if (c < 0) { + for (int i = 0; i < same1; i++) { + System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i+i1))); + addDeletion(ss1.get(i+i1)); + } + i1 += same1; + } else { + for (int i = 0; i < same2; i++) { + System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i+i2))); + addAddition(ss2.get(i+i2)); + } + + i2 += same2; + } + + } + } + + private void compareUnreliableStatements(List ss1, List ss2) throws DatabaseException { + sortStatement(ss1, ss2); + + int i1 = 0; + int i2 = 0; + + while (true) { + if (i1 >= ss1.size()) { + if (i2 >= ss2.size()) { + break; + } else { + while (i2 < ss2.size()) { + System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i2))); + + addAddition(ss2.get(i2)); + i2++; + } + break; + } + } else if (i2 >= ss2.size()) { + while (i1 < ss1.size()) { + System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i1))); + addDeletion(ss1.get(i1)); + i1++; + } + break; + } + int same1 = sameRel(ss1, i1); + int same2 = sameRel(ss2, i2); + int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate()); + if (c == 0) { + compareStatements(ss1, i1, same1, ss2, i2, same2,null, null, null, null); i1+=same1; i2+=same2; } else if (c < 0) { @@ -431,10 +606,14 @@ public class GraphComparator { private int compareObject(Resource o1, Resource o2) throws DatabaseException { if (comparableResources.contains(o1, o2)) return (-1); + if (comparableResources.containsLeft(o1)) + return Integer.MAX_VALUE; + if (comparableResources.containsRight(o2)) + return Integer.MAX_VALUE; return comparator.compare(g, o1, o2); } - private void compareStatements(List ss1, int off1, int len1, List ss2, int off2, int len2, Stack stack1, Stack stack2) throws DatabaseException { + private void compareStatements(List ss1, int off1, int len1, List ss2, int off2, int len2, Stack objectsLeft, Stack objectsRight, Stack unreliableLeft, Stack unreliableRight) throws DatabaseException { boolean[] used1 = new boolean[len1]; for (int i = 0; i < used1.length; i++) { used1[i] = false; @@ -452,7 +631,8 @@ public class GraphComparator { List diff = new ArrayList(); for (int i2 = off2; i2 < off2 + len2; i2++) { Statement s2 = ss2.get(i2); - diff.add(compareObject(s1.getObject(), s2.getObject())); + int d = compareObject(s1.getObject(), s2.getObject()); + diff.add(d); } differences.add(diff); } @@ -469,43 +649,56 @@ public class GraphComparator { Arrays.sort(pris); for (Integer pri : pris) { - if (pri == Integer.MAX_VALUE) + if (pri == Integer.MAX_VALUE) { + + } else if (pri == 0) { + Set s1s = new HashSet(); + Set s2s = new HashSet(); + List i1s = priorities.getValues(pri); + for (Integer i1 : i1s) { + + List i2diff = differences.get(i1); + for (int i2 = 0; i2 < i2diff.size(); i2++) { + if (i2diff.get(i2) == pri) { + used1[i1] = true; + used2[i2] = true; + Statement s1 = ss1.get(i1+off1); + Statement s2 = ss2.get(i2+off2); + s1s.add(s1); + s2s.add(s2); + } + } + } + if (unreliableLeft != null) { + unreliableLeft.addAll(s1s); + unreliableRight.addAll(s2s); + } continue; - 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; - used1[i1] = true; - used2[i2] = true; - Statement s1 = ss1.get(i1+off1); - Statement s2 = ss2.get(i2+off2); - - if (stack1 != null) { - - stack1.add(s1.getObject()); - stack2.add(s2.getObject()); - - } else { - // TODO : how should we report non traversed differences - // using compareProps assumes that referenced objects are the same (references are not different) - // using propsDiffCount assumes that objects are different, and cannot report changes in referred object. - + } else { + 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; + used1[i1] = true; + used2[i2] = true; + Statement s1 = ss1.get(i1+off1); + Statement s2 = ss2.get(i2+off2); -// int diff = propsDiffCount(ss1.get(i1+off1).getObject(), ss2.get(i2+off2).getObject()); -// if (diff != 0) { -// //changes1.add(ss1.get(i1+off1)); -// //changes2.add(ss2.get(i2+off2)); -// modifies.add(new Pair(ss1.get(i1+off1), ss2.get(i2+off2))); -// } + if (objectsLeft != null) { + + objectsLeft.add(s1.getObject()); + objectsRight.add(s2.getObject()); + + } + comparableStatements.map(s1, s2); + //comparableResources.map(s1.getObject(), s2.getObject()); + break; } - comparableStatements.map(s1, s2); - //comparableResources.map(s1.getObject(), s2.getObject()); - break; } } } @@ -653,6 +846,32 @@ public class GraphComparator { } } + public class SubjectComparator implements Comparator { + @Override + public int compare(Statement o1, Statement o2) { + if (comparableResources.contains(o1.getSubject(), o2.getSubject())) + return 0; + if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId()) + return -1; + if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId()) + return 1; + return 0; + } + } + + public class ObjectComparator implements Comparator { + @Override + public int compare(Statement o1, Statement o2) { + if (comparableResources.contains(o1.getObject(), o2.getObject())) + return 0; + if (o1.getObject().getResourceId() < o2.getObject().getResourceId()) + return -1; + if (o1.getObject().getResourceId() > o2.getObject().getResourceId()) + return 1; + return 0; + } + } + public static class FullStatementComparator implements Comparator { @Override public int compare(Statement o1, Statement o2) { @@ -674,7 +893,7 @@ public class GraphComparator { - public class ResourceComparator implements Comparator { + public class ResComparator implements Comparator { @Override public int compare(Resource o1, Resource o2) { if (comparableResources.contains(o1, o2)) diff --git a/org.simantics.interop/src/org/simantics/interop/test/ObjectComparator.java b/org.simantics.interop/src/org/simantics/interop/test/ResourceComparator.java similarity index 74% rename from org.simantics.interop/src/org/simantics/interop/test/ObjectComparator.java rename to org.simantics.interop/src/org/simantics/interop/test/ResourceComparator.java index 059d4f8..3d31d22 100644 --- a/org.simantics.interop/src/org/simantics/interop/test/ObjectComparator.java +++ b/org.simantics.interop/src/org/simantics/interop/test/ResourceComparator.java @@ -9,7 +9,7 @@ import org.simantics.db.exception.DatabaseException; * @author Marko Luukkainen * */ -public abstract class ObjectComparator { +public abstract class ResourceComparator { private GraphComparator comparator; @@ -22,7 +22,11 @@ public abstract class ObjectComparator { } /** - * Compares two resources and returns numeric value of differences. Result value is Integer.MAX_VALUE if objects are not comparable. + * Compares two resources and returns numeric value of differences, minimum value is 1. + * + * Special values: + * Integer.MAX_VALUE: Objects are not comparable. + * 0 (zero): Object comparison is not reliable. * @param g * @param o1 * @param o2 diff --git a/org.simantics.interop/src/org/simantics/interop/test/TypeComparator.java b/org.simantics.interop/src/org/simantics/interop/test/TypeComparator.java index fc0268e..96ef610 100644 --- a/org.simantics.interop/src/org/simantics/interop/test/TypeComparator.java +++ b/org.simantics.interop/src/org/simantics/interop/test/TypeComparator.java @@ -21,7 +21,7 @@ import org.simantics.layer0.Layer0; * @author Marko Luukkainen * */ -public class TypeComparator extends ObjectComparator { +public class TypeComparator extends ResourceComparator { ArrayList rs1 = new ArrayList(); @@ -69,11 +69,14 @@ public class TypeComparator extends ObjectComparator { ss1.addAll(g.getStatements(r1, l0.HasProperty)); ss2.addAll(g.getStatements(r2, l0.HasProperty)); + if (ss1.size() == 0 && ss2.size() == 0) + return 0; + Comparator scomp = getComparator().getStatementComparator(); getComparator().sortStatement(ss1, ss2); - int count = 0; + int count = 1; int i1 = 0; int i2 = 0; -- 2.47.1