import java.util.HashSet;
import java.util.List;
import java.util.Map;
+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;
import org.simantics.db.common.request.ReadRequest;
import org.simantics.db.common.utils.NameUtils;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.interop.test.GraphChanges.Modification;
import org.simantics.layer0.Layer0;
import org.simantics.utils.datastructures.BijectionMap;
import org.simantics.utils.datastructures.MapList;
private Resource r1;
private Resource r2;
- private Set<Resource> strong = new HashSet<Resource>(); // List of relations that identify object, if subject is already identified.
- private List<Resource> traversed = new ArrayList<Resource>(); // list of relations that are traversed (and tested)
- private List<Resource> tested = new ArrayList<Resource>(); // list of relations that are tested, but not traversed
- private List<Resource> nonTraversed = new ArrayList<Resource>(); // list of relations that are not traversed
- private List<Resource> nonTested = new ArrayList<Resource>(); // list of relations that are not tested
-
- private List<Statement> changes1 = new ArrayList<Statement>();
- private List<Statement> changes2 = new ArrayList<Statement>();
- private List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();
- private Set<Statement> changes1Set = new HashSet<Statement>();
- private Set<Statement> changes2Set = new HashSet<Statement>();
- private Set<Pair<Statement,Statement>> modificationsSet = new HashSet<Pair<Statement,Statement>>();
+ private Set<Resource> strong = new HashSet<>(); // List of relations that identify object, if subject is already identified.
+ private List<Resource> traversed = new ArrayList<>(); // list of relations that are traversed (and tested)
+ private List<Resource> tested = new ArrayList<>(); // list of relations that are tested, but not traversed
+ private List<Resource> nonTraversed = new ArrayList<>(); // list of relations that are not traversed
+ private List<Resource> nonTested = new ArrayList<>(); // list of relations that are not tested
+
+ private List<Statement> changes1 = new ArrayList<>();
+ private List<Statement> changes2 = new ArrayList<>();
+ private List<Modification> modifications = new ArrayList<>();
+ private Set<Statement> changes1Set = new HashSet<>();
+ private Set<Statement> changes2Set = new HashSet<>();
+ private Set<Modification> modificationsSet = new HashSet<>();
- private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<Statement, Statement>();
- private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<Resource, Resource>();
+ private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<>();
+ private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<>();
private Set<Resource> processedResources = new HashSet<Resource>();
this.g = g;
this.b = Layer0.getInstance(g);
comparator.setComparator(this);
+ comparator.initialize(g, r1, r2);
Stack<Resource> objectsLeft = new Stack<Resource>();
Stack<Resource> objectsRight = new Stack<Resource>();
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.
if (!comparableStatements.containsRight(s))
addAddition(s);
}
-
-
}
public void test(Session session) throws DatabaseException {
comparator.setComparator(this);
- addComparable(r1, r2, false);
+ session.syncRequest(new ReadRequest() {
+
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ comparator.initialize(graph, r1, r2);
+ }
+ });
+
+ addComparable(r1, r2);
final Stack<Resource> objectsLeft = new Stack<Resource>();
final Stack<Resource> objectsRight = new Stack<Resource>();
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.
}
for (Statement s : unreliableLeft) {
if (!comparableStatements.containsLeft(s))
+ if (s.getObject().getResourceId() == 303248)
+ System.out.println();
addDeletion(s);
}
for (Statement s : unreliableRight) {
if((comparableResources.containsLeft(r1)||comparableResources.containsRight(r2)) && !comparableResources.contains(r1, r2)) {
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, false);
+ addComparable(r1, r2);
//System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));
compareProps(r1, r2);
}
for (Resource left : subjectLeft.getKeys()) {
- if (!comparableResources.containsLeft(left))
- continue;
Resource right = comparableResources.getRight(left);
+ if (right == null)
+ continue;
for (Statement leftS : subjectLeft.getValues(left)) {
Resource leftO = leftS.getObject();
- if (!comparableResources.containsLeft(leftO))
- continue;
if (!unreliableLeft.contains(leftS))
continue;
Resource rightO = comparableResources.getRight(leftO);
+ if (rightO == null)
+ continue;
for (Statement rightS : subjectRight.getValues(right)) {
if (!rightS.getObject().equals(rightO))
continue;
comparableResources.contains(leftS.getPredicate(), rightS.getPredicate())) {
unreliableLeft.remove(leftS);
unreliableRight.remove(rightS);
- addComparable(leftS, rightS, false);
+ addComparable(leftS, rightS);
}
}
}
}
}
+ compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);
+
for (Resource similarOl : comparableOLeft.getKeys()) {
List<Statement> similarLeft = comparableOLeft.getValues(similarOl);
if (similarLeft.size() == left.size()) {
for (int j = 0; j < left.size(); j++) {
if (useSL[j])
continue;
+ // compare predicates
Resource pl = left.get(i).getPredicate();
Resource psl = similarLeft.get(j).getPredicate();
if (pl.equals(psl)) {
- useL[i] = true;
- useSL[j] = true;
- break;
+ // 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) {
+ useL[i] = true;
+ useSL[j] = true;
+ break;
+ }
}
}
}
if (!comparableResources.contains(ls.getSubject(), rs.getSubject()))
continue;
if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) {
- iLeft[l] = r;
- iRight[r] = l;
+ // compare objects (unreliable result is not accepted)
+ int comp = comparator.compare(g, ls.getObject(), rs.getObject());
+ if (comp > 0 && comp < Integer.MAX_VALUE) {
+ iLeft[l] = r;
+ iRight[r] = l;
+ break;
+ }
break;
}
}
objectsLeft.add(ol);
objectsRight.add(or);
- addComparable(ol, or, false);
+ addComparable(ol, or);
for (int l = 0; l < left.size(); l++) {
int r = indices.first[l];
Statement sl = left.get(l);
Statement sr = right.get(r);
- addComparable(sl, sr, true);
+ addComparable(sl, sr);
unreliableLeft.remove(sl);
unreliableRight.remove(sr);
}
+ } else {
+
}
}
}
+ private void processUnreliable2(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {
+ MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
+ MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
+ MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();
+ MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();
+
+ 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<Statement> left = objectLeft.getValues(ol);
+ // all subjects that have statements to the left side object (ol)
+ Set<Resource> sLeft = new HashSet<Resource>();
+ // all matching subjects on the right side
+ Set<Resource> sRight = new HashSet<Resource>();
+ for (Statement s : left) {
+ sLeft.add(s.getSubject());
+ sRight.add(comparableResources.getRight(s.getSubject()));
+ }
+
+ if (sLeft.size() == 1 && sRight.size() == 1) {
+ List<Statement> ss1 = new ArrayList<Statement>(subjectLeft.getValues(sLeft.iterator().next()));
+ List<Statement> ss2 = new ArrayList<Statement>(subjectRight.getValues(sRight.iterator().next()));
+
+ int count = comparableStatements.size();
+ compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);
+ if (comparableStatements.size() > count) {
+ for (Entry<Statement, Statement> entry : comparableStatements.getEntries()) {
+ unreliableLeft.remove(entry.getKey());
+ unreliableRight.remove(entry.getValue());
+ }
+ }
+ }
+ }
+ }
+
private void processUnreliableDeep(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws DatabaseException {
MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();
MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();
objectsLeft.add(ol);
objectsRight.add(or);
- addComparable(ol, or, false);
+ addComparable(ol, or);
Collection<Statement> statementsLeft = objectLeft.getValues(ol);
Collection<Statement> statementsRight = objectRight.getValues(or);
unreliableLeft.removeAll(statementsLeft);
for (Path left : map.getLeftSet()) {
Path right = map.getRight(left);
for (int i = 0; i < left.getLength(); i++) {
- addComparable(left.getStatements().get(i),right.getStatements().get(i),false);
+ addComparable(left.getStatements().get(i),right.getStatements().get(i));
}
}
}
return new GraphChanges(r1,r2,changes1,changes2,modifications,comparableResources);
}
- private void addComparable(Statement left, Statement right, boolean process) throws DatabaseException {
- addComparable(left.getObject(), right.getObject(), process);
+ 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, boolean process) throws DatabaseException {
+ private void addComparable(Resource left, Resource right) throws DatabaseException {
if(!comparableResources.contains(left, right)) {
if (comparableResources.containsLeft(left)||comparableResources.containsRight(right)) {
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);
+ comparableResources.map(left, right);
}
}
}
}
- private void addModification(Statement s1, Statement s2) {
- Pair<Statement, Statement> mod = new Pair<Statement, Statement>(s1,s2);
+ private void addModification(Resource sub1, Statement s1, Resource sub2, Statement s2) {
+ Modification mod = new Modification(sub1, sub2, s1, s2);
if (!modificationsSet.contains(mod)) {
modificationsSet.add(mod);
modifications.add(mod);
objectsLeft.add(s1.getObject());
objectsRight.add(s2.getObject());
}
- addComparable(s1, s2, true);
+ addComparable(s1, s2);
break;
}
}
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 = compareValue(v1, v2);
+// Object v1 = g.getValue(s1.getObject());
+// Object v2 = g.getValue(s2.getObject());
+// boolean eq = compareValue(v1, v2);
+ boolean eq = compareValue(g,b,s1.getObject(), s2.getObject());
if (!eq) {
- addModification(s1, s2);
- addComparable(s1, s2, false);
+ addModification(r1,s1,r2,s2);
+ if (!s1.isAsserted(r1) && !s2.isAsserted(r2))
+ addComparable(s1, s2);
}
} else {
if (!s1.getObject().equals(s1.getSubject()) && !s2.getObject().equals(s2.getSubject()))
compareProps(s1.getObject(), s2.getObject());
}
} else {
- addModification(s1, s2);
- addComparable(s1, s2, false);
+ addModification(r1,s1,r2,s2);
+ if (!s1.isAsserted(r1) && !s2.isAsserted(r2))
+ addComparable(s1, s2);
}
i1++;
i2++;
}
+ 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);