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.StandardProceduralChildVariable;
71 import org.simantics.utils.datastructures.MapList;
73 import gnu.trove.map.hash.THashMap;
75 public class Functions {
77 @SCLValue(type="ValueAccessor")
78 public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() {
80 public Binding getBinding() {
81 return Bindings.STRING;
85 public void setValue(WriteGraph graph, Variable context, Object value)
86 throws DatabaseException {
88 if(getValue(graph, context) != null)
89 clearExpression(graph, context);
93 // Get all necessary data
94 String expression = (String)value;
95 Variable parent = context.getParent(graph);
96 if(!(parent instanceof AbstractPropertyVariable)) return;
97 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
98 Resource propertyResource = property.getRepresents(graph);
99 if(propertyResource == null) return;
100 Resource container = property.getContainerResource(graph);
101 if(container == null) return;
102 Resource predicate = property.getPossiblePredicateResource(graph);
103 if(predicate == null) return;
104 Statement stat = graph.getPossibleStatement(container, predicate);
105 StructuralResource2 STR = StructuralResource2.getInstance(graph);
108 boolean createNew = false;
109 if(stat.isAsserted(container))
111 else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) {
112 graph.deny(propertyResource);
115 Layer0 L0 = Layer0.getInstance(graph);
117 propertyResource = graph.newResource();
118 graph.claim(container, predicate, propertyResource);
119 graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue);
121 graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING);
124 private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException {
125 Variable parent = context.getParent(graph);
126 if(!(parent instanceof AbstractPropertyVariable)) return;
127 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
128 Resource container = property.getContainerResource(graph);
129 if(container == null) return;
130 Resource predicate = property.getPossiblePredicateResource(graph);
131 if(predicate == null) return;
132 graph.deny(container, predicate);
136 public Object getValue(ReadGraph graph, Variable context)
137 throws DatabaseException {
138 Variable parent = context.getParent(graph);
139 if(!(parent instanceof AbstractPropertyVariable))
141 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
142 Resource propertyResource = property.getPossibleRepresents(graph);
143 if(propertyResource == null) return null;
144 StructuralResource2 STR = StructuralResource2.getInstance(graph);
145 if(!graph.isInstanceOf(propertyResource, STR.SCLValue))
147 Layer0 L0 = Layer0.getInstance(graph);
148 return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression);
153 @SCLValue(type="ValueAccessor")
154 public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {
157 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
158 throw new UnsupportedOperationException();
161 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
162 throw new UnsupportedOperationException();
165 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
167 Object value = getValue(graph, context);
168 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
169 return Bindings.adapt(value, srcBinding, binding);
170 } catch (AdaptException e) {
171 throw new DatabaseException(e);
172 } catch (BindingException e) {
173 throw new DatabaseException(e);
178 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
179 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
180 return new ConnectionImpl(variable.property.predicate);
184 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
186 return Datatypes.getDatatype(Connection.class);
187 } catch (DatatypeConstructionException e) {
188 throw new DatabaseException(e);
195 @SCLValue(type = "VariableMap")
196 public static VariableMap structuralChildDomainProperties = new VariableMapImpl() {
198 public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
200 Map<String, PropertyInfo> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
201 PropertyInfo cp = connectionPoints.get(name);
202 if(cp == null) return null;
203 else return new StandardGraphPropertyVariable(graph, variable, cp.predicate);
207 public Map<String, Variable> collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map<String, Variable> map, boolean needSynchronized) throws DatabaseException {
209 if(graph.isImmutable(context)) {
211 Map<String, PropertyInfo> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
212 if(cps.size() == 0) return map;
214 if(map == null) map = new THashMap<String,Variable>(cps.size());
216 for(Map.Entry<String, PropertyInfo> entry : cps.entrySet()) {
217 String name = entry.getKey();
218 PropertyInfo cp = entry.getValue();
219 if(needSynchronized && !graph.isInstanceOf(cp.predicate, STR.SynchronizedConnectionRelation)) continue;
220 map.put(name, new StandardGraphPropertyVariable(graph, variable, cp.predicate));
227 Collection<Resource> predicates = graph.getPredicates(context);
229 for(Resource predicate : predicates) {
231 PropertyInfo info = graph.isImmutable(predicate) ?
232 graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
233 graph.syncRequest(new PossibleConnectionPointInfo(predicate));
236 if(map == null) map = new THashMap<String,Variable>(4);
237 if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue;
238 map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate));
250 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
251 final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
252 Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name);
253 if(cp != null) return cp;
254 return All.getStandardChildDomainPropertyVariable(graph, context, name);
258 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
259 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
260 StructuralResource2 STR = StructuralResource2.getInstance(graph);
261 map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false);
262 return All.getStandardChildDomainPropertyVariables(graph, context, map);
265 public Map<String,Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String,Variable> map) throws DatabaseException {
266 if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) {
267 return All.getStandardChildDomainPropertyVariables(graph, context, classification, map);
268 } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) {
269 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
270 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true);
271 } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) {
272 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
273 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false);
275 return super.getVariables(graph, context, classification, map);
280 public static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {
282 public StructuralChildMapOfResource(Resource resource) {
287 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
288 StructuralResource2 STR = StructuralResource2.getInstance(graph);
289 Resource type = graph.getPossibleType(resource, STR.Component);
291 Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy);
292 if(definition != null) {
293 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
298 Map<String, Resource> directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));
299 return directChildren;
304 public static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {
306 public StructuralChildMapOfResourceT(Resource resource) {
311 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
312 StructuralResource2 STR = StructuralResource2.getInstance(graph);
313 Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);
314 if(definition != null) {
315 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
319 return Collections.emptyMap();
324 static class StructuralRunChildMapOfResource extends ResourceRead<Map<String, Resource>> {
326 public StructuralRunChildMapOfResource(Resource resource) {
330 public Map<String, Resource> fromContext(ReadGraph graph, Resource context) throws DatabaseException {
331 return graph.sync(new StructuralChildMapOfResource(context));
335 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
337 Layer0 L0 = Layer0.getInstance(graph);
338 SimulationResource SIMU = SimulationResource.getInstance(graph);
339 Resource model = graph.sync(new PossibleIndexRoot(resource));
340 if(graph.isInstanceOf(model, L0.RVIContext)) {
341 return fromContext(graph, model);
343 Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
344 if(configuration != null) {
345 if(graph.isInstanceOf(configuration, L0.RVIContext)) {
346 return fromContext(graph, configuration);
350 return Collections.emptyMap();
356 private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {
357 public SubstructureRequest(Variable context) {
362 public List<SubstructureElement> perform(ReadGraph graph) {
364 Resource type = variable.getPossibleType(graph);
367 return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable);
368 } catch (Throwable t) {
375 public static List<SubstructureElement> getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException {
376 StructuralResource2 STR = StructuralResource2.getInstance(graph);
377 final Resource type = context.getPossibleType(graph);
379 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
380 return graph.syncRequest(new SubstructureRequest(context));
386 public static Map<String,Variable> getProcedural(ReadGraph graph, Variable context, List<SubstructureElement> elements, Map<String,Variable> map) throws DatabaseException {
388 if(map == null) map = new THashMap<String,Variable>();
390 MapList<String,org.simantics.structural2.procedural.Connection> conns = new MapList<String,org.simantics.structural2.procedural.Connection>();
391 for(SubstructureElement sub : elements) {
392 if(sub instanceof org.simantics.structural2.procedural.Connection) {
393 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub;
394 for(ConnectionPoint cp : conn.connectionPoints) {
395 if(cp instanceof Terminal) {
396 Terminal t = (Terminal)cp;
397 conns.add(t.component, conn);
403 Map<String,Component> proceduralChildren = new THashMap<String, Component>();
404 for(SubstructureElement sub : elements) {
405 if(sub instanceof Component) {
406 Component comp = (Component)sub;
407 proceduralChildren.put(comp.name, comp);
411 Collection<Object> nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context);
412 Set<String> used = new HashSet<String>(nodeChildren.size());
413 for(Object nodeChild : nodeChildren) {
414 @SuppressWarnings("rawtypes")
415 NodeSupport support = ((AbstractChildVariable)context).node.support;
416 @SuppressWarnings("rawtypes")
417 NodeManager manager = support.manager;
418 @SuppressWarnings("unchecked")
419 String name = manager.getName(nodeChild);
421 Component proceduralChild = proceduralChildren.get(name);
422 if(proceduralChild != null) {
423 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
427 for(Map.Entry<String, Component> entry : proceduralChildren.entrySet()) {
428 String name = entry.getKey();
429 if(used.contains(name)) continue;
430 Component proceduralChild = entry.getValue();
431 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
438 private static class ProceduralSubstructureRequest extends VariableRead<Map<String,Variable>> {
440 public ProceduralSubstructureRequest(Variable variable) {
445 public Map<String, Variable> perform(ReadGraph graph)
446 throws DatabaseException {
447 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
449 return getProcedural(graph, variable, elements, null);
456 @SCLValue(type = "VariableMap")
457 public static VariableMap structuralChildDomainChildren = new VariableMapImpl() {
460 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
462 final Resource type = context.getPossibleType(graph);
464 StructuralResource2 STR = StructuralResource2.getInstance(graph);
465 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
466 Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),
467 TransientCacheListener.<Map<String,Variable>>instance());
468 if(map != null) return map.get(name);
472 Resource represents = context.getPossibleRepresents(graph);
473 if(represents == null) {
474 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));
475 Resource child = children.get(name);
476 return All.getStandardChildDomainChildVariable(graph, context, child, name);
478 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));
479 Resource child = children.get(name);
480 return All.getStandardChildDomainChildVariable(graph, context, child, name);
484 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
486 final Resource type = context.getPossibleType(graph);
488 StructuralResource2 STR = StructuralResource2.getInstance(graph);
489 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
490 Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),
491 TransientCacheListener.<Map<String,Variable>>instance());
492 if(mapPrime != null) {
494 map.putAll(mapPrime);
502 Resource represents = context.getPossibleRepresents(graph);
503 if(represents == null) {
504 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(type));
505 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
507 Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));
508 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
513 @SCLValue(type = "VariableMap")
514 public static VariableMap structuralRunDomainChildren = new VariableMapImpl() {
517 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
518 Map<String, Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(context.getRepresents(graph)));
519 Resource child = children.get(name);
520 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
524 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
525 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
526 Map<String,Resource> children = graph.syncRequest(new StructuralRunChildMapOfResource(variable.resource));
527 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
532 @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]")
533 public static List<Resource> connectionExtension(ReadGraph graph, List<Resource> rs) throws DatabaseException {
535 StructuralResource2 STR = StructuralResource2.getInstance(graph);
536 HashSet<Resource> extension = new HashSet<Resource>(8);
537 for(Resource r : rs) {
538 if(graph.isInstanceOf(r, STR.Connection)) {
539 extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
541 if(graph.isInstanceOf(r, STR.ConnectionJoin)) {
542 extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
546 HashSet<Resource> components = new HashSet<Resource>(8);
547 for(Resource r : extension) {
548 components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component)));
551 if(!extension.isEmpty()) {
552 ArrayList<Resource> result = new ArrayList<Resource>(rs.size() + extension.size());
554 result.addAll(extension);
555 result.addAll(components);
563 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
564 public static List<Issue> connectionValidator(ReadGraph graph, Resource component) throws DatabaseException {
566 if(!graph.hasStatement(component)) return Collections.emptyList();
568 ArrayList<Issue> result = new ArrayList<Issue>();
570 Layer0 L0 = Layer0.getInstance(graph);
571 StructuralResource2 sr = StructuralResource2.getInstance(graph);
573 Resource type = graph.getSingleType(component, sr.Component);
575 Set<Resource> requiredConnections = new HashSet<Resource>();
576 for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) {
577 Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN);
578 if(required != null && required)
579 requiredConnections.add(connectionRelation);
582 Set<Resource> connections = new HashSet<Resource>();
584 for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) {
585 connections.add(stm.getPredicate());
586 connections.addAll(graph.getSuperrelations(stm.getPredicate()));
589 for(Resource req : requiredConnections) {
590 if(!connections.contains(req)) {
591 result.add(new StandardIssue(sr.ConnectionConstraint_ErrorIssue, component, req));
599 @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
600 public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
601 List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);
602 String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName);
603 return "'" + attributeName + "' should be connected.";
606 public static class InterfacePathMap extends VariableRead<GraphMap<Map<String,InterfaceResolution>>> {
608 public InterfacePathMap(Variable context) {
613 public GraphMap<Map<String,InterfaceResolution>> perform(ReadGraph graph) throws DatabaseException {
615 return new GraphMap<Map<String,InterfaceResolution>>() {
618 Map<String, InterfaceResolution> get(ReadGraph graph, String key) throws DatabaseException {
620 Variable child = variable.getChild(graph, key);
622 Map<String,InterfaceResolution> childMap = new THashMap<String,InterfaceResolution>();
623 Collection<InterfaceResolution> paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath");
625 for(InterfaceResolution r : paths) {
626 childMap.put(r.interfaceName, r);
639 public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException {
641 GraphMap<Map<String,InterfaceResolution>> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.<GraphMap<Map<String,InterfaceResolution>>>instance());
642 Map<String,InterfaceResolution> childMap = map.get(graph, component);
643 if(childMap == null) return "";
645 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.<PropertyInfo>instance());
647 InterfaceResolution match = childMap.get(info.name);
649 String comp = URIStringUtils.escape(component);
650 Variable newContext = context.getChild(graph, component);
651 return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint);
653 return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name);
658 public static class InterfaceResolution {
660 public Resource interfaceConnectionPoint;
661 public String interfaceName;
662 public String componentName;
663 public Resource connectionPoint;
665 public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) {
666 this.interfaceConnectionPoint = interfaceConnectionPoint;
667 this.interfaceName = interfaceName;
668 this.componentName = componentName;
669 this.connectionPoint = connectionPoint;
674 public static Collection<InterfaceResolution> computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException {
676 StructuralResource2 STR = StructuralResource2.getInstance(graph);
677 Resource type = variable.getPossibleType(graph);
679 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
680 ArrayList<InterfaceResolution> result = new ArrayList<InterfaceResolution>();
681 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
682 if(elements != null) {
683 for(SubstructureElement e : elements) {
684 if(e instanceof org.simantics.structural2.procedural.Connection) {
685 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e;
686 Interface inf = null;
687 for(ConnectionPoint cp : conn.connectionPoints) {
688 if(cp instanceof Interface) {
689 if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection.");
693 if(inf != null && conn.connectionPoints.size() > 1) {
694 Layer0 L0 = Layer0.getInstance(graph);
695 String cpName = URIStringUtils.escape( graph.<String>getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) );
696 for(ConnectionPoint cp : conn.connectionPoints) {
697 if(cp == inf) continue;
698 Terminal t = (Terminal)cp;
699 result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation));
710 final Collection<InterfaceResolution> interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type));
711 if(interfaces != null) return interfaces;
715 return BUILTIN_STRUCTURAL_CPS;
719 static class InterfacePathRequest extends VariableRead<Collection<InterfaceResolution>> {
721 public InterfacePathRequest(Variable variable) {
726 public Collection<InterfaceResolution> perform(ReadGraph graph) throws DatabaseException {
727 return computeInterfacePaths(graph, variable);
732 static class DefinedUCInterfaceMap extends ResourceRead<Collection<InterfaceResolution>> {
734 public DefinedUCInterfaceMap(Resource resource) {
739 public Collection<InterfaceResolution> perform(ReadGraph graph)
740 throws DatabaseException {
742 StructuralResource2 STR = StructuralResource2.getInstance(graph);
743 Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);
744 if(definition != null) {
745 Collection<InterfaceResolution> result = new ArrayList<InterfaceResolution>();
746 Layer0 L0 = Layer0.getInstance(graph);
747 for(Resource cp : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, STR.ConnectionRelation))) {
748 String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING);
749 for(Resource conn : graph.getObjects(cp, STR.IsBoundBy)) {
750 Statement stm = graph.getPossibleStatement(conn, STR.Connects);
751 if(stm == null) continue;
752 Resource component = stm.getObject();
753 String componentName = graph.getRelatedValue(component, L0.HasName, Bindings.STRING);
754 result.add(new InterfaceResolution(cp, cpName, componentName, graph.getInverse(stm.getPredicate())));
764 public static final Collection<InterfaceResolution> BUILTIN_STRUCTURAL_CPS = new ArrayList<InterfaceResolution>();
766 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
767 public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
768 return CompileStructuralValueRequest.compileAndEvaluate(graph, context);
771 public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException {
772 SCLContext sclContext = SCLContext.getCurrent();
773 Object oldGraph = sclContext.get("graph");
775 Function1<Variable,Object> exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) {
776 protected String getExpressionText(ReadGraph graph) throws DatabaseException {
780 TransientCacheListener.<Function1<Variable,Object>>instance());
781 sclContext.put("graph", graph);
782 return exp.apply(context);
783 } catch (DatabaseException e) {
784 throw (DatabaseException)e;
785 } catch (Throwable t) {
786 throw new DatabaseException(t);
788 sclContext.put("graph", oldGraph);
792 static abstract class InterfacePathProperty extends LazyPropertyVariable {
794 public InterfacePathProperty(Variable parent) {
795 super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY);
799 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
800 return getValue(graph);
805 static abstract class GraphMap<Value> {
807 abstract Value get(ReadGraph graph, String key) throws DatabaseException;