From: luukkainen Date: Mon, 19 Sep 2011 13:55:06 +0000 (+0000) Subject: GraphComparator behavior can be customized with ObjectComparator X-Git-Tag: v1.31.0~117 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=65dc4008773b79bd9672956204512fb87edb4f23;p=simantics%2Finterop.git GraphComparator behavior can be customized with ObjectComparator git-svn-id: https://www.simantics.org/svn/simantics/interoperability/trunk@22324 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/org.simantics.interop/src/org/simantics/interop/test/GraphChanges.java b/org.simantics.interop/src/org/simantics/interop/test/GraphChanges.java index 871be6d..f022209 100644 --- a/org.simantics.interop/src/org/simantics/interop/test/GraphChanges.java +++ b/org.simantics.interop/src/org/simantics/interop/test/GraphChanges.java @@ -2,23 +2,40 @@ package org.simantics.interop.test; import java.util.List; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; import org.simantics.db.Statement; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.ServiceException; +import org.simantics.db.exception.ValidationException; import org.simantics.utils.datastructures.Pair; public class GraphChanges { + private Resource r1; + private Resource r2; private List deletions; private List additions; private List> modifications; - public GraphChanges(List deletions, List additions, + public GraphChanges(Resource r1, Resource r2, List deletions, List additions, List> modifications) { super(); + this.r1 = r1; + this.r2 = r2; this.deletions = deletions; this.additions = additions; this.modifications = modifications; } + public Resource getResource1() { + return r1; + } + + public Resource getResource2() { + return r2; + } + public List getAdditions() { return additions; } @@ -30,5 +47,41 @@ public class GraphChanges { public List> getModifications() { return modifications; } + + public String toString(ReadGraph graph) throws ValidationException, ServiceException { + StringBuilder sb = new StringBuilder(); + sb.append("Del:\n"); + for (Statement stm : deletions) { + sb.append(NameUtils.getSafeName(graph, stm.getSubject()) + " "+ + NameUtils.getSafeName(graph, stm.getPredicate()) + " " + + NameUtils.getSafeName(graph, stm.getObject()) + " (" + + stm.getSubject() + " " +stm.getPredicate() + " " + stm.getObject() + ")\n"); + } + sb.append("Add:\n"); + for (Statement stm : additions) { + sb.append(NameUtils.getSafeName(graph, stm.getSubject()) + " "+ + NameUtils.getSafeName(graph, stm.getPredicate()) + " " + + NameUtils.getSafeName(graph, stm.getObject()) + " (" + + stm.getSubject() + " " +stm.getPredicate() + " " + stm.getObject() + ")\n"); + } + sb.append("Mod:\n"); + for (Pair mod :modifications) { + { + Statement stm = mod.first; + sb.append(NameUtils.getSafeName(graph, stm.getSubject()) + " "+ + NameUtils.getSafeName(graph, stm.getPredicate()) + " " + + NameUtils.getSafeName(graph, stm.getObject()) + " (" + + stm.getSubject() + " " +stm.getPredicate() + " " + stm.getObject() + ")\n"); + } + { + Statement stm = mod.second; + sb.append(NameUtils.getSafeName(graph, stm.getSubject()) + " "+ + NameUtils.getSafeName(graph, stm.getPredicate()) + " " + + NameUtils.getSafeName(graph, stm.getObject()) + " (" + + stm.getSubject() + " " +stm.getPredicate() + " " + stm.getObject() + ")\n"); + } + } + return sb.toString(); + } } 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 6c96858..e529fbb 100644 --- a/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java +++ b/org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java @@ -25,8 +25,8 @@ import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Statement; import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.DoesNotContainValueException; -import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; import org.simantics.db.exception.ServiceException; import org.simantics.db.exception.ValidationException; import org.simantics.layer0.Layer0; @@ -48,7 +48,8 @@ import org.simantics.utils.datastructures.Pair; */ public class GraphComparator { - + private Resource r1; + private Resource r2; 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 @@ -65,15 +66,24 @@ public class GraphComparator { private BijectionMap comparableResources = new BijectionMap(); + private ObjectComparator comparator; + // runtime attributes private ReadGraph g; private Layer0 b; - ArrayList rs1 = new ArrayList(); - ArrayList rs2 = new ArrayList(); + public GraphComparator() { + comparator = new TypeComparator(); + } + + public GraphComparator(ObjectComparator comparator) { + this.comparator = comparator; + } + ArrayList ss1 = new ArrayList(); ArrayList ss2 = new ArrayList(); + Comparator scomp = new PredicateComparator(); Comparator rcomp = new ResourceComparator(); @@ -115,10 +125,12 @@ public class GraphComparator { tested.clear(); } - public void test(ReadGraph g, Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException { + public void test(ReadGraph g, Resource r1, Resource r2) throws DatabaseException { this.g = g; this.b = Layer0.getInstance(g); + this.r1 = r1; + this.r2 = r2; changes1Set.clear(); changes2Set.clear(); modificationsSet.clear(); @@ -159,7 +171,7 @@ public class GraphComparator { ss1 = filterNonTested(ss1); ss2 = filterNonTested(ss2); - compareStatement(ss1, ss2, null, null); + compareStatements(ss1, ss2, null, null); ss1.clear(); ss2.clear(); } @@ -169,7 +181,7 @@ public class GraphComparator { ss2.addAll(g.getStatements(r2, rel)); ss1 = filterAsserted(r1, ss1); ss2 = filterAsserted(r2, ss2); - compareStatement(ss1, ss2, stack1, stack2); + compareStatements(ss1, ss2, stack1, stack2); ss1.clear(); ss2.clear(); } @@ -183,14 +195,7 @@ public class GraphComparator { } public GraphChanges getChanges() { -// List deletions = new ArrayList(); -// List additions = new ArrayList(); -// deletions.addAll(changes1); -// additions.addAll(changes2); -// Collections.sort(deletions, new FullStatementComparator()); -// Collections.sort(additions, new FullStatementComparator()); -// return new GraphChanges(deletions, additions, modifications); - return new GraphChanges(changes1,changes2,modifications); + return new GraphChanges(r1,r2,changes1,changes2,modifications); } private List filterAsserted(Resource r, Collection in) throws ServiceException { @@ -258,7 +263,7 @@ public class GraphComparator { } } - private void compareStatement(List ss1, List ss2, Stack stack1, Stack stack2) throws ServiceException, DoesNotContainValueException, ValidationException { + private void compareStatements(List ss1, List ss2, Stack stack1, Stack stack2) throws DatabaseException { Collections.sort(ss1, scomp); Collections.sort(ss2, scomp); @@ -290,7 +295,7 @@ public class GraphComparator { int same2 = sameRel(ss2, i2); int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate()); if (c == 0) { - compareObject(ss1, i1, same1, ss2, i2, same2,stack1,stack2); + compareStatements(ss1, i1, same1, ss2, i2, same2,stack1,stack2); i1+=same1; i2+=same2; } else if (c < 0) { @@ -326,8 +331,13 @@ public class GraphComparator { } + private int compareObject(Resource o1, Resource o2) throws DatabaseException { + if (comparableResources.contains(o1, o2)) + return (-1); + return comparator.compare(g, o1, o2); + } - private void compareObject(List ss1, int off1, int len1, List ss2, int off2, int len2, Stack stack1, Stack stack2) throws ServiceException, DoesNotContainValueException, ValidationException { + private void compareStatements(List ss1, int off1, int len1, List ss2, int off2, int len2, Stack stack1, Stack stack2) throws DatabaseException { boolean[] used1 = new boolean[len1]; for (int i = 0; i < used1.length; i++) { used1[i] = false; @@ -342,18 +352,10 @@ public class GraphComparator { List> differences = new ArrayList>(); for (int i1 = off1; i1 < off1 + len1; i1++) { Statement s1 = ss1.get(i1); - //Map differences = new HashMap(); List diff = new ArrayList(); for (int i2 = off2; i2 < off2 + len2; i2++) { Statement s2 = ss2.get(i2); - if (!compareType(s1.getObject(), s2.getObject())) { - diff.add(Integer.MAX_VALUE); - continue; - } - if (comparableResources.contains(s1.getObject(), s2.getObject())) - diff.add(-1); - else - diff.add(propsDiffCount(s1.getObject(), s2.getObject())); + diff.add(compareObject(s1.getObject(), s2.getObject())); } differences.add(diff); } @@ -425,30 +427,7 @@ public class GraphComparator { } } - private boolean compareType(Resource r1, Resource r2) throws ServiceException, ManyObjectsForFunctionalRelationException { - rs1.addAll(g.getObjects(r1, b.InstanceOf)); - rs2.addAll(g.getObjects(r2, b.InstanceOf)); - if (rs1.size() != rs2.size()) { - rs1.clear(); - rs2.clear(); - return false; - } - Collections.sort(rs1, rcomp); - Collections.sort(rs2, rcomp); - for (int i = 0; i < rs1.size(); i++) { - int c = rcomp.compare(rs1.get(i), rs2.get(i)); - if (c != 0) { - rs1.clear(); - rs2.clear(); - return false; - } - } - - rs1.clear(); - rs2.clear(); - - return true; - } + /** * compares properties, assumes functional relations @@ -500,26 +479,8 @@ public class GraphComparator { if (b1) { Object v1 = g.getValue(s1.getObject()); Object v2 = g.getValue(s2.getObject()); - boolean eq = false; - if (v1 instanceof Object[] && v2 instanceof Object[]) - eq = Arrays.deepEquals((Object[])v1, (Object[])v2); - else if (v1 instanceof int[] && v2 instanceof int[]) - eq = Arrays.equals((int[])v1, (int[])v2); - else if (v1 instanceof float[] && v2 instanceof float[]) - eq = Arrays.equals((float[])v1, (float[])v2); - else if (v1 instanceof double[] && v2 instanceof double[]) - eq = Arrays.equals((double[])v1, (double[])v2); - else if (v1 instanceof long[] && v2 instanceof long[]) - eq = Arrays.equals((long[])v1, (long[])v2); - else if (v1 instanceof byte[] && v2 instanceof byte[]) - eq = Arrays.equals((byte[])v1, (byte[])v2); - else if (v1 instanceof boolean[] && v2 instanceof boolean[]) - eq = Arrays.equals((boolean[])v1, (boolean[])v2); - else - eq = v1.equals(v2); + boolean eq = compareValue(v1, v2); if (!eq) { - //changes1.add(s1); - //changes2.add(s2); addModification(s1, s2); comparableStatements.map(s1, s2); comparableResources.map(s1.getObject(),s2.getObject()); @@ -528,8 +489,6 @@ public class GraphComparator { compareProps(s1.getObject(), s2.getObject()); } } else { - //changes1.add(s1); - //changes2.add(s2); addModification(s1, s2); comparableStatements.map(s1, s2); comparableResources.map(s1.getObject(),s2.getObject()); @@ -561,104 +520,29 @@ public class GraphComparator { } - private int propsDiffCount(Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException { - ArrayList ss1 = new ArrayList(); - ArrayList ss2 = new ArrayList(); - ss1.addAll(g.getStatements(r1, b.HasProperty)); - ss2.addAll(g.getStatements(r2, b.HasProperty)); - //System.out.println("Props count " + GraphUtils.getReadableName(g, r1) + " " + GraphUtils.getReadableName(g, r2)); - Collections.sort(ss1, scomp); - Collections.sort(ss2, scomp); - - int count = 0; - - int i1 = 0; - int i2 = 0; - - while (true) { - if (i1 >= ss1.size()) { - if (i2 >= ss2.size()) - break; - else { - while (i2 < ss2.size()) { - count++; - i2++; - } - break; - } - } else if (i2 >= ss2.size()) { - while (i1 < ss1.size()) { - count++; - i1++; - } - break; - } - Statement s1 = ss1.get(i1); - Statement s2 = ss2.get(i2); - int c = scomp.compare(s1, s2); - switch (c) { - case 0:{ - boolean b1 = g.hasValue(s1.getObject()); - boolean b2 = g.hasValue(s2.getObject()); - if (b1 == b2) { - if (b1) { - Object v1 = g.getValue(s1.getObject()); - Object v2 = g.getValue(s2.getObject()); - boolean eq = false; - if (v1 instanceof Object[] && v2 instanceof Object[]) - eq = Arrays.deepEquals((Object[])v1, (Object[])v2); - else if (v1 instanceof int[] && v2 instanceof int[]) - eq = Arrays.equals((int[])v1, (int[])v2); - else if (v1 instanceof float[] && v2 instanceof float[]) - eq = Arrays.equals((float[])v1, (float[])v2); - else if (v1 instanceof double[] && v2 instanceof double[]) - eq = Arrays.equals((double[])v1, (double[])v2); - else if (v1 instanceof long[] && v2 instanceof long[]) - eq = Arrays.equals((long[])v1, (long[])v2); - else if (v1 instanceof byte[] && v2 instanceof byte[]) - eq = Arrays.equals((byte[])v1, (byte[])v2); - else if (v1 instanceof boolean[] && v2 instanceof boolean[]) - eq = Arrays.equals((boolean[])v1, (boolean[])v2); - else - eq = v1.equals(v2); - if (!eq) { - count++; - } - //System.out.println("Prop count values " + v1 + " " + v2); - } else { - count += propsDiffCount(s1.getObject(), s2.getObject()); - } - } else { - //System.out.println("Props count structural vs literal"); - count++; - } - i1++; - i2++; - break; - } - case -1:{ - count++; - i1++; - break; - } - - case 1:{ - count++; - i2++; - break; - } - } - - } - - ss1.clear(); - ss2.clear(); - return count; + + public static boolean compareValue(Object v1, Object v2) { + if (v1 instanceof Object[] && v2 instanceof Object[]) + return Arrays.deepEquals((Object[])v1, (Object[])v2); + else if (v1 instanceof int[] && v2 instanceof int[]) + return Arrays.equals((int[])v1, (int[])v2); + else if (v1 instanceof float[] && v2 instanceof float[]) + return Arrays.equals((float[])v1, (float[])v2); + else if (v1 instanceof double[] && v2 instanceof double[]) + return Arrays.equals((double[])v1, (double[])v2); + else if (v1 instanceof long[] && v2 instanceof long[]) + return Arrays.equals((long[])v1, (long[])v2); + else if (v1 instanceof byte[] && v2 instanceof byte[]) + return Arrays.equals((byte[])v1, (byte[])v2); + else if (v1 instanceof boolean[] && v2 instanceof boolean[]) + return Arrays.equals((boolean[])v1, (boolean[])v2); + else + return v1.equals(v2); } - public class PredicateComparator implements Comparator { + public static class PredicateComparator implements Comparator { @Override public int compare(Statement o1, Statement o2) { if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId()) @@ -669,7 +553,7 @@ public class GraphComparator { } } - public class FullStatementComparator implements Comparator { + public static class FullStatementComparator implements Comparator { @Override public int compare(Statement o1, Statement o2) { if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId()) @@ -690,7 +574,7 @@ public class GraphComparator { - public class ResourceComparator implements Comparator { + public static class ResourceComparator implements Comparator { @Override public int compare(Resource o1, Resource o2) { if (o1.getResourceId() < o2.getResourceId()) @@ -700,4 +584,6 @@ public class GraphComparator { return 0; } } + + } diff --git a/org.simantics.interop/src/org/simantics/interop/test/NameComparator.java b/org.simantics.interop/src/org/simantics/interop/test/NameComparator.java new file mode 100644 index 0000000..abc2ab2 --- /dev/null +++ b/org.simantics.interop/src/org/simantics/interop/test/NameComparator.java @@ -0,0 +1,38 @@ +package org.simantics.interop.test; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; + +/** + * * Object comparator that uses type and name of objects to check if objects are comparable. + * + * Difference value is amount of properties that have different values. + * + * @author Marko Luukkainen + * + */ +public class NameComparator extends TypeComparator { + + @Override + public int compare(ReadGraph g, Resource o1, Resource o2) + throws DatabaseException { + if (!compareType(g,o1, o2)) { + return Integer.MAX_VALUE; + } + Layer0 l0 = Layer0.getInstance(g); + String n1 = g.getPossibleRelatedValue(o1, l0.HasName); + String n2 = g.getPossibleRelatedValue(o2, l0.HasName); + if (n1 != null && n2 != null) { + if (!n1.equals(n2)) + return Integer.MAX_VALUE; + } else if (n1 == null && n2 == null) { + + } else { + return Integer.MAX_VALUE; + } + return propsDiffCount(g,o1, o2); + } + +} diff --git a/org.simantics.interop/src/org/simantics/interop/test/ObjectComparator.java b/org.simantics.interop/src/org/simantics/interop/test/ObjectComparator.java new file mode 100644 index 0000000..0484def --- /dev/null +++ b/org.simantics.interop/src/org/simantics/interop/test/ObjectComparator.java @@ -0,0 +1,24 @@ +package org.simantics.interop.test; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; + +/** + * + * @author Marko Luukkainen + * + */ +public interface ObjectComparator { + + /** + * Compares two resources and returns numeric value of differences. Result value is Integer.MAX_VALUE if objects are not comparable. + * @param g + * @param o1 + * @param o2 + * @return + * @throws DatabaseException + */ + public int compare(ReadGraph g, Resource o1, Resource o2) throws DatabaseException; + +} diff --git a/org.simantics.interop/src/org/simantics/interop/test/TypeComparator.java b/org.simantics.interop/src/org/simantics/interop/test/TypeComparator.java new file mode 100644 index 0000000..0526a07 --- /dev/null +++ b/org.simantics.interop/src/org/simantics/interop/test/TypeComparator.java @@ -0,0 +1,149 @@ +package org.simantics.interop.test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.DoesNotContainValueException; +import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; +import org.simantics.db.exception.ServiceException; +import org.simantics.db.exception.ValidationException; +import org.simantics.interop.test.GraphComparator.PredicateComparator; +import org.simantics.interop.test.GraphComparator.ResourceComparator; +import org.simantics.layer0.Layer0; + +/** + * Object comparator that uses type of objects to check if objects are comparable. + * + * Difference value is amount of properties that have different values. + * + * @author Marko Luukkainen + * + */ +public class TypeComparator implements ObjectComparator { + + Comparator scomp = new PredicateComparator(); + Comparator rcomp = new ResourceComparator(); + + ArrayList rs1 = new ArrayList(); + ArrayList rs2 = new ArrayList(); + + @Override + public int compare(ReadGraph g, Resource o1, Resource o2) throws DatabaseException{ + if (!compareType(g,o1, o2)) { + return (Integer.MAX_VALUE); + } + return propsDiffCount(g,o1, o2); + } + + protected boolean compareType(ReadGraph g,Resource r1, Resource r2) throws ServiceException, ManyObjectsForFunctionalRelationException { + Layer0 l0 = Layer0.getInstance(g); + rs1.addAll(g.getObjects(r1, l0.InstanceOf)); + rs2.addAll(g.getObjects(r2, l0.InstanceOf)); + if (rs1.size() != rs2.size()) { + rs1.clear(); + rs2.clear(); + return false; + } + Collections.sort(rs1, rcomp); + Collections.sort(rs2, rcomp); + for (int i = 0; i < rs1.size(); i++) { + int c = rcomp.compare(rs1.get(i), rs2.get(i)); + if (c != 0) { + rs1.clear(); + rs2.clear(); + return false; + } + } + + rs1.clear(); + rs2.clear(); + + return true; + } + + protected int propsDiffCount(ReadGraph g, Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException { + Layer0 l0 = Layer0.getInstance(g); + ArrayList ss1 = new ArrayList(); + ArrayList ss2 = new ArrayList(); + ss1.addAll(g.getStatements(r1, l0.HasProperty)); + ss2.addAll(g.getStatements(r2, l0.HasProperty)); + Collections.sort(ss1, scomp); + Collections.sort(ss2, scomp); + + int count = 0; + + int i1 = 0; + int i2 = 0; + + while (true) { + if (i1 >= ss1.size()) { + if (i2 >= ss2.size()) + break; + else { + while (i2 < ss2.size()) { + count++; + i2++; + } + break; + } + } else if (i2 >= ss2.size()) { + while (i1 < ss1.size()) { + count++; + i1++; + } + break; + } + Statement s1 = ss1.get(i1); + Statement s2 = ss2.get(i2); + int c = scomp.compare(s1, s2); + switch (c) { + case 0:{ + boolean b1 = g.hasValue(s1.getObject()); + boolean b2 = g.hasValue(s2.getObject()); + if (b1 == b2) { + if (b1) { + Object v1 = g.getValue(s1.getObject()); + Object v2 = g.getValue(s2.getObject()); + boolean eq = GraphComparator.compareValue(v1, v2); + + if (!eq) { + count++; + } + //System.out.println("Prop count values " + v1 + " " + v2); + } else { + count += propsDiffCount(g,s1.getObject(), s2.getObject()); + } + } else { + //System.out.println("Props count structural vs literal"); + count++; + } + i1++; + i2++; + break; + } + case -1:{ + count++; + i1++; + break; + } + + case 1:{ + count++; + i2++; + break; + } + } + + } + + ss1.clear(); + ss2.clear(); + return count; + } + +}