1 package org.simantics.structural2.variables;
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;
10 import java.util.Objects;
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;
39 import gnu.trove.map.hash.THashMap;
41 public class StandardProceduralChildVariable extends AbstractChildVariable {
43 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 StandardProceduralChildVariable(ReadGraph graph, Variable parent, VariableNode node, String name, Resource type, List<Property> properties, Collection<Connection> conns) throws DatabaseException {
74 this.properties = new THashMap<String,Variable>();
76 this.propertyIdentity = new ArrayList<Object>(properties.size()+conns.size());
77 propertyIdentity.addAll(properties);
78 propertyIdentity.addAll(conns);
80 Layer0 L0 = Layer0.getInstance(graph);
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);
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);
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()));
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()));
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));
125 LOGGER.warn("Ignored attempt to override asserted property {}/{}#{} with a different relation", parent.getURI(graph), name, pn);
128 this.properties.put(pn, new StandardConstantGraphPropertyVariable(graph, this, p.relation, p.value) );
133 Map<Resource,FixedConnection> map = new HashMap<Resource,FixedConnection>();
134 for(Connection conn : conns) {
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)) {
144 cps.add(Pair.make(t.component, t.relation));
146 if(cp instanceof Interface) {
147 Interface inf = (Interface)cp;
148 cps.add(new Pair<String,Resource>(null, inf.relation));
152 FixedConnection fc = map.get(p);
154 fc = new FixedConnection(parent);
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()));
169 public void validate(ReadGraph graph) throws DatabaseException {
173 public Resource getType(ReadGraph graph) throws DatabaseException {
178 public Resource getPossibleType(ReadGraph graph) throws DatabaseException {
183 public Resource getType(ReadGraph graph, Resource baseType) throws DatabaseException {
184 if (graph.isInheritedFrom(type, baseType))
186 throw new NoSingleResultException("variable " + getPossibleURI(graph) + " has no type", -1);
190 public Resource getPossibleType(ReadGraph graph, Resource baseType) throws DatabaseException {
191 return graph.isInheritedFrom(type, baseType) ? type : null;
195 protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
196 return properties.get(name);
200 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
201 return Functions.structuralChildDomainChildren.getVariable(graph, this, name);
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);
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();
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();
228 public String getName(ReadGraph graph) throws DatabaseException {
233 public Variable getParent(ReadGraph graph) throws DatabaseException {
238 final public Resource getRepresents(ReadGraph graph) throws DatabaseException {
243 public int hashCode() {
244 return parent.hashCode() + 31*name.hashCode() + 41*type.hashCode() + 71*System.identityHashCode(propertyIdentity);
248 public boolean equals(Object obj) {
254 if (getClass() != obj.getClass())
257 StandardProceduralChildVariable other = (StandardProceduralChildVariable) obj;
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;