1 package org.simantics.structural2.variables;
3 import gnu.trove.map.hash.THashMap;
4 import gnu.trove.set.hash.THashSet;
6 import java.util.ArrayList;
7 import java.util.Collection;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.List;
15 import org.simantics.databoard.Bindings;
16 import org.simantics.db.ReadGraph;
17 import org.simantics.db.Resource;
18 import org.simantics.db.Statement;
19 import org.simantics.db.common.utils.Logger;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.exception.NoSingleResultException;
22 import org.simantics.db.layer0.function.All;
23 import org.simantics.db.layer0.request.ClassificationsRequest;
24 import org.simantics.db.layer0.variable.AbstractChildVariable;
25 import org.simantics.db.layer0.variable.NodeSupport;
26 import org.simantics.db.layer0.variable.StandardAssertedGraphPropertyVariable;
27 import org.simantics.db.layer0.variable.StandardConstantGraphPropertyVariable;
28 import org.simantics.db.layer0.variable.Variable;
29 import org.simantics.db.layer0.variable.VariableNode;
30 import org.simantics.layer0.Layer0;
31 import org.simantics.simulator.variable.NodeManager;
32 import org.simantics.structural2.Functions;
33 import org.simantics.structural2.procedural.Connection;
34 import org.simantics.structural2.procedural.ConnectionPoint;
35 import org.simantics.structural2.procedural.Expression;
36 import org.simantics.structural2.procedural.Interface;
37 import org.simantics.structural2.procedural.Property;
38 import org.simantics.structural2.procedural.Terminal;
39 import org.simantics.utils.datastructures.Pair;
40 import org.slf4j.LoggerFactory;
42 public class StandardProceduralChildVariable extends AbstractChildVariable {
44 private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(StandardProceduralChildVariable.class);
49 public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {
53 public void collectSpecialChildren(ReadGraph graph, Map<String, Variable> children) throws DatabaseException {
57 * Standard implementation
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;
67 public static class FixedConnection implements org.simantics.structural2.variables.Connection {
69 final public Collection<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();
71 final private Variable parent;
73 public FixedConnection(Variable parent) {
78 public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
80 Set<Variable> result = new THashSet<Variable>();
81 for(Pair<String,Resource> cp : cps) {
82 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first);
83 Variable cp2 = component.getPossibleProperty(graph, cp.second);
85 for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
86 result.add(desc.getVariable(graph));
89 LOGGER.warn("no cp " + cp.first + " for " + component.getURI(graph));
96 public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
98 Set<String> result = new THashSet<String>();
99 for(Pair<String,Resource> cp : cps) {
100 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first);
101 Variable cp2 = component.getPossibleProperty(graph, cp.second);
103 for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, cp.second, relationType)) {
104 result.add(desc.getURI(graph));
107 LOGGER.warn("no cp " + cp.first + " for " + component.getURI(graph));
114 public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
116 Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>();
117 for(Pair<String,Resource> cp : cps) {
118 Variable component = cp.first == null ? parent : parent.getChild(graph, cp.first);
119 Variable cp2 = component.getPossibleProperty(graph, cp.second);
121 result.addAll(ConnectionBrowser.flatten(graph, component, cp.second, relationType));
123 LOGGER.warn("no cp " + cp.first + " for " + component.getURI(graph));
130 public int hashCode() {
131 final int prime = 31;
133 result = prime * result + ((cps == null) ? 0 : cps.hashCode());
134 result = prime * result
135 + ((parent == null) ? 0 : parent.hashCode());
140 public boolean equals(Object obj) {
145 if (getClass() != obj.getClass())
147 FixedConnection other = (FixedConnection) obj;
149 if (other.cps != null)
151 } else if (!cps.equals(other.cps))
153 if (parent == null) {
154 if (other.parent != null)
156 } else if (!parent.equals(other.parent))
163 public StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {
168 this.parent = parent;
170 this.properties = new THashMap<String,Variable>();
172 this.propertyIdentity = new ArrayList<Object>(properties.size()+conns.size());
173 propertyIdentity.addAll(properties);
174 propertyIdentity.addAll(conns);
176 Layer0 L0 = Layer0.getInstance(graph);
178 Map<String,Statement> assertedProperties = new THashMap<String, Statement>();
179 for(Statement stm : graph.getAssertedStatements(type, L0.HasProperty)) {
180 String pn = graph.getRelatedValue(stm.getPredicate(), L0.HasName, Bindings.STRING);
181 assertedProperties.put(pn, stm);
184 Collection<Object> nodeProperties = All.getPossibleNodeProperties(graph, (AbstractChildVariable)this);
185 Set<String> used = new HashSet<String>(nodeProperties.size());
186 for(Object nodeProperty : nodeProperties) {
187 @SuppressWarnings("rawtypes")
188 NodeSupport support = node.support;
189 @SuppressWarnings("rawtypes")
190 NodeManager manager = support.manager;
191 @SuppressWarnings("unchecked")
192 String pName = manager.getName(nodeProperty);
194 Statement assertedProperty = assertedProperties.get(pName);
195 if(assertedProperty != null) {
196 this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, new VariableNode(support, nodeProperty), assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));
200 for(Map.Entry<String, Statement> entry : assertedProperties.entrySet()) {
201 String pName = entry.getKey();
202 if(used.contains(pName)) continue;
203 Statement assertedProperty = entry.getValue();
204 this.properties.put(pName, new StandardAssertedGraphPropertyVariable(graph, this, null, assertedProperty.getSubject(), assertedProperty.getPredicate(), assertedProperty.getObject()));
208 for(Property p : properties) {
209 String pn = graph.getRelatedValue(p.relation, L0.HasName, Bindings.STRING);
210 if(p.value == null) {
211 Logger.defaultLogError("StandardProceduralChildVariable " + getURI(graph) + ": null value for property " + pn);
212 } else if (p.value instanceof Expression) {
213 Expression expression = (Expression)p.value;
214 this.properties.put(pn, new StructuralProceduralExpressionPropertyVariable(graph, this, p.relation, expression.text) );
216 this.properties.put(pn, new StandardConstantGraphPropertyVariable(graph, this, p.relation, p.value) );
221 Map<Resource,FixedConnection> map = new HashMap<Resource,FixedConnection>();
222 for(Connection conn : conns) {
224 List<Pair<String,Resource>> cps = new ArrayList<Pair<String,Resource>>();
225 for(ConnectionPoint cp : conn.connectionPoints) {
226 if(cp instanceof Terminal) {
227 Terminal t = (Terminal)cp;
228 if(t.component.equals(name)) {
232 cps.add(Pair.make(t.component, t.relation));
234 if(cp instanceof Interface) {
235 Interface inf = (Interface)cp;
236 cps.add(new Pair<String,Resource>(null, inf.relation));
240 FixedConnection fc = map.get(p);
242 fc = new FixedConnection(parent);
248 for(Map.Entry<Resource, FixedConnection> entry : map.entrySet()) {
249 Resource cp = entry.getKey();
250 String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);
251 this.properties.put(cpName, new StandardConstantGraphPropertyVariable(graph, this, cp, entry.getValue()));
257 public void validate(ReadGraph graph) throws DatabaseException {
261 public Resource getType(ReadGraph graph) throws DatabaseException {
266 public Resource getPossibleType(ReadGraph graph) throws DatabaseException {
271 public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {
272 if (graph.isInheritedFrom(type, baseType))
274 throw new NoSingleResultException("variable " + getPossibleURI(graph) + " has no type");
278 public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {
279 return graph.isInheritedFrom(type, baseType) ? type : null;
283 protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
284 return properties.get(name);
288 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
289 return Functions.structuralChildDomainChildren.getVariable(graph, this, name);
293 public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> properties) throws DatabaseException {
294 if(!this.properties.isEmpty()) {
295 if(properties == null) properties = new THashMap<String,Variable>(this.properties.size());
296 properties.putAll(this.properties);
302 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
303 Map<String,Variable> result = Functions.structuralChildDomainChildren.getVariables(graph, this, null);
304 if(result == null) return Collections.emptyList();
305 else return result.values();
308 public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {
309 Resource type = getPossibleType(graph);
310 return (type != null)
311 ? graph.syncRequest(new ClassificationsRequest(Collections.singleton(type)))
312 : Collections.<String>emptySet();
316 public String getName(ReadGraph graph) throws DatabaseException {
321 public Variable getParent(ReadGraph graph) throws DatabaseException {
326 final public Resource getRepresents(ReadGraph graph) throws DatabaseException {
331 public int hashCode() {
332 return parent.hashCode() + 31*name.hashCode() + 41*type.hashCode() + 71*System.identityHashCode(propertyIdentity);
336 public boolean equals(Object obj) {
342 if (getClass() != obj.getClass())
345 StandardProceduralChildVariable other = (StandardProceduralChildVariable) obj;
347 if(!name.equals(other.name)) return false;
348 if(!type.equals(other.type)) return false;
349 if(!parent.equals(other.parent)) return false;
350 if(propertyIdentity != other.propertyIdentity) return false;