1 /*******************************************************************************
2 * Copyright (c) 2007, 2014 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
12 *******************************************************************************/
13 package org.simantics.modeling.rules;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.HashSet;
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.Resource;
22 import org.simantics.db.Statement;
23 import org.simantics.db.WriteGraph;
24 import org.simantics.db.common.utils.NameUtils;
25 import org.simantics.db.exception.DatabaseException;
26 import org.simantics.diagram.stubs.DiagramResource;
27 import org.simantics.modeling.ModelingResources;
28 import org.simantics.structural.stubs.StructuralResource2;
29 import org.simantics.structural2.modelingRules.AbstractModelingRules;
30 import org.simantics.structural2.modelingRules.CPConnection;
31 import org.simantics.structural2.modelingRules.CPConnectionJoin;
32 import org.simantics.structural2.modelingRules.CPIgnore;
33 import org.simantics.structural2.modelingRules.CPTerminal;
34 import org.simantics.structural2.modelingRules.ConnectionJudgement;
35 import org.simantics.structural2.modelingRules.IAttachmentRelationMap;
36 import org.simantics.structural2.modelingRules.IConnectionPoint;
37 import org.simantics.structural2.modelingRules.IModelingRules;
38 import org.simantics.structural2.modelingRules.Policy;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 public class MappedModelingRules extends AbstractModelingRules {
44 private static final Logger LOGGER = LoggerFactory.getLogger(MappedModelingRules.class);
45 IModelingRules baseRules;
48 public MappedModelingRules(IModelingRules baseRules, IMapping mapping) {
50 this.baseRules = baseRules;
51 this.mapping = mapping;
54 public MappedModelingRules(ReadGraph g, IModelingRules baseRules) throws DatabaseException {
55 this(baseRules, new Mapping(g));
59 public boolean canPopulate(ReadGraph g, Resource componentType)
60 throws DatabaseException {
61 Resource mappedComponentType = mapping.mapComponentType(g, componentType);
62 if(mappedComponentType == null)
64 return baseRules.canPopulate(g, mappedComponentType);
68 public void setConnectionType(WriteGraph g, Resource connection,
69 Resource connectionType) throws DatabaseException {
70 StructuralResource2 sr = StructuralResource2.getInstance(g);
71 DiagramResource DIA = DiagramResource.getInstance(g);
72 ModelingResources MOD = ModelingResources.getInstance(g);
74 if(Policy.DEBUG_STANDARD_MODELING_RULES)
75 LOGGER.info("setConnectionType(" + NameUtils.getSafeName(g, connection) + ", " + NameUtils.getSafeName(g, connectionType) + ")");
77 RelatedDiagramConnections rdc = new RelatedDiagramConnections(g);
78 rdc.addConnection(connection);
79 for(Resource c : rdc.connections) {
80 g.deny(c, sr.HasConnectionType);
81 g.claim(c, sr.HasConnectionType, null, connectionType);
84 // Fix MOD.HasConnectionMappingSpecification in output connector(s).
85 if (!rdc.outputConnectors.isEmpty()) {
86 Resource requiredConnectionMappingSpecification = g.getPossibleObject(connectionType, MOD.ConnectionTypeToConnectionMappingSpecification);
87 for (Resource connector : rdc.outputConnectors) {
88 for (Statement connects : g.getStatements(connector, sr.Connects)) {
89 if (g.isInstanceOf(connects.getObject(), DIA.Connection))
91 Resource dcp = g.getPossibleInverse(connects.getPredicate());
93 Resource cp = g.getPossibleObject(dcp, MOD.DiagramConnectionRelationToConnectionRelation);
95 g.deny(connector, MOD.HasConnectionMappingSpecification);
96 if (requiredConnectionMappingSpecification != null && g.hasStatement(cp, MOD.NeedsConnectionMappingSpecification)) {
97 g.claim(connector, MOD.HasConnectionMappingSpecification, requiredConnectionMappingSpecification);
106 class MappedAttachmentRelationMap implements IAttachmentRelationMap {
108 IAttachmentRelationMap baseMap;
110 public MappedAttachmentRelationMap(IAttachmentRelationMap baseMap) {
111 this.baseMap = baseMap;
115 public Resource get(ReadGraph g, CPTerminal cp)
116 throws DatabaseException {
117 IConnectionPoint mcp = mapping.mapConnectionPoint(g, cp);
118 if(mcp instanceof CPTerminal)
119 return baseMap.get(g, (CPTerminal)mcp);
126 private ArrayList<IConnectionPoint> getMappedConnectionPoints(ReadGraph g,
127 Collection<IConnectionPoint> connectionPoints)
128 throws DatabaseException {
130 // Map connection points to configuration
131 ArrayList<IConnectionPoint> mappedConnectionPoints =
132 new ArrayList<IConnectionPoint>(connectionPoints.size());
134 // Map connection points to configuration
135 for(IConnectionPoint cp : connectionPoints) {
137 throw new IllegalArgumentException("Null connection point encountered.");
138 if(Policy.DEBUG_STANDARD_MODELING_RULES)
139 LOGGER.info("Mapping CP: " + cp.toString(g));
140 int mcps = mapping.mapToConnectionPoints(g, cp, mappedConnectionPoints);
142 if(Policy.DEBUG_STANDARD_MODELING_RULES)
143 for (IConnectionPoint mcpt : mappedConnectionPoints.subList(mappedConnectionPoints.size()-mcps, mappedConnectionPoints.size()))
144 LOGGER.info("Mapped CP: " + mcpt.toString(g));
146 if(cp instanceof CPTerminal) {
147 // TODO move this logic elsewhere
148 CPTerminal terminal = (CPTerminal)cp;
149 DiagramResource dr = DiagramResource.getInstance(g);
150 if(terminal.component != null && g.isInstanceOf(terminal.component, dr.Flag)) {
151 if(g.hasStatement(terminal.component, dr.Flag_ConnectionPoint))
153 for(Resource join : g.getObjects(terminal.component, dr.FlagIsJoinedBy))
154 mappedConnectionPoints.add(new CPConnectionJoin(join));
156 Resource isLiftedAs = g.getPossibleObject(terminal.component, dr.IsLiftedAs);
157 if (isLiftedAs != null) {
158 // This is a lifted flag in a structural configuration.
159 mappedConnectionPoints.add(new CPTerminal(terminal.component, isLiftedAs));
161 // Do nothing, because the flag is not connected
164 } else if (cp instanceof CPConnection) {
165 // Do nothing, because ignored connection points are not
166 // meant to affect modelling rules in any way.
167 //System.out.println("Non-mappable connection " + cp.toString(g));
168 } else if (cp instanceof CPIgnore) {
169 // Do nothing, because ignored connection points are not
170 // meant to affect modelling rules in any way.
171 // FIXME: this is maybe a bit of a hack.
172 //System.out.println("Ignoring " + cp.toString(g));
179 return mappedConnectionPoints;
184 public ConnectionJudgement judgeConnection(ReadGraph g, Collection<IConnectionPoint> connectionPoints)
185 throws DatabaseException {
187 ArrayList<IConnectionPoint> mappedConnectionPoints = getMappedConnectionPoints(g, connectionPoints);
188 if(mappedConnectionPoints == null) return ConnectionJudgement.ILLEGAL;
190 // Judge mapped connection
191 ConnectionJudgement judgement = baseRules.judgeConnection(g, mappedConnectionPoints);
193 // Inverse map attachment relations
194 if(judgement.attachmentRelations != null)
195 judgement.attachmentRelations =
196 new MappedAttachmentRelationMap(judgement.attachmentRelations);
203 public Resource computeConnectionType(ReadGraph g, Collection<IConnectionPoint> connectionPoints) throws DatabaseException {
205 ArrayList<IConnectionPoint> mappedConnectionPoints = getMappedConnectionPoints(g, connectionPoints);
206 if(mappedConnectionPoints == null) return null;
208 return baseRules.computeConnectionType(g, mappedConnectionPoints);
213 public IAttachmentRelationMap getAttachmentRelations(ReadGraph g,
214 Resource connection) throws DatabaseException {
215 Resource mappedConnection = mapping.mapConnection(g, connection);
216 if(mappedConnection == null)
217 LOGGER.warn("Connection mapped from " + NameUtils.getSafeName(g, connection, true) + " is null");
218 return new MappedAttachmentRelationMap(
219 baseRules.getAttachmentRelations(g, mappedConnection)
224 public Set<CPTerminal> resolveTerminals(ReadGraph g, Collection<IConnectionPoint> connectionPoints)
225 throws DatabaseException {
226 Set<CPTerminal> terminals = new HashSet<CPTerminal>();
227 StructuralResource2 STR = StructuralResource2.getInstance(g);
228 DiagramResource DIA = DiagramResource.getInstance(g);
229 for(IConnectionPoint cp : connectionPoints) {
230 //System.out.println(this + ": translate connection point: " + cp.toString(g));
231 if(cp instanceof CPTerminal)
232 terminals.add((CPTerminal)cp);
233 else if(cp instanceof CPConnection) {
234 CPConnection connection = (CPConnection)cp;
235 for (Resource connector : g.getObjects(connection.connection, DIA.HasConnector)) {
236 for (Statement stat : g.getStatements(connector, STR.Connects)) {
237 if(stat.getObject().equals(connection.connection)) continue;
238 terminals.add(new CPTerminal(stat.getObject(),
239 g.getInverse(stat.getPredicate())));
244 throw new IllegalArgumentException("Connection point " + cp + " encountered.");