import java.util.Collection;\r
import java.util.Collections;\r
import java.util.Comparator;\r
+import java.util.HashSet;\r
import java.util.List;\r
+import java.util.Set;\r
import java.util.Stack;\r
\r
import org.simantics.db.ReadGraph;\r
import org.simantics.db.Resource;\r
import org.simantics.db.Statement;\r
+import org.simantics.db.common.utils.NameUtils;\r
import org.simantics.db.exception.DoesNotContainValueException;\r
import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
import org.simantics.db.exception.ServiceException;\r
import org.simantics.db.exception.ValidationException;\r
import org.simantics.layer0.Layer0;\r
-import org.simantics.layer0.utils.direct.GraphUtils;\r
import org.simantics.utils.datastructures.BijectionMap;\r
import org.simantics.utils.datastructures.MapList;\r
+import org.simantics.utils.datastructures.Pair;\r
\r
/**\r
* Compares two subgraphs and reports differences.\r
\r
private List<Resource> traversed = new ArrayList<Resource>(); // list of relations that are traversed (and tested)\r
private List<Resource> tested = new ArrayList<Resource>(); // list of relations that are tested, but not traversed\r
- \r
+ private List<Resource> nonTraversed = new ArrayList<Resource>(); // list of relations that are not traversed\r
\r
private List<Statement> changes1 = new ArrayList<Statement>();\r
private List<Statement> changes2 = new ArrayList<Statement>();\r
+ private List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();\r
+ private Set<Statement> changes1Set = new HashSet<Statement>();\r
+ private Set<Statement> changes2Set = new HashSet<Statement>();\r
+ private Set<Pair<Statement,Statement>> modificationsSet = new HashSet<Pair<Statement,Statement>>();\r
+\r
private BijectionMap<Statement, Statement> comparable = new BijectionMap<Statement, Statement>();\r
\r
\r
ArrayList<Resource> rs2 = new ArrayList<Resource>();\r
ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
- Comparator<Statement> scomp = new StatementComparator();\r
+ Comparator<Statement> scomp = new PredicateComparator();\r
Comparator<Resource> rcomp = new ResourceComparator();\r
\r
\r
traversed.addAll(rels);\r
}\r
\r
+ public void addNonTraversed(Resource rel) {\r
+ nonTraversed.add(rel);\r
+ }\r
+ \r
+ public void addNonTraversed(Collection<Resource> rels) {\r
+ nonTraversed.addAll(rels);\r
+ }\r
+ \r
public void addTested(Resource rel) {\r
tested.add(rel);\r
}\r
this.g = g;\r
this.b = Layer0.getInstance(g);\r
\r
+ changes1Set.clear();\r
+ changes2Set.clear();\r
+ modificationsSet.clear();\r
changes1.clear();\r
changes2.clear();\r
+ modifications.clear();\r
\r
Stack<Resource> stack1 = new Stack<Resource>();\r
Stack<Resource> stack2 = new Stack<Resource>();\r
stack1.push(r1);\r
stack2.push(r2);\r
\r
- ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
- ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
+ List<Statement> ss1 = new ArrayList<Statement>();\r
+ List<Statement> ss2 = new ArrayList<Statement>();\r
\r
while (!stack1.isEmpty()) {\r
r1 = stack1.pop();\r
r2 = stack2.pop();\r
\r
- System.out.println("test " + GraphUtils.getReadableName(g, r1) + " " + GraphUtils.getReadableName(g, r2));\r
+ System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
compareProps(r1, r2);\r
\r
for (Resource rel : tested) {\r
- filterTraversed(g.getStatements(r1, rel), ss1);\r
- filterTraversed(g.getStatements(r2, rel), ss2);\r
+ ss1.addAll(g.getStatements(r1, rel));\r
+ ss2.addAll(g.getStatements(r2, rel));\r
+ ss1 = filterAsserted(r1, ss1);\r
+ ss2 = filterAsserted(r2, ss2);\r
+ ss1 = filterTraversed(ss1);\r
+ ss2 = filterTraversed(ss2);\r
\r
compareStatement(ss1, ss2, null, null);\r
ss1.clear();\r
for (Resource rel : traversed) {\r
ss1.addAll(g.getStatements(r1, rel));\r
ss2.addAll(g.getStatements(r2, rel));\r
+ ss1 = filterAsserted(r1, ss1);\r
+ ss2 = filterAsserted(r2, ss2);\r
compareStatement(ss1, ss2, stack1, stack2);\r
ss1.clear();\r
ss2.clear();\r
}\r
}\r
\r
- public Collection<Statement> getChanges1() {\r
- return changes1;\r
- }\r
\r
- public Collection<Statement> getChanges2() {\r
- return changes2;\r
- }\r
\r
public BijectionMap<Statement, Statement> getComparable() {\r
return comparable;\r
}\r
\r
- private void filterTraversed(Collection<Statement> in, Collection<Statement> out) throws ServiceException {\r
+ public GraphChanges getChanges() {\r
+// List<Statement> deletions = new ArrayList<Statement>();\r
+// List<Statement> additions = new ArrayList<Statement>();\r
+// deletions.addAll(changes1);\r
+// additions.addAll(changes2);\r
+// Collections.sort(deletions, new FullStatementComparator());\r
+// Collections.sort(additions, new FullStatementComparator());\r
+// return new GraphChanges(deletions, additions, modifications);\r
+ return new GraphChanges(changes1,changes2,modifications);\r
+ }\r
+ \r
+ private List<Statement> filterAsserted(Resource r, Collection<Statement> in) throws ServiceException {\r
+ List<Statement> out = new ArrayList<Statement>();\r
+ for (Statement s : in) {\r
+ if (!s.isAsserted(r))\r
+ out.add(s);\r
+ \r
+ }\r
+ return out;\r
+ }\r
+ \r
+ private String printStatement(ReadGraph graph, Statement s) throws ValidationException, ServiceException {\r
+ return NameUtils.getSafeName(graph, s.getSubject()) + " " + NameUtils.getSafeName(graph, s.getPredicate()) + " " + NameUtils.getSafeName(graph, s.getObject());\r
+ }\r
+ \r
+ private List<Statement> filterTraversed(Collection<Statement> in) throws ServiceException {\r
+ List<Statement> out = new ArrayList<Statement>();\r
for (Statement s : in) {\r
boolean usable = true;\r
for (Resource r : traversed) {\r
}\r
\r
}\r
+ return out;\r
+ }\r
+ \r
+ \r
+ private void addDeletion(Statement s) {\r
+ if (!changes1Set.contains(s)) {\r
+ changes1Set.add(s);\r
+ changes1.add(s);\r
+ }\r
+ }\r
+ \r
+ private void addAddition(Statement s) {\r
+ if (!changes2Set.contains(s)) {\r
+ changes2Set.add(s);\r
+ changes2.add(s);\r
+ }\r
+ }\r
+ \r
+ private void addModification(Statement s1, Statement s2) {\r
+ Pair<Statement, Statement> mod = new Pair<Statement, Statement>(s1,s2);\r
+ if (!modificationsSet.contains(mod)) {\r
+ modificationsSet.add(mod);\r
+ modifications.add(mod);\r
+ }\r
}\r
\r
private void compareStatement(List<Statement> ss1, List<Statement> ss2, Stack<Resource> stack1, Stack<Resource> stack2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
break;\r
} else {\r
while (i2 < ss2.size()) {\r
- changes2.add(ss2.get(i2));\r
+ System.out.println("Compare Statement diff2 " + printStatement(g,ss2.get(i2)));\r
+ \r
+ addAddition(ss2.get(i2));\r
i2++;\r
}\r
break;\r
}\r
} else if (i2 >= ss2.size()) {\r
while (i1 < ss1.size()) {\r
- changes1.add(ss1.get(i1));\r
+ System.out.println("Compare Statement diff1 " + printStatement(g,ss1.get(i1)));\r
+ addDeletion(ss1.get(i1));\r
i1++;\r
}\r
break;\r
i2+=same2;\r
} else if (c < 0) {\r
for (int i = 0; i < same1; i++) {\r
- changes1.add(ss1.get(i+i1));\r
+ System.out.println("Compare Statement diff1 " + printStatement(g,ss1.get(i+i1)));\r
+ addDeletion(ss1.get(i+i1));\r
}\r
i1 += same1;\r
- } else {\r
- for (int i = 0; i < same2; i++) {\r
- changes2.add(ss2.get(i+i2));\r
+ } else {\r
+ for (int i = 0; i < same2; i++) {\r
+ System.out.println("Compare Statement diff2 " + printStatement(g,ss2.get(i+i2)));\r
+ addAddition(ss2.get(i+i2));\r
}\r
+ \r
i2 += same2;\r
}\r
\r
for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
if (i2diff.get(i2) == pri) {\r
if (used2[i2])\r
- break;\r
+ continue;\r
used1[i1] = true;\r
used2[i2] = true;\r
if (stack1 != null) {\r
// using compareProps assumes that referenced objects are the same (references are not different)\r
// using propsDiffCount assumes that objects are different, and cannot report changes in referred object.\r
\r
- //compareProps(ss1.get(i1+off1).getObject(), ss2.get(i2+off2).getObject());\r
- int diff = propsDiffCount(ss1.get(i1+off1).getObject(), ss2.get(i2+off2).getObject());\r
- if (diff != 0) {\r
- changes1.add(ss1.get(i1+off1));\r
- changes2.add(ss2.get(i2+off2));\r
- }\r
+ \r
+// int diff = propsDiffCount(ss1.get(i1+off1).getObject(), ss2.get(i2+off2).getObject());\r
+// if (diff != 0) {\r
+// //changes1.add(ss1.get(i1+off1));\r
+// //changes2.add(ss2.get(i2+off2));\r
+// modifies.add(new Pair<Statement, Statement>(ss1.get(i1+off1), ss2.get(i2+off2)));\r
+// }\r
}\r
+ break;\r
}\r
}\r
}\r
}\r
for (int i1 = off1; i1 < off1 + len1; i1++) {\r
- if (!used1[i1-off1])\r
- changes1.add(ss1.get(i1));\r
+ if (!used1[i1-off1]) {\r
+ System.out.println("Compare Object diff1 " + printStatement(g,ss1.get(i1)));\r
+ addDeletion(ss1.get(i1));\r
+ }\r
}\r
for (int i2 = off2; i2 < off2 + len2; i2++) {\r
- if (!used2[i2-off2])\r
- changes2.add(ss2.get(i2));\r
+ if (!used2[i2-off2]) {\r
+ System.out.println("Compare Object diff2 " + printStatement(g,ss2.get(i2)));\r
+ addAddition(ss2.get(i2));\r
+ }\r
}\r
}\r
\r
* compares properties, assumes functional relations\r
* @param r1\r
* @param r2\r
- * @throws ManyObjectsForFunctionalRelationException\r
* @throws ServiceException\r
* @throws DoesNotContainValueException\r
+ * @throws ValidationException \r
*/\r
- private void compareProps(Resource r1, Resource r2) throws ManyObjectsForFunctionalRelationException, ServiceException, DoesNotContainValueException {\r
+ private void compareProps(Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
ss1.addAll(g.getStatements(r1, b.HasProperty));\r
break;\r
else {\r
while (i2 < ss2.size()) {\r
- changes2.add(ss2.get(i2));\r
+ System.out.println("Compare Prop diff2 " + printStatement(g,ss2.get(i2)));\r
+ addAddition(ss2.get(i2));\r
i2++;\r
}\r
break;\r
}\r
} else if (i2 >= ss2.size()) {\r
while (i1 < ss1.size()) {\r
- changes1.add(ss1.get(i1));\r
+ System.out.println("Compare Prop diff1 " + printStatement(g,ss1.get(i1)));\r
+ addDeletion(ss1.get(i1));\r
i1++;\r
}\r
break;\r
boolean eq = false;\r
if (v1 instanceof Object[] && v2 instanceof Object[])\r
eq = Arrays.deepEquals((Object[])v1, (Object[])v2);\r
+ else if (v1 instanceof int[] && v2 instanceof int[]) \r
+ eq = Arrays.equals((int[])v1, (int[])v2);\r
+ else if (v1 instanceof float[] && v2 instanceof float[]) \r
+ eq = Arrays.equals((float[])v1, (float[])v2);\r
+ else if (v1 instanceof double[] && v2 instanceof double[]) \r
+ eq = Arrays.equals((double[])v1, (double[])v2);\r
+ else if (v1 instanceof long[] && v2 instanceof long[]) \r
+ eq = Arrays.equals((long[])v1, (long[])v2);\r
+ else if (v1 instanceof byte[] && v2 instanceof byte[]) \r
+ eq = Arrays.equals((byte[])v1, (byte[])v2);\r
+ else if (v1 instanceof boolean[] && v2 instanceof boolean[]) \r
+ eq = Arrays.equals((boolean[])v1, (boolean[])v2);\r
else\r
eq = v1.equals(v2);\r
if (!eq) {\r
- changes1.add(s1);\r
- changes2.add(s2);\r
+ //changes1.add(s1);\r
+ //changes2.add(s2);\r
+ addModification(s1, s2);\r
comparable.map(s1, s2);\r
}\r
} else {\r
compareProps(s1.getObject(), s2.getObject());\r
}\r
} else {\r
- changes1.add(s1);\r
- changes2.add(s2);\r
+ //changes1.add(s1);\r
+ //changes2.add(s2);\r
+ addModification(s1, s2);\r
comparable.map(s1, s2);\r
}\r
i1++;\r
break;\r
}\r
case -1:{\r
- changes1.add(s1);\r
+ System.out.println("Compare Prop diff1s " + printStatement(g,s1));\r
+ addDeletion(s1);\r
i1++;\r
break;\r
}\r
\r
case 1:{\r
- changes2.add(s2);\r
+ System.out.println("Compare Prop diff2s " + printStatement(g,s2));\r
+ addAddition(s2);\r
i2++;\r
break;\r
}\r
Statement s2 = ss2.get(i2);\r
int c = scomp.compare(s1, s2);\r
switch (c) {\r
- case 0:{\r
- boolean b1 = g.hasValue(s1.getObject());\r
- boolean b2 = g.hasValue(s2.getObject());\r
- if (b1 == b2) {\r
- if (b1) {\r
- Object v1 = g.getValue(s1.getObject());\r
- Object v2 = g.getValue(s2.getObject());\r
- boolean eq = false;\r
- if (v1 instanceof Object[] && v2 instanceof Object[])\r
- eq = Arrays.deepEquals((Object[])v1, (Object[])v2);\r
- else\r
- eq = v1.equals(v2);\r
- if (!eq) {\r
- count++;\r
+ case 0:{\r
+ boolean b1 = g.hasValue(s1.getObject());\r
+ boolean b2 = g.hasValue(s2.getObject());\r
+ if (b1 == b2) {\r
+ if (b1) {\r
+ Object v1 = g.getValue(s1.getObject());\r
+ Object v2 = g.getValue(s2.getObject());\r
+ boolean eq = false;\r
+ if (v1 instanceof Object[] && v2 instanceof Object[])\r
+ eq = Arrays.deepEquals((Object[])v1, (Object[])v2);\r
+ else if (v1 instanceof int[] && v2 instanceof int[]) \r
+ eq = Arrays.equals((int[])v1, (int[])v2);\r
+ else if (v1 instanceof float[] && v2 instanceof float[]) \r
+ eq = Arrays.equals((float[])v1, (float[])v2);\r
+ else if (v1 instanceof double[] && v2 instanceof double[]) \r
+ eq = Arrays.equals((double[])v1, (double[])v2);\r
+ else if (v1 instanceof long[] && v2 instanceof long[]) \r
+ eq = Arrays.equals((long[])v1, (long[])v2);\r
+ else if (v1 instanceof byte[] && v2 instanceof byte[]) \r
+ eq = Arrays.equals((byte[])v1, (byte[])v2);\r
+ else if (v1 instanceof boolean[] && v2 instanceof boolean[]) \r
+ eq = Arrays.equals((boolean[])v1, (boolean[])v2);\r
+ else\r
+ eq = v1.equals(v2);\r
+ if (!eq) {\r
+ count++;\r
+ }\r
+ //System.out.println("Prop count values " + v1 + " " + v2);\r
+ } else {\r
+ count += propsDiffCount(s1.getObject(), s2.getObject());\r
}\r
- //System.out.println("Prop count values " + v1 + " " + v2);\r
} else {\r
- count += propsDiffCount(s1.getObject(), s2.getObject());\r
+ //System.out.println("Props count structural vs literal");\r
+ count++;\r
}\r
- } else {\r
- //System.out.println("Props count structural vs literal");\r
+ i1++;\r
+ i2++;\r
+ break;\r
+ }\r
+ case -1:{\r
count++;\r
+ i1++;\r
+ break;\r
+ }\r
+ \r
+ case 1:{\r
+ count++;\r
+ i2++;\r
+ break;\r
}\r
- i1++;\r
- i2++;\r
- break;\r
- }\r
- case -1:{\r
- count++;\r
- i1++;\r
- break;\r
- }\r
- \r
- case 1:{\r
- count++;\r
- i2++;\r
- break;\r
- }\r
}\r
- \r
\r
}\r
\r
\r
\r
\r
- public class StatementComparator implements Comparator<Statement> {\r
+ public class PredicateComparator implements Comparator<Statement> {\r
+ @Override\r
+ public int compare(Statement o1, Statement o2) {\r
+ if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
+ return -1;\r
+ if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
+ return 1;\r
+ return 0;\r
+ }\r
+ }\r
+ \r
+ public class FullStatementComparator implements Comparator<Statement> {\r
@Override\r
public int compare(Statement o1, Statement o2) {\r
+ if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
+ return -1;\r
+ if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
+ return 1;\r
if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
return -1;\r
if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
return 1;\r
+ if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
+ return -1;\r
+ if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
+ return 1;\r
return 0;\r
}\r
}\r
public int compare(Resource o1, Resource o2) {\r
if (o1.getResourceId() < o2.getResourceId())\r
return -1;\r
- if (o2.getResourceId() > o2.getResourceId())\r
+ if (o1.getResourceId() > o2.getResourceId())\r
return 1;\r
return 0;\r
}\r
import org.simantics.db.Statement;\r
import org.simantics.db.common.ResourceArray;\r
import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.utils.NameUtils;\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.db.exception.InvalidResourceReferenceException;\r
import org.simantics.db.exception.ServiceException;\r
import org.simantics.db.request.Read;\r
import org.simantics.db.service.SerialisationSupport;\r
import org.simantics.layer0.Layer0;\r
-import org.simantics.layer0.utils.direct.GraphUtils;\r
import org.simantics.ui.SimanticsUI;\r
import org.simantics.ui.dnd.LocalObjectTransfer;\r
import org.simantics.ui.dnd.ResourceReferenceTransfer;\r
import org.simantics.ui.dnd.ResourceTransferUtils;\r
import org.simantics.ui.utils.ResourceAdaptionUtils;\r
import org.simantics.utils.datastructures.BijectionMap;\r
+import org.simantics.utils.datastructures.Pair;\r
\r
/**\r
* Simple multi line text viewer for seeing differences in two subgraphs. \r
BijectionMap<Statement, Statement> map = comparator.getComparable();\r
Map<Statement, Integer> indices = new HashMap<Statement, Integer>();\r
final StringBuilder sb1 = new StringBuilder();\r
+ final StringBuilder sb2 = new StringBuilder();\r
int index = 0;\r
- for (Statement s : comparator.getChanges1()) {\r
+ \r
+ GraphChanges changes = comparator.getChanges();\r
+ \r
+ for (Pair<Statement,Statement> mod : changes.getModifications()) {\r
+ {\r
+ String sub;\r
+ try {\r
+ Statement s = mod.first;\r
+ sub = NameUtils.getSafeName(graph, s.getSubject());\r
+ String pre = NameUtils.getSafeName(graph, s.getPredicate());\r
+ String obj = NameUtils.getSafeName(graph, s.getObject());\r
+ if (map.containsLeft(s)) {\r
+ index++;\r
+ indices.put(s, index);\r
+ sb1.append("["+index + "] ");\r
+ }\r
+ sb1.append(sub + " - " + pre + " - " + obj);\r
+ sb1.append(" ["+s.getSubject().getResourceId() + " " + s.getPredicate().getResourceId() + " " + s.getObject().getResourceId()+"]");\r
+ sb1.append("\n");\r
+ } catch (ValidationException e) {\r
+ e.printStackTrace();\r
+ } catch (ServiceException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ {\r
+ String sub;\r
+ try {\r
+ Statement s = mod.second;\r
+ sub = NameUtils.getSafeName(graph, s.getSubject());\r
+ String pre = NameUtils.getSafeName(graph, s.getPredicate());\r
+ String obj = NameUtils.getSafeName(graph, s.getObject());\r
+ if (map.containsRight(s)) {\r
+ index = indices.get(map.getLeft(s));\r
+ sb2.append("["+index + "] ");\r
+ }\r
+ sb2.append(sub + " - " + pre + " - " + obj);\r
+ sb2.append(" ["+s.getSubject().getResourceId() + " " + s.getPredicate().getResourceId() + " " + s.getObject().getResourceId()+"]");\r
+ sb2.append("\n");\r
+ } catch (ValidationException e) {\r
+ e.printStackTrace();\r
+ } catch (ServiceException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+ for (Statement s : changes.getDeletions()) {\r
String sub;\r
try {\r
\r
- sub = GraphUtils.getReadableName(graph, s.getSubject());\r
- String pre = GraphUtils.getReadableName(graph, s.getPredicate());\r
- String obj = GraphUtils.getReadableName(graph, s.getObject());\r
+ sub = NameUtils.getSafeName(graph, s.getSubject());\r
+ String pre = NameUtils.getSafeName(graph, s.getPredicate());\r
+ String obj = NameUtils.getSafeName(graph, s.getObject());\r
if (map.containsLeft(s)) {\r
index++;\r
indices.put(s, index);\r
}\r
\r
}\r
- final StringBuilder sb2 = new StringBuilder();\r
- for (Statement s : comparator.getChanges2()) {\r
+ \r
+ for (Statement s : changes.getAdditions()) {\r
String sub;\r
try {\r
- sub = GraphUtils.getReadableName(graph, s.getSubject());\r
- String pre = GraphUtils.getReadableName(graph, s.getPredicate());\r
- String obj = GraphUtils.getReadableName(graph, s.getObject());\r
+ sub = NameUtils.getSafeName(graph, s.getSubject());\r
+ String pre = NameUtils.getSafeName(graph, s.getPredicate());\r
+ String obj = NameUtils.getSafeName(graph, s.getObject());\r
if (map.containsRight(s)) {\r
index = indices.get(map.getLeft(s));\r
sb2.append("["+index + "] ");\r
@Override\r
public String perform(ReadGraph graph)\r
throws DatabaseException {\r
- return GraphUtils.getReadableName(graph, r);\r
+ return NameUtils.getSafeName(graph, r);\r
}\r
}));\r
} catch (DatabaseException e) {\r