]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/utils/StructuralUtils.java
Work in progress
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / utils / StructuralUtils.java
1 package org.simantics.structural2.utils;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Set;
8
9 import org.simantics.databoard.Bindings;
10 import org.simantics.db.ReadGraph;
11 import org.simantics.db.RequestProcessor;
12 import org.simantics.db.Resource;
13 import org.simantics.db.Statement;
14 import org.simantics.db.WriteGraph;
15 import org.simantics.db.common.CommentMetadata;
16 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
17 import org.simantics.db.common.request.ObjectsWithType;
18 import org.simantics.db.common.request.PossibleTypedParent;
19 import org.simantics.db.common.utils.NameUtils;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.layer0.exception.MissingVariableException;
22 import org.simantics.db.layer0.request.InstantiateRequest;
23 import org.simantics.db.layer0.util.Layer0Utils;
24 import org.simantics.db.layer0.variable.Variable;
25 import org.simantics.layer0.Layer0;
26 import org.simantics.structural.stubs.StructuralResource2;
27 import org.simantics.structural2.Functions.StructuralOverrideData;
28 import org.simantics.structural2.internal.queries.ConnectedTo;
29 import org.simantics.structural2.internal.queries.RelatedConnections;
30 import org.simantics.structural2.internal.queries.RelatedConnectionsOfConnectionJoin;
31 import org.simantics.structural2.queries.Terminal;
32 import org.simantics.structural2.variables.Connection;
33 import org.simantics.utils.datastructures.Pair;
34
35 import gnu.trove.set.hash.THashSet;
36
37 /**
38  * A utility class for manipulating structural models.
39  * 
40  * @author Hannu Niemistö
41  */
42 public class StructuralUtils {
43     
44         public static enum StructuralComponentClass {
45                 
46                 PRIMITIVE,REPLACEABLE,DEFINED,PROCEDURAL;
47
48                 public static StructuralComponentClass get(ReadGraph graph, Resource componentType) throws DatabaseException {
49                         StructuralResource2 STR = StructuralResource2.getInstance(graph);
50                         if(graph.isInstanceOf(componentType, STR.ProceduralComponentType))
51                                 return StructuralComponentClass.PROCEDURAL;
52                         else if(graph.hasStatement(componentType, STR.IsDefinedBy))
53                                 return StructuralComponentClass.DEFINED;
54                         else if(graph.isInstanceOf(componentType, STR.ReplaceableDefinedComponentType))
55                                 return StructuralComponentClass.REPLACEABLE;
56                         else
57                                 return StructuralComponentClass.PRIMITIVE;
58                 }
59
60         }
61         
62     public static Collection<Resource> getConnectionRelations(ReadGraph graph, Resource componentType) throws DatabaseException {
63         Layer0 L0 = Layer0.getInstance(graph);
64         StructuralResource2 STR = StructuralResource2.getInstance(graph);
65         return graph.syncRequest(new ObjectsWithType(componentType, L0.DomainOf, STR.ConnectionRelation));
66     }
67
68     public static Collection<Resource> getPropertyRelations(ReadGraph graph, Resource componentType) throws DatabaseException {
69         Layer0 L0 = Layer0.getInstance(graph);
70         ArrayList<Resource> result = new ArrayList<Resource>();
71         for(Resource relation : graph.getObjects(componentType, L0.DomainOf))
72             if(graph.isSubrelationOf(relation, L0.HasProperty))
73                 result.add(relation);
74         return result;
75     }
76     
77     public static boolean isDomainOfRelation(ReadGraph graph,
78             Resource componentType, Resource connectionRelation) throws DatabaseException {
79         Layer0 L0 = Layer0.getInstance(graph);
80         for(Resource domain : graph.getObjects(connectionRelation, L0.HasDomain))
81             if(graph.isInheritedFrom(componentType, domain))
82                 return true;
83         return false;
84     }
85     
86     public static void addConnectionPoint(WriteGraph g, Resource componentType,
87             Resource connectionPoint) throws DatabaseException {
88         Layer0 L0 = Layer0.getInstance(g);
89         g.claim(connectionPoint, L0.HasDomain, componentType);
90     }
91     
92     public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource copy) throws DatabaseException {
93         String proposition = NameUtils.getSafeName(g, copy);
94         String newName = NameUtils.findFreshName(g, proposition, componentType);
95         return createConnectionPoint(g, componentType, copy, newName);
96     }
97     
98     public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource copy, String name) throws DatabaseException {
99         return createConnectionPointP(g, componentType, copy, name).first;
100     }
101     
102     public static Pair<Resource,Resource> createConnectionPointP(WriteGraph g, Resource componentType, Resource copy, String name) throws DatabaseException {
103         
104         Layer0 L0 = Layer0.getInstance(g);
105         StructuralResource2 STR = StructuralResource2.getInstance(g);
106
107         // Create the connection point
108         Resource connectionPoint = g.newResource();
109         Resource connectionPointInv = g.newResource();
110
111         for (Resource superrelation : g.getObjects(copy, L0.SubrelationOf)) {
112             g.claim(connectionPoint, L0.SubrelationOf, null, superrelation);
113             Resource inverse = g.getPossibleInverse(superrelation);
114             if (inverse != null)
115                 g.claim(connectionPointInv, L0.SubrelationOf, null, inverse);
116         }
117         for (Resource type : g.getObjects(copy, L0.InstanceOf)) {
118             g.claim(connectionPoint, L0.InstanceOf, null, type);
119         }
120         for (Resource attachment : g.getObjects(copy, STR.HasAttachmentRelation)) {
121             g.claim(connectionPoint, STR.HasAttachmentRelation, attachment);
122         }
123         for (Statement stm : g.getStatements(copy, STR.AllowsConnectionType)) {
124             if (!stm.isAsserted(copy)) {
125                 g.claim(connectionPoint, stm.getPredicate(), stm.getObject());
126             }
127         }
128
129         g.claim(connectionPoint, L0.InverseOf, connectionPointInv);
130         g.claimLiteral(connectionPoint, L0.HasName, name, Bindings.STRING);
131         g.claim(connectionPoint, L0.ConsistsOf, connectionPointInv);
132         g.claimLiteral(connectionPointInv, L0.HasName, "Inverse", Bindings.STRING);
133
134         StructuralUtils.addConnectionPoint(g, componentType, connectionPoint);
135
136         g.claim(componentType, L0.ConsistsOf, connectionPoint);
137
138         return Pair.make(connectionPoint, connectionPointInv);
139         
140     }
141
142     /**
143      * Creates a new component and the templates associated with it.
144      * This method does not check whether there already exists 
145      * a component with the same name and parent.
146      * @param g
147      * @param parent The parent composite of the new component.
148      * @param name The name of the new component.
149      * @param componentType The type of the new component.
150      * @return
151      * @throws DatabaseException
152      */
153     public static Resource newComponent(WriteGraph g, Resource parent, String name, Resource componentType) throws DatabaseException {
154         Layer0 L0 = Layer0.getInstance(g);
155         
156         HashMap<String,Object> parameters = new HashMap<String,Object>();
157         parameters.put("parent", parent);
158
159         InstantiateRequest ir = new InstantiateRequest(componentType, parameters);
160         Resource component = ir.perform(g);        
161         g.claim(component, L0.HasName, Layer0Utils.literal(g, name));
162         g.claim(component, L0.HasLabel, Layer0Utils.literal(g, ""));
163         g.claim(parent, L0.ConsistsOf, component);
164         Layer0Utils.claimNewIdentifier(g, component, true);
165         // Add comment to change set.
166         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
167         g.addMetadata(cm.add("Created component " + component));
168         return component;
169     }
170     
171     /**
172      * Returns all child components of a composite.
173      */
174     public static Collection<Resource> getChildComponents(ReadGraph g, Resource parent) throws DatabaseException {
175         Layer0 L0 = Layer0.getInstance(g);
176         StructuralResource2 STR = StructuralResource2.getInstance(g);
177         
178         Collection<Resource> allChildren = g.getObjects(parent, L0.ConsistsOf);
179         ArrayList<Resource> result = new ArrayList<Resource>(allChildren.size());
180         for(Resource child : allChildren)
181             // Composite may contain other things than components, therefore we must do checking
182             if(g.isInstanceOf(child, STR.Component))
183                 result.add(child);
184         return result;
185     }
186
187     /**
188      * Returns the component type of the given component or null if the 
189      * parameter is not a component.
190      */
191     @Deprecated
192     public static Resource getComponentType(ReadGraph g, Resource component) throws DatabaseException {
193         StructuralResource2 STR = StructuralResource2.getInstance(g);
194         return g.getPossibleType(component, STR.Component);
195     }
196     
197     /**
198      * Returns the definitions of the component type or null, if the component
199      * type does not have a definition.
200      */
201     public static Resource getComponentTypeDefinition(ReadGraph g, Resource componentType) throws DatabaseException {
202         StructuralResource2 STR = StructuralResource2.getInstance(g);
203         return g.getPossibleObject(componentType, STR.IsDefinedBy);
204     }
205     
206     /**
207      * Returns all (component,connectionRelation) pairs that are connected
208      * to the given component and connectionRelation.
209      * @param component
210      * @param bindingRelation
211      * @return
212      */
213     public static Set<Terminal> getRelatedTerminals(RequestProcessor g, Resource component, Resource connectionRelation) throws DatabaseException {
214         return g.syncRequest(new ConnectedTo(component, connectionRelation));
215     }
216     
217     /**
218      * Returns all connections that are reachable from the given connection
219      * with IsJoinedBy-relation including the given connection itself. 
220      */ 
221     public static Set<Resource> getRelatedConnections(RequestProcessor g, Resource connection) throws DatabaseException {
222         return g.syncRequest(new RelatedConnections(connection));
223     }
224     
225     /**
226      * Returns all connections that are reachable from the given connection join.     * 
227      */ 
228     public static Set<Resource> getRelatedConnectionsOfConnectionJoin(RequestProcessor g, Resource connectionJoin) throws DatabaseException {
229         return g.syncRequest(new RelatedConnectionsOfConnectionJoin(connectionJoin));
230     }
231     
232     /**
233      * Returns all connections that are reachable from the given connection join
234      * without visiting the resources in the collection excludedConnections.
235      */
236     public static Set<Resource> getRelatedConnectionsOfConnectionJoin(RequestProcessor g, Resource connectionJoin, Collection<Resource> excludedConnections) throws DatabaseException {
237         return g.syncRequest(new RelatedConnectionsOfConnectionJoin(connectionJoin, excludedConnections));
238     }
239     
240     /**
241      * Returns true if the given composite is a parent of some/all components 
242      * where the connection is attached to.
243      */
244     public static boolean isConnectionInComposite(ReadGraph g, Resource connection, Resource composite) throws DatabaseException {
245         StructuralResource2 STR = StructuralResource2.getInstance(g);
246         Layer0 L0 = Layer0.getInstance(g);
247         Collection<Resource> connects = g.getObjects(connection, STR.Connects);
248         if (!connects.isEmpty()) {
249             for(Resource component : connects)
250                 for(Resource parent : g.getObjects(component, L0.PartOf))
251                     if(parent.equals(composite))
252                         return true;
253         } else {
254             Set<Resource> joinedComposites = null;
255             for(Resource join : g.getObjects(connection, STR.IsJoinedBy)) {
256                 Collection<Resource> joined = g.getObjects(join, STR.JoinsComposite);
257                 if (joinedComposites == null) {
258                     joinedComposites = new THashSet<Resource>(joined);
259                 } else {
260                     joinedComposites.retainAll(joined);
261                 }
262             }
263             if (joinedComposites != null && joinedComposites.size() == 1) {
264                 return joinedComposites.contains(composite);
265             }
266         }
267         return false;
268     }
269     
270     public static Variable getConnectionPoint(ReadGraph graph, Variable component, Resource relation) throws DatabaseException {
271         Layer0 L0 = Layer0.getInstance(graph);
272         String relationName = graph.getRelatedValue(relation, L0.HasName, Bindings.STRING);
273         return component.getProperty(graph, relationName);
274     }
275
276     public static Variable getPossibleConnectionPoint(ReadGraph graph, Variable component, Resource relation) throws DatabaseException {
277         try {
278                 return getConnectionPoint(graph, component, relation);
279         } catch (MissingVariableException e) {
280                 return null;
281         }
282     }
283
284     public static Variable getPossibleConnectionTo(ReadGraph graph, Variable component, Resource relation) throws DatabaseException {
285         Variable property = component.getPossibleProperty(graph, relation);
286         if(property == null) return null;
287         Connection conn = property.getPossibleValue(graph);
288         if(conn == null) return null;
289         Collection<Variable> cps = conn.getConnectionPoints(graph, component, null);
290         if(cps.size() == 2) {
291                 for(Variable var : cps) {
292                         if(property.equals(var)) continue;
293                         return var;
294                 }
295         }
296         return null;
297     }
298
299     public static boolean isImmutable(ReadGraph graph, Resource r) throws DatabaseException {
300         StructuralResource2 STR = StructuralResource2.getInstance(graph);
301         Resource uc = graph.syncRequest(new PossibleTypedParent(r, STR.ComponentType));
302         return graph.isImmutable(r)
303                 // Anything under a published or locked user component is published as well
304                 || (uc != null && (Layer0Utils.isPublished(graph, uc)
305                          || graph.hasStatement(uc, STR.ComponentType_Locked)))
306                 // Anything under a published container (shared library) is published as well
307                 || Layer0Utils.isContainerPublished(graph, r)
308                 ;
309     }
310     
311     public static List<Variable> structuralConnectionConnectionPoints(ReadGraph graph, Variable component, Connection conn, Resource relationType) throws DatabaseException {
312         return new ArrayList<Variable>(conn.getConnectionPoints(graph, component, relationType));
313     }
314     
315     public static Resource structuralTypeResource(ReadGraph graph, Variable component, Resource baseType) throws DatabaseException {
316
317         if(component.getURI(graph).endsWith("/Alternative/Alternative/Panel2"))
318                 System.err.println("structuralTypeResource " + component.getURI(graph));
319         
320         StructuralOverrideData od = StructuralOverrideData.compute(graph, component);
321         return od.type();
322         
323 //      Resource represents = component.getPossibleRepresents(graph);
324 //      if(represents == null) {
325 //              String uri = component.getPossiblePropertyValue(graph, "typeURI");
326 //              if(uri != null) return graph.syncRequest(new org.simantics.db.common.primitiverequest.Resource(uri), TransientCacheAsyncListener.<Resource>instance());
327 //              throw new DatabaseException("No type for " + component.getURI(graph));
328 //      }
329 //      return graph.getPossibleType(represents, baseType);
330 //      
331 //      Pair<Resource,Resource> representsAndType = graph.syncRequest(new PossibleRepresentsAndTypeWithOverrides(component));
332 //      return representsAndType.second;
333         
334     }
335     
336     public static Resource getComponentType(ReadGraph graph, Variable configuration, Resource component) throws DatabaseException {
337
338         Variable componentVariable = configuration.browse(graph, component);
339         return componentVariable.getType(graph);
340         
341     }
342     
343
344
345 }