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.primitiverequest.IsInstanceOf;
27 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
28 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
29 import org.simantics.db.common.request.ObjectsWithType;
30 import org.simantics.db.common.request.PossibleIndexRoot;
31 import org.simantics.db.common.request.PossibleObjectWithType;
32 import org.simantics.db.common.request.ResourceRead;
33 import org.simantics.db.common.request.TernaryRead;
34 import org.simantics.db.common.uri.UnescapedChildMapOfResource;
35 import org.simantics.db.exception.DatabaseException;
36 import org.simantics.db.layer0.function.All;
37 import org.simantics.db.layer0.function.StandardChildDomainChildren;
38 import org.simantics.db.layer0.request.PropertyInfo;
39 import org.simantics.db.layer0.request.PropertyInfoRequest;
40 import org.simantics.db.layer0.request.VariableRead;
41 import org.simantics.db.layer0.variable.AbstractChildVariable;
42 import org.simantics.db.layer0.variable.AbstractPropertyVariable;
43 import org.simantics.db.layer0.variable.LazyPropertyVariable;
44 import org.simantics.db.layer0.variable.NodeSupport;
45 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
46 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
47 import org.simantics.db.layer0.variable.ValueAccessor;
48 import org.simantics.db.layer0.variable.ValueAccessorWithBinding;
49 import org.simantics.db.layer0.variable.Variable;
50 import org.simantics.db.layer0.variable.VariableMap;
51 import org.simantics.db.layer0.variable.VariableMapImpl;
52 import org.simantics.db.layer0.variable.VariableNode;
53 import org.simantics.db.layer0.variable.Variables;
54 import org.simantics.db.service.CollectionSupport;
55 import org.simantics.issues.common.IssueUtils;
56 import org.simantics.layer0.Layer0;
57 import org.simantics.scl.reflection.annotations.SCLValue;
58 import org.simantics.scl.runtime.SCLContext;
59 import org.simantics.scl.runtime.function.Function1;
60 import org.simantics.scl.runtime.tuple.Tuple2;
61 import org.simantics.simulation.ontology.SimulationResource;
62 import org.simantics.simulator.variable.NodeManager;
63 import org.simantics.structural.stubs.StructuralResource2;
64 import org.simantics.structural2.procedural.Component;
65 import org.simantics.structural2.procedural.ConnectionPoint;
66 import org.simantics.structural2.procedural.Interface;
67 import org.simantics.structural2.procedural.SubstructureElement;
68 import org.simantics.structural2.procedural.Terminal;
69 import org.simantics.structural2.queries.ConnectionComponents;
70 import org.simantics.structural2.queries.ConnectionJoinComponents;
71 import org.simantics.structural2.queries.ConnectionPointMapOfResource;
72 import org.simantics.structural2.queries.PossibleConnectionPointInfo;
73 import org.simantics.structural2.scl.CompileStructuralValueRequest;
74 import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest;
75 import org.simantics.structural2.utils.StructuralUtils.StructuralComponentClass;
76 import org.simantics.structural2.variables.Connection;
77 import org.simantics.structural2.variables.StandardProceduralChildVariable;
78 import org.simantics.utils.datastructures.MapList;
80 import gnu.trove.map.hash.THashMap;
82 public class Functions {
84 @SCLValue(type="ValueAccessor")
85 public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() {
87 public Binding getBinding() {
88 return Bindings.STRING;
92 public void setValue(WriteGraph graph, Variable context, Object value)
93 throws DatabaseException {
95 if(getValue(graph, context) != null)
96 clearExpression(graph, context);
100 // Get all necessary data
101 String expression = (String)value;
102 Variable parent = context.getParent(graph);
103 if(!(parent instanceof AbstractPropertyVariable)) return;
104 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
105 Resource propertyResource = property.getRepresents(graph);
106 if(propertyResource == null) return;
107 Resource container = property.getContainerResource(graph);
108 if(container == null) return;
109 Resource predicate = property.getPossiblePredicateResource(graph);
110 if(predicate == null) return;
111 Statement stat = graph.getPossibleStatement(container, predicate);
112 StructuralResource2 STR = StructuralResource2.getInstance(graph);
115 boolean createNew = false;
116 if(stat.isAsserted(container))
118 else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) {
119 graph.deny(propertyResource);
122 Layer0 L0 = Layer0.getInstance(graph);
124 propertyResource = graph.newResource();
125 graph.claim(container, predicate, propertyResource);
126 graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue);
128 graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING);
131 private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException {
132 Variable parent = context.getParent(graph);
133 if(!(parent instanceof AbstractPropertyVariable)) return;
134 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
135 Resource container = property.getContainerResource(graph);
136 if(container == null) return;
137 Resource predicate = property.getPossiblePredicateResource(graph);
138 if(predicate == null) return;
139 graph.deny(container, predicate);
143 public Object getValue(ReadGraph graph, Variable context)
144 throws DatabaseException {
145 Variable parent = context.getParent(graph);
146 if(!(parent instanceof AbstractPropertyVariable))
148 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
149 Resource propertyResource = property.getPossibleRepresents(graph);
150 if(propertyResource == null) return null;
151 StructuralResource2 STR = StructuralResource2.getInstance(graph);
152 if(!graph.isInstanceOf(propertyResource, STR.SCLValue))
154 Layer0 L0 = Layer0.getInstance(graph);
155 return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression);
160 @SCLValue(type="ValueAccessor")
161 public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {
164 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
165 throw new UnsupportedOperationException();
168 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
169 throw new UnsupportedOperationException();
172 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
174 Object value = getValue(graph, context);
175 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
176 return Bindings.adapt(value, srcBinding, binding);
177 } catch (AdaptException e) {
178 throw new DatabaseException(e);
179 } catch (BindingException e) {
180 throw new DatabaseException(e);
185 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
186 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
187 return new ConnectionImpl(context.getParent(graph), variable.property.predicate);
191 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
193 return Datatypes.getDatatype(Connection.class);
194 } catch (DatatypeConstructionException e) {
195 throw new DatabaseException(e);
202 @SCLValue(type = "VariableMap")
203 public static VariableMap structuralChildDomainProperties = new VariableMapImpl() {
205 public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
207 Map<String, PropertyInfo> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
208 PropertyInfo cp = connectionPoints.get(name);
209 if(cp == null) return null;
210 else return new StandardGraphPropertyVariable(graph, variable, cp.predicate);
214 public Map<String, Variable> collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map<String, Variable> map, boolean needSynchronized) throws DatabaseException {
216 if(graph.isImmutable(context)) {
218 Map<String, PropertyInfo> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
219 if(cps.size() == 0) return map;
221 if(map == null) map = new THashMap<String,Variable>(cps.size());
223 for(Map.Entry<String, PropertyInfo> entry : cps.entrySet()) {
224 String name = entry.getKey();
225 PropertyInfo cp = entry.getValue();
226 if(needSynchronized && !graph.isInstanceOf(cp.predicate, STR.SynchronizedConnectionRelation)) continue;
227 map.put(name, new StandardGraphPropertyVariable(graph, variable, cp.predicate));
234 Collection<Resource> predicates = graph.getPredicates(context);
236 for(Resource predicate : predicates) {
238 PropertyInfo info = graph.isImmutable(predicate) ?
239 graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
240 graph.syncRequest(new PossibleConnectionPointInfo(predicate));
243 if(map == null) map = new THashMap<String,Variable>(4);
244 if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue;
245 map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate));
257 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
258 final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
259 Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name);
260 if(cp != null) return cp;
261 return All.getStandardChildDomainPropertyVariable(graph, context, name);
265 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
266 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
267 StructuralResource2 STR = StructuralResource2.getInstance(graph);
268 map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false);
269 return All.getStandardChildDomainPropertyVariables(graph, context, map);
272 public Map<String,Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String,Variable> map) throws DatabaseException {
273 if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) {
274 return All.getStandardChildDomainPropertyVariables(graph, context, classification, map);
275 } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) {
276 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
277 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true);
278 } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) {
279 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
280 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false);
282 return super.getVariables(graph, context, classification, map);
287 static class StructuralRunContext extends ResourceRead<Resource> {
289 public StructuralRunContext(Resource resource) {
294 public Resource perform(ReadGraph graph) throws DatabaseException {
296 Layer0 L0 = Layer0.getInstance(graph);
297 SimulationResource SIMU = SimulationResource.getInstance(graph);
298 Resource model = graph.sync(new PossibleIndexRoot(resource));
299 if(graph.isInstanceOf(model, L0.RVIContext)) {
302 Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
303 if(configuration != null) {
304 if(graph.isInstanceOf(configuration, L0.RVIContext)) {
305 return configuration;
315 private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {
316 public SubstructureRequest(Variable context) {
321 public List<SubstructureElement> perform(ReadGraph graph) {
323 Resource type = variable.getPossibleType(graph);
326 return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable);
327 } catch (Throwable t) {
334 public static List<SubstructureElement> getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException {
335 StructuralResource2 STR = StructuralResource2.getInstance(graph);
336 Variable config = Variables.getConfigurationVariable(graph, context);
337 final Resource type = config.getPossibleType(graph);
339 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
340 return graph.syncRequest(new SubstructureRequest(config));
346 public static Map<String,Variable> getProcedural(ReadGraph graph, Variable context, List<SubstructureElement> elements, Map<String,Variable> map) throws DatabaseException {
348 if(map == null) map = new THashMap<String,Variable>();
350 MapList<String,org.simantics.structural2.procedural.Connection> conns = new MapList<String,org.simantics.structural2.procedural.Connection>();
351 for(SubstructureElement sub : elements) {
352 if(sub instanceof org.simantics.structural2.procedural.Connection) {
353 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub;
354 for(ConnectionPoint cp : conn.connectionPoints) {
355 if(cp instanceof Terminal) {
356 Terminal t = (Terminal)cp;
357 conns.add(t.component, conn);
363 Map<String,Component> proceduralChildren = new THashMap<String, Component>();
364 for(SubstructureElement sub : elements) {
365 if(sub instanceof Component) {
366 Component comp = (Component)sub;
367 proceduralChildren.put(comp.name, comp);
371 Collection<Object> nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context);
372 Set<String> used = new HashSet<String>(nodeChildren.size());
373 for(Object nodeChild : nodeChildren) {
374 @SuppressWarnings("rawtypes")
375 NodeSupport support = ((AbstractChildVariable)context).node.support;
376 @SuppressWarnings("rawtypes")
377 NodeManager manager = support.manager;
378 @SuppressWarnings("unchecked")
379 String name = manager.getName(nodeChild);
381 Component proceduralChild = proceduralChildren.get(name);
382 if(proceduralChild != null) {
383 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
387 for(Map.Entry<String, Component> entry : proceduralChildren.entrySet()) {
388 String name = entry.getKey();
389 if(used.contains(name)) continue;
390 Component proceduralChild = entry.getValue();
391 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
398 private static class ProceduralSubstructureRequest extends VariableRead<Map<String,Variable>> {
400 public ProceduralSubstructureRequest(Variable variable) {
405 public Map<String, Variable> perform(ReadGraph graph)
406 throws DatabaseException {
407 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
409 return getProcedural(graph, variable, elements, null);
415 public static class StructuralTypeOverrideMap extends ResourceRead<Map<Resource,Resource>> {
417 protected StructuralTypeOverrideMap(Resource composite) {
422 public Map<Resource, Resource> perform(ReadGraph graph) throws DatabaseException {
424 Layer0 L0 = Layer0.getInstance(graph);
426 StructuralResource2 STR = StructuralResource2.getInstance(graph);
428 CollectionSupport cs = graph.getService(CollectionSupport.class);
430 Map<Resource,Resource> result = null;
432 for(Resource override : graph.getObjects(resource, STR.HasTypeOverride)) {
433 Resource original = graph.getSingleObject(override, STR.TypeOverride_HasOriginalType);
434 Resource replacement = graph.getSingleObject(override, STR.TypeOverride_HasReplacementType);
435 if(result == null) result = cs.createMap(Resource.class);
436 result.put(original, replacement);
439 if(result == null) return Collections.emptyMap();
447 public static class StructuralOverrideData {
449 public int hashCode() {
450 final int prime = 31;
452 result = prime * result + ((actualRepresents == null) ? 0 : actualRepresents.hashCode());
453 result = prime * result + ((actualType == null) ? 0 : actualType.hashCode());
454 result = prime * result + ((overrideType == null) ? 0 : overrideType.hashCode());
458 public boolean equals(Object obj) {
463 if (getClass() != obj.getClass())
465 StructuralOverrideData other = (StructuralOverrideData) obj;
466 if (actualRepresents == null) {
467 if (other.actualRepresents != null)
469 } else if (!actualRepresents.equals(other.actualRepresents))
471 if (actualType == null) {
472 if (other.actualType != null)
474 } else if (!actualType.equals(other.actualType))
476 if (overrideType == null) {
477 if (other.overrideType != null)
479 } else if (!overrideType.equals(other.overrideType))
483 Resource actualRepresents;
485 Resource overrideType;
486 public StructuralOverrideData(Resource actualRepresents, Resource actualType, Resource overrideType) {
487 this.actualRepresents = actualRepresents;
488 this.actualType = actualType;
489 this.overrideType = overrideType;
492 public static StructuralOverrideData compute(ReadGraph graph, Variable context) throws DatabaseException {
493 return graph.syncRequest(new StructuralOverrideDataRequest(context));
496 public Resource type() {
497 if(overrideType != null)
502 public Resource represents() {
503 return actualRepresents;
508 private static class StructuralOverrideDataWalkRequest
509 extends TernaryRead<Variable, Resource, Resource, StructuralOverrideData> {
511 public StructuralOverrideDataWalkRequest(Variable component, Resource actualRepresents, Resource actualType) {
512 super(component, actualRepresents, actualType);
516 public StructuralOverrideData perform(ReadGraph graph) throws DatabaseException {
517 Variable component = parameter;
518 Resource actualRepresents = parameter2;
519 Resource actualType = parameter3;
520 // System.err.println(component.getURI(graph));
521 Resource represents = component.getPossibleRepresents(graph);
522 if (represents != null) {
523 Layer0 L0 = Layer0.getInstance(graph);
524 StructuralResource2 STR = StructuralResource2.getInstance(graph);
525 Resource container = graph
526 .syncRequest(new PossibleObjectWithType(represents, L0.PartOf, STR.Composite));
527 if (container != null) {
528 Map<Resource, Resource> overrides = graph.syncRequest(new StructuralTypeOverrideMap(container), TransientCacheListener.instance());
529 Resource override = overrides.get(actualType);
530 if (override != null) {
531 return new StructuralOverrideData(actualRepresents, actualType, override);
535 Variable parent = component.getParent(graph);
537 return new StructuralOverrideData(actualRepresents, actualType, null);
539 return graph.syncRequest(new StructuralOverrideDataWalkRequest(parent, represents, actualType), TransientCacheListener.instance());
544 public static class StructuralOverrideDataRequest extends VariableRead<StructuralOverrideData> {
546 public StructuralOverrideDataRequest(Variable component) {
551 public StructuralOverrideData perform(ReadGraph graph) throws DatabaseException {
553 Resource represents = variable.getPossibleRepresents(graph);
554 if(represents == null) {
555 String uri = variable.getPossiblePropertyValue(graph, "typeURI");
557 Resource actualType = graph.syncRequest(new org.simantics.db.common.primitiverequest.Resource(uri), TransientCacheAsyncListener.<Resource>instance());
558 if (graph.syncRequest(new IsInstanceOf(actualType, StructuralResource2.getInstance(graph).ReplaceableDefinedComponentType), TransientCacheListener.instance()) ) {
559 return graph.syncRequest(new StructuralOverrideDataWalkRequest(variable, null, actualType), TransientCacheListener.instance());
561 // can not have replaceable type
565 throw new DatabaseException("No type for " + variable.getURI(graph));
567 StructuralResource2 STR = StructuralResource2.getInstance(graph);
568 Resource possibleType = graph.getPossibleType(represents, STR.Component);
569 if (possibleType == null) {
570 possibleType = graph.getPossibleType(represents, Layer0.getInstance(graph).Entity);
571 if (possibleType == null)
574 if (graph.syncRequest(new IsInstanceOf(possibleType, STR.ReplaceableDefinedComponentType), TransientCacheListener.instance()) ) {
575 return graph.syncRequest(new StructuralOverrideDataWalkRequest(variable, represents, possibleType), TransientCacheListener.instance());
586 private static class StructureTypeAndChildMapRequest extends ResourceRead<Tuple2> {
588 protected StructureTypeAndChildMapRequest(Resource resource) {
593 public Tuple2 perform(ReadGraph graph) throws DatabaseException {
594 StructuralComponentClass clazz = StructuralComponentClass.get(graph, resource);
595 if (StructuralComponentClass.DEFINED.equals(clazz)) {
596 StructuralResource2 STR = StructuralResource2.getInstance(graph);
597 Resource def = graph.getSingleObject(resource, STR.IsDefinedBy);
598 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(def), TransientCacheListener.instance());
599 return new Tuple2(clazz, children);
601 return new Tuple2(clazz, null);
606 @SCLValue(type = "VariableMap")
607 public static VariableMap structuralChildDomainChildren = new VariableMapImpl() {
610 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
611 StructuralResource2 STR = StructuralResource2.getInstance(graph);
612 Resource type = context.getPossibleType(graph, STR.Component);
613 if(type == null) return null;
615 Tuple2 result = graph.syncRequest(new StructureTypeAndChildMapRequest(type), TransientCacheListener.instance());
616 StructuralComponentClass clazz = (StructuralComponentClass) result.c0;
618 if(StructuralComponentClass.PROCEDURAL.equals(clazz)) {
619 Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),
620 TransientCacheListener.<Map<String,Variable>>instance());
621 if(map != null) return map.get(name);
623 } else if (StructuralComponentClass.DEFINED.equals(clazz)) {
624 Map<String, Resource> children = (Map<String, Resource>) result.c1;
625 Resource child = children.get(name);
626 if(child == null) return null;
627 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
629 Resource represents = context.getPossibleRepresents(graph);
630 if(represents == null) return null;
631 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(represents), TransientCacheListener.instance());
632 Resource child = children.get(name);
633 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
639 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
641 Resource type = context.getPossibleType(graph);
642 if(type == null) return null;
644 StructuralComponentClass clazz = StructuralComponentClass.get(graph, type);
645 if(StructuralComponentClass.PROCEDURAL.equals(clazz)) {
646 Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),
647 TransientCacheListener.<Map<String,Variable>>instance());
648 if(mapPrime != null) {
650 map.putAll(mapPrime);
657 } else if (StructuralComponentClass.DEFINED.equals(clazz)) {
658 StructuralResource2 STR = StructuralResource2.getInstance(graph);
659 Resource def = graph.getSingleObject(type, STR.IsDefinedBy);
660 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(def), TransientCacheListener.instance());
661 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
663 Resource represents = context.getPossibleRepresents(graph);
664 if(represents == null) return null;
665 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(represents));
666 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
673 @SCLValue(type = "VariableMap")
674 public static VariableMap structuralRunDomainChildren = new VariableMapImpl() {
677 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
678 Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph)));
679 if(ctx == null) return null;
680 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(ctx));
681 Resource child = children.get(name);
682 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
686 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
687 Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph)));
688 if(ctx == null) return map;
689 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(ctx));
690 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
695 @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]")
696 public static List<Resource> connectionExtension(ReadGraph graph, List<Resource> rs) throws DatabaseException {
698 StructuralResource2 STR = StructuralResource2.getInstance(graph);
699 HashSet<Resource> extension = new HashSet<Resource>(8);
700 for(Resource r : rs) {
701 if(graph.isInstanceOf(r, STR.Connection)) {
702 extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
704 if(graph.isInstanceOf(r, STR.ConnectionJoin)) {
705 extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
709 HashSet<Resource> components = new HashSet<Resource>(8);
710 for(Resource r : extension) {
711 components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component)));
714 if(!extension.isEmpty()) {
715 ArrayList<Resource> result = new ArrayList<Resource>(rs.size() + extension.size());
717 result.addAll(extension);
718 result.addAll(components);
726 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
727 public static List<Issue> connectionValidator(ReadGraph graph, Resource component) throws DatabaseException {
729 if(!graph.hasStatement(component)) return Collections.emptyList();
731 ArrayList<Issue> result = new ArrayList<Issue>();
733 Layer0 L0 = Layer0.getInstance(graph);
734 StructuralResource2 sr = StructuralResource2.getInstance(graph);
736 Resource type = graph.getSingleType(component, sr.Component);
738 Set<Resource> requiredConnections = new HashSet<Resource>();
739 for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) {
740 Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN);
741 if(required != null && required)
742 requiredConnections.add(connectionRelation);
745 Set<Resource> connections = new HashSet<Resource>();
747 for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) {
748 connections.add(stm.getPredicate());
749 connections.addAll(graph.getSuperrelations(stm.getPredicate()));
752 for(Resource req : requiredConnections) {
753 if(!connections.contains(req)) {
754 result.add(new StandardIssue(sr.ConnectionValidationConstraint_ErrorIssue, component, req));
762 @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
763 public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
764 List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);
765 String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName);
766 return "'" + attributeName + "' should be connected.";
769 public static class InterfacePathMap extends VariableRead<GraphMap<Map<String,InterfaceResolution>>> {
771 public InterfacePathMap(Variable context) {
776 public GraphMap<Map<String,InterfaceResolution>> perform(ReadGraph graph) throws DatabaseException {
778 return new GraphMap<Map<String,InterfaceResolution>>() {
781 Map<String, InterfaceResolution> get(ReadGraph graph, String key) throws DatabaseException {
783 Variable child = variable.getChild(graph, key);
785 Map<String,InterfaceResolution> childMap = new THashMap<String,InterfaceResolution>();
786 Collection<InterfaceResolution> paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath");
788 for(InterfaceResolution r : paths) {
789 childMap.put(r.interfaceName, r);
802 public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException {
804 GraphMap<Map<String,InterfaceResolution>> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.<GraphMap<Map<String,InterfaceResolution>>>instance());
805 Map<String,InterfaceResolution> childMap = map.get(graph, component);
806 if(childMap == null) return "";
808 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.<PropertyInfo>instance());
810 InterfaceResolution match = childMap.get(info.name);
812 String comp = URIStringUtils.escape(component);
813 Variable newContext = context.getChild(graph, component);
814 return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint);
816 return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name);
821 public static class InterfaceResolution {
823 public Resource interfaceConnectionPoint;
824 public String interfaceName;
825 public String componentName;
826 public Resource connectionPoint;
828 public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) {
829 this.interfaceConnectionPoint = interfaceConnectionPoint;
830 this.interfaceName = interfaceName;
831 this.componentName = componentName;
832 this.connectionPoint = connectionPoint;
837 public static Collection<InterfaceResolution> computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException {
839 StructuralResource2 STR = StructuralResource2.getInstance(graph);
840 Resource type = variable.getPossibleType(graph);
842 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
843 ArrayList<InterfaceResolution> result = new ArrayList<InterfaceResolution>();
844 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
845 if(elements != null) {
846 for(SubstructureElement e : elements) {
847 if(e instanceof org.simantics.structural2.procedural.Connection) {
848 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e;
849 Interface inf = null;
850 for(ConnectionPoint cp : conn.connectionPoints) {
851 if(cp instanceof Interface) {
852 if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection.");
856 if(inf != null && conn.connectionPoints.size() > 1) {
857 Layer0 L0 = Layer0.getInstance(graph);
858 String cpName = URIStringUtils.escape( graph.<String>getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) );
859 for(ConnectionPoint cp : conn.connectionPoints) {
860 if(cp == inf) continue;
861 Terminal t = (Terminal)cp;
862 result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation));
873 final Collection<InterfaceResolution> interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type), TransientCacheListener.instance());
874 if(interfaces != null) return interfaces;
878 return BUILTIN_STRUCTURAL_CPS;
882 static class InterfacePathRequest extends VariableRead<Collection<InterfaceResolution>> {
884 public InterfacePathRequest(Variable variable) {
889 public Collection<InterfaceResolution> perform(ReadGraph graph) throws DatabaseException {
890 return computeInterfacePaths(graph, variable);
895 public static final Collection<InterfaceResolution> BUILTIN_STRUCTURAL_CPS = new ArrayList<InterfaceResolution>();
897 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
898 public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
899 return CompileStructuralValueRequest.compileAndEvaluate(graph, context);
902 public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException {
903 SCLContext sclContext = SCLContext.getCurrent();
904 Object oldGraph = sclContext.get("graph");
906 Function1<Object,Object> exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) {
907 protected String getExpressionText(ReadGraph graph) throws DatabaseException {
911 TransientCacheListener.instance());
912 sclContext.put("graph", graph);
913 return exp.apply(context);
914 } catch (DatabaseException e) {
915 throw (DatabaseException)e;
916 } catch (Throwable t) {
917 throw new DatabaseException(t);
919 sclContext.put("graph", oldGraph);
923 static abstract class InterfacePathProperty extends LazyPropertyVariable {
925 public InterfacePathProperty(Variable parent) {
926 super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY);
930 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
931 return getValue(graph);
936 static abstract class GraphMap<Value> {
938 abstract Value get(ReadGraph graph, String key) throws DatabaseException;