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