]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.linking.ui/src/org/simantics/document/linking/utils/SourceLinkUtil.java
12c2b5b998aa0fb105f0ce3d879612634dffc9dc
[simantics/platform.git] / bundles / org.simantics.document.linking.ui / src / org / simantics / document / linking / utils / SourceLinkUtil.java
1 package org.simantics.document.linking.utils;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collection;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9 import java.util.UUID;
10
11 import org.simantics.databoard.Bindings;
12 import org.simantics.db.ReadGraph;
13 import org.simantics.db.Resource;
14 import org.simantics.db.WriteGraph;
15 import org.simantics.db.common.request.ObjectsWithType;
16 import org.simantics.db.exception.DatabaseException;
17 import org.simantics.db.layer0.adapter.Instances;
18 import org.simantics.db.layer0.variable.Variable;
19 import org.simantics.document.DocumentResource;
20 import org.simantics.document.linking.ontology.DocumentLink;
21 import org.simantics.document.linking.report.evaluator.PredefinedVariables;
22 import org.simantics.layer0.Layer0;
23 import org.simantics.modeling.ModelingResources;
24 import org.simantics.simulation.ontology.SimulationResource;
25
26 /**
27  * 
28  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
29  *
30  */
31 public class SourceLinkUtil {
32         
33         /**
34          * Creates a document link
35          * @param graph
36          * @param instance Object, where the link is attached
37          * @param relation Property relation (functional) or null.
38          * @param document
39          * @return
40          * @throws DatabaseException
41          */
42         public static Resource createDocumentLink(WriteGraph graph, Resource instance, Resource relation, Resource document) throws DatabaseException {
43                 Layer0 l0 = Layer0.getInstance(graph);
44                 
45                 Resource link = null;
46                 DependencyCheckResult result = checkDependecies(graph, document, instance);
47                 if (result == DependencyCheckResult.NoLocationModel)
48                         throw new DatabaseException("Location of document link is not part of a model.");
49                 if (result == DependencyCheckResult.DifferentModel) {
50                         throw new DatabaseException("Location of document link and document are in different models, document link cannot be created.");
51                 }
52                 if (result == DependencyCheckResult.NoReferenceModel) {
53                         //referred document and location are not in the same model, create an URI reference.
54                         String uri = graph.getPossibleURI(document);
55                         if (uri != null) {
56                                 if (relation != null && graph.isInstanceOf(relation, l0.FunctionalRelation)) {
57                                         link = SourceLinkUtil.createFunctionalSource(graph, uri, instance, relation);
58                                 } else {
59                                         link = SourceLinkUtil.createInstanceSource(graph, uri, instance);
60                                 }
61                         }
62                 }
63                 if (link == null) {
64                         if (relation != null && graph.isInstanceOf(relation, l0.FunctionalRelation)) {
65                                 link = SourceLinkUtil.createFunctionalSource(graph, document, instance, relation);
66                         } else {
67                                 link = SourceLinkUtil.createInstanceSource(graph, document, instance);
68                         }
69                 }
70                 
71                 return link;
72         }
73         
74         public static Resource createDocumentLink(WriteGraph graph, Resource instance, Resource document) throws DatabaseException {
75             return createDocumentLink(graph, instance, null, document);
76         }
77         
78         public static Resource createInstanceSource(WriteGraph graph, Resource reference, Resource location) throws DatabaseException {
79                 return createInstanceSource(graph, reference, location, "");
80         }
81
82         public static Resource createInstanceSource(WriteGraph graph, Resource reference, Resource location, String comment) throws DatabaseException {
83                 Layer0 l0 = Layer0.getInstance(graph);
84                 DocumentLink sl = DocumentLink.getInstance(graph);
85                 
86                 
87                 
88                 // prevent duplicate references         
89                 Collection<Resource> sources = graph.syncRequest(new ObjectsWithType(location, sl.hasFunctionalSource, sl.InstanceSource));
90                 for (Resource source : sources) {
91                         if (reference.equals(graph.getPossibleObject(source, sl.hasSourceReference)))
92                                 return source;
93                 }
94                 
95                 if (!ensureDependencies(graph, reference, location))
96                         return null;
97                 
98                 Resource source = graph.newResource();
99                 graph.claim(source, l0.InstanceOf, sl.InstanceSource);
100                 graph.claim(source, sl.hasSourceReference, reference);
101                 graph.claimLiteral(source, sl.hasSourceComment, comment, Bindings.STRING);
102                 graph.claim(location, sl.hasInstanceSource, source);
103                 // search / indexing requires this
104                 graph.claim(location, l0.ConsistsOf, source);
105                 graph.claimLiteral(source, l0.HasName,UUID.randomUUID().toString(), Bindings.STRING);
106                 return source;
107         }
108         
109         public static Resource createInstanceSource(WriteGraph graph, String reference, Resource location) throws DatabaseException {
110                 return createInstanceSource(graph, reference, location, "");
111         }
112
113         public static Resource createInstanceSource(WriteGraph graph, String reference, Resource location, String comment) throws DatabaseException {
114                 Layer0 l0 = Layer0.getInstance(graph);
115                 DocumentLink sl = DocumentLink.getInstance(graph);
116                 
117                 
118                 
119                 // prevent duplicate references         
120                 Collection<Resource> sources = graph.syncRequest(new ObjectsWithType(location, sl.hasFunctionalSource, sl.InstanceSource));
121                 for (Resource source : sources) {
122                         if (reference.equals(graph.getPossibleRelatedValue(source, sl.hasSourceReferenceURI, Bindings.STRING)))
123                                 return source;
124                 }
125                 
126                 if (!ensureDependencies(graph, null, location))
127                         return null;
128                 
129                 Resource source = graph.newResource();
130                 graph.claim(source, l0.InstanceOf, sl.InstanceSource);
131                 graph.claimLiteral(source, sl.hasSourceReferenceURI, reference, Bindings.STRING);
132                 graph.claimLiteral(source, sl.hasSourceComment, comment, Bindings.STRING);
133                 graph.claim(location, sl.hasInstanceSource, source);
134                 // search / indexing requires this
135                 graph.claim(location, l0.ConsistsOf, source);
136                 graph.claimLiteral(source, l0.HasName,UUID.randomUUID().toString(), Bindings.STRING);
137                 return source;
138         }
139         
140         public static Resource createFunctionalSource(WriteGraph graph, Resource reference, Resource location, Resource relation) throws DatabaseException {
141                 return createFunctionalSource(graph, reference, location, relation, "");
142         }
143
144         
145         public static Resource createFunctionalSource(WriteGraph graph, Resource reference, Resource location, Resource relation, String comment) throws DatabaseException {
146                 Layer0 l0 = Layer0.getInstance(graph);
147                 DocumentLink sl = DocumentLink.getInstance(graph);
148                 
149                 
150                 
151                 // prevent duplicate references
152                 Collection<Resource> sources = graph.syncRequest(new ObjectsWithType(location, sl.hasFunctionalSource, sl.FunctionalSource));
153                 for (Resource source : sources) {
154                         if (relation.equals(graph.getPossibleObject(source, sl.consernsRelation)) && 
155                                 reference.equals(graph.getPossibleObject(source, sl.hasSourceReference)))
156                                 return null;
157                 }
158                 
159                 if (!ensureDependencies(graph, reference, location))
160                         return null;
161                 
162                 Resource source = graph.newResource();
163                 graph.claim(source, l0.InstanceOf, sl.FunctionalSource);
164                 graph.claim(source, sl.hasSourceReference, reference);
165                 graph.claimLiteral(source, sl.hasSourceComment, comment, Bindings.STRING);
166                 graph.claim(source, sl.consernsRelation, relation);
167                 
168                 graph.claim(location, sl.hasFunctionalSource, source);
169                 // search / indexing requires this
170                 graph.claim(location, l0.ConsistsOf, source);
171                 graph.claimLiteral(source, l0.HasName,UUID.randomUUID().toString(), Bindings.STRING);
172                 return source;
173         }
174         
175         public static Resource createFunctionalSource(WriteGraph graph, String reference, Resource location, Resource relation) throws DatabaseException {
176                 return createFunctionalSource(graph, reference, location, relation, "");
177         }
178
179         
180         public static Resource createFunctionalSource(WriteGraph graph, String reference, Resource location, Resource relation, String comment) throws DatabaseException {
181                 Layer0 l0 = Layer0.getInstance(graph);
182                 DocumentLink sl = DocumentLink.getInstance(graph);
183                 
184                 
185                 
186                 // prevent duplicate references
187                 Collection<Resource> sources = graph.syncRequest(new ObjectsWithType(location, sl.hasFunctionalSource, sl.FunctionalSource));
188                 for (Resource source : sources) {
189                         if (relation.equals(graph.getPossibleObject(source, sl.consernsRelation)) && 
190                                 reference.equals(graph.getPossibleRelatedValue(source, sl.hasSourceReferenceURI, Bindings.STRING)))
191                                 return null;
192                 }
193                 
194                 if (!ensureDependencies(graph, null, location))
195                         return null;
196                 
197                 Resource source = graph.newResource();
198                 graph.claim(source, l0.InstanceOf, sl.FunctionalSource);
199                 graph.claimLiteral(source, sl.hasSourceReferenceURI, reference, Bindings.STRING);
200                 graph.claimLiteral(source, sl.hasSourceComment, comment, Bindings.STRING);
201                 graph.claim(source, sl.consernsRelation, relation);
202                 
203                 graph.claim(location, sl.hasFunctionalSource, source);
204                 // search / indexing requires this
205                 graph.claim(location, l0.ConsistsOf, source);
206                 graph.claimLiteral(source, l0.HasName,UUID.randomUUID().toString(), Bindings.STRING);
207                 return source;
208         }
209         
210         public static Resource getModel(ReadGraph graph, Resource location) throws DatabaseException {
211                 SimulationResource sim = SimulationResource.getInstance(graph);
212                 Layer0 l0 = Layer0.getInstance(graph);
213                 List<Resource> list = new ArrayList<Resource>();
214                 list.add(l0.PartOf);
215                 list.add(l0.IsDependencyOf);
216                 list.add(l0.PropertyOf);
217                 list.add(l0.IsOwnedBy);
218                 
219                 Resource r = location;
220                 Resource model = null;
221                 while (r != null) {
222                         if (graph.isInstanceOf(r, sim.Model)) {
223                                 model = r;
224                                 break;
225                         }
226                         Resource r2 = null;
227                         for (Resource rel : list) {
228                                 r2 = graph.getPossibleObject(r, rel);
229                                 if (r2 != null)
230                                         break;
231                         }
232                         r = r2;
233                 }
234                 
235                 return model;
236         }
237         
238         /**
239          * Ensures that the model's ontology dependencies are correct, and the reference will not create dependency between two models.
240          * 
241          * @param graph
242          * @param reference
243          * @param location
244          * @return true, if everything is correct. 
245          * @throws DatabaseException
246          */
247         private static boolean ensureDependencies(WriteGraph graph, Resource reference, Resource location) throws DatabaseException {
248
249                 Layer0 l0 = Layer0.getInstance(graph);
250                 Resource model = getModel(graph, location);
251
252                 if (model == null)
253                         return true;
254
255                 DocumentLink sl = DocumentLink.getInstance(graph);
256                 Set<Resource> depencecies = new HashSet<Resource>();
257                 depencecies.add(getOntology(graph, sl.Source));
258                 if (reference != null) {
259                         Resource refModel = getModel(graph, reference);
260                         if (refModel != null && !refModel.equals(model))
261                                 return false;
262                         for (Resource t : graph.getTypes(reference)) {
263                                 Resource o = getOntology(graph, t);
264                                 if (o != null)
265                                         depencecies.add(o);
266                         }
267                 }
268                 
269                 Collection<Resource> linkedTo = graph.getObjects(model, l0.IsLinkedTo);
270                 for (Resource dep : depencecies) {
271                         if (!linkedTo.contains(dep)) {
272                                 graph.claim(model, l0.IsLinkedTo, dep);
273                         }
274                 }
275                 return true;
276         }
277         
278         private static enum DependencyCheckResult{NoLocationModel, NoReferenceModel, SameModel,DifferentModel};
279         
280         private static DependencyCheckResult checkDependecies(ReadGraph graph, Resource reference, Resource location) throws DatabaseException{
281                 Resource model = getModel(graph, location);
282
283                 if (model == null)
284                         return DependencyCheckResult.NoLocationModel;
285                 Resource refModel = getModel(graph, reference);
286                 if (refModel != null) {
287                         if (refModel.equals(model))
288                                 return DependencyCheckResult.SameModel;
289                         return DependencyCheckResult.DifferentModel;
290                 }
291                 return DependencyCheckResult.NoReferenceModel;
292         }
293         
294         
295         private static Resource getOntology(ReadGraph graph, Resource type) throws DatabaseException{
296                 Layer0 l0 = Layer0.getInstance(graph);
297                 Resource r = type;
298                 while (r != null) {
299                         if (graph.isInstanceOf(r, l0.Ontology))
300                                 return r;
301                         r = graph.getPossibleObject(r, l0.PartOf);
302                 }
303                 
304                 r = type;
305                 while (r != null) {
306                         if (graph.isInstanceOf(r, l0.Library))
307                                 return r;
308                         r = graph.getPossibleObject(r, l0.PartOf);
309                 }       
310                 return null;
311         }
312         
313         public static boolean isSource(ReadGraph graph, Resource source) throws DatabaseException{
314                 DocumentLink sl = DocumentLink.getInstance(graph);
315                 return (graph.isInstanceOf(source, sl.Source));
316         }
317         
318         public static boolean isValidSource(ReadGraph graph, Resource source) throws DatabaseException{
319                 Resource reference = getReferredDocument(graph, source);
320                 return isValidReference(graph, reference);
321         }
322         
323         public static boolean isUpToDateSource(ReadGraph graph, Resource source) throws DatabaseException{
324                 Resource reference = getReferredDocument(graph, source);
325                 return isUpToDateReference(graph, reference);
326         }
327         
328         public static Resource getReferredDocument(ReadGraph graph, Resource source) throws DatabaseException {
329                 DocumentLink sl = DocumentLink.getInstance(graph);
330                 Resource document =  graph.getPossibleObject(source, sl.hasSourceReference);
331                 if (document != null) {
332                         return document;
333                 }
334                 String URI = graph.getPossibleRelatedValue(source, sl.hasSourceReferenceURI, Bindings.STRING);
335                 if (URI != null)
336                         return graph.getPossibleResource(URI);
337                 return null;
338         }
339         
340         public static boolean isValidReference(ReadGraph graph, Resource reference) throws DatabaseException{
341                 if (reference == null)
342                         return false;
343                 return graph.hasStatement(reference);
344                 
345         }
346         
347         public static boolean isUpToDateReference(ReadGraph graph, Resource reference) throws DatabaseException{
348                 if (reference == null)
349                         return false;
350                 DocumentResource doc = DocumentResource.getInstance(graph);
351                 return !graph.hasStatement(reference,doc.HasNewerVersion);
352                 
353         }
354         
355         public static void updateToLatest(WriteGraph graph, Resource source) throws DatabaseException {
356                 DocumentLink sl = DocumentLink.getInstance(graph);
357                 DocumentResource doc = DocumentResource.getInstance(graph);
358                 
359                 if (!graph.isInstanceOf(source, sl.Source))
360                         return;
361                 Resource reference = getReferredDocument(graph, source);
362                 Resource newRef = reference;
363                 while (true) {
364                         Resource r = graph.getPossibleObject(newRef, doc.HasNewerVersion);
365                         if (r != null)
366                                 newRef = r;
367                         else
368                                 break;
369                 }
370                 if (newRef.equals(reference))
371                         return;
372                 if (graph.hasStatement(source, sl.hasSourceReference)) {
373                         graph.deny(source, sl.hasSourceReference,reference);
374                         graph.claim(source, sl.hasSourceReference, newRef);
375                 } else if (graph.hasStatement(source,sl.hasSourceReferenceURI)) {
376                         graph.deny(source, sl.hasSourceReferenceURI);
377                         graph.claimLiteral(source, sl.hasSourceReferenceURI, graph.getURI(newRef),Bindings.STRING);
378                 }
379         }
380         
381         public static Collection<Resource> findAllSources(ReadGraph graph, Resource model, Resource resource) throws DatabaseException {
382                 DocumentLink sl = DocumentLink.getInstance(graph);
383                 Instances instancesQuery = graph.adapt(sl.Source, Instances.class);
384         Collection<Resource> found = instancesQuery.find(graph, model);
385         Collection<Resource> result = new ArrayList<Resource>();
386         for (Resource source : found) {
387                 if (graph.hasStatement(source,sl.hasSourceReference,resource) || graph.hasStatement(source, sl.hasSourceReferenceURI))
388                         result.add(source);
389         }
390         return result;
391         }
392         
393         public static String getValueString(Object value) {
394                 if (value.getClass().isArray()) {
395                         if (value instanceof double[]) {
396                                 return Arrays.toString((double[])value);
397                         } else if (value instanceof float[]) {
398                                 return Arrays.toString((float[])value);
399                         } else if (value instanceof int[]) {
400                                 return Arrays.toString((int[])value);
401                         } else if (value instanceof boolean[]) {
402                                 return Arrays.toString((boolean[])value);
403                         } else if (value instanceof byte[]) {
404                                 return Arrays.toString((byte[])value);
405                         } else if (value instanceof String[]) {
406                                 return Arrays.toString((String[])value);
407                         } else if (value instanceof Object[]) {
408                                 return Arrays.toString((Object[])value);
409                         } else {
410                                 return "TODO: Array " + value.getClass().getSimpleName();
411                         }
412                 } else {
413                         return value.toString();
414                 }
415         }
416         
417         public static List<Resource> getPath(ReadGraph graph, Resource model, Resource obj) throws DatabaseException {
418                 Layer0 l0 = Layer0.getInstance(graph);
419                 List<Resource> path = new ArrayList<Resource>();
420                 Resource r = obj;
421                 while (r != null && !r.equals(model)) {
422                         path.add(0, r);
423                         r = graph.getPossibleObject(r, l0.PartOf);
424                 }
425                 return path;
426         }
427         
428         public static List<Resource> getDiagramPath(ReadGraph graph, Resource model, Resource obj) throws DatabaseException {
429                 ModelingResources mod = ModelingResources.getInstance(graph);
430                 List<Resource> path = getPath(graph, model, obj);
431                 for (int i = path.size()-1; i >= 0; i--) {
432                         if (graph.hasStatement(path.get(i),mod.CompositeToDiagram))
433                                 return path.subList(0, i+1);
434                 }
435                 return null;
436         }
437         
438         public static String getCustomizedString(ReadGraph graph, Resource document, List<String> annotationContent) throws DatabaseException{
439                 String label = "";
440                 Variable doc = graph.adapt(document, Variable.class);
441                 for (String path : annotationContent) {
442                         if (path.startsWith("\"") && path.endsWith("\"")) {
443                                 label += path.substring(1,path.length()-1)+ " ";
444                         } else {
445                                 Variable v = PredefinedVariables.getInstance().getVariable(graph, path, null, doc);
446                                 if (v != null) {
447                                         label += v.getValue(graph) + " ";
448                                 }
449                         }
450                 }
451                 return label;
452         }
453 }