-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.structural2.modelingRules;\r
-\r
-\r
-import gnu.trove.set.hash.THashSet;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Set;\r
-\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Statement;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
-import org.simantics.structural2.utils.StructuralUtils;\r
-import org.simantics.utils.strings.AlphanumComparator;\r
-\r
-public class StandardModelingRules extends AbstractModelingRules {\r
-\r
- Layer0 L0;\r
- StructuralResource2 STR;\r
-\r
- public StandardModelingRules(ReadGraph g) {\r
- L0 = Layer0.getInstance(g);\r
- STR = StructuralResource2.getInstance(g);\r
- }\r
-\r
- private ConnectionJudgement judgeConnection(ReadGraph g,\r
- Collection<IConnectionPoint> connectionPoints, boolean allowExisting)\r
- throws DatabaseException {\r
-\r
- // TODO: not a 100% sure if this is safe, will some critical cases break\r
- // in other applications than Apros? Anyway, this by default allows\r
- // any connections without classifiable connection points.\r
- if (connectionPoints.isEmpty()) {\r
- ConnectionJudgement judgement = new ConnectionJudgement(ConnectionJudgementType.LEGAL);\r
- judgement.attachmentRelations = StandardAttachmentRelationMap.INSTANCE;\r
- return judgement;\r
- }\r
-\r
- // Check that connecting to all of the terminals is allowed\r
- if(!allowExisting) {\r
- for(IConnectionPoint cp : connectionPoints) {\r
- if(cp instanceof CPTerminal) {\r
- CPTerminal terminal = (CPTerminal)cp;\r
- if(g.isInstanceOf(terminal.relation, L0.FunctionalRelation)) {\r
- if(terminal.component == null)\r
- continue;\r
- if (g.hasStatement(terminal.component, terminal.relation)) {\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println(terminal.toString(g) + " failed FunctionalRelation test -> ILLEGAL");\r
- return ConnectionJudgement.ILLEGAL;\r
- }\r
- for(Resource eqRelation : g.getObjects(terminal.relation, STR.ConnectionRelation_equivalentConnectionPoint))\r
- if (g.hasStatement(terminal.component, eqRelation)) {\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println(terminal.toString(g) + " failed FunctionalRelation test of equivalent connection point -> ILLEGAL");\r
- return ConnectionJudgement.ILLEGAL;\r
- } \r
- }\r
- }\r
- }\r
- }\r
- \r
- // Translate all connection points to terminals\r
- Set<CPTerminal> terminals = resolveTerminals(g, connectionPoints);\r
- \r
- // If there is a single default connection type that all connection\r
- // points agree on, it will be stored here. It will be used if there\r
- // is no single unambiguous connection type \r
- Resource defaultConnectionType = null;\r
- boolean singleDefaultConnectionType = false;\r
-\r
- // Determine the set of connection types all connection points accept\r
- Collection<Set<Resource>> typeSets = new ArrayList<Set<Resource>>();\r
- for(CPTerminal terminal : terminals) {\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println(this + ": allowed connection types determination: " + terminal.toString(g) + " " + terminal.relation);\r
- Collection<Resource> allowedConnectionTypes = g.syncRequest(new AllowedConnectionTypes(terminal.relation));\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- for (Resource type : allowedConnectionTypes)\r
- System.out.println("\tallowedConnectionType: " + NameUtils.getSafeName(g, type, true));\r
- typeSets.add(new THashSet<Resource>(allowedConnectionTypes));\r
-\r
- // Default connection type calculation\r
- Resource defaultsTo = g.getPossibleObject(terminal.relation, STR.DefaultsToConnectionType);\r
- if (defaultsTo != null) {\r
- if (defaultConnectionType == null) {\r
- defaultConnectionType = defaultsTo;\r
- singleDefaultConnectionType = true;\r
- } else if (!defaultsTo.equals(defaultConnectionType)) {\r
- singleDefaultConnectionType = false;\r
- }\r
- }\r
- }\r
- \r
- Collection<Resource> connectionTypes = getAllowedConnectionTypes(g, typeSets);\r
- \r
- if(connectionTypes == null) {\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println("No connection types -> CANBEMADELEGAL");\r
- return ConnectionJudgement.CANBEMADELEGAL;\r
- }\r
-\r
- // Validate connection types\r
- Resource possibleConnectionType = null;\r
- Resource chosenConnectionType = null;\r
- String chosenConnectionTypeName = null;\r
- connectionTypeLoop:\r
- for(Resource connectionType : connectionTypes) {\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println("Check constraints for " + NameUtils.getSafeName(g, connectionType));\r
-\r
- switch (evaluateConstraints(g, connectionType, terminals)) {\r
- case ILLEGAL:\r
- continue connectionTypeLoop;\r
-\r
- case CANBEMADELEGAL:\r
- possibleConnectionType = connectionType;\r
- break;\r
-\r
- case LEGAL:\r
- if (chosenConnectionType != null) {\r
- if (singleDefaultConnectionType) {\r
- chosenConnectionType = defaultConnectionType;\r
- break connectionTypeLoop;\r
- }\r
- // There is no single unambiguous legal connection type.\r
- // Make a deterministic choice out of the available types\r
- // based on their names. Select that connection type placed\r
- // first in ascending lexicograpical order. \r
- if (chosenConnectionTypeName == null)\r
- chosenConnectionTypeName = NameUtils.getSafeName(g, chosenConnectionType);\r
- String connectionTypeName = NameUtils.getSafeName(g, connectionType);\r
- if (AlphanumComparator.COMPARATOR.compare(chosenConnectionTypeName, connectionTypeName) > 0) {\r
- chosenConnectionType = connectionType;\r
- chosenConnectionTypeName = connectionTypeName;\r
- }\r
- } else {\r
- chosenConnectionType = connectionType;\r
- }\r
- }\r
- }\r
- \r
- // Create result\r
- if(chosenConnectionType != null) {\r
- ConnectionJudgement judgement = new ConnectionJudgement(chosenConnectionType);\r
- judgement.attachmentRelations = StandardAttachmentRelationMap.INSTANCE;\r
- return judgement;\r
- }\r
- else if(possibleConnectionType != null) {\r
- ConnectionJudgement judgement = new ConnectionJudgement(\r
- ConnectionJudgementType.CANBEMADELEGAL, possibleConnectionType);\r
- judgement.attachmentRelations = StandardAttachmentRelationMap.INSTANCE;\r
- return judgement;\r
- }\r
- else\r
- return ConnectionJudgement.ILLEGAL;\r
- }\r
-\r
- private Collection<Resource> getAllowedConnectionTypes(ReadGraph graph, Collection<Set<Resource>> typeSets) throws DatabaseException {\r
- \r
- // Preprocess sets according to STR.IsIncludedInConnectionType\r
- Set<Resource> all = new THashSet<Resource>();\r
- for(Set<Resource> s : typeSets) all.addAll(s);\r
- for(Resource r : all)\r
- for(Resource inc : graph.getObjects(r, STR.IsIncludedInConnectionType))\r
- for(Set<Resource> s : typeSets)\r
- if(s.contains(inc)) s.add(r);\r
- \r
- ArrayList<Resource> connectionTypes = null;\r
- for(Set<Resource> allowedConnectionTypes : typeSets) {\r
- if(!allowedConnectionTypes.isEmpty()) {\r
- if(connectionTypes == null)\r
- connectionTypes = new ArrayList<Resource>(allowedConnectionTypes);\r
- else\r
- connectionTypes.retainAll(allowedConnectionTypes);\r
- }\r
- }\r
-\r
- return connectionTypes;\r
- \r
- }\r
-\r
- private ConnectionJudgementType evaluateConstraints(ReadGraph g, Resource connectionType, Set<CPTerminal> terminals) throws DatabaseException {\r
- boolean legal = true;\r
- for (Resource constraint : g.getObjects(connectionType, STR.HasConnectionConstraint)) {\r
- IConnectionConstraint cc = g.adapt(constraint, IConnectionConstraint.class);\r
- switch(cc.isLegal(g, terminals)) {\r
- case ILLEGAL:\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println(" " + cc.getClass().getSimpleName() +\r
- " -> ILLEGAL");\r
- return ConnectionJudgementType.ILLEGAL;\r
- case CANBEMADELEGAL:\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println(" " + cc.getClass().getSimpleName() +\r
- " -> CANBEMADELEGAL");\r
- legal = false;\r
- default:\r
- break;\r
- }\r
- }\r
- return legal ? ConnectionJudgementType.LEGAL : ConnectionJudgementType.CANBEMADELEGAL;\r
- }\r
-\r
- @Override\r
- public ConnectionJudgement judgeConnection(ReadGraph g,\r
- Collection<IConnectionPoint> connectionPoints)\r
- throws DatabaseException {\r
- \r
- return judgeConnection(g, connectionPoints, false);\r
- \r
- }\r
-\r
- @Override\r
- public Resource computeConnectionType(ReadGraph g,\r
- Collection<IConnectionPoint> connectionPoints)\r
- throws DatabaseException {\r
-\r
- return judgeConnection(g, connectionPoints, true).connectionType;\r
- \r
- }\r
- \r
- @Override\r
- public IAttachmentRelationMap getAttachmentRelations(ReadGraph g,\r
- Resource connection) {\r
- return StandardAttachmentRelationMap.INSTANCE;\r
- }\r
-\r
- @Override\r
- public Set<CPTerminal> resolveTerminals(ReadGraph g, Collection<IConnectionPoint> connectionPoints) \r
- throws DatabaseException {\r
- Set<CPTerminal> terminals = new THashSet<CPTerminal>();\r
- StructuralResource2 STR = StructuralResource2.getInstance(g);\r
- for(IConnectionPoint cp : connectionPoints) {\r
- if(Policy.DEBUG_STANDARD_MODELING_RULES)\r
- System.out.println(this + ": translate connection point: " + cp.toString(g));\r
- if(cp instanceof CPTerminal)\r
- terminals.add((CPTerminal)cp);\r
- else if(cp instanceof CPConnection) {\r
- CPConnection connection = (CPConnection)cp;\r
- for (Resource c : StructuralUtils.getRelatedConnections(g, connection.connection)) {\r
- for (Statement stat : g.getStatements(c, STR.Connects))\r
- terminals.add(new CPTerminal(stat.getObject(),\r
- g.getInverse(stat.getPredicate())));\r
- Resource inf = g.getPossibleObject(c, STR.Binds);\r
- // TODO: figure out a better component\r
- if(inf != null) terminals.add(new CPTerminal(inf, inf));\r
- }\r
- }\r
- else if(cp instanceof CPConnectionJoin) {\r
- CPConnectionJoin connectionJoin = (CPConnectionJoin)cp;\r
- for (Resource c : StructuralUtils.getRelatedConnectionsOfConnectionJoin(g, connectionJoin.connectionJoin))\r
- for (Statement stat : g.getStatements(c, STR.Connects))\r
- terminals.add(new CPTerminal(stat.getObject(),\r
- g.getInverse(stat.getPredicate())));\r
- }\r
- else\r
- throw new IllegalArgumentException("Connection point " + cp + " encountered.");\r
- }\r
- \r
- return terminals;\r
- \r
- }\r
- \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.structural2.modelingRules;
+
+
+import gnu.trove.set.hash.THashSet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Statement;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.layer0.Layer0;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.structural2.utils.StructuralUtils;
+import org.simantics.utils.strings.AlphanumComparator;
+
+public class StandardModelingRules extends AbstractModelingRules {
+
+ Layer0 L0;
+ StructuralResource2 STR;
+
+ public StandardModelingRules(ReadGraph g) {
+ L0 = Layer0.getInstance(g);
+ STR = StructuralResource2.getInstance(g);
+ }
+
+ private ConnectionJudgement judgeConnection(ReadGraph g,
+ Collection<IConnectionPoint> connectionPoints, boolean allowExisting)
+ throws DatabaseException {
+
+ // TODO: not a 100% sure if this is safe, will some critical cases break
+ // in other applications than Apros? Anyway, this by default allows
+ // any connections without classifiable connection points.
+ if (connectionPoints.isEmpty()) {
+ ConnectionJudgement judgement = new ConnectionJudgement(ConnectionJudgementType.LEGAL);
+ judgement.attachmentRelations = StandardAttachmentRelationMap.INSTANCE;
+ return judgement;
+ }
+
+ // Check that connecting to all of the terminals is allowed
+ if(!allowExisting) {
+ for(IConnectionPoint cp : connectionPoints) {
+ if(cp instanceof CPTerminal) {
+ CPTerminal terminal = (CPTerminal)cp;
+ if(g.isInstanceOf(terminal.relation, L0.FunctionalRelation)) {
+ if(terminal.component == null)
+ continue;
+ if (g.hasStatement(terminal.component, terminal.relation)) {
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println(terminal.toString(g) + " failed FunctionalRelation test -> ILLEGAL");
+ return ConnectionJudgement.ILLEGAL;
+ }
+ for(Resource eqRelation : g.getObjects(terminal.relation, STR.ConnectionRelation_equivalentConnectionPoint))
+ if (g.hasStatement(terminal.component, eqRelation)) {
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println(terminal.toString(g) + " failed FunctionalRelation test of equivalent connection point -> ILLEGAL");
+ return ConnectionJudgement.ILLEGAL;
+ }
+ }
+ }
+ }
+ }
+
+ // Translate all connection points to terminals
+ Set<CPTerminal> terminals = resolveTerminals(g, connectionPoints);
+
+ // If there is a single default connection type that all connection
+ // points agree on, it will be stored here. It will be used if there
+ // is no single unambiguous connection type
+ Resource defaultConnectionType = null;
+ boolean singleDefaultConnectionType = false;
+
+ // Determine the set of connection types all connection points accept
+ Collection<Set<Resource>> typeSets = new ArrayList<Set<Resource>>();
+ for(CPTerminal terminal : terminals) {
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println(this + ": allowed connection types determination: " + terminal.toString(g) + " " + terminal.relation);
+ Collection<Resource> allowedConnectionTypes = g.syncRequest(new AllowedConnectionTypes(terminal.relation));
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ for (Resource type : allowedConnectionTypes)
+ System.out.println("\tallowedConnectionType: " + NameUtils.getSafeName(g, type, true));
+ typeSets.add(new THashSet<Resource>(allowedConnectionTypes));
+
+ // Default connection type calculation
+ Resource defaultsTo = g.getPossibleObject(terminal.relation, STR.DefaultsToConnectionType);
+ if (defaultsTo != null) {
+ if (defaultConnectionType == null) {
+ defaultConnectionType = defaultsTo;
+ singleDefaultConnectionType = true;
+ } else if (!defaultsTo.equals(defaultConnectionType)) {
+ singleDefaultConnectionType = false;
+ }
+ }
+ }
+
+ Collection<Resource> connectionTypes = getAllowedConnectionTypes(g, typeSets);
+
+ if(connectionTypes == null) {
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println("No connection types -> CANBEMADELEGAL");
+ return ConnectionJudgement.CANBEMADELEGAL;
+ }
+
+ // Validate connection types
+ Resource possibleConnectionType = null;
+ Resource chosenConnectionType = null;
+ String chosenConnectionTypeName = null;
+ connectionTypeLoop:
+ for(Resource connectionType : connectionTypes) {
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println("Check constraints for " + NameUtils.getSafeName(g, connectionType));
+
+ switch (evaluateConstraints(g, connectionType, terminals)) {
+ case ILLEGAL:
+ continue connectionTypeLoop;
+
+ case CANBEMADELEGAL:
+ possibleConnectionType = connectionType;
+ break;
+
+ case LEGAL:
+ if (chosenConnectionType != null) {
+ if (singleDefaultConnectionType) {
+ chosenConnectionType = defaultConnectionType;
+ break connectionTypeLoop;
+ }
+ // There is no single unambiguous legal connection type.
+ // Make a deterministic choice out of the available types
+ // based on their names. Select that connection type placed
+ // first in ascending lexicograpical order.
+ if (chosenConnectionTypeName == null)
+ chosenConnectionTypeName = NameUtils.getSafeName(g, chosenConnectionType);
+ String connectionTypeName = NameUtils.getSafeName(g, connectionType);
+ if (AlphanumComparator.COMPARATOR.compare(chosenConnectionTypeName, connectionTypeName) > 0) {
+ chosenConnectionType = connectionType;
+ chosenConnectionTypeName = connectionTypeName;
+ }
+ } else {
+ chosenConnectionType = connectionType;
+ }
+ }
+ }
+
+ // Create result
+ if(chosenConnectionType != null) {
+ ConnectionJudgement judgement = new ConnectionJudgement(chosenConnectionType);
+ judgement.attachmentRelations = StandardAttachmentRelationMap.INSTANCE;
+ return judgement;
+ }
+ else if(possibleConnectionType != null) {
+ ConnectionJudgement judgement = new ConnectionJudgement(
+ ConnectionJudgementType.CANBEMADELEGAL, possibleConnectionType);
+ judgement.attachmentRelations = StandardAttachmentRelationMap.INSTANCE;
+ return judgement;
+ }
+ else
+ return ConnectionJudgement.ILLEGAL;
+ }
+
+ private Collection<Resource> getAllowedConnectionTypes(ReadGraph graph, Collection<Set<Resource>> typeSets) throws DatabaseException {
+
+ // Preprocess sets according to STR.IsIncludedInConnectionType
+ Set<Resource> all = new THashSet<Resource>();
+ for(Set<Resource> s : typeSets) all.addAll(s);
+ for(Resource r : all)
+ for(Resource inc : graph.getObjects(r, STR.IsIncludedInConnectionType))
+ for(Set<Resource> s : typeSets)
+ if(s.contains(inc)) s.add(r);
+
+ ArrayList<Resource> connectionTypes = null;
+ for(Set<Resource> allowedConnectionTypes : typeSets) {
+ if(!allowedConnectionTypes.isEmpty()) {
+ if(connectionTypes == null)
+ connectionTypes = new ArrayList<Resource>(allowedConnectionTypes);
+ else
+ connectionTypes.retainAll(allowedConnectionTypes);
+ }
+ }
+
+ return connectionTypes;
+
+ }
+
+ private ConnectionJudgementType evaluateConstraints(ReadGraph g, Resource connectionType, Set<CPTerminal> terminals) throws DatabaseException {
+ boolean legal = true;
+ for (Resource constraint : g.getObjects(connectionType, STR.HasConnectionConstraint)) {
+ IConnectionConstraint cc = g.adapt(constraint, IConnectionConstraint.class);
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println("Checking " + cc.getClass().getSimpleName());
+ switch(cc.isLegal(g, terminals)) {
+ case ILLEGAL:
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println(" " + cc.getClass().getSimpleName() +
+ " -> ILLEGAL");
+ return ConnectionJudgementType.ILLEGAL;
+ case CANBEMADELEGAL:
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println(" " + cc.getClass().getSimpleName() +
+ " -> CANBEMADELEGAL");
+ legal = false;
+ default:
+ break;
+ }
+ }
+ return legal ? ConnectionJudgementType.LEGAL : ConnectionJudgementType.CANBEMADELEGAL;
+ }
+
+ @Override
+ public ConnectionJudgement judgeConnection(ReadGraph g,
+ Collection<IConnectionPoint> connectionPoints)
+ throws DatabaseException {
+
+ return judgeConnection(g, connectionPoints, false);
+
+ }
+
+ @Override
+ public Resource computeConnectionType(ReadGraph g,
+ Collection<IConnectionPoint> connectionPoints)
+ throws DatabaseException {
+
+ return judgeConnection(g, connectionPoints, true).connectionType;
+
+ }
+
+ @Override
+ public IAttachmentRelationMap getAttachmentRelations(ReadGraph g,
+ Resource connection) {
+ return StandardAttachmentRelationMap.INSTANCE;
+ }
+
+ @Override
+ public Set<CPTerminal> resolveTerminals(ReadGraph g, Collection<IConnectionPoint> connectionPoints)
+ throws DatabaseException {
+ Set<CPTerminal> terminals = new THashSet<CPTerminal>();
+ StructuralResource2 STR = StructuralResource2.getInstance(g);
+ for(IConnectionPoint cp : connectionPoints) {
+ if(Policy.DEBUG_STANDARD_MODELING_RULES)
+ System.out.println(this + ": translate connection point: " + cp.toString(g));
+ if(cp instanceof CPTerminal)
+ terminals.add((CPTerminal)cp);
+ else if(cp instanceof CPConnection) {
+ CPConnection connection = (CPConnection)cp;
+ for (Resource c : StructuralUtils.getRelatedConnections(g, connection.connection)) {
+ for (Statement stat : g.getStatements(c, STR.Connects))
+ terminals.add(new CPTerminal(stat.getObject(),
+ g.getInverse(stat.getPredicate())));
+ Resource inf = g.getPossibleObject(c, STR.Binds);
+ // TODO: figure out a better component
+ if(inf != null) terminals.add(new CPTerminal(inf, inf));
+ }
+ }
+ else if(cp instanceof CPConnectionJoin) {
+ CPConnectionJoin connectionJoin = (CPConnectionJoin)cp;
+ for (Resource c : StructuralUtils.getRelatedConnectionsOfConnectionJoin(g, connectionJoin.connectionJoin))
+ for (Statement stat : g.getStatements(c, STR.Connects))
+ terminals.add(new CPTerminal(stat.getObject(),
+ g.getInverse(stat.getPredicate())));
+ }
+ else
+ throw new IllegalArgumentException("Connection point " + cp + " encountered.");
+ }
+
+ return terminals;
+
+ }
+
+}