--- /dev/null
+package org.simantics.structural2.utils;\r
+\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Set;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.datatypes.literal.GUID;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.CommentMetadata;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.exception.MissingVariableException;\r
+import org.simantics.db.layer0.request.InstantiateRequest;\r
+import org.simantics.db.layer0.util.Layer0Utils;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.structural2.internal.queries.ConnectedTo;\r
+import org.simantics.structural2.internal.queries.RelatedConnections;\r
+import org.simantics.structural2.internal.queries.RelatedConnectionsOfConnectionJoin;\r
+import org.simantics.structural2.queries.Terminal;\r
+import org.simantics.structural2.variables.Connection;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+/**\r
+ * A utility class for manipulating structural models.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public class StructuralUtils {\r
+ \r
+ public static Collection<Resource> getConnectionRelations(ReadGraph graph, Resource componentType) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+ return graph.syncRequest(new ObjectsWithType(componentType, L0.DomainOf, STR.ConnectionRelation));\r
+ }\r
+\r
+ public static Collection<Resource> getPropertyRelations(ReadGraph graph, Resource componentType) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ ArrayList<Resource> result = new ArrayList<Resource>();\r
+ for(Resource relation : graph.getObjects(componentType, L0.DomainOf))\r
+ if(graph.isSubrelationOf(relation, L0.HasProperty))\r
+ result.add(relation);\r
+ return result;\r
+ }\r
+ \r
+ public static boolean isDomainOfRelation(ReadGraph graph,\r
+ Resource componentType, Resource connectionRelation) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for(Resource domain : graph.getObjects(connectionRelation, L0.HasDomain))\r
+ if(graph.isInheritedFrom(componentType, domain))\r
+ return true;\r
+ return false;\r
+ }\r
+ \r
+ public static void addConnectionPoint(WriteGraph g, Resource componentType,\r
+ Resource connectionPoint) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ g.claim(connectionPoint, L0.HasDomain, componentType);\r
+ }\r
+ \r
+ public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource copy) throws DatabaseException {\r
+ String proposition = NameUtils.getSafeName(g, copy);\r
+ String newName = NameUtils.findFreshName(g, proposition, componentType);\r
+ return createConnectionPoint(g, componentType, copy, newName);\r
+ }\r
+ \r
+ public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource copy, String name) throws DatabaseException {\r
+ return createConnectionPointP(g, componentType, copy, name).first;\r
+ }\r
+ \r
+ public static Pair<Resource,Resource> createConnectionPointP(WriteGraph g, Resource componentType, Resource copy, String name) throws DatabaseException {\r
+ \r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+\r
+ // Create the connection point\r
+ Resource connectionPoint = g.newResource();\r
+ Resource connectionPointInv = g.newResource();\r
+\r
+ for (Resource superrelation : g.getObjects(copy, L0.SubrelationOf)) {\r
+ g.claim(connectionPoint, L0.SubrelationOf, null, superrelation);\r
+ Resource inverse = g.getPossibleInverse(superrelation);\r
+ if (inverse != null)\r
+ g.claim(connectionPointInv, L0.SubrelationOf, null, inverse);\r
+ }\r
+ for (Resource type : g.getObjects(copy, L0.InstanceOf)) {\r
+ g.claim(connectionPoint, L0.InstanceOf, null, type);\r
+ }\r
+ for (Resource attachment : g.getObjects(copy, STR.HasAttachmentRelation)) {\r
+ g.claim(connectionPoint, STR.HasAttachmentRelation, attachment);\r
+ }\r
+ for (Statement stm : g.getStatements(copy, STR.AllowsConnectionType)) {\r
+ if (!stm.isAsserted(copy)) {\r
+ g.claim(connectionPoint, stm.getPredicate(), stm.getObject());\r
+ }\r
+ }\r
+\r
+ g.claim(connectionPoint, L0.InverseOf, connectionPointInv);\r
+ g.claimLiteral(connectionPoint, L0.HasName, name, Bindings.STRING);\r
+ g.claim(connectionPoint, L0.ConsistsOf, connectionPointInv);\r
+ g.claimLiteral(connectionPointInv, L0.HasName, "Inverse", Bindings.STRING);\r
+\r
+ StructuralUtils.addConnectionPoint(g, componentType, connectionPoint);\r
+\r
+ g.claim(componentType, L0.ConsistsOf, connectionPoint);\r
+\r
+ return Pair.make(connectionPoint, connectionPointInv);\r
+ \r
+ }\r
+\r
+ /**\r
+ * Creates a new component and the templates associated with it.\r
+ * This method does not check whether there already exists \r
+ * a component with the same name and parent.\r
+ * @param g\r
+ * @param parent The parent composite of the new component.\r
+ * @param name The name of the new component.\r
+ * @param componentType The type of the new component.\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static Resource newComponent(WriteGraph g, Resource parent, String name, Resource componentType) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ HashMap<String,Object> parameters = new HashMap<String,Object>();\r
+ parameters.put("parent", parent);\r
+\r
+ InstantiateRequest ir = new InstantiateRequest(componentType, parameters);\r
+ Resource component = ir.perform(g); \r
+ g.claim(component, L0.HasName, Layer0Utils.literal(g, name));\r
+ g.claim(component, L0.HasLabel, Layer0Utils.literal(g, ""));\r
+ g.addLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, GUID.random(), GUID.BINDING);\r
+ g.claim(parent, L0.ConsistsOf, component);\r
+ // Add comment to change set.\r
+ CommentMetadata cm = g.getMetadata(CommentMetadata.class);\r
+ g.addMetadata(cm.add("Created component " + component));\r
+ return component;\r
+ }\r
+ \r
+ /**\r
+ * Returns all child components of a composite.\r
+ */\r
+ public static Collection<Resource> getChildComponents(ReadGraph g, Resource parent) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ \r
+ Collection<Resource> allChildren = g.getObjects(parent, L0.ConsistsOf);\r
+ ArrayList<Resource> result = new ArrayList<Resource>(allChildren.size());\r
+ for(Resource child : allChildren)\r
+ // Composite may contain other things than components, therefore we must do checking\r
+ if(g.isInstanceOf(child, STR.Component))\r
+ result.add(child);\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Returns the component type of the given component or null if the \r
+ * parameter is not a component.\r
+ */\r
+ public static Resource getComponentType(ReadGraph g, Resource component) throws DatabaseException {\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ return g.getPossibleType(component, STR.Component);\r
+ }\r
+ \r
+ /**\r
+ * Returns the definitions of the component type or null, if the component\r
+ * type does not have a definition.\r
+ */\r
+ public static Resource getComponentTypeDefinition(ReadGraph g, Resource componentType) throws DatabaseException {\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ return g.getPossibleObject(componentType, STR.IsDefinedBy);\r
+ }\r
+ \r
+ /**\r
+ * Returns all (component,connectionRelation) pairs that are connected\r
+ * to the given component and connectionRelation.\r
+ * @param component\r
+ * @param bindingRelation\r
+ * @return\r
+ */\r
+ public static Set<Terminal> getRelatedTerminals(RequestProcessor g, Resource component, Resource connectionRelation) throws DatabaseException {\r
+ return g.syncRequest(new ConnectedTo(component, connectionRelation));\r
+ }\r
+ \r
+ /**\r
+ * Returns all connections that are reachable from the given connection\r
+ * with IsJoinedBy-relation including the given connection itself. \r
+ */ \r
+ public static Set<Resource> getRelatedConnections(RequestProcessor g, Resource connection) throws DatabaseException {\r
+ return g.syncRequest(new RelatedConnections(connection));\r
+ }\r
+ \r
+ /**\r
+ * Returns all connections that are reachable from the given connection join. * \r
+ */ \r
+ public static Set<Resource> getRelatedConnectionsOfConnectionJoin(RequestProcessor g, Resource connectionJoin) throws DatabaseException {\r
+ return g.syncRequest(new RelatedConnectionsOfConnectionJoin(connectionJoin));\r
+ }\r
+ \r
+ /**\r
+ * Returns all connections that are reachable from the given connection join\r
+ * without visiting the resources in the collection excludedConnections.\r
+ */\r
+ public static Set<Resource> getRelatedConnectionsOfConnectionJoin(RequestProcessor g, Resource connectionJoin, Collection<Resource> excludedConnections) throws DatabaseException {\r
+ return g.syncRequest(new RelatedConnectionsOfConnectionJoin(connectionJoin, excludedConnections));\r
+ }\r
+ \r
+ /**\r
+ * Returns true if the given composite is a parent of some/all components \r
+ * where the connection is attached to.\r
+ */\r
+ public static boolean isConnectionInComposite(ReadGraph g, Resource connection, Resource composite) throws DatabaseException {\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ Collection<Resource> connects = g.getObjects(connection, STR.Connects);\r
+ if (!connects.isEmpty()) {\r
+ for(Resource component : connects)\r
+ for(Resource parent : g.getObjects(component, L0.PartOf))\r
+ if(parent.equals(composite))\r
+ return true;\r
+ } else {\r
+ Set<Resource> joinedComposites = null;\r
+ for(Resource join : g.getObjects(connection, STR.IsJoinedBy)) {\r
+ Collection<Resource> joined = g.getObjects(join, STR.JoinsComposite);\r
+ if (joinedComposites == null) {\r
+ joinedComposites = new THashSet<Resource>(joined);\r
+ } else {\r
+ joinedComposites.retainAll(joined);\r
+ }\r
+ }\r
+ if (joinedComposites != null && joinedComposites.size() == 1) {\r
+ return joinedComposites.contains(composite);\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ public static Variable getConnectionPoint(ReadGraph graph, Variable component, Resource relation) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ String relationName = graph.getRelatedValue(relation, L0.HasName, Bindings.STRING);\r
+ return component.getProperty(graph, relationName);\r
+ }\r
+\r
+ public static Variable getPossibleConnectionPoint(ReadGraph graph, Variable component, Resource relation) throws DatabaseException {\r
+ try {\r
+ return getConnectionPoint(graph, component, relation);\r
+ } catch (MissingVariableException e) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public static Variable getPossibleConnectionTo(ReadGraph graph, Variable component, Resource relation) throws DatabaseException {\r
+ Variable property = component.getPossibleProperty(graph, relation);\r
+ if(property == null) return null;\r
+ Connection conn = property.getPossibleValue(graph);\r
+ if(conn == null) return null;\r
+ Collection<Variable> cps = conn.getConnectionPoints(graph, null);\r
+ if(cps.size() == 2) {\r
+ for(Variable var : cps) {\r
+ if(property.equals(var)) continue;\r
+ return var;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+}\r