Merge "Log an error if there are two resources with the same GUID."
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / StructuralRVIResolver.java
1 package org.simantics.structural2;
2
3 import java.util.Collection;
4 import java.util.LinkedList;
5
6 import org.simantics.databoard.Databoard;
7 import org.simantics.databoard.binding.Binding;
8 import org.simantics.datatypes.literal.GUID;
9 import org.simantics.db.ReadGraph;
10 import org.simantics.db.Resource;
11 import org.simantics.db.common.utils.NameUtils;
12 import org.simantics.db.exception.DatabaseException;
13 import org.simantics.db.layer0.adapter.Instances;
14 import org.simantics.db.layer0.exception.MissingVariableException;
15 import org.simantics.db.layer0.variable.RVI;
16 import org.simantics.db.layer0.variable.RVI.GuidRVIPart;
17 import org.simantics.db.layer0.variable.RVI.RVIPart;
18 import org.simantics.db.layer0.variable.RVIBuilder;
19 import org.simantics.db.layer0.variable.StandardRVIResolver;
20 import org.simantics.db.layer0.variable.Variable;
21 import org.simantics.db.layer0.variable.Variables;
22 import org.simantics.layer0.Layer0;
23 import org.simantics.simulation.ontology.SimulationResource;
24 import org.simantics.structural.stubs.StructuralResource2;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 public class StructuralRVIResolver extends StandardRVIResolver {
29     private static final Logger LOGGER = LoggerFactory.getLogger(StructuralRVIResolver.class);
30
31     protected boolean isRVIBase(ReadGraph graph, Variable variable) throws DatabaseException {
32         if (Variables.isContext(graph, variable)) return true;
33         StructuralResource2 STR = StructuralResource2.getInstance(graph);
34         Resource represents = variable.getRepresents(graph);
35         if (represents == null) return false;
36         if (graph.isInstanceOf(represents, STR.Composite)) return false;
37         return true;
38     }
39     
40     @Override
41     public RVI getRVI(ReadGraph graph, Variable variable) throws DatabaseException {
42         if (Variables.isContext(graph, variable)) {
43             Databoard databoard = graph.getService( Databoard.class );
44             Binding rviBinding = databoard.getBindingUnchecked( RVI.class );
45             return RVI.empty(rviBinding);
46         }
47         else {
48             Variable base = variable.getParent(graph);
49             while(!isRVIBase(graph, base)) base = base.getParent(graph);
50             RVIPart part = getRVIPart(graph, variable);
51             return new RVIBuilder(base.getRVI(graph)).append(part).toRVI();
52         }
53     }
54     
55     @Override
56     public RVI getPossibleRVI(ReadGraph graph, Variable variable) throws DatabaseException {
57         if (Variables.isContext(graph, variable)) {
58             Databoard databoard = graph.getService( Databoard.class );
59             Binding rviBinding = databoard.getBindingUnchecked( RVI.class );
60             return RVI.empty(rviBinding);
61         }
62         else {
63             Variable base = variable.getParent(graph);
64             if(base == null) return null;
65             while(!isRVIBase(graph, base)) {
66                 base = base.getParent(graph);
67                 if(base == null) return null;
68             }
69             RVIPart part = getRVIPart(graph, variable);
70             if(part == null) return null;
71             RVI baseRVI = base.getPossibleRVI(graph);
72             if(baseRVI == null) return null;
73             return new RVIBuilder(baseRVI).append(part).toRVI();
74         }
75     }
76
77     protected boolean isPartOfComponentType(ReadGraph graph, Resource resource)
78             throws DatabaseException {
79         Layer0 L0 = Layer0.getInstance(graph);
80         StructuralResource2 STR = StructuralResource2.getInstance(graph);
81         Resource container = graph.getPossibleObject(resource, L0.PartOf);
82         if(container != null && graph.isInstanceOf(container, STR.Composite)) {
83             return graph.hasStatement(container, STR.Defines);
84         }
85         return false;
86     }
87
88     protected Resource getBase(ReadGraph graph, Variable variable, Resource resource) throws DatabaseException {
89         Layer0 L0 = Layer0.getInstance(graph);
90         SimulationResource SIMU = SimulationResource.getInstance(graph);
91         Resource represents = variable.getPossibleRepresents(graph);
92         if(represents != null && graph.isInstanceOf(represents, SIMU.Run)) return Variables.getPossibleConfigurationContextResource(graph, represents);
93         else if(isPartOfComponentType(graph, resource)) return graph.getPossibleObject(resource, L0.PartOf);
94         return represents;
95     }
96
97     protected Collection<Resource> getRVIPath(ReadGraph graph, Variable variable, Resource resource)
98             throws DatabaseException {
99         Resource base = getBase(graph, variable, resource);
100         if (base == null)
101             return null;
102         LinkedList<Resource> result = new LinkedList<Resource>();
103         result.add(resource);
104         Layer0 L0 = Layer0.getInstance(graph);
105         resource = graph.getPossibleObject(resource, L0.PartOf);
106         if(resource == null) return null;
107         while(!base.equals(resource)) {
108             result.addFirst(resource);
109             resource = graph.getPossibleObject(resource, L0.PartOf);
110             if(resource == null) return null;
111         }
112         return result;
113     }
114     
115     protected Collection<Resource> getRVIPath(ReadGraph graph, Variable variable, GuidRVIPart part)
116             throws DatabaseException {
117
118         if(part.resource != null) {
119                 return getRVIPath(graph, variable, part.resource);
120         } else {
121                 Resource indexRoot = variable.getIndexRoot(graph);
122                 Instances instances = graph.adapt(Layer0.getInstance(graph).Entity, Instances.class);
123                 GUID guid = new GUID(part.mostSignificant, part.leastSignificant);
124                 Collection<Resource> queryResult = instances.find(graph, indexRoot, "GUID:"+guid.indexString());
125                 if(queryResult.size() != 1) {
126                     if(queryResult.size() > 1) {
127                         StringBuilder b = new StringBuilder();
128                         boolean first = true;
129                         for(Resource r : queryResult) {
130                             if(first)
131                                 first = false;
132                             else
133                                 b.append(", ");
134                             b.append(NameUtils.getURIOrSafeNameInternal(graph, r));
135                         }
136                         LOGGER.error("Found {} resources with the same GUID {}: {}.", queryResult.size(), guid, b);
137                     }
138                     return null;
139                 }
140                 return getRVIPath(graph, variable, queryResult.iterator().next());
141         }
142         
143     }
144
145     @Override
146     protected Variable resolveChild(ReadGraph graph, Variable variable, Resource resource) throws DatabaseException {
147         Collection<Resource> path = getRVIPath(graph, variable, resource);
148         if (path == null)
149             throw new MissingVariableException("Didn't find a variable related to " + resource + ".", resource);
150         for (Resource r : path)
151             variable = variable.browse(graph, r);
152         return variable;
153     }
154
155     @Override
156     protected Variable resolveChild(ReadGraph graph, Variable variable, GuidRVIPart part) throws DatabaseException {
157         Collection<Resource> path = getRVIPath(graph, variable, part);
158         if (path == null)
159             throw new MissingVariableException("Didn't find a variable related to " + part + ".", variable.getPossibleRepresents(graph));
160         for (Resource r : path)
161             variable = variable.browse(graph, r);
162         return variable;
163     }
164
165 }