1 package org.simantics.structural2;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.HashSet;
12 import org.simantics.databoard.Bindings;
13 import org.simantics.databoard.Datatypes;
14 import org.simantics.databoard.adapter.AdaptException;
15 import org.simantics.databoard.binding.Binding;
16 import org.simantics.databoard.binding.error.BindingException;
17 import org.simantics.databoard.binding.error.DatatypeConstructionException;
18 import org.simantics.databoard.type.Datatype;
19 import org.simantics.databoard.util.URIStringUtils;
20 import org.simantics.db.Issue;
21 import org.simantics.db.ReadGraph;
22 import org.simantics.db.Resource;
23 import org.simantics.db.Statement;
24 import org.simantics.db.WriteGraph;
25 import org.simantics.db.common.issue.StandardIssue;
26 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
27 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
28 import org.simantics.db.common.request.ObjectsWithType;
29 import org.simantics.db.common.request.PossibleIndexRoot;
30 import org.simantics.db.common.request.ResourceRead;
31 import org.simantics.db.common.uri.UnescapedChildMapOfResource;
32 import org.simantics.db.exception.DatabaseException;
33 import org.simantics.db.layer0.function.All;
34 import org.simantics.db.layer0.function.StandardChildDomainChildren;
35 import org.simantics.db.layer0.request.PropertyInfo;
36 import org.simantics.db.layer0.request.PropertyInfoRequest;
37 import org.simantics.db.layer0.request.VariableRead;
38 import org.simantics.db.layer0.variable.AbstractChildVariable;
39 import org.simantics.db.layer0.variable.AbstractPropertyVariable;
40 import org.simantics.db.layer0.variable.LazyPropertyVariable;
41 import org.simantics.db.layer0.variable.NodeSupport;
42 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
43 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
44 import org.simantics.db.layer0.variable.ValueAccessor;
45 import org.simantics.db.layer0.variable.ValueAccessorWithBinding;
46 import org.simantics.db.layer0.variable.Variable;
47 import org.simantics.db.layer0.variable.VariableMap;
48 import org.simantics.db.layer0.variable.VariableMapImpl;
49 import org.simantics.db.layer0.variable.VariableNode;
50 import org.simantics.issues.common.IssueUtils;
51 import org.simantics.layer0.Layer0;
52 import org.simantics.scl.reflection.annotations.SCLValue;
53 import org.simantics.scl.runtime.SCLContext;
54 import org.simantics.scl.runtime.function.Function1;
55 import org.simantics.simulation.ontology.SimulationResource;
56 import org.simantics.simulator.variable.NodeManager;
57 import org.simantics.structural.stubs.StructuralResource2;
58 import org.simantics.structural2.procedural.Component;
59 import org.simantics.structural2.procedural.ConnectionPoint;
60 import org.simantics.structural2.procedural.Interface;
61 import org.simantics.structural2.procedural.SubstructureElement;
62 import org.simantics.structural2.procedural.Terminal;
63 import org.simantics.structural2.queries.ConnectionComponents;
64 import org.simantics.structural2.queries.ConnectionJoinComponents;
65 import org.simantics.structural2.queries.ConnectionPointMapOfResource;
66 import org.simantics.structural2.queries.PossibleConnectionPointInfo;
67 import org.simantics.structural2.scl.CompileStructuralValueRequest;
68 import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest;
69 import org.simantics.structural2.variables.Connection;
70 import org.simantics.structural2.variables.ConnectionBrowser;
71 import org.simantics.structural2.variables.StandardProceduralChildVariable;
72 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
73 import org.simantics.utils.datastructures.MapList;
75 import gnu.trove.map.hash.THashMap;
76 import gnu.trove.set.hash.THashSet;
78 public class Functions {
80 @SCLValue(type="ValueAccessor")
81 public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() {
83 public Binding getBinding() {
84 return Bindings.STRING;
88 public void setValue(WriteGraph graph, Variable context, Object value)
89 throws DatabaseException {
91 if(getValue(graph, context) != null)
92 clearExpression(graph, context);
96 // Get all necessary data
97 String expression = (String)value;
98 Variable parent = context.getParent(graph);
99 if(!(parent instanceof AbstractPropertyVariable)) return;
100 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
101 Resource propertyResource = property.getRepresents(graph);
102 if(propertyResource == null) return;
103 Resource container = property.getContainerResource(graph);
104 if(container == null) return;
105 Resource predicate = property.getPossiblePredicateResource(graph);
106 if(predicate == null) return;
107 Statement stat = graph.getPossibleStatement(container, predicate);
108 StructuralResource2 STR = StructuralResource2.getInstance(graph);
111 boolean createNew = false;
112 if(stat.isAsserted(container))
114 else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) {
115 graph.deny(propertyResource);
118 Layer0 L0 = Layer0.getInstance(graph);
120 propertyResource = graph.newResource();
121 graph.claim(container, predicate, propertyResource);
122 graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue);
124 graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING);
127 private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException {
128 Variable parent = context.getParent(graph);
129 if(!(parent instanceof AbstractPropertyVariable)) return;
130 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
131 Resource container = property.getContainerResource(graph);
132 if(container == null) return;
133 Resource predicate = property.getPossiblePredicateResource(graph);
134 if(predicate == null) return;
135 graph.deny(container, predicate);
139 public Object getValue(ReadGraph graph, Variable context)
140 throws DatabaseException {
141 Variable parent = context.getParent(graph);
142 if(!(parent instanceof AbstractPropertyVariable))
144 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
145 Resource propertyResource = property.getPossibleRepresents(graph);
146 if(propertyResource == null) return null;
147 StructuralResource2 STR = StructuralResource2.getInstance(graph);
148 if(!graph.isInstanceOf(propertyResource, STR.SCLValue))
150 Layer0 L0 = Layer0.getInstance(graph);
151 return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression);
156 static class ConnectionImpl implements Connection {
158 final private StandardGraphPropertyVariable connectionPoint;
160 public ConnectionImpl(StandardGraphPropertyVariable connectionPoint) {
161 this.connectionPoint = connectionPoint;
165 public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
166 Set<Variable> result = new THashSet<Variable>();
167 for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {
168 result.add(desc.getVariable(graph));
174 public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
175 Set<String> result = new THashSet<String>();
176 for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {
177 result.add(desc.getURI(graph));
183 public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
184 return ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType);
189 @SCLValue(type="ValueAccessor")
190 public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {
193 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
194 throw new UnsupportedOperationException();
197 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
198 throw new UnsupportedOperationException();
201 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
203 Object value = getValue(graph, context);
204 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
205 return Bindings.adapt(value, srcBinding, binding);
206 } catch (AdaptException e) {
207 throw new DatabaseException(e);
208 } catch (BindingException e) {
209 throw new DatabaseException(e);
214 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
215 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
216 return new ConnectionImpl(variable);
220 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
222 return Datatypes.getDatatype(Connection.class);
223 } catch (DatatypeConstructionException e) {
224 throw new DatabaseException(e);
231 @SCLValue(type = "VariableMap")
232 public static VariableMap structuralChildDomainProperties = new VariableMapImpl() {
234 public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
236 Map<String, Resource> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());
237 Resource cp = connectionPoints.get(name);
238 if(cp == null) return null;
239 else return new StandardGraphPropertyVariable(graph, variable, cp);
243 public Map<String, Variable> collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map<String, Variable> map, boolean needSynchronized) throws DatabaseException {
245 if(graph.isImmutable(context)) {
247 Map<String, Resource> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());
248 if(cps.size() == 0) return map;
250 if(map == null) map = new THashMap<String,Variable>(cps.size());
252 for(Map.Entry<String, Resource> entry : cps.entrySet()) {
253 String name = entry.getKey();
254 Resource cp = entry.getValue();
255 if(needSynchronized && !graph.isInstanceOf(cp, STR.SynchronizedConnectionRelation)) continue;
256 map.put(name, new StandardGraphPropertyVariable(graph, variable, cp));
263 Collection<Resource> predicates = graph.getPredicates(context);
265 for(Resource predicate : predicates) {
267 PropertyInfo info = graph.isImmutable(predicate) ?
268 graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
269 graph.syncRequest(new PossibleConnectionPointInfo(predicate));
272 if(map == null) map = new THashMap<String,Variable>(4);
273 if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue;
274 map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate));
286 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
287 final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
288 Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name);
289 if(cp != null) return cp;
290 return All.getStandardChildDomainPropertyVariable(graph, context, name);
294 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
295 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
296 StructuralResource2 STR = StructuralResource2.getInstance(graph);
297 map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false);
298 return All.getStandardChildDomainPropertyVariables(graph, context, map);
301 public Map<String,Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String,Variable> map) throws DatabaseException {
302 if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) {
303 return All.getStandardChildDomainPropertyVariables(graph, context, classification, map);
304 } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) {
305 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
306 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true);
307 } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) {
308 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
309 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false);
311 return super.getVariables(graph, context, classification, map);
316 static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {
318 public StructuralChildMapOfResource(Resource resource) {
323 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
324 StructuralResource2 STR = StructuralResource2.getInstance(graph);
325 Resource type = graph.getPossibleType(resource, STR.Component);
327 Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy);
328 if(definition != null) {
329 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
334 Map<String, Resource> directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));
335 return directChildren;
340 static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {
342 public StructuralChildMapOfResourceT(Resource resource) {
347 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
348 StructuralResource2 STR = StructuralResource2.getInstance(graph);
349 Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);
350 if(definition != null) {
351 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
355 return Collections.emptyMap();
360 static class StructuralRunChildMapOfResource extends ResourceRead<Map<String, Resource>> {
362 public StructuralRunChildMapOfResource(Resource resource) {
366 public Map<String, Resource> fromContext(ReadGraph graph, Resource context) throws DatabaseException {
367 return graph.sync(new StructuralChildMapOfResource(context));
371 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
373 Layer0 L0 = Layer0.getInstance(graph);
374 SimulationResource SIMU = SimulationResource.getInstance(graph);
375 Resource model = graph.sync(new PossibleIndexRoot(resource));
376 if(graph.isInstanceOf(model, L0.RVIContext)) {
377 return fromContext(graph, model);
379 Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
380 if(configuration != null) {
381 if(graph.isInstanceOf(configuration, L0.RVIContext)) {
382 return fromContext(graph, configuration);
386 return Collections.emptyMap();
392 private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {
393 public SubstructureRequest(Variable context) {
398 public List<SubstructureElement> perform(ReadGraph graph) {
400 Resource type = variable.getPossibleType(graph);
403 return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable);
404 } catch (Throwable t) {
411 public static List<SubstructureElement> getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException {
412 StructuralResource2 STR = StructuralResource2.getInstance(graph);
413 final Resource type = context.getPossibleType(graph);
415 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
416 return graph.syncRequest(new SubstructureRequest(context));
422 public static Map<String,Variable> getProcedural(ReadGraph graph, Variable context, List<SubstructureElement> elements, Map<String,Variable> map) throws DatabaseException {
424 if(map == null) map = new THashMap<String,Variable>();
426 MapList<String,org.simantics.structural2.procedural.Connection> conns = new MapList<String,org.simantics.structural2.procedural.Connection>();
427 for(SubstructureElement sub : elements) {
428 if(sub instanceof org.simantics.structural2.procedural.Connection) {
429 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub;
430 for(ConnectionPoint cp : conn.connectionPoints) {
431 if(cp instanceof Terminal) {
432 Terminal t = (Terminal)cp;
433 conns.add(t.component, conn);
439 Map<String,Component> proceduralChildren = new THashMap<String, Component>();
440 for(SubstructureElement sub : elements) {
441 if(sub instanceof Component) {
442 Component comp = (Component)sub;
443 proceduralChildren.put(comp.name, comp);
447 Collection<Object> nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context);
448 Set<String> used = new HashSet<String>(nodeChildren.size());
449 for(Object nodeChild : nodeChildren) {
450 @SuppressWarnings("rawtypes")
451 NodeSupport support = ((AbstractChildVariable)context).node.support;
452 @SuppressWarnings("rawtypes")
453 NodeManager manager = support.manager;
454 @SuppressWarnings("unchecked")
455 String name = manager.getName(nodeChild);
457 Component proceduralChild = proceduralChildren.get(name);
458 if(proceduralChild != null) {
459 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
463 for(Map.Entry<String, Component> entry : proceduralChildren.entrySet()) {
464 String name = entry.getKey();
465 if(used.contains(name)) continue;
466 Component proceduralChild = entry.getValue();
467 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
474 private static class ProceduralSubstructureRequest extends VariableRead<Map<String,Variable>> {
476 public ProceduralSubstructureRequest(Variable variable) {
481 public Map<String, Variable> perform(ReadGraph graph)
482 throws DatabaseException {
483 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
485 return getProcedural(graph, variable, elements, null);
492 @SCLValue(type = "VariableMap")
493 public static VariableMap structuralChildDomainChildren = new VariableMapImpl() {
496 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
498 final Resource type = context.getPossibleType(graph);
500 StructuralResource2 STR = StructuralResource2.getInstance(graph);
501 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
502 Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),
503 TransientCacheListener.<Map<String,Variable>>instance());
504 if(map != null) return map.get(name);
508 Resource represents = context.getPossibleRepresents(graph);
509 if(represents == null) {
510 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));
511 Resource child = children.get(name);
512 return All.getStandardChildDomainChildVariable(graph, context, child, name);
514 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));
515 Resource child = children.get(name);
516 return All.getStandardChildDomainChildVariable(graph, context, child, name);
520 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
522 final Resource type = context.getPossibleType(graph);
524 StructuralResource2 STR = StructuralResource2.getInstance(graph);
525 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
526 Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),
527 TransientCacheListener.<Map<String,Variable>>instance());
528 if(mapPrime != null) {
530 map.putAll(mapPrime);
538 Resource represents = context.getPossibleRepresents(graph);
539 if(represents == null) {
540 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));
541 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
543 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));
544 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
549 @SCLValue(type = "VariableMap")
550 public static VariableMap structuralRunDomainChildren = new VariableMapImpl() {
553 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
554 Map<String, Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(context.getRepresents(graph)));
555 Resource child = children.get(name);
556 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
560 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
561 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
562 Map<String,Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(variable.resource));
563 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
568 @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]")
569 public static List<Resource> connectionExtension(ReadGraph graph, List<Resource> rs) throws DatabaseException {
571 StructuralResource2 STR = StructuralResource2.getInstance(graph);
572 HashSet<Resource> extension = new HashSet<Resource>(8);
573 for(Resource r : rs) {
574 if(graph.isInstanceOf(r, STR.Connection)) {
575 extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
577 if(graph.isInstanceOf(r, STR.ConnectionJoin)) {
578 extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
582 HashSet<Resource> components = new HashSet<Resource>(8);
583 for(Resource r : extension) {
584 components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component)));
587 if(!extension.isEmpty()) {
588 ArrayList<Resource> result = new ArrayList<Resource>(rs.size() + extension.size());
590 result.addAll(extension);
591 result.addAll(components);
599 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
600 public static List<Issue> connectionValidator(ReadGraph graph, Resource component) throws DatabaseException {
602 if(!graph.hasStatement(component)) return Collections.emptyList();
604 ArrayList<Issue> result = new ArrayList<Issue>();
606 Layer0 L0 = Layer0.getInstance(graph);
607 StructuralResource2 sr = StructuralResource2.getInstance(graph);
609 Resource type = graph.getSingleType(component, sr.Component);
611 Set<Resource> requiredConnections = new HashSet<Resource>();
612 for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) {
613 Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN);
614 if(required != null && required)
615 requiredConnections.add(connectionRelation);
618 Set<Resource> connections = new HashSet<Resource>();
620 for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) {
621 connections.add(stm.getPredicate());
622 connections.addAll(graph.getSuperrelations(stm.getPredicate()));
625 for(Resource req : requiredConnections) {
626 if(!connections.contains(req)) {
627 result.add(new StandardIssue(sr.ConnectionConstraint_ErrorIssue, component, req));
635 @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
636 public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
637 List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);
638 String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName);
639 return "'" + attributeName + "' should be connected.";
642 public static class InterfacePathMap extends VariableRead<GraphMap<Map<String,InterfaceResolution>>> {
644 public InterfacePathMap(Variable context) {
649 public GraphMap<Map<String,InterfaceResolution>> perform(ReadGraph graph) throws DatabaseException {
651 return new GraphMap<Map<String,InterfaceResolution>>() {
654 Map<String, InterfaceResolution> get(ReadGraph graph, String key) throws DatabaseException {
656 Variable child = variable.getChild(graph, key);
658 Map<String,InterfaceResolution> childMap = new THashMap<String,InterfaceResolution>();
659 Collection<InterfaceResolution> paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath");
661 for(InterfaceResolution r : paths) {
662 childMap.put(r.interfaceName, r);
675 public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException {
677 GraphMap<Map<String,InterfaceResolution>> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.<GraphMap<Map<String,InterfaceResolution>>>instance());
678 Map<String,InterfaceResolution> childMap = map.get(graph, component);
679 if(childMap == null) return "";
681 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.<PropertyInfo>instance());
683 InterfaceResolution match = childMap.get(info.name);
685 String comp = URIStringUtils.escape(component);
686 Variable newContext = context.getChild(graph, component);
687 return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint);
689 return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name);
694 public static class InterfaceResolution {
696 public Resource interfaceConnectionPoint;
697 public String interfaceName;
698 public String componentName;
699 public Resource connectionPoint;
701 public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) {
702 this.interfaceConnectionPoint = interfaceConnectionPoint;
703 this.interfaceName = interfaceName;
704 this.componentName = componentName;
705 this.connectionPoint = connectionPoint;
710 public static Collection<InterfaceResolution> computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException {
712 StructuralResource2 STR = StructuralResource2.getInstance(graph);
713 Resource type = variable.getPossibleType(graph);
715 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
716 ArrayList<InterfaceResolution> result = new ArrayList<InterfaceResolution>();
717 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
718 if(elements != null) {
719 for(SubstructureElement e : elements) {
720 if(e instanceof org.simantics.structural2.procedural.Connection) {
721 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e;
722 Interface inf = null;
723 for(ConnectionPoint cp : conn.connectionPoints) {
724 if(cp instanceof Interface) {
725 if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection.");
729 if(inf != null && conn.connectionPoints.size() > 1) {
730 Layer0 L0 = Layer0.getInstance(graph);
731 String cpName = URIStringUtils.escape( graph.<String>getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) );
732 for(ConnectionPoint cp : conn.connectionPoints) {
733 if(cp == inf) continue;
734 Terminal t = (Terminal)cp;
735 result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation));
746 final Collection<InterfaceResolution> interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type));
747 if(interfaces != null) return interfaces;
751 return BUILTIN_STRUCTURAL_CPS;
755 static class InterfacePathRequest extends VariableRead<Collection<InterfaceResolution>> {
757 public InterfacePathRequest(Variable variable) {
762 public Collection<InterfaceResolution> perform(ReadGraph graph) throws DatabaseException {
763 return computeInterfacePaths(graph, variable);
768 static class DefinedUCInterfaceMap extends ResourceRead<Collection<InterfaceResolution>> {
770 public DefinedUCInterfaceMap(Resource resource) {
775 public Collection<InterfaceResolution> perform(ReadGraph graph)
776 throws DatabaseException {
778 StructuralResource2 STR = StructuralResource2.getInstance(graph);
779 Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);
780 if(definition != null) {
781 Collection<InterfaceResolution> result = new ArrayList<InterfaceResolution>();
782 Layer0 L0 = Layer0.getInstance(graph);
783 for(Resource cp : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, STR.ConnectionRelation))) {
784 String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);
785 for(Resource conn : graph.getObjects(cp, STR.IsBoundBy)) {
786 Statement stm = graph.getPossibleStatement(conn, STR.Connects);
787 if(stm == null) continue;
788 Resource component = stm.getObject();
789 String componentName = graph.getRelatedValue(component, L0.HasName, Bindings.STRING);
790 result.add(new InterfaceResolution(cp, cpName, componentName, graph.getInverse(stm.getPredicate())));
800 public static final Collection<InterfaceResolution> BUILTIN_STRUCTURAL_CPS = new ArrayList<InterfaceResolution>();
802 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
803 public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
804 return CompileStructuralValueRequest.compileAndEvaluate(graph, context);
807 public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException {
808 SCLContext sclContext = SCLContext.getCurrent();
809 Object oldGraph = sclContext.get("graph");
811 Function1<Variable,Object> exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) {
812 protected String getExpressionText(ReadGraph graph) throws DatabaseException {
816 TransientCacheListener.<Function1<Variable,Object>>instance());
817 sclContext.put("graph", graph);
818 return exp.apply(context);
819 } catch (DatabaseException e) {
820 throw (DatabaseException)e;
821 } catch (Throwable t) {
822 throw new DatabaseException(t);
824 sclContext.put("graph", oldGraph);
828 static abstract class InterfacePathProperty extends LazyPropertyVariable {
830 public InterfacePathProperty(Variable parent) {
831 super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY);
835 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
836 return getValue(graph);
841 static abstract class GraphMap<Value> {
843 abstract Value get(ReadGraph graph, String key) throws DatabaseException;