]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/variables/StandardProceduralChildVariable.java
Non-constant external value configuration via procedural UCs.
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / variables / StandardProceduralChildVariable.java
1 package org.simantics.structural2.variables;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Objects;
11 import java.util.Set;
12
13 import org.simantics.databoard.Bindings;
14 import org.simantics.db.ReadGraph;
15 import org.simantics.db.Resource;
16 import org.simantics.db.Statement;
17 import org.simantics.db.exception.DatabaseException;
18 import org.simantics.db.exception.NoSingleResultException;
19 import org.simantics.db.layer0.function.All;
20 import org.simantics.db.layer0.request.ClassificationsRequest;
21 import org.simantics.db.layer0.variable.AbstractChildVariable;
22 import org.simantics.db.layer0.variable.NodeSupport;
23 import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;
24 import org.simantics.db.layer0.variable.StandardConstantGraphPropertyVariable;
25 import org.simantics.db.layer0.variable.Variable;
26 import org.simantics.db.layer0.variable.VariableNode;
27 import org.simantics.layer0.Layer0;
28 import org.simantics.simulator.variable.NodeManager;
29 import org.simantics.structural2.Functions;
30 import org.simantics.structural2.procedural.Connection;
31 import org.simantics.structural2.procedural.ConnectionPoint;
32 import org.simantics.structural2.procedural.Expression;
33 import org.simantics.structural2.procedural.Interface;
34 import org.simantics.structural2.procedural.Property;
35 import org.simantics.structural2.procedural.Terminal;
36 import org.simantics.utils.datastructures.Pair;
37 import org.slf4j.LoggerFactory;
38
39 import gnu.trove.map.hash.THashMap;
40
41 public class StandardProceduralChildVariable extends AbstractChildVariable {
42
43         private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(StandardProceduralChildVariable.class);
44
45         /*
46          * Extension points
47          * 
48          */
49         public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {
50                 return null;
51         }
52
53         public void collectSpecialChildren(ReadGraph graph, Map<String, Variable> children) throws DatabaseException {
54         }
55
56         /*
57          * Standard implementation
58          * 
59          */
60         
61         final protected String name;
62         final protected Variable parent;
63         final private Resource type;
64         final private Map<String, Variable> properties;
65         final private List<Object> propertyIdentity;
66         
67         public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {
68                 super(node);
69                 assert name != null;
70         assert type != null;
71         this.name = name;
72                 this.parent = parent;
73                 this.type = type;
74                 this.properties = new THashMap<String,Variable>();
75                 
76                 this.propertyIdentity = new ArrayList<Object>(properties.size()+conns.size());
77                 propertyIdentity.addAll(properties);
78                 propertyIdentity.addAll(conns);
79                 
80                 Layer0 L0 = Layer0.getInstance(graph);
81
82                 Map<String,Statement> assertedProperties = new THashMap<String, Statement>();
83                 for(Statement stm : graph.getAssertedStatements(type, L0.HasProperty)) {
84             String pn = graph.getRelatedValue(stm.getPredicate(), L0.HasName, Bindings.STRING);
85             assertedProperties.put(pn, stm);
86                 }
87                 
88         Collection<Object> nodeProperties = All.getPossibleNodeProperties(graph, (AbstractChildVariable)this);
89         Set<String> used = new HashSet<String>(nodeProperties.size());
90         for(Object nodeProperty : nodeProperties) {
91             @SuppressWarnings("rawtypes")
92             NodeSupport support = node.support;
93             @SuppressWarnings("rawtypes")
94             NodeManager manager = support.manager;
95             @SuppressWarnings("unchecked")
96             String pName = manager.getName(nodeProperty);
97             used.add(pName);
98             Statement assertedProperty = assertedProperties.get(pName); 
99             if(assertedProperty != null) {
100                 this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, new VariableNode(support, nodeProperty), assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));
101             }
102         }
103         
104         for(Map.Entry<String, Statement> entry : assertedProperties.entrySet()) {
105             String pName = entry.getKey();
106             if(used.contains(pName)) continue;
107             Statement assertedProperty = entry.getValue();
108             this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, null, assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));
109         }
110                 
111                 
112                 for(Property p : properties) {
113                     String pn = graph.getRelatedValue(p.relation, L0.HasName, Bindings.STRING);
114                     if(p.value == null) {
115                         LOGGER.error("StandardProceduralChildVariable " + getURI(graph) + ": null value for property " + pn);
116                     } else if (p.value instanceof Expression) {
117                         Expression expression = (Expression)p.value;
118                             this.properties.put(pn, new StructuralProceduralExpressionPropertyVariable(graph, this, p.relation, expression.text) );
119                     } else if (this.properties.containsKey(pn)) {
120                         // The property overrides the value of an asserted property variable
121                         StandardAssertedGraphPropertyVariable assertedValue = (StandardAssertedGraphPropertyVariable) this.properties.get(pn);
122                         if (Objects.equals(assertedValue.property.predicate, p.relation)) {
123                                 this.properties.put(pn, new StandardProdeduralPropertyVariable(graph, this, assertedValue, p.value));
124                         } else {
125                                 LOGGER.warn("Ignored attempt to override asserted property {}/{}#{} with a different relation", parent.getURI(graph), name, pn);
126                         }
127                     } else {
128                             this.properties.put(pn, new StandardConstantGraphPropertyVariable(graph, this, p.relation, p.value) );
129                     }
130                         
131                         
132                 }
133             Map<Resource,FixedConnection> map = new HashMap<Resource,FixedConnection>();
134                 for(Connection conn : conns) {
135                     Resource p = null;
136                     List<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();
137                     for(ConnectionPoint cp : conn.connectionPoints) {
138                         if(cp instanceof Terminal) {
139                             Terminal t = (Terminal)cp;
140                             if(t.component.equals(name)) {
141                                 p = t.relation;
142                                 continue;
143                             }
144                             cps.add(Pair.make(t.component, t.relation));
145                         }
146                         if(cp instanceof Interface) {
147                                 Interface inf = (Interface)cp;
148                             cps.add(new Pair<String,Resource>(null, inf.relation));
149                         }
150                     }
151                     if(p != null) {
152                         FixedConnection fc = map.get(p);
153                         if(fc == null) {
154                                 fc = new FixedConnection(parent);
155                                 map.put(p, fc);
156                         }
157                         fc.addAll(cps);
158                     }
159                 }
160                 for(Map.Entry<Resource, FixedConnection> entry : map.entrySet()) {
161                         Resource cp = entry.getKey();
162             String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);
163                 this.properties.put(cpName, new StandardConstantGraphPropertyVariable(graph, this, cp, entry.getValue()));
164                 }
165                 
166         }
167
168         @Override
169         public void validate(ReadGraph graph) throws DatabaseException {
170         }
171         
172         @Override
173         public Resource getType(ReadGraph graph) throws DatabaseException {
174             return type;
175         }
176         
177         @Override
178         public Resource getPossibleType(ReadGraph graph) throws DatabaseException {
179             return type;
180         }
181         
182         @Override
183         public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {
184                 if (graph.isInheritedFrom(type, baseType))
185                         return type;
186                 throw new NoSingleResultException("variable " + getPossibleURI(graph) + " has no type", -1);
187         }
188         
189         @Override
190         public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {
191                 return graph.isInheritedFrom(type, baseType) ? type : null;
192         }
193         
194         @Override
195         protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
196             return properties.get(name);
197         }
198
199         @Override
200         public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
201             return Functions.structuralChildDomainChildren.getVariable(graph, this, name);
202         }
203
204         @Override
205         public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException {
206                 if(!this.properties.isEmpty()) {
207                         if(properties == null) properties = new THashMap<String,Variable>(this.properties.size());
208                         properties.putAll(this.properties);
209                 }
210                 return properties;
211         }
212
213         @Override
214         public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
215              Map<String,Variable> result = Functions.structuralChildDomainChildren.getVariables(graph, this, null);
216              if(result == null) return Collections.emptyList();
217              else return result.values();
218         }
219
220         public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {
221                 Resource type = getPossibleType(graph);
222                 return (type != null)
223                                 ? graph.syncRequest(new ClassificationsRequest(Collections.singleton(type)))
224                                 : Collections.<String>emptySet();
225         }
226
227         @Override
228         public String getName(ReadGraph graph) throws DatabaseException {
229             return name;
230         }
231
232         @Override
233         public Variable getParent(ReadGraph graph) throws DatabaseException {
234                 return parent;
235         }
236         
237         @Override
238         final public Resource getRepresents(ReadGraph graph) throws DatabaseException {
239             return null;
240         }
241
242         @Override
243         public int hashCode() {
244                 return parent.hashCode() + 31*name.hashCode() + 41*type.hashCode() + 71*System.identityHashCode(propertyIdentity);
245         }
246
247         @Override
248         public boolean equals(Object obj) {
249                 
250                 if (this == obj)
251                         return true;
252                 if (obj == null)
253                         return false;
254                 if (getClass() != obj.getClass())
255                         return false;
256                 
257                 StandardProceduralChildVariable other = (StandardProceduralChildVariable) obj;
258                 
259                 if(!name.equals(other.name)) return false;
260                 if(!type.equals(other.type)) return false;
261                 if(!parent.equals(other.parent)) return false;
262                 if(propertyIdentity != other.propertyIdentity) return false;
263                                 
264                 return true;
265                 
266         }
267         
268 }