]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop/src/org/simantics/interop/test/GraphChanges.java
Process changes in smaller chunks
[simantics/interop.git] / org.simantics.interop / src / org / simantics / interop / test / GraphChanges.java
1 package org.simantics.interop.test;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.List;
6 import java.util.Map.Entry;
7
8 import org.simantics.db.ReadGraph;
9 import org.simantics.db.Resource;
10 import org.simantics.db.Session;
11 import org.simantics.db.Statement;
12 import org.simantics.db.common.request.ReadRequest;
13 import org.simantics.db.common.utils.NameUtils;
14 import org.simantics.db.exception.DatabaseException;
15 import org.simantics.utils.datastructures.BijectionMap;
16
17 public class GraphChanges {
18         
19         private Resource r1;
20         private Resource r2;
21         private List<Statement> deletions;
22         private List<Statement> additions;
23         private List<Modification> modifications;
24         
25         private BijectionMap<Resource, Resource> comparable;
26         
27         public static class Modification {
28                 Resource leftSub;
29                 Resource rightSub;
30                 Statement leftStm;
31                 Statement rightStm;
32
33                 
34                 int hashCode;
35                 
36                 public Modification(Resource leftSub, Resource rightSub, Statement leftStm, Statement rightStm) {
37                         this.leftSub = leftSub;
38                         this.rightSub = rightSub;
39                         this.leftStm = leftStm;
40                         this.rightStm = rightStm;
41                         
42                         hashCode = leftSub.hashCode() + rightSub.hashCode();
43                         if (leftStm != null)
44                                 hashCode += leftStm.hashCode();
45                         if (rightStm != null)
46                                 hashCode += rightStm.hashCode();
47                 }
48
49                 public boolean isLeftAsserted() {
50                         return !leftSub.equals(leftStm.getSubject());
51                 }
52                 
53                 public boolean isRightAsserted() {
54                         return !rightSub.equals(rightStm.getSubject());
55                 }
56
57                 public Resource getLeftSub() {
58                         return leftSub;
59                 }
60
61                 public void setLeftSub(Resource leftSub) {
62                         this.leftSub = leftSub;
63                 }
64
65                 public Resource getRightSub() {
66                         return rightSub;
67                 }
68
69                 public void setRightSub(Resource rightSub) {
70                         this.rightSub = rightSub;
71                 }
72
73                 public Statement getLeftStm() {
74                         return leftStm;
75                 }
76
77                 public void setLeftStm(Statement leftStm) {
78                         this.leftStm = leftStm;
79                 }
80
81                 public Statement getRightStm() {
82                         return rightStm;
83                 }
84
85                 public void setRightStm(Statement rightStm) {
86                         this.rightStm = rightStm;
87                 }
88                 
89                 public Resource getPredicate() {
90                     if (leftStm != null)
91                         return leftStm.getPredicate();
92                     return rightStm.getPredicate();
93                 }
94                 
95                 @Override
96                 public boolean equals(Object obj) {
97                         if (obj.getClass() != this.getClass())
98                                 return false;
99                         Modification other = (Modification)obj;
100                         if (!leftSub.equals(other.leftSub))
101                                 return false;
102                         if (!rightSub.equals(other.rightSub))
103                                 return false;
104                         if (leftStm != null) {
105                                 if (!leftStm.equals(other.leftStm))
106                                         return false;
107                         } else if (other.leftStm != null)
108                                 return false;
109                         if (rightStm != null) {
110                                 if (!rightStm.equals(other.rightStm))
111                                         return false;
112                         } else if (other.rightStm != null)
113                                 return false;
114                         return true;
115                 }
116                 
117                 @Override
118                 public int hashCode() {
119                         return hashCode;
120                 }
121
122         }
123         
124         public GraphChanges(Resource r1, Resource r2, List<Statement> deletions, List<Statement> additions,
125                         List<Modification> modifications, BijectionMap<Resource, Resource> comparable) {
126                 super();
127                 this.r1 = r1;
128                 this.r2 = r2;
129                 this.deletions = deletions;
130                 this.additions = additions;
131                 this.modifications = modifications;
132                 this.comparable = comparable;
133         }
134         
135         public Resource getResource1() {
136                 return r1;
137         }
138         
139         public Resource getResource2() {
140                 return r2;
141         }
142         
143         public List<Statement> getAdditions() {
144                 return additions;
145         }
146         
147         public List<Statement> getDeletions() {
148                 return deletions;
149         }
150         
151         public List<Modification> getModifications() {
152                 return modifications;
153         }
154         
155         public BijectionMap<Resource, Resource> getComparable() {
156                 return comparable;
157         }
158         
159         public String toString(ReadGraph graph) throws DatabaseException {
160                 StringBuilder sb = new StringBuilder();
161                 sb.append("Del:\n");
162                 for (Statement stm : deletions) {
163                         sb.append(toString(graph, stm));
164                         sb.append("\n");
165         }
166                 sb.append("Add:\n");
167                 for (Statement stm : additions) {
168                         sb.append(toString(graph, stm));
169                         sb.append("\n");
170         }
171                 sb.append("Mod:\n");
172                 for (Modification mod :modifications) {
173                         sb.append(toString(graph, mod));
174                         sb.append("\n");
175         }
176                 return sb.toString();
177         }
178         
179         public static String toString(ReadGraph graph, Statement stm) throws DatabaseException{
180                 return NameUtils.getSafeName(graph, stm.getSubject()) + " "+
181                                    NameUtils.getSafeName(graph, stm.getPredicate()) + " " +
182                            NameUtils.getSafeName(graph, stm.getObject()) + " (" +
183                            stm.getSubject() + " " +stm.getPredicate() + " " + stm.getObject();
184         }
185         
186         public static String toString(ReadGraph graph, Modification mod) throws DatabaseException{
187                 StringBuilder sb = new StringBuilder();
188                 {
189                         Statement stm = mod.getLeftStm();
190                         if (stm != null) {
191                                 sb.append(NameUtils.getSafeName(graph, mod.getLeftSub()) + " "+
192                                                    NameUtils.getSafeName(graph, stm.getPredicate()) + " " +
193                                                    truncate(NameUtils.getSafeName(graph, stm.getObject())) + " (" +
194                                                    mod.getLeftSub() + " " + stm.getSubject() + " " +stm.getPredicate() + " " + stm.getObject() + ")\n");
195                         } else {
196                                 sb.append(NameUtils.getSafeName(graph, mod.getLeftSub()) + " "+  mod.getLeftSub() + " N/A\n");
197                         }
198                 }
199                 {
200                         Statement stm = mod.getRightStm();
201                         if (stm != null) {
202                                 sb.append(NameUtils.getSafeName(graph, mod.getRightSub()) + " "+
203                                                    NameUtils.getSafeName(graph, stm.getPredicate()) + " " +
204                                                    truncate(NameUtils.getSafeName(graph, stm.getObject())) + " (" +
205                                                    mod.getRightSub() + " " + stm.getSubject() + " " +stm.getPredicate() + " " + stm.getObject() + ")");
206                         } else {
207                                 sb.append(NameUtils.getSafeName(graph, mod.getRightSub()) + " "+  mod.getRightSub() + " N/A");
208                         }
209                         
210                 }
211                 return sb.toString();
212         }
213         
214         public static String truncate(String s) {
215                 if (s.length() < 100)
216                         return s;
217                 return s.substring(0, 100)+"...";
218         }
219         
220         public String comparableToString(ReadGraph graph) throws DatabaseException {
221                 StringBuilder sb = new StringBuilder();
222                 sb.append("Comparable:\n");
223                 for (Entry<Resource, Resource> entry : comparable.getEntries()) {
224                         sb.append(NameUtils.getSafeName(graph, entry.getKey()) + " "+
225                                            NameUtils.getSafeName(graph, entry.getValue()) + " (" +
226                                            entry.getKey() + " " +entry.getValue() + ")\n");
227                         
228                 }
229                 return sb.toString();
230         }
231         
232         /**
233          * Adapts GraphChanges between A1 and B to A2 and B, when A2 is copy of A1.
234          * @param changes changes between A1 and B
235          * @param bijection changes between A1 and A2. Expected to be a bijection, so no additions or removals.
236          * @return
237          * @throws DatabaseException
238          */
239         public static GraphChanges adapt(Session session, GraphChanges changes, GraphChanges bijection) throws DatabaseException{
240                 if (!changes.getResource1().equals(bijection.getResource1()))
241                         throw new DatabaseException("Left side model must be the same");
242                 //if (bijection.getDeletions().size() > 0 || bijection.getAdditions().size() > 0)
243                 //      throw new DatabaseException("Bijection change is not a bijection, it contains additions and/or removals");
244                 BijectionMap<Resource, Resource> comparable = new BijectionMap<Resource, Resource>();
245                 for (Entry<Resource, Resource> entry : changes.comparable.getEntries()) {
246                         if (entry.getKey().equals(entry.getValue())) {
247                                 comparable.map(entry.getKey(), entry.getValue());
248                         } else {
249                                 Resource nl = bijection.getComparable().getRight(entry.getKey());
250                                 if (nl == null) {
251                                         // Matching literal resources are not included in bijection map.
252                                         // TODO : should we check that the resource is literal?
253                                         // throw new DatabaseException("Did not find matching resource from bijection for " + entry.getKey());
254                                         continue;
255                                 }
256                                 comparable.map(nl, entry.getValue());
257                         }
258                 }
259                 List<Statement> deletions = new ArrayList<Statement>(changes.getDeletions().size()); // Removals must be adapted from A1 to A2.
260                 List<Statement> additions = new ArrayList<Statement>(changes.getAdditions()); // Additions can be copied, since they are statements in B.
261                 session.syncRequest(new ReadRequest() {
262                         
263                         @Override
264                         public void run(ReadGraph graph) throws DatabaseException {
265                                 for (Statement del : changes.getDeletions()) {
266                                         Resource s1 = del.getSubject();
267                                         Resource s2 = bijection.getComparable().getRight(s1);
268                                         Resource p1 = del.getPredicate();
269                                         Resource p2 = bijection.getComparable().getRight(p1);
270                                         if (p2 == null)
271                                                 p2 = p1;
272                                         Resource o1 = del.getObject();
273                                         Resource o2 = bijection.getComparable().getRight(o1);
274                                         
275                                         if (s2 == null || p2 == null || o2 == null) {
276                                                 throw new DatabaseException("Did not find matching statement from bijection for (" + s1 +","+p1+","+o1+"), got (" + s2 +","+p2+","+o2+")");
277                                         }
278                                         Statement stm2 = null;
279                                         for (Statement s : graph.getStatements(s2, p2)) {
280                                                 if (s.getObject().equals(o2)) {
281                                                         stm2 = s;
282                                                         break;
283                                                 }
284                                         }
285                                         if (stm2 == null) {
286                                                 throw new DatabaseException("Did not find matching statement from bijection for (" + s1 +","+p1+","+o1+"), got (" + s2 +","+p2+","+o2+"), but it is not in DB!");
287                                         }
288                                         deletions.add(stm2);
289                                 }
290                                 
291                         }
292                 });
293                 
294                 List<Modification> modifications = new ArrayList<GraphChanges.Modification>(changes.getModifications().size());
295                 
296                 session.syncRequest(new ReadRequest() {
297                         
298                         @Override
299                         public void run(ReadGraph graph) throws DatabaseException {
300                                 for (Modification mod : changes.getModifications()) {
301                                         Statement del = mod.leftStm;
302                                         Resource sub1 = mod.getLeftSub();
303                                         Resource sub2 = bijection.getComparable().getRight(sub1);
304                                         if (sub2 == null) {
305                                                 throw new DatabaseException("Did not find matching resource from bijection for " + sub1);
306                                         }
307                                         Resource s1 = del.getSubject();
308                                         Resource s2 = bijection.getComparable().getRight(s1);
309                                         Resource p1 = del.getPredicate();
310                                         Resource p2 = bijection.getComparable().getRight(p1);
311                                         if (p2 == null)
312                                                 p2 = p1;
313                                         Resource o1 = del.getObject();
314                                         Resource o2 = bijection.getComparable().getRight(o1);
315                                         if (mod.isLeftAsserted()) {
316                                                 if (s2 == null)
317                                                         s2 = s1;
318                                                 if (o2 == null)
319                                                         o2 = o1;
320                                         } 
321                                         
322                                         if (s2 == null || p2 == null) {
323                                                 throw new DatabaseException("Did not find matching statement from bijection for (" + s1 +","+p1+","+o1+"), got (" + s2 +","+p2+","+o2+")");
324                                         }
325                                         Collection<Statement> stms = graph.getStatements(s2, p2);
326                                         Statement stm2 = null;
327                                         if (o2 == null) {
328                                                 // Matching literal resources are not included in bijection map.
329                                                 if (stms.size() == 1) {
330                                                          stm2 = stms.iterator().next();
331                                                 } else {
332                                                          throw new DatabaseException("Did not find matching statement from bijection for (" + s1 +","+p1+","+o1+"), got (" + s2 +","+p2+","+o2+")");
333                                                 }
334                                         } else {
335                                                 for (Statement s : stms) {
336                                                         if (s.getObject().equals(o2)) {
337                                                                 stm2 = s;
338                                                                 break;
339                                                         }
340                                                 }
341                                         }
342                                         if (stm2 == null) {
343                                                 throw new DatabaseException("Did not find matching statement from bijection for (" + s1 +","+p1+","+o1+"), got (" + s2 +","+p2+","+o2+"), but it is not in DB!");
344                                         }
345                                         Modification mod2 = new Modification(sub2, mod.rightSub, stm2, mod.rightStm);
346                                         modifications.add(mod2);
347                                 }
348                                 
349                         }
350                 });
351                 
352                 return new GraphChanges(bijection.r2, changes.r2, deletions, additions, modifications, comparable);
353         }
354
355 }