]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/rules/MappedModelingRules.java
Handle componentless parent nodes of UCs in synchronization
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / rules / MappedModelingRules.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2014 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *     Semantum Oy - #5290
12  *******************************************************************************/
13 package org.simantics.modeling.rules;
14
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.HashSet;
18 import java.util.Set;
19
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;
41
42 public class MappedModelingRules extends AbstractModelingRules {
43
44     private static final Logger LOGGER = LoggerFactory.getLogger(MappedModelingRules.class);
45     IModelingRules baseRules;
46     IMapping mapping;
47
48     public MappedModelingRules(IModelingRules baseRules, IMapping mapping) {
49         super();
50         this.baseRules = baseRules;
51         this.mapping = mapping;
52     }
53
54     public MappedModelingRules(ReadGraph g, IModelingRules baseRules) throws DatabaseException {
55         this(baseRules, new Mapping(g));
56     }
57
58     @Override
59     public boolean canPopulate(ReadGraph g, Resource componentType)
60     throws DatabaseException {
61         Resource mappedComponentType = mapping.mapComponentType(g, componentType);
62         if(mappedComponentType == null)
63             return false;
64         return baseRules.canPopulate(g, mappedComponentType);
65     }
66
67     @Override
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);
73
74         if(Policy.DEBUG_STANDARD_MODELING_RULES)
75             LOGGER.info("setConnectionType(" + NameUtils.getSafeName(g, connection) + ", " + NameUtils.getSafeName(g, connectionType) + ")");
76
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);
82         }
83
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))
90                         continue;
91                     Resource dcp  = g.getPossibleInverse(connects.getPredicate());
92                     if (dcp != null) {
93                         Resource cp = g.getPossibleObject(dcp, MOD.DiagramConnectionRelationToConnectionRelation);
94                         if (cp != null) {
95                             g.deny(connector, MOD.HasConnectionMappingSpecification);
96                             if (requiredConnectionMappingSpecification != null && g.hasStatement(cp, MOD.NeedsConnectionMappingSpecification)) {
97                                 g.claim(connector, MOD.HasConnectionMappingSpecification, requiredConnectionMappingSpecification);
98                             }
99                         }
100                     }
101                 }
102             }
103         }
104     }
105
106     class MappedAttachmentRelationMap implements IAttachmentRelationMap {
107
108         IAttachmentRelationMap baseMap;
109
110         public MappedAttachmentRelationMap(IAttachmentRelationMap baseMap) {
111             this.baseMap = baseMap;
112         }
113
114         @Override
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);
120             else
121                 return null;
122         }
123
124     }
125     
126     private ArrayList<IConnectionPoint> getMappedConnectionPoints(ReadGraph g,
127                 Collection<IConnectionPoint> connectionPoints)
128                             throws DatabaseException {
129
130         // Map connection points to configuration
131         ArrayList<IConnectionPoint> mappedConnectionPoints =
132                 new ArrayList<IConnectionPoint>(connectionPoints.size());
133         
134          // Map connection points to configuration
135         for(IConnectionPoint cp : connectionPoints) {
136             if(cp == null)
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);
141             if(mcps > 0) {
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));
145             } else {
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))
152                             return null;
153                         for(Resource join : g.getObjects(terminal.component, dr.FlagIsJoinedBy))
154                             mappedConnectionPoints.add(new CPConnectionJoin(join));
155                         
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));
160                         } else {
161                             // Do nothing, because the flag is not connected
162                         }
163                     }
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));
173                 }
174                 else
175                     return null;
176             }
177         }
178         
179         return mappedConnectionPoints;
180         
181     }
182     
183     @Override
184     public ConnectionJudgement judgeConnection(ReadGraph g, Collection<IConnectionPoint> connectionPoints)
185                 throws DatabaseException {
186
187         ArrayList<IConnectionPoint> mappedConnectionPoints = getMappedConnectionPoints(g, connectionPoints);
188         if(mappedConnectionPoints == null) return ConnectionJudgement.ILLEGAL; 
189
190         // Judge mapped connection
191         ConnectionJudgement judgement = baseRules.judgeConnection(g, mappedConnectionPoints);
192
193         // Inverse map attachment relations
194         if(judgement.attachmentRelations != null)
195             judgement.attachmentRelations =
196                 new MappedAttachmentRelationMap(judgement.attachmentRelations);
197
198         return judgement;
199         
200     }
201     
202     @Override
203     public Resource computeConnectionType(ReadGraph g, Collection<IConnectionPoint> connectionPoints) throws DatabaseException {
204         
205         ArrayList<IConnectionPoint> mappedConnectionPoints = getMappedConnectionPoints(g, connectionPoints);
206         if(mappedConnectionPoints == null) return null;
207         
208         return baseRules.computeConnectionType(g, mappedConnectionPoints);
209         
210     }
211
212     @Override
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)
220         );
221     }
222     
223         @Override
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())));
240                                         }
241                                 }
242                         }
243                         else
244                                 throw new IllegalArgumentException("Connection point " + cp + " encountered.");
245                 }
246                 return terminals;
247         }
248
249 }