]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop/src/org/simantics/interop/test/GraphComparator.java
More extensive search for comparable resources
[simantics/interop.git] / org.simantics.interop / src / org / simantics / interop / test / GraphComparator.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     Foster Wheeler Energia Oy - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.interop.test;\r
13 \r
14 import java.math.MathContext;\r
15 import java.util.ArrayList;\r
16 import java.util.Arrays;\r
17 import java.util.Collection;\r
18 import java.util.Collections;\r
19 import java.util.Comparator;\r
20 import java.util.HashMap;\r
21 import java.util.HashSet;\r
22 import java.util.List;\r
23 import java.util.Map;\r
24 import java.util.Set;\r
25 import java.util.Stack;\r
26 \r
27 import org.simantics.db.ReadGraph;\r
28 import org.simantics.db.Resource;\r
29 import org.simantics.db.Statement;\r
30 import org.simantics.db.common.utils.NameUtils;\r
31 import org.simantics.db.exception.DatabaseException;\r
32 import org.simantics.db.exception.DoesNotContainValueException;\r
33 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
34 import org.simantics.db.exception.ServiceException;\r
35 import org.simantics.db.exception.ValidationException;\r
36 import org.simantics.layer0.Layer0;\r
37 import org.simantics.utils.datastructures.BijectionMap;\r
38 import org.simantics.utils.datastructures.MapList;\r
39 import org.simantics.utils.datastructures.Pair;\r
40 \r
41 /**\r
42  * Compares two subgraphs and reports differences.\r
43  * \r
44  * Assumes that subgraphs (defined using traverse relations) are not cyclic.\r
45  * \r
46  * Assumes that properties can be used to identify objects, if relation type is not enough.\r
47  * \r
48  * \r
49  * \r
50  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
51  *\r
52  */\r
53 public class GraphComparator {\r
54 \r
55         private Resource r1;\r
56         private Resource r2;\r
57         private Set<Resource> strong = new HashSet<Resource>();       // List of relations that identify object, if subject is already identified. \r
58         private List<Resource> traversed = new ArrayList<Resource>(); // list of relations that are traversed (and tested)\r
59         private List<Resource> tested = new ArrayList<Resource>();    // list of relations that are tested, but not traversed\r
60         private List<Resource> nonTraversed = new ArrayList<Resource>(); // list of relations that are not traversed\r
61         private List<Resource> nonTested = new ArrayList<Resource>(); // list of relations that are not tested\r
62         \r
63         private List<Statement> changes1 = new ArrayList<Statement>();\r
64         private List<Statement> changes2 = new ArrayList<Statement>();\r
65         private List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();\r
66         private Set<Statement> changes1Set = new HashSet<Statement>();\r
67         private Set<Statement> changes2Set = new HashSet<Statement>();\r
68         private Set<Pair<Statement,Statement>> modificationsSet = new HashSet<Pair<Statement,Statement>>();\r
69 \r
70         private BijectionMap<Statement, Statement> comparableStatements = new BijectionMap<Statement, Statement>();\r
71         private BijectionMap<Resource, Resource> comparableResources = new BijectionMap<Resource, Resource>();\r
72         \r
73         \r
74         private ResourceComparator comparator;\r
75         \r
76         private Comparator<Statement> scomp = new PredicateComparator();\r
77         private Comparator<Resource> rcomp = new ResComparator();\r
78         \r
79         // runtime attributes\r
80         \r
81         private ReadGraph g;\r
82         private Layer0 b;\r
83         \r
84         public GraphComparator(Resource r1, Resource r2) {\r
85                 this.r1 = r1;\r
86                 this.r2 = r2;\r
87                 comparator = new TypeComparator();\r
88         }\r
89         \r
90         public GraphComparator(Resource r1, Resource r2, ResourceComparator comparator) {\r
91                 this.r1 = r1;\r
92                 this.r2 = r2;\r
93                 this.comparator = comparator;\r
94         }\r
95         \r
96         ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
97         ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
98         \r
99         \r
100         public Comparator<Resource> getResourceComparator() {\r
101                 return rcomp;\r
102         }\r
103         \r
104         public Comparator<Statement> getStatementComparator() {\r
105                 return scomp;\r
106         }\r
107         \r
108         public Resource getR1() {\r
109                 return r1;\r
110         }\r
111         \r
112         public Resource getR2() {\r
113                 return r2;\r
114         }\r
115         \r
116         public void addTraversed(Resource rel) {\r
117                 traversed.add(rel);\r
118         }\r
119         \r
120         public void addTraversed(Collection<Resource> rels) {\r
121                 traversed.addAll(rels);\r
122         }\r
123         \r
124         public void addNonTraversed(Resource rel) {\r
125                 nonTraversed.add(rel);\r
126         }\r
127         \r
128         public void addNonTraversed(Collection<Resource> rels) {\r
129                 nonTraversed.addAll(rels);\r
130         }\r
131         \r
132         public void addTested(Resource rel) {\r
133                 tested.add(rel);\r
134         }\r
135         \r
136         public void addTested(Collection<Resource> rels) {\r
137                 tested.addAll(rels);\r
138         }\r
139         \r
140         public void addNonTested(Resource rel) {\r
141                 nonTested.add(rel);\r
142         }\r
143         \r
144         public void addNonTested(Collection<Resource> rels) {\r
145                 nonTested.addAll(rels);\r
146         }\r
147         \r
148         public void addComparableResources(Resource r1, Resource r2) {\r
149                 comparableResources.map(r1, r2);\r
150         }\r
151         \r
152         public void addComparableResources(BijectionMap<Resource, Resource> matching) {\r
153                 comparableResources.addAll(matching);\r
154         }\r
155         \r
156         public void addStrong(Resource r) {\r
157                 strong.add(r);\r
158         }\r
159         \r
160         public void clearRels() {\r
161                 traversed.clear();\r
162                 tested.clear();\r
163                 nonTraversed.clear();\r
164                 nonTested.clear();\r
165         }\r
166         \r
167         public void test(ReadGraph g) throws DatabaseException {\r
168                 this.g = g;\r
169                 this.b = Layer0.getInstance(g);\r
170                 comparator.setComparator(this);\r
171                 \r
172                 Stack<Resource> objectsLeft = new Stack<Resource>();\r
173                 Stack<Resource> objectsRight = new Stack<Resource>();\r
174                 objectsLeft.push(r1);\r
175                 objectsRight.push(r2);\r
176                 \r
177                 \r
178                 \r
179                 \r
180                 Set<Statement> unreliableLeft = new HashSet<Statement>();\r
181                 Set<Statement> unreliableRight = new HashSet<Statement>();\r
182                 \r
183                 while (true) {\r
184                         if (objectsLeft.isEmpty())\r
185                                 break;\r
186                         \r
187                         // process compares objects that are identified and searches for more resources to process. \r
188                         process(objectsLeft, objectsRight, unreliableLeft, unreliableRight);\r
189                         // process unreliable handles cases where unidentified resources have path of length one to identified resource\r
190                         processUnreliable(unreliableLeft, unreliableRight,objectsLeft,objectsRight);\r
191                         if (objectsLeft.isEmpty() && unreliableLeft.size() > 0 && unreliableRight.size() > 0) {\r
192                                 // comparison is ending, but we have still unprocessed unidentified resources left.\r
193                                 // These cases have longer path than one to identified objects.\r
194                                 processUnreliableDeep(unreliableLeft, unreliableRight, objectsLeft, objectsRight);\r
195                         }\r
196                         \r
197                 }\r
198                 for (Statement s : unreliableLeft) {\r
199                         if (!comparableStatements.containsLeft(s))\r
200                                 addDeletion(s);\r
201                 }\r
202                 for (Statement s : unreliableRight) {\r
203                         if (!comparableStatements.containsRight(s))\r
204                                 addAddition(s);\r
205                 }\r
206                 \r
207                 \r
208         }\r
209         \r
210         private void process(Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Set<Statement> unreliableLeft, Set<Statement> unreliableRight) throws DatabaseException {\r
211                 List<Statement> ss1 = new ArrayList<Statement>();\r
212                 List<Statement> ss2 = new ArrayList<Statement>();\r
213                 \r
214                 while (!objectsLeft.isEmpty()) {\r
215                         Resource r1 = objectsLeft.pop();\r
216                         Resource r2 = objectsRight.pop();\r
217                 \r
218                         if (comparableResources.contains(r1, r2)) {\r
219                                 //System.out.println("already tested " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
220                                 continue;\r
221                         }\r
222                         comparableResources.map(r1, r2);\r
223                         \r
224                         //System.out.println("test " + NameUtils.getSafeName(g, r1) + " " + NameUtils.getSafeName(g, r2));\r
225                         compareProps(r1, r2);\r
226                         \r
227                         for (Resource rel : tested) {\r
228                                 ss1.addAll(g.getStatements(r1, rel));\r
229                                 ss2.addAll(g.getStatements(r2, rel));\r
230                                 ss1 = filterAsserted(r1, ss1);\r
231                                 ss2 = filterAsserted(r2, ss2);\r
232                                 ss1 = filterTraversed(ss1);\r
233                                 ss2 = filterTraversed(ss2);\r
234                                 ss1 = filterNonTested(ss1);\r
235                                 ss2 = filterNonTested(ss2);\r
236                                 \r
237                                 compareStatements(ss1, ss2, null, null,null,null);\r
238                                 ss1.clear();\r
239                                 ss2.clear();\r
240                         }\r
241                         \r
242                         for (Resource rel : traversed) {\r
243                                 ss1.addAll(g.getStatements(r1, rel));\r
244                                 ss2.addAll(g.getStatements(r2, rel));\r
245                                 ss1 = filterAsserted(r1, ss1);\r
246                                 ss2 = filterAsserted(r2, ss2);\r
247                                 compareStatements(ss1, ss2, objectsLeft, objectsRight,unreliableLeft,unreliableRight);\r
248                                 ss1.clear();\r
249                                 ss2.clear();\r
250                                 \r
251                         }\r
252                 }\r
253         }\r
254         private void processUnreliable(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) {\r
255                 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();\r
256                 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();\r
257                 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();\r
258                 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();\r
259                 \r
260                 for (Statement s : unreliableLeft) {\r
261                         subjectLeft.add(s.getSubject(),s);\r
262                         objectLeft.add(s.getObject(),s);\r
263                 }\r
264                 for (Statement s : unreliableRight) {\r
265                         subjectRight.add(s.getSubject(),s);\r
266                         objectRight.add(s.getObject(),s);\r
267                 }\r
268                 \r
269                 for (Resource ol : objectLeft.getKeys()) {\r
270 \r
271                         // all statements to the left side object\r
272                         List<Statement> left = objectLeft.getValues(ol);\r
273                         // all subjects that have statements to the left side object (ol)\r
274                         Set<Resource> sLeft = new HashSet<Resource>();\r
275                         // all matching subjects on the right side\r
276                         Set<Resource> sRight = new HashSet<Resource>();\r
277                         for (Statement s : left) {\r
278                                 sLeft.add(s.getSubject());\r
279                                 sRight.add(comparableResources.getRight(s.getSubject()));\r
280                         }\r
281                         // all objects that subjects on the right side point to. Object left has its matching resource among these, if it has matching resource\r
282                         MapList<Resource,Statement> possibleOR = new MapList<Resource, Statement>();\r
283                         for (Resource sr : sRight) {\r
284                                 for (Statement s : subjectRight.getValues(sr))\r
285                                         possibleOR.add(s.getObject(),s);\r
286                         }\r
287                         \r
288                         // filter possible right side objects to those that have same amount of statements as the left side object\r
289                         for (Resource or : possibleOR.getKeys().toArray(new Resource[possibleOR.getKeys().size()])) {\r
290                                 List<Statement> right = possibleOR.getValues(or);\r
291                                 if (right.size() != left.size())\r
292                                         possibleOR.remove(or);\r
293                                         \r
294                         }\r
295                         \r
296                         // check for matching statements (comparable subjects, matching predicates)\r
297                         MapList<Resource,Statement> matchingOR = new MapList<Resource, Statement>(); // list of objects that have matching statements\r
298                         Map<Resource,Pair<int[], int[]>> matchingStatements = new HashMap<Resource, Pair<int[], int[]>>(); // matching statements\r
299                         for (Resource or : possibleOR.getKeys()) {\r
300                                 List<Statement> right = possibleOR.getValues(or);\r
301                                 int iLeft[] = new int[left.size()];\r
302                                 int iRight[] = new int[right.size()];\r
303                                 \r
304                                 for (int i = 0; i < left.size(); i++) {\r
305                                         iLeft[i] = -1;\r
306                                         iRight[i] = -1;\r
307                                 }\r
308                                 \r
309                                 for (int l = 0; l < left.size(); l++) {\r
310                                         Statement ls = left.get(l);\r
311                                         for (int r = 0; r < right.size(); r++) {\r
312                                                 if (iRight[r] >= 0)\r
313                                                         continue;\r
314                                                 Statement rs = right.get(r);\r
315                                                 if (!comparableResources.contains(ls.getSubject(), rs.getSubject()))\r
316                                                         continue;\r
317                                                 if (rcomp.compare(ls.getPredicate(),rs.getPredicate()) == 0) {\r
318                                                         iLeft[l] = r;\r
319                                                         iRight[r] = l;\r
320                                                         break;\r
321                                                 }\r
322                                         }\r
323                                         \r
324                                 }\r
325                                 boolean success = true;\r
326                                 for (int i = 0; i < left.size(); i++) {\r
327                                         if (iLeft[i] < 0) {\r
328                                                 success = false;\r
329                                                 break;\r
330                                         }\r
331                                         if (iRight[i] < 0) {\r
332                                                 success = false;\r
333                                                 break;\r
334                                         }\r
335                                                 \r
336                                 }\r
337                                 if (success) {\r
338                                         for (Statement s : right) \r
339                                                 matchingOR.add(or,s);\r
340                                         matchingStatements.put(or, new Pair<int[], int[]>(iLeft, iRight));\r
341                                 }\r
342                         }\r
343                         // if there is only one matching right side object, we have found a match \r
344                         if (matchingOR.getKeySize() == 1) {\r
345                                 Resource or = matchingOR.getKeys().iterator().next();\r
346                                 List<Statement> right = matchingOR.getValues(or);\r
347                                 Pair<int[], int[]> indices = matchingStatements.get(or);\r
348                                 \r
349                                 //comparableResources.map(ol, or);\r
350                                 objectsLeft.add(ol);\r
351                                 objectsRight.add(or);\r
352                                 for (int l = 0; l < left.size(); l++) {\r
353                                         int r = indices.first[l];\r
354                                         comparableStatements.map(left.get(l), right.get(r));\r
355                                         unreliableLeft.remove(left.get(l));\r
356                                         unreliableRight.remove(right.get(r));\r
357                                 }\r
358                                 \r
359                         }\r
360 \r
361                 }\r
362                 \r
363                 \r
364         }\r
365         \r
366         private void processUnreliableDeep(Set<Statement> unreliableLeft, Set<Statement> unreliableRight, Stack<Resource> objectsLeft, Stack<Resource> objectsRight) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
367                 MapList<Resource,Statement> subjectLeft = new MapList<Resource, Statement>();\r
368                 MapList<Resource,Statement> subjectRight = new MapList<Resource, Statement>();\r
369                 MapList<Resource,Statement> objectLeft = new MapList<Resource, Statement>();\r
370                 MapList<Resource,Statement> objectRight = new MapList<Resource, Statement>();\r
371                 \r
372                 for (Statement s : unreliableLeft) {\r
373                         subjectLeft.add(s.getSubject(),s);\r
374                         objectLeft.add(s.getObject(),s);\r
375                 }\r
376                 for (Statement s : unreliableRight) {\r
377                         subjectRight.add(s.getSubject(),s);\r
378                         objectRight.add(s.getObject(),s);\r
379                 }\r
380                 for (Resource ol : objectLeft.getKeys()) {\r
381                         Set<Path> pathsLeft = new HashSet<Path>();\r
382                         for (Resource rel : traversed) {\r
383                                 pathsLeft.addAll(Path.create(g.getStatements(ol, rel)));\r
384                         }\r
385                         while (true) {\r
386                                 expand(pathsLeft);\r
387                                 if (pathsLeft.size() == 0)\r
388                                         break;\r
389                                 Collection<Path> endPaths = new ArrayList<Path>(1);\r
390                                 for (Path p : pathsLeft) {\r
391                                         if (comparableResources.containsLeft(p.getEnd())) {\r
392                                                 endPaths.add(p);\r
393                                         }\r
394                                 }\r
395                                 if (endPaths.size() > 0) {\r
396                                         pathsLeft.clear();\r
397                                         pathsLeft.addAll(endPaths);\r
398                                         break;\r
399                                 }       \r
400                         }\r
401                         if (pathsLeft.size() > 0) {\r
402                                 Resource sl = objectLeft.getValues(ol).get(0).getSubject();\r
403                                 Resource sr = comparableResources.getRight(sl);\r
404                                 Collection<Resource> possibleOR = new ArrayList<Resource>();\r
405                                 for (Statement s : subjectRight.getValues(sr)) {\r
406                                         possibleOR.add(s.getObject());\r
407                                 }\r
408                                 Map<Resource,Set<Path>> matchingPaths = new HashMap<Resource, Set<Path>>();\r
409                                 for (Resource or : possibleOR) {\r
410                                         Set<Path> possiblePathsRight = new HashSet<Path>();\r
411                                         for (Path leftPath : pathsLeft) {\r
412                                                 possiblePathsRight.addAll(findComparableRight(leftPath, or));\r
413                                         }\r
414                                         if (possiblePathsRight.size() == pathsLeft.size()) {\r
415                                                 matchingPaths.put(or, possiblePathsRight);\r
416                                         }\r
417                                 }\r
418                                 if (matchingPaths.size() > 0) {\r
419                                         if (matchingPaths.size() == 1) {\r
420                                                 Resource or = matchingPaths.keySet().iterator().next();\r
421                                                 objectsLeft.add(ol);\r
422                                                 objectsRight.add(or);\r
423                                                 Collection<Statement> statementsLeft = objectLeft.getValues(ol);\r
424                                                 Collection<Statement> statementsRight = objectRight.getValues(or);\r
425                                                 unreliableLeft.removeAll(statementsLeft);\r
426                                                 unreliableRight.removeAll(statementsRight);\r
427                                                 System.out.println();\r
428                                         } else {\r
429                                                 System.out.println();\r
430                                         }\r
431                                 }\r
432                         }\r
433                         \r
434                 }\r
435                 \r
436         }\r
437         \r
438         private void expand(Set<Path> paths) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
439                 Set<Path> stepPathsLeft = new HashSet<Path>();\r
440                 if (paths.size() == 0)\r
441                         return;\r
442                 int length = paths.iterator().next().getLength() + 1;\r
443                 for (Path p : paths) {\r
444                         for (Resource rel : traversed) {\r
445                                 stepPathsLeft.addAll(Path.expand(p,g.getStatements(p.getEnd(), rel)));\r
446                         }\r
447                 }\r
448                 paths.clear();\r
449                 for (Path p : stepPathsLeft) {\r
450                         if (p.getLength() == length)\r
451                                 paths.add(p);\r
452                 }\r
453         }\r
454         \r
455         private Collection<Path> findComparableRight(Path leftPath, Resource beginRight) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
456                 Set<Path> rightPaths = new HashSet<Path>();\r
457                 rightPaths.addAll(Path.create(g.getStatements(beginRight, getRight(leftPath.getStatements().get(0).getPredicate()))));\r
458                 for (int i = 1; i < leftPath.getLength(); i++) {\r
459                         if (rightPaths.size() == 0)\r
460                                 return rightPaths;\r
461                         Set<Path> stepPaths = new HashSet<Path>();\r
462                         for (Path p : rightPaths) {\r
463                                 stepPaths.addAll(Path.expand(p, g.getStatements(p.getEnd(), getRight(leftPath.getStatements().get(i).getPredicate()))));\r
464                         }\r
465                         rightPaths.clear();\r
466                         for (Path p : stepPaths)\r
467                                 if (p.getLength() == i+1) \r
468                                         rightPaths.add(p);\r
469                 }\r
470                 return rightPaths;\r
471                 \r
472         }\r
473         \r
474         private Resource getRight(Resource r) {\r
475                 if (comparableResources.containsLeft(r))\r
476                         return comparableResources.getRight(r);\r
477                 return r;\r
478         }\r
479         \r
480 \r
481         \r
482         public BijectionMap<Statement, Statement> getComparableStatements() {\r
483                 return comparableStatements;\r
484         }\r
485         \r
486         public GraphChanges getChanges() {\r
487                 return new GraphChanges(r1,r2,changes1,changes2,modifications,comparableResources);\r
488         }\r
489         \r
490         private List<Statement> filterAsserted(Resource r, Collection<Statement> in) throws ServiceException {\r
491                 List<Statement> out = new ArrayList<Statement>();\r
492                 for (Statement s : in) {\r
493                         if (!s.isAsserted(r))\r
494                                 out.add(s);\r
495                         \r
496                 }\r
497                 return out;\r
498         }\r
499         \r
500         private String printStatement(ReadGraph graph, Statement s) throws ValidationException, ServiceException {\r
501                 return NameUtils.getSafeName(graph, s.getSubject()) + " " + NameUtils.getSafeName(graph, s.getPredicate()) + " " + NameUtils.getSafeName(graph, s.getObject());\r
502         }\r
503         \r
504         private List<Statement> filterTraversed(List<Statement> in) throws ServiceException {\r
505                 return filter(traversed, in);\r
506         }\r
507         \r
508         private List<Statement> filterNonTested(List<Statement> in) throws ServiceException {\r
509                 return filter(nonTested, in);\r
510         }\r
511         \r
512         private List<Statement> filter(Collection<Resource> toFilter, List<Statement> in) throws ServiceException {\r
513                 if (toFilter.size() == 0)\r
514                         return in;\r
515                 List<Statement> out = new ArrayList<Statement>();\r
516                 for (Statement s : in) {\r
517                         boolean usable = true;\r
518                         for (Resource r : toFilter) {\r
519                                 if (g.isSubrelationOf(s.getPredicate(),r)) {\r
520                                         usable = false;\r
521                                         break;\r
522                                 }\r
523                         }\r
524                         if (usable) {\r
525                                 out.add(s);\r
526                         }\r
527                         \r
528                 }\r
529                 return out;\r
530         }\r
531         \r
532         \r
533         private void addDeletion(Statement s) {\r
534                 if (!changes1Set.contains(s)) {\r
535                         changes1Set.add(s);\r
536                         changes1.add(s);\r
537                 }\r
538         }\r
539         \r
540         private void addAddition(Statement s) {\r
541                 if (!changes2Set.contains(s)) {\r
542                         changes2Set.add(s);\r
543                         changes2.add(s);\r
544                 }\r
545         }\r
546         \r
547         private void addModification(Statement s1, Statement s2) {\r
548                 Pair<Statement, Statement> mod = new Pair<Statement, Statement>(s1,s2);\r
549                 if (!modificationsSet.contains(mod)) {\r
550                         modificationsSet.add(mod);\r
551                         modifications.add(mod);\r
552                 }\r
553         }\r
554         \r
555         public void sortStatement(List<Statement> list1, List<Statement> list2) {\r
556                 sortStatement(list1, list2, scomp);\r
557         }\r
558         \r
559         public void sortStatement(List<Statement> list1, List<Statement> list2, Comparator<Statement> scomp) {\r
560                 Collections.sort(list1,scomp);\r
561                 Collections.sort(list2,scomp);\r
562                 \r
563                 List<Statement> sorted1 = new ArrayList<Statement>(list1.size());\r
564                 List<Statement> sorted2 = new ArrayList<Statement>(list2.size());\r
565                 sorted1.addAll(list1);\r
566                 sorted2.addAll(list2);\r
567                 \r
568                 int ss1 = 0;\r
569                 int ss2 = 0;\r
570                 for (int i = 0; i < list1.size(); ) {\r
571                         Statement s1 = list1.get(i);\r
572                         int same1 = sameRel(list1, i);  \r
573                         for (int j = 0; j < list2.size(); j++) {\r
574                                 Statement s2 = list2.get(j);\r
575                                 if (scomp.compare(s1, s2) == 0) {\r
576                                         int same2 = sameRel(list2, j);\r
577                                         copy(sorted1,ss1,list1,i,same1);\r
578                                         ss1 += same1;\r
579                                         copy(sorted2,ss2,list2,j,same2);\r
580                                         ss2 += same2;\r
581                                         break;\r
582                                 }\r
583                         }\r
584                         i+= same1;\r
585                 }\r
586                 if (ss1 < sorted1.size()) {\r
587                         for (Statement s : list1) {\r
588                                 if (!sorted1.contains(s)) {\r
589                                         sorted1.set(ss1,s);\r
590                                         ss1++;\r
591                                 }\r
592                         }\r
593                 }\r
594                 if (ss2 < sorted2.size()) {\r
595                         for (Statement s : list2) {\r
596                                 if (!sorted2.contains(s)) {\r
597                                         sorted2.set(ss2,s);\r
598                                         ss2++;\r
599                                 }\r
600                         }\r
601                 }\r
602                 \r
603                 list1.clear();\r
604                 list2.clear();\r
605                 list1.addAll(sorted1);\r
606                 list2.addAll(sorted2);\r
607         }\r
608         \r
609         public <T> void copy(List<T> to, int toIndex, List<T> from, int fromIndex, int amount) {\r
610                 for (int i = 0; i <  amount; i++) {\r
611                         to.set(toIndex + i, from.get(fromIndex+ i));\r
612                 }\r
613         }\r
614         \r
615         public void sortResource(List<Resource> list1, List<Resource> list2) {\r
616                 Collections.sort(list1,rcomp);\r
617                 int js = 0;\r
618                 for (int i = 0; i < list1.size(); i++) {\r
619                         Resource s1 = list1.get(i);\r
620                         for (int j = js; j < list2.size(); j++) {\r
621                                 Resource s2 = list2.get(j);\r
622                                 if (rcomp.compare(s1, s2) == 0) {\r
623                                         Resource t = list2.get(js);\r
624                                         list2.set(js, s2);\r
625                                         list2.set(j, t);\r
626                                         break;\r
627                                 }\r
628                         }\r
629                         js++;\r
630                         \r
631                 }\r
632         }\r
633         \r
634         private void compareStatements(List<Statement> ss1, List<Statement> ss2, Stack<Resource> objectsLeft, Stack<Resource> objectsRight, Collection<Statement> unreliableLeft, Collection<Statement> unreliableRight) throws DatabaseException {\r
635                 sortStatement(ss1, ss2);\r
636                 \r
637                 int i1 = 0;\r
638                 int i2 = 0;\r
639                 \r
640                 while (true) {\r
641                         if (i1 >= ss1.size()) {\r
642                                 if (i2 >= ss2.size()) {\r
643                                         break;\r
644                                 } else {\r
645                                         while (i2 < ss2.size()) {\r
646                                                 System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i2)));\r
647                                                 \r
648                                                 addAddition(ss2.get(i2));\r
649                                                 i2++;\r
650                                         }\r
651                                         break;\r
652                                 }\r
653                         } else if (i2 >= ss2.size()) {\r
654                                 while (i1 < ss1.size()) {\r
655                                         System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i1)));\r
656                                         addDeletion(ss1.get(i1));\r
657                                         i1++;\r
658                                 }\r
659                                 break;\r
660                         }\r
661                         int same1 = sameRel(ss1, i1);\r
662                         int same2 = sameRel(ss2, i2);\r
663                         int c = rcomp.compare(ss1.get(i1).getPredicate(),ss2.get(i2).getPredicate());\r
664                         if (c == 0) {\r
665                                 compareStatements(ss1, i1, same1, ss2, i2, same2,objectsLeft,objectsRight,unreliableLeft,unreliableRight);\r
666                                 i1+=same1;\r
667                                 i2+=same2;\r
668                         } else if (c < 0) {\r
669                                 for (int i = 0; i < same1; i++) {\r
670                                         System.out.println("Compare Statements diff1 " + printStatement(g,ss1.get(i+i1)));\r
671                                         addDeletion(ss1.get(i+i1));\r
672                                 }\r
673                                 i1 += same1;\r
674                         } else {\r
675                                 for (int i = 0; i < same2; i++) {\r
676                                         System.out.println("Compare Statements diff2 " + printStatement(g,ss2.get(i+i2)));\r
677                                         addAddition(ss2.get(i+i2));\r
678                                 }\r
679                                 \r
680                                 i2 += same2;\r
681                         }\r
682                         \r
683                 }\r
684         }\r
685         \r
686 \r
687         \r
688         private int sameRel(List<Statement> statements, int off) {\r
689                 if (statements.size() <= off)\r
690                         return 0;\r
691                 int same = 1;\r
692                 long id = statements.get(off).getPredicate().getResourceId();\r
693                 for (int i = off+1; i <statements.size(); i++) {\r
694                         if (statements.get(i).getPredicate().getResourceId() == id)\r
695                                 same++;\r
696                         else \r
697                                 break;\r
698                 }\r
699                 return same;\r
700                 \r
701         }\r
702 \r
703         private int compareObject(Resource o1, Resource o2) throws DatabaseException {\r
704                 if (comparableResources.contains(o1, o2))\r
705                         return (-1);\r
706                 if (comparableResources.containsLeft(o1))\r
707                         return Integer.MAX_VALUE;\r
708                 if (comparableResources.containsRight(o2))\r
709                         return Integer.MAX_VALUE;\r
710                 return comparator.compare(g, o1, o2);\r
711         }\r
712         \r
713         private void compareStatements(List<Statement> ss1, int off1, int len1, List<Statement> ss2, int off2, int len2, Collection<Resource> objectsLeft, Collection<Resource> objectsRight, Collection<Statement> unreliableLeft, Collection<Statement> unreliableRight) throws DatabaseException {\r
714                 boolean[] used1 = new boolean[len1];\r
715                 for (int i = 0; i < used1.length; i++) {\r
716                         used1[i] = false;\r
717                 }\r
718                 \r
719                 boolean[] used2 = new boolean[len2];\r
720                 for (int i = 0; i < used2.length; i++) {\r
721                         used2[i] = false;\r
722                 }\r
723                 \r
724                 // left, right, difference\r
725                 List<List<Integer>> differences = new ArrayList<List<Integer>>();\r
726                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
727                         Statement s1 = ss1.get(i1);\r
728                         List<Integer> diff = new ArrayList<Integer>();\r
729                         for (int i2 = off2; i2 < off2 + len2; i2++) {\r
730                                 Statement s2 = ss2.get(i2);\r
731                                 int d = compareObject(s1.getObject(), s2.getObject());\r
732                                 if (d == 0) {\r
733                                         for (Resource t : strong) {\r
734                                                  if (s1.getPredicate().equals(t) || g.isSubrelationOf(s1.getPredicate(), t)) {\r
735                                                          d = 1;\r
736                                                          break;\r
737                                                  }\r
738                                         }\r
739                                 }\r
740                                 diff.add(d);\r
741                         }\r
742                         differences.add(diff);\r
743                 }\r
744                 // difference, left\r
745                 MapList<Integer, Integer> priorities = new MapList<Integer, Integer>();\r
746                 for (int i = 0; i < differences.size(); i++) {\r
747                         List<Integer> list = differences.get(i);\r
748                         for (int j = 0; j < list.size(); j++) {\r
749                                 priorities.add(list.get(j), i);\r
750                         }\r
751                 }\r
752                 \r
753                 Integer[] pris = priorities.getKeys(new Integer[]{});\r
754                 Arrays.sort(pris);\r
755                 \r
756                 for (Integer pri : pris) {\r
757                         if (pri == Integer.MAX_VALUE) {\r
758 \r
759                         } else if (pri == 0) {\r
760                                 \r
761                         } else {\r
762                                 List<Integer> i1s = priorities.getValues(pri);\r
763                                 for (Integer i1 : i1s) {\r
764                                         if (used1[i1])\r
765                                                 continue;\r
766                                         List<Integer> i2diff = differences.get(i1);\r
767                                         for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
768                                                 if (i2diff.get(i2) == pri) {\r
769                                                         if (used2[i2])\r
770                                                                 continue;\r
771                                                         used1[i1] = true;\r
772                                                         used2[i2] = true;\r
773                                                         Statement s1  = ss1.get(i1+off1);\r
774                                                         Statement s2  = ss2.get(i2+off2);\r
775                                                         \r
776                                                         if (objectsLeft != null) {\r
777                                                                 \r
778                                                                         objectsLeft.add(s1.getObject());\r
779                                                                         objectsRight.add(s2.getObject());\r
780                                                                 \r
781                                                         } \r
782                                                         comparableStatements.map(s1, s2);\r
783                                                         //comparableResources.map(s1.getObject(), s2.getObject());\r
784                                                         break;\r
785                                                 }\r
786                                         }\r
787                                 }\r
788                         }\r
789                 }\r
790                 \r
791                 for (Integer pri : pris) {\r
792                         if (pri != 0)\r
793                                 continue;\r
794                         Set<Statement> s1s = new HashSet<Statement>();\r
795                         Set<Statement> s2s = new HashSet<Statement>();\r
796                         Set<Integer> s1i = new HashSet<Integer>();\r
797                         Set<Integer> s2i = new HashSet<Integer>();\r
798                         List<Integer> i1s = priorities.getValues(pri);\r
799                         for (Integer i1 : i1s) {\r
800                                 if (used1[i1])\r
801                                         continue;\r
802                                 List<Integer> i2diff = differences.get(i1);\r
803                                 for (int i2 = 0; i2 < i2diff.size(); i2++) {\r
804                                         if (i2diff.get(i2) == pri) {\r
805                                                 if (used2[i2])\r
806                                                         continue;\r
807                                                 Statement s1  = ss1.get(i1+off1);\r
808                                                 Statement s2  = ss2.get(i2+off2);\r
809                                                 s1s.add(s1);\r
810                                                 s2s.add(s2);\r
811                                                 s1i.add(i1);\r
812                                                 s2i.add(i2);\r
813                                         }\r
814                                 }\r
815                         }\r
816                         if (unreliableLeft != null) {\r
817                                 unreliableLeft.addAll(s1s);\r
818                                 unreliableRight.addAll(s2s);\r
819                         }\r
820                         for (Integer i : s1i)\r
821                                 used1[i] = true;\r
822                         for (Integer i : s2i)\r
823                                 used2[i] = true;\r
824 \r
825                 }\r
826                 for (int i1 = off1; i1 < off1 + len1; i1++) {\r
827                         if (!used1[i1-off1]) {\r
828                                 System.out.println("Compare Object diff1 " + printStatement(g,ss1.get(i1)));\r
829                                 addDeletion(ss1.get(i1));\r
830                         }\r
831                 }\r
832                 for (int i2 = off2; i2 < off2 + len2; i2++) {\r
833                         if (!used2[i2-off2]) {\r
834                                 System.out.println("Compare Object diff2 " + printStatement(g,ss2.get(i2)));\r
835                                 addAddition(ss2.get(i2));\r
836                         }\r
837                 }\r
838         }\r
839         \r
840         \r
841         \r
842         /**\r
843          * compares properties, assumes functional relations\r
844          * @param r1\r
845          * @param r2\r
846          * @throws ServiceException\r
847          * @throws DoesNotContainValueException\r
848          * @throws ValidationException \r
849          */\r
850         private void compareProps(Resource r1, Resource r2) throws ServiceException, DoesNotContainValueException, ValidationException {\r
851                 ArrayList<Statement> ss1 = new ArrayList<Statement>();\r
852                 ArrayList<Statement> ss2 = new ArrayList<Statement>();\r
853                 ss1.addAll(g.getStatements(r1, b.HasProperty));\r
854                 ss2.addAll(g.getStatements(r2, b.HasProperty));\r
855                 sortStatement(ss1, ss2);\r
856 //              Collections.sort(ss1, scomp);\r
857 //              Collections.sort(ss2, scomp);\r
858                 \r
859                 int i1 = 0; \r
860                 int i2 = 0;\r
861                 \r
862                 while (true) {\r
863                         if (i1 >= ss1.size()) {\r
864                                 if (i2 >= ss2.size())\r
865                                         break;\r
866                                 else {\r
867                                         while (i2 < ss2.size()) {\r
868                                                 System.out.println("Compare Prop diff2 " + printStatement(g,ss2.get(i2)));\r
869                                                 addAddition(ss2.get(i2));\r
870                                                 i2++;\r
871                                         }\r
872                                         break;\r
873                                 }\r
874                         } else if (i2 >= ss2.size()) {\r
875                                 while (i1 < ss1.size()) {\r
876                                         System.out.println("Compare Prop diff1 " + printStatement(g,ss1.get(i1)));\r
877                                         addDeletion(ss1.get(i1));\r
878                                         i1++;\r
879                                 }\r
880                                 break;\r
881                         }\r
882                         Statement s1 = ss1.get(i1);\r
883                         Statement s2 = ss2.get(i2);\r
884                         int c = scomp.compare(s1, s2);\r
885                         switch (c) {\r
886                         case 0:{\r
887                                 boolean b1 = g.hasValue(s1.getObject());\r
888                                 boolean b2 = g.hasValue(s2.getObject());\r
889                                 if (b1 == b2) {\r
890                                         if (b1) {\r
891                                                 Object v1 = g.getValue(s1.getObject());\r
892                                                 Object v2 = g.getValue(s2.getObject());\r
893                                                 boolean eq = compareValue(v1, v2);\r
894                                                 if (!eq) {\r
895                                                         addModification(s1, s2);\r
896                                                         comparableStatements.map(s1, s2);\r
897                                                         comparableResources.map(s1.getObject(),s2.getObject());\r
898                                                 }\r
899                                         } else {\r
900                                                 compareProps(s1.getObject(), s2.getObject());\r
901                                         }\r
902                                 } else {\r
903                                         addModification(s1, s2);\r
904                                         comparableStatements.map(s1, s2);\r
905                                         comparableResources.map(s1.getObject(),s2.getObject());\r
906                                 }\r
907                                 i1++;\r
908                                 i2++;\r
909                                 break;\r
910                         }\r
911                         case -1:{\r
912                                 System.out.println("Compare Prop diff1s " + printStatement(g,s1));\r
913                                 addDeletion(s1);\r
914                                 i1++;\r
915                                 break;\r
916                         }\r
917                                 \r
918                         case 1:{\r
919                                 System.out.println("Compare Prop diff2s " + printStatement(g,s2));\r
920                                 addAddition(s2);\r
921                                 i2++;\r
922                                 break;\r
923                         }\r
924                         }\r
925                         \r
926                         \r
927                 }\r
928                 \r
929                 ss1.clear();\r
930                 ss2.clear();\r
931                 \r
932         }\r
933         \r
934         \r
935         public static boolean compareValue(Object v1, Object v2) {\r
936                 if (v1 instanceof Object[] && v2 instanceof Object[])\r
937                         return Arrays.deepEquals((Object[])v1, (Object[])v2);\r
938                 else if (v1 instanceof int[] && v2 instanceof int[]) \r
939                         return Arrays.equals((int[])v1, (int[])v2);\r
940                 else if (v1 instanceof float[] && v2 instanceof float[]) \r
941                         return Arrays.equals((float[])v1, (float[])v2);\r
942                 else if (v1 instanceof double[] && v2 instanceof double[]) \r
943                         return Arrays.equals((double[])v1, (double[])v2);\r
944                 else if (v1 instanceof long[] && v2 instanceof long[]) \r
945                         return  Arrays.equals((long[])v1, (long[])v2);\r
946                 else if (v1 instanceof byte[] && v2 instanceof byte[]) \r
947                         return Arrays.equals((byte[])v1, (byte[])v2);\r
948                 else if (v1 instanceof boolean[] && v2 instanceof boolean[]) \r
949                         return Arrays.equals((boolean[])v1, (boolean[])v2);\r
950                 else\r
951                         return v1.equals(v2);\r
952         }\r
953 \r
954         \r
955         \r
956         public class PredicateComparator implements Comparator<Statement> {\r
957                 @Override\r
958                 public int compare(Statement o1, Statement o2) {\r
959                         if (comparableResources.contains(o1.getPredicate(), o2.getPredicate()))\r
960                                 return 0;\r
961                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
962                                 return -1;\r
963                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
964                                 return 1;\r
965                         return 0;\r
966                 }\r
967         }\r
968         \r
969         public class SubjectComparator implements Comparator<Statement> {\r
970                 @Override\r
971                 public int compare(Statement o1, Statement o2) {\r
972                         if (comparableResources.contains(o1.getSubject(), o2.getSubject()))\r
973                                 return 0;\r
974                         if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
975                                 return -1;\r
976                         if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
977                                 return 1;\r
978                         return 0;\r
979                 }\r
980         }\r
981         \r
982         public class ObjectComparator implements Comparator<Statement> {\r
983                 @Override\r
984                 public int compare(Statement o1, Statement o2) {\r
985                         if (comparableResources.contains(o1.getObject(), o2.getObject()))\r
986                                 return 0;\r
987                         if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
988                                 return -1;\r
989                         if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
990                                 return 1;\r
991                         return 0;\r
992                 }\r
993         }\r
994         \r
995         public static class FullStatementComparator implements Comparator<Statement> {\r
996                 @Override\r
997                 public int compare(Statement o1, Statement o2) {\r
998                         if (o1.getSubject().getResourceId() < o2.getSubject().getResourceId())\r
999                                 return -1;\r
1000                         if (o1.getSubject().getResourceId() > o2.getSubject().getResourceId())\r
1001                                 return 1;\r
1002                         if (o1.getPredicate().getResourceId() < o2.getPredicate().getResourceId())\r
1003                                 return -1;\r
1004                         if (o1.getPredicate().getResourceId() > o2.getPredicate().getResourceId())\r
1005                                 return 1;\r
1006                         if (o1.getObject().getResourceId() < o2.getObject().getResourceId())\r
1007                                 return -1;\r
1008                         if (o1.getObject().getResourceId() > o2.getObject().getResourceId())\r
1009                                 return 1;\r
1010                         return 0;\r
1011                 }\r
1012         }\r
1013         \r
1014 \r
1015         \r
1016         public class ResComparator implements Comparator<Resource> {\r
1017                 @Override\r
1018                 public int compare(Resource o1, Resource o2) {\r
1019                         if (comparableResources.contains(o1, o2))\r
1020                                 return 0;\r
1021                         if (o1.getResourceId() < o2.getResourceId())\r
1022                                 return -1;\r
1023                         if (o1.getResourceId() > o2.getResourceId())\r
1024                                 return 1;\r
1025                         return 0;\r
1026                 }\r
1027         }\r
1028         \r
1029         \r
1030 }\r