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