]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/rules/MappedModelingRules.java
a47a1b63f580a80fc94b389d2557ee50b9238c94
[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
40 public class MappedModelingRules extends AbstractModelingRules {
41
42     IModelingRules baseRules;
43     IMapping mapping;
44
45     public MappedModelingRules(IModelingRules baseRules, IMapping mapping) {
46         super();
47         this.baseRules = baseRules;
48         this.mapping = mapping;
49     }
50
51     public MappedModelingRules(ReadGraph g, IModelingRules baseRules) throws DatabaseException {
52         this(baseRules, new Mapping(g));
53     }
54
55     @Override
56     public boolean canPopulate(ReadGraph g, Resource componentType)
57     throws DatabaseException {
58         Resource mappedComponentType = mapping.mapComponentType(g, componentType);
59         if(mappedComponentType == null)
60             return false;
61         return baseRules.canPopulate(g, mappedComponentType);
62     }
63
64     @Override
65     public void setConnectionType(WriteGraph g, Resource connection,
66             Resource connectionType) throws DatabaseException {
67         StructuralResource2 sr = StructuralResource2.getInstance(g);
68         DiagramResource DIA = DiagramResource.getInstance(g); 
69         ModelingResources MOD = ModelingResources.getInstance(g);
70
71         if(Policy.DEBUG_STANDARD_MODELING_RULES)
72             System.out.println("setConnectionType(" + NameUtils.getSafeName(g, connection) + ", " + NameUtils.getSafeName(g, connectionType) + ")");
73
74         RelatedDiagramConnections rdc = new RelatedDiagramConnections(g);
75         rdc.addConnection(connection);
76         for(Resource c : rdc.connections) {
77             g.deny(c, sr.HasConnectionType);
78             g.claim(c, sr.HasConnectionType, null, connectionType);
79         }
80
81         // Fix MOD.HasConnectionMappingSpecification in output connector(s).
82         if (!rdc.outputConnectors.isEmpty()) {
83             Resource requiredConnectionMappingSpecification = g.getPossibleObject(connectionType, MOD.ConnectionTypeToConnectionMappingSpecification);
84             for (Resource connector : rdc.outputConnectors) {
85                 for (Statement connects : g.getStatements(connector, sr.Connects)) {
86                     if (g.isInstanceOf(connects.getObject(), DIA.Connection))
87                         continue;
88                     Resource dcp  = g.getPossibleInverse(connects.getPredicate());
89                     if (dcp != null) {
90                         Resource cp = g.getPossibleObject(dcp, MOD.DiagramConnectionRelationToConnectionRelation);
91                         if (cp != null) {
92                             g.deny(connector, MOD.HasConnectionMappingSpecification);
93                             if (requiredConnectionMappingSpecification != null && g.hasStatement(cp, MOD.NeedsConnectionMappingSpecification)) {
94                                 g.claim(connector, MOD.HasConnectionMappingSpecification, requiredConnectionMappingSpecification);
95                             }
96                         }
97                     }
98                 }
99             }
100         }
101     }
102
103     class MappedAttachmentRelationMap implements IAttachmentRelationMap {
104
105         IAttachmentRelationMap baseMap;
106
107         public MappedAttachmentRelationMap(IAttachmentRelationMap baseMap) {
108             this.baseMap = baseMap;
109         }
110
111         @Override
112         public Resource get(ReadGraph g, CPTerminal cp)
113         throws DatabaseException {
114             IConnectionPoint mcp = mapping.mapConnectionPoint(g, cp);
115             if(mcp instanceof CPTerminal)
116                 return baseMap.get(g, (CPTerminal)mcp);
117             else
118                 return null;
119         }
120
121     }
122     
123     private ArrayList<IConnectionPoint> getMappedConnectionPoints(ReadGraph g,
124                 Collection<IConnectionPoint> connectionPoints)
125                             throws DatabaseException {
126
127         // Map connection points to configuration
128         ArrayList<IConnectionPoint> mappedConnectionPoints =
129                 new ArrayList<IConnectionPoint>(connectionPoints.size());
130         
131          // Map connection points to configuration
132         for(IConnectionPoint cp : connectionPoints) {
133             if(cp == null)
134                 throw new IllegalArgumentException("Null connection point encountered.");
135             if(Policy.DEBUG_STANDARD_MODELING_RULES)
136                 System.out.println("Mapping CP: " + cp.toString(g));
137             int mcps = mapping.mapToConnectionPoints(g, cp, mappedConnectionPoints);
138             if(mcps > 0) {
139                 if(Policy.DEBUG_STANDARD_MODELING_RULES)
140                     for (IConnectionPoint mcpt : mappedConnectionPoints.subList(mappedConnectionPoints.size()-mcps, mappedConnectionPoints.size()))
141                         System.out.println("Mapped CP: " + mcpt.toString(g));
142             } else {
143                 if(cp instanceof CPTerminal) {
144                     // TODO move this logic elsewhere
145                     CPTerminal terminal = (CPTerminal)cp;
146                     DiagramResource dr = DiagramResource.getInstance(g);
147                     if(terminal.component != null && g.isInstanceOf(terminal.component, dr.Flag)) {
148                         if(g.hasStatement(terminal.component, dr.Flag_ConnectionPoint))
149                             return null;
150                         for(Resource join : g.getObjects(terminal.component, dr.FlagIsJoinedBy))
151                             mappedConnectionPoints.add(new CPConnectionJoin(join));
152                         
153                         Resource isLiftedAs = g.getPossibleObject(terminal.component, dr.IsLiftedAs);
154                         if (isLiftedAs != null) {
155                             // This is a lifted flag in a structural configuration.
156                             mappedConnectionPoints.add(new CPTerminal(terminal.component, isLiftedAs));
157                         } else {
158                             // Do nothing, because the flag is not connected
159                         }
160                     }
161                 } else if (cp instanceof CPConnection) {
162                     // Do nothing, because ignored connection points are not
163                     // meant to affect modelling rules in any way.
164                     //System.out.println("Non-mappable connection " + cp.toString(g));
165                 } else if (cp instanceof CPIgnore) {
166                     // Do nothing, because ignored connection points are not
167                     // meant to affect modelling rules in any way.
168                     // FIXME: this is maybe a bit of a hack.
169                     //System.out.println("Ignoring " + cp.toString(g));
170                 }
171                 else
172                     return null;
173             }
174         }
175         
176         return mappedConnectionPoints;
177         
178     }
179     
180     @Override
181     public ConnectionJudgement judgeConnection(ReadGraph g, Collection<IConnectionPoint> connectionPoints)
182                 throws DatabaseException {
183
184         ArrayList<IConnectionPoint> mappedConnectionPoints = getMappedConnectionPoints(g, connectionPoints);
185         if(mappedConnectionPoints == null) return ConnectionJudgement.ILLEGAL; 
186
187         // Judge mapped connection
188         ConnectionJudgement judgement = baseRules.judgeConnection(g, mappedConnectionPoints);
189
190         // Inverse map attachment relations
191         if(judgement.attachmentRelations != null)
192             judgement.attachmentRelations =
193                 new MappedAttachmentRelationMap(judgement.attachmentRelations);
194
195         return judgement;
196         
197     }
198     
199     @Override
200     public Resource computeConnectionType(ReadGraph g, Collection<IConnectionPoint> connectionPoints) throws DatabaseException {
201         
202         ArrayList<IConnectionPoint> mappedConnectionPoints = getMappedConnectionPoints(g, connectionPoints);
203         if(mappedConnectionPoints == null) return null;
204         
205         return baseRules.computeConnectionType(g, mappedConnectionPoints);
206         
207     }
208
209     @Override
210     public IAttachmentRelationMap getAttachmentRelations(ReadGraph g,
211             Resource connection) throws DatabaseException {
212         Resource mappedConnection = mapping.mapConnection(g, connection);
213         if(mappedConnection == null)
214             System.err.println("Connection mapped from " + NameUtils.getSafeName(g, connection, true) + " is null");
215         return new MappedAttachmentRelationMap(
216                 baseRules.getAttachmentRelations(g, mappedConnection)
217         );
218     }
219     
220         @Override
221         public Set<CPTerminal> resolveTerminals(ReadGraph g, Collection<IConnectionPoint> connectionPoints) 
222                         throws DatabaseException {
223                 Set<CPTerminal> terminals = new HashSet<CPTerminal>();
224                 StructuralResource2 STR = StructuralResource2.getInstance(g);
225                 DiagramResource DIA = DiagramResource.getInstance(g);
226                 for(IConnectionPoint cp : connectionPoints) {
227                         //System.out.println(this + ": translate connection point: " + cp.toString(g));
228                         if(cp instanceof CPTerminal)
229                                 terminals.add((CPTerminal)cp);
230                         else if(cp instanceof CPConnection) {
231                                 CPConnection connection = (CPConnection)cp;
232                                 for (Resource connector : g.getObjects(connection.connection, DIA.HasConnector)) {
233                                         for (Statement stat : g.getStatements(connector, STR.Connects)) {
234                                                 if(stat.getObject().equals(connection.connection)) continue;
235                                                 terminals.add(new CPTerminal(stat.getObject(),
236                                                                 g.getInverse(stat.getPredicate())));
237                                         }
238                                 }
239                         }
240                         else
241                                 throw new IllegalArgumentException("Connection point " + cp + " encountered.");
242                 }
243                 return terminals;
244         }
245
246 }