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.PossibleObjectWithType;
31 import org.simantics.db.common.request.ResourceRead;
32 import org.simantics.db.common.uri.UnescapedChildMapOfResource;
33 import org.simantics.db.exception.DatabaseException;
34 import org.simantics.db.layer0.function.All;
35 import org.simantics.db.layer0.function.StandardChildDomainChildren;
36 import org.simantics.db.layer0.request.PropertyInfo;
37 import org.simantics.db.layer0.request.PropertyInfoRequest;
38 import org.simantics.db.layer0.request.VariableRead;
39 import org.simantics.db.layer0.variable.AbstractChildVariable;
40 import org.simantics.db.layer0.variable.AbstractPropertyVariable;
41 import org.simantics.db.layer0.variable.LazyPropertyVariable;
42 import org.simantics.db.layer0.variable.NodeSupport;
43 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
44 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
45 import org.simantics.db.layer0.variable.ValueAccessor;
46 import org.simantics.db.layer0.variable.ValueAccessorWithBinding;
47 import org.simantics.db.layer0.variable.Variable;
48 import org.simantics.db.layer0.variable.VariableMap;
49 import org.simantics.db.layer0.variable.VariableMapImpl;
50 import org.simantics.db.layer0.variable.VariableNode;
51 import org.simantics.db.service.CollectionSupport;
52 import org.simantics.issues.common.IssueUtils;
53 import org.simantics.layer0.Layer0;
54 import org.simantics.scl.reflection.annotations.SCLValue;
55 import org.simantics.scl.runtime.SCLContext;
56 import org.simantics.scl.runtime.function.Function1;
57 import org.simantics.simulation.ontology.SimulationResource;
58 import org.simantics.simulator.variable.NodeManager;
59 import org.simantics.structural.stubs.StructuralResource2;
60 import org.simantics.structural2.procedural.Component;
61 import org.simantics.structural2.procedural.ConnectionPoint;
62 import org.simantics.structural2.procedural.Interface;
63 import org.simantics.structural2.procedural.SubstructureElement;
64 import org.simantics.structural2.procedural.Terminal;
65 import org.simantics.structural2.queries.ConnectionComponents;
66 import org.simantics.structural2.queries.ConnectionJoinComponents;
67 import org.simantics.structural2.queries.ConnectionPointMapOfResource;
68 import org.simantics.structural2.queries.PossibleConnectionPointInfo;
69 import org.simantics.structural2.scl.CompileStructuralValueRequest;
70 import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest;
71 import org.simantics.structural2.utils.StructuralUtils.StructuralComponentClass;
72 import org.simantics.structural2.variables.Connection;
73 import org.simantics.structural2.variables.StandardProceduralChildVariable;
74 import org.simantics.utils.datastructures.MapList;
76 import gnu.trove.map.hash.THashMap;
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 @SCLValue(type="ValueAccessor")
157 public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {
160 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
161 throw new UnsupportedOperationException();
164 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
165 throw new UnsupportedOperationException();
168 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
170 Object value = getValue(graph, context);
171 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
172 return Bindings.adapt(value, srcBinding, binding);
173 } catch (AdaptException e) {
174 throw new DatabaseException(e);
175 } catch (BindingException e) {
176 throw new DatabaseException(e);
181 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
182 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
183 return new ConnectionImpl(context.getParent(graph), variable.property.predicate);
187 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
189 return Datatypes.getDatatype(Connection.class);
190 } catch (DatatypeConstructionException e) {
191 throw new DatabaseException(e);
198 @SCLValue(type = "VariableMap")
199 public static VariableMap structuralChildDomainProperties = new VariableMapImpl() {
201 public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
203 Map<String, PropertyInfo> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
204 PropertyInfo cp = connectionPoints.get(name);
205 if(cp == null) return null;
206 else return new StandardGraphPropertyVariable(graph, variable, cp.predicate);
210 public Map<String, Variable> collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map<String, Variable> map, boolean needSynchronized) throws DatabaseException {
212 if(graph.isImmutable(context)) {
214 Map<String, PropertyInfo> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
215 if(cps.size() == 0) return map;
217 if(map == null) map = new THashMap<String,Variable>(cps.size());
219 for(Map.Entry<String, PropertyInfo> entry : cps.entrySet()) {
220 String name = entry.getKey();
221 PropertyInfo cp = entry.getValue();
222 if(needSynchronized && !graph.isInstanceOf(cp.predicate, STR.SynchronizedConnectionRelation)) continue;
223 map.put(name, new StandardGraphPropertyVariable(graph, variable, cp.predicate));
230 Collection<Resource> predicates = graph.getPredicates(context);
232 for(Resource predicate : predicates) {
234 PropertyInfo info = graph.isImmutable(predicate) ?
235 graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
236 graph.syncRequest(new PossibleConnectionPointInfo(predicate));
239 if(map == null) map = new THashMap<String,Variable>(4);
240 if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue;
241 map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate));
253 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
254 final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
255 Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name);
256 if(cp != null) return cp;
257 return All.getStandardChildDomainPropertyVariable(graph, context, name);
261 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
262 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
263 StructuralResource2 STR = StructuralResource2.getInstance(graph);
264 map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false);
265 return All.getStandardChildDomainPropertyVariables(graph, context, map);
268 public Map<String,Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String,Variable> map) throws DatabaseException {
269 if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) {
270 return All.getStandardChildDomainPropertyVariables(graph, context, classification, map);
271 } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) {
272 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
273 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true);
274 } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) {
275 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
276 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false);
278 return super.getVariables(graph, context, classification, map);
283 static class StructuralRunContext extends ResourceRead<Resource> {
285 public StructuralRunContext(Resource resource) {
290 public Resource perform(ReadGraph graph) throws DatabaseException {
292 Layer0 L0 = Layer0.getInstance(graph);
293 SimulationResource SIMU = SimulationResource.getInstance(graph);
294 Resource model = graph.sync(new PossibleIndexRoot(resource));
295 if(graph.isInstanceOf(model, L0.RVIContext)) {
298 Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
299 if(configuration != null) {
300 if(graph.isInstanceOf(configuration, L0.RVIContext)) {
301 return configuration;
311 public static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {
313 public StructuralChildMapOfResource(Resource resource) {
318 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
319 StructuralResource2 STR = StructuralResource2.getInstance(graph);
320 Resource type = graph.getPossibleType(resource, STR.Component);
322 Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy);
323 if(definition != null) {
324 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
329 Map<String, Resource> directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));
330 return directChildren;
335 public static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {
337 public StructuralChildMapOfResourceT(Resource resource) {
342 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
343 StructuralResource2 STR = StructuralResource2.getInstance(graph);
344 Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);
345 if(definition != null) {
346 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
350 return Collections.emptyMap();
355 static class StructuralRunChildMapOfResource extends ResourceRead<Map<String, Resource>> {
357 public StructuralRunChildMapOfResource(Resource resource) {
361 public Map<String, Resource> fromContext(ReadGraph graph, Resource context) throws DatabaseException {
362 return graph.sync(new StructuralChildMapOfResource(context));
366 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
368 Layer0 L0 = Layer0.getInstance(graph);
369 SimulationResource SIMU = SimulationResource.getInstance(graph);
370 Resource model = graph.sync(new PossibleIndexRoot(resource));
371 if(graph.isInstanceOf(model, L0.RVIContext)) {
372 return fromContext(graph, model);
374 Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
375 if(configuration != null) {
376 if(graph.isInstanceOf(configuration, L0.RVIContext)) {
377 return fromContext(graph, configuration);
381 return Collections.emptyMap();
387 private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {
388 public SubstructureRequest(Variable context) {
393 public List<SubstructureElement> perform(ReadGraph graph) {
395 Resource type = variable.getPossibleType(graph);
398 return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable);
399 } catch (Throwable t) {
406 public static List<SubstructureElement> getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException {
407 StructuralResource2 STR = StructuralResource2.getInstance(graph);
408 final Resource type = context.getPossibleType(graph);
410 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
411 return graph.syncRequest(new SubstructureRequest(context));
417 public static Map<String,Variable> getProcedural(ReadGraph graph, Variable context, List<SubstructureElement> elements, Map<String,Variable> map) throws DatabaseException {
419 if(map == null) map = new THashMap<String,Variable>();
421 MapList<String,org.simantics.structural2.procedural.Connection> conns = new MapList<String,org.simantics.structural2.procedural.Connection>();
422 for(SubstructureElement sub : elements) {
423 if(sub instanceof org.simantics.structural2.procedural.Connection) {
424 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub;
425 for(ConnectionPoint cp : conn.connectionPoints) {
426 if(cp instanceof Terminal) {
427 Terminal t = (Terminal)cp;
428 conns.add(t.component, conn);
434 Map<String,Component> proceduralChildren = new THashMap<String, Component>();
435 for(SubstructureElement sub : elements) {
436 if(sub instanceof Component) {
437 Component comp = (Component)sub;
438 proceduralChildren.put(comp.name, comp);
442 Collection<Object> nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context);
443 Set<String> used = new HashSet<String>(nodeChildren.size());
444 for(Object nodeChild : nodeChildren) {
445 @SuppressWarnings("rawtypes")
446 NodeSupport support = ((AbstractChildVariable)context).node.support;
447 @SuppressWarnings("rawtypes")
448 NodeManager manager = support.manager;
449 @SuppressWarnings("unchecked")
450 String name = manager.getName(nodeChild);
452 Component proceduralChild = proceduralChildren.get(name);
453 if(proceduralChild != null) {
454 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
458 for(Map.Entry<String, Component> entry : proceduralChildren.entrySet()) {
459 String name = entry.getKey();
460 if(used.contains(name)) continue;
461 Component proceduralChild = entry.getValue();
462 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
469 private static class ProceduralSubstructureRequest extends VariableRead<Map<String,Variable>> {
471 public ProceduralSubstructureRequest(Variable variable) {
476 public Map<String, Variable> perform(ReadGraph graph)
477 throws DatabaseException {
478 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
480 return getProcedural(graph, variable, elements, null);
486 public static class StructuralTypeOverrideMap extends ResourceRead<Map<Resource,Resource>> {
488 protected StructuralTypeOverrideMap(Resource composite) {
493 public Map<Resource, Resource> perform(ReadGraph graph) throws DatabaseException {
495 Layer0 L0 = Layer0.getInstance(graph);
497 StructuralResource2 STR = StructuralResource2.getInstance(graph);
499 CollectionSupport cs = graph.getService(CollectionSupport.class);
501 Map<Resource,Resource> result = null;
503 for(Resource override : graph.getObjects(resource, STR.HasTypeOverride)) {
504 Resource original = graph.getSingleObject(override, STR.TypeOverride_HasOriginalType);
505 Resource replacement = graph.getSingleObject(override, STR.TypeOverride_HasReplacementType);
506 if(result == null) result = cs.createMap(Resource.class);
507 result.put(original, replacement);
510 if(result == null) return Collections.emptyMap();
518 public static class StructuralOverrideData {
520 public int hashCode() {
521 final int prime = 31;
523 result = prime * result + ((actualRepresents == null) ? 0 : actualRepresents.hashCode());
524 result = prime * result + ((actualType == null) ? 0 : actualType.hashCode());
525 result = prime * result + ((overrideType == null) ? 0 : overrideType.hashCode());
529 public boolean equals(Object obj) {
534 if (getClass() != obj.getClass())
536 StructuralOverrideData other = (StructuralOverrideData) obj;
537 if (actualRepresents == null) {
538 if (other.actualRepresents != null)
540 } else if (!actualRepresents.equals(other.actualRepresents))
542 if (actualType == null) {
543 if (other.actualType != null)
545 } else if (!actualType.equals(other.actualType))
547 if (overrideType == null) {
548 if (other.overrideType != null)
550 } else if (!overrideType.equals(other.overrideType))
554 Resource actualRepresents;
556 Resource overrideType;
557 public StructuralOverrideData(Resource actualRepresents, Resource actualType, Resource overrideType) {
558 this.actualRepresents = actualRepresents;
559 this.actualType = actualType;
560 this.overrideType = overrideType;
563 public static StructuralOverrideData compute(ReadGraph graph, Variable context) throws DatabaseException {
564 return graph.syncRequest(new StructuralOverrideDataRequest(context));
567 public Resource type() {
568 if(overrideType != null)
573 public Resource represents() {
574 return actualRepresents;
579 public static class StructuralOverrideDataRequest extends VariableRead<StructuralOverrideData> {
581 public StructuralOverrideDataRequest(Variable component) {
585 public StructuralOverrideData walk(ReadGraph graph, Variable component, Resource actualRepresents, Resource actualType) throws DatabaseException {
586 Resource represents = component.getPossibleRepresents(graph);
587 if(represents != null) {
588 Layer0 L0 = Layer0.getInstance(graph);
589 StructuralResource2 STR = StructuralResource2.getInstance(graph);
590 Resource container = graph.syncRequest(new PossibleObjectWithType(represents, L0.PartOf, STR.Composite));
591 if(container != null) {
592 Map<Resource,Resource> overrides = graph.syncRequest(new StructuralTypeOverrideMap(container));
593 Resource override = overrides.get(actualType);
594 if(override != null) {
595 return new StructuralOverrideData(actualRepresents, actualType, override);
599 Variable parent = component.getParent(graph);
600 if(parent == null) return new StructuralOverrideData(actualRepresents, actualType, null);
601 else return walk(graph, parent, represents, actualType);
605 public StructuralOverrideData perform(ReadGraph graph) throws DatabaseException {
607 Resource represents = variable.getPossibleRepresents(graph);
608 if(represents == null) {
609 String uri = variable.getPossiblePropertyValue(graph, "typeURI");
611 Resource actualType = graph.syncRequest(new org.simantics.db.common.primitiverequest.Resource(uri), TransientCacheAsyncListener.<Resource>instance());
612 return walk(graph, variable, null, actualType);
614 throw new DatabaseException("No type for " + variable.getURI(graph));
616 return walk(graph, variable, represents, graph.getPossibleType(represents, Layer0.getInstance(graph).Entity));
624 @SCLValue(type = "VariableMap")
625 public static VariableMap structuralChildDomainChildren = new VariableMapImpl() {
628 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
630 Resource type = context.getPossibleType(graph);
631 if(type == null) return null;
633 StructuralComponentClass clazz = StructuralComponentClass.get(graph, type);
634 if(StructuralComponentClass.PROCEDURAL.equals(clazz)) {
635 Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),
636 TransientCacheListener.<Map<String,Variable>>instance());
637 if(map != null) return map.get(name);
639 } else if (StructuralComponentClass.DEFINED.equals(clazz)) {
640 StructuralResource2 STR = StructuralResource2.getInstance(graph);
641 Resource def = graph.getSingleObject(type, STR.IsDefinedBy);
642 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(def));
643 Resource child = children.get(name);
644 if(child == null) return null;
645 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
647 Resource represents = context.getPossibleRepresents(graph);
648 if(represents == null) return null;
649 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(represents));
650 Resource child = children.get(name);
651 if(child == null) return null;
652 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
658 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
660 Resource type = context.getPossibleType(graph);
661 if(type == null) return null;
663 StructuralComponentClass clazz = StructuralComponentClass.get(graph, type);
664 if(StructuralComponentClass.PROCEDURAL.equals(clazz)) {
665 Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),
666 TransientCacheListener.<Map<String,Variable>>instance());
667 if(mapPrime != null) {
669 map.putAll(mapPrime);
676 } else if (StructuralComponentClass.DEFINED.equals(clazz)) {
677 StructuralResource2 STR = StructuralResource2.getInstance(graph);
678 Resource def = graph.getSingleObject(type, STR.IsDefinedBy);
679 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(def));
680 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
682 Resource represents = context.getPossibleRepresents(graph);
683 if(represents == null) return null;
684 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(represents));
685 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
692 @SCLValue(type = "VariableMap")
693 public static VariableMap structuralRunDomainChildren = new VariableMapImpl() {
696 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
697 Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph)));
698 if(ctx == null) return null;
699 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(ctx));
700 Resource child = children.get(name);
701 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
705 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
706 Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph)));
707 if(ctx == null) return map;
708 Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(ctx));
709 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
714 @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]")
715 public static List<Resource> connectionExtension(ReadGraph graph, List<Resource> rs) throws DatabaseException {
717 StructuralResource2 STR = StructuralResource2.getInstance(graph);
718 HashSet<Resource> extension = new HashSet<Resource>(8);
719 for(Resource r : rs) {
720 if(graph.isInstanceOf(r, STR.Connection)) {
721 extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
723 if(graph.isInstanceOf(r, STR.ConnectionJoin)) {
724 extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
728 HashSet<Resource> components = new HashSet<Resource>(8);
729 for(Resource r : extension) {
730 components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component)));
733 if(!extension.isEmpty()) {
734 ArrayList<Resource> result = new ArrayList<Resource>(rs.size() + extension.size());
736 result.addAll(extension);
737 result.addAll(components);
745 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
746 public static List<Issue> connectionValidator(ReadGraph graph, Resource component) throws DatabaseException {
748 if(!graph.hasStatement(component)) return Collections.emptyList();
750 ArrayList<Issue> result = new ArrayList<Issue>();
752 Layer0 L0 = Layer0.getInstance(graph);
753 StructuralResource2 sr = StructuralResource2.getInstance(graph);
755 Resource type = graph.getSingleType(component, sr.Component);
757 Set<Resource> requiredConnections = new HashSet<Resource>();
758 for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) {
759 Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN);
760 if(required != null && required)
761 requiredConnections.add(connectionRelation);
764 Set<Resource> connections = new HashSet<Resource>();
766 for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) {
767 connections.add(stm.getPredicate());
768 connections.addAll(graph.getSuperrelations(stm.getPredicate()));
771 for(Resource req : requiredConnections) {
772 if(!connections.contains(req)) {
773 result.add(new StandardIssue(sr.ConnectionConstraint_ErrorIssue, component, req));
781 @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
782 public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
783 List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);
784 String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName);
785 return "'" + attributeName + "' should be connected.";
788 public static class InterfacePathMap extends VariableRead<GraphMap<Map<String,InterfaceResolution>>> {
790 public InterfacePathMap(Variable context) {
795 public GraphMap<Map<String,InterfaceResolution>> perform(ReadGraph graph) throws DatabaseException {
797 return new GraphMap<Map<String,InterfaceResolution>>() {
800 Map<String, InterfaceResolution> get(ReadGraph graph, String key) throws DatabaseException {
802 Variable child = variable.getChild(graph, key);
804 Map<String,InterfaceResolution> childMap = new THashMap<String,InterfaceResolution>();
805 Collection<InterfaceResolution> paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath");
807 for(InterfaceResolution r : paths) {
808 childMap.put(r.interfaceName, r);
821 public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException {
823 GraphMap<Map<String,InterfaceResolution>> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.<GraphMap<Map<String,InterfaceResolution>>>instance());
824 Map<String,InterfaceResolution> childMap = map.get(graph, component);
825 if(childMap == null) return "";
827 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.<PropertyInfo>instance());
829 InterfaceResolution match = childMap.get(info.name);
831 String comp = URIStringUtils.escape(component);
832 Variable newContext = context.getChild(graph, component);
833 return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint);
835 return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name);
840 public static class InterfaceResolution {
842 public Resource interfaceConnectionPoint;
843 public String interfaceName;
844 public String componentName;
845 public Resource connectionPoint;
847 public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) {
848 this.interfaceConnectionPoint = interfaceConnectionPoint;
849 this.interfaceName = interfaceName;
850 this.componentName = componentName;
851 this.connectionPoint = connectionPoint;
856 public static Collection<InterfaceResolution> computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException {
858 StructuralResource2 STR = StructuralResource2.getInstance(graph);
859 Resource type = variable.getPossibleType(graph);
861 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
862 ArrayList<InterfaceResolution> result = new ArrayList<InterfaceResolution>();
863 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
864 if(elements != null) {
865 for(SubstructureElement e : elements) {
866 if(e instanceof org.simantics.structural2.procedural.Connection) {
867 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e;
868 Interface inf = null;
869 for(ConnectionPoint cp : conn.connectionPoints) {
870 if(cp instanceof Interface) {
871 if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection.");
875 if(inf != null && conn.connectionPoints.size() > 1) {
876 Layer0 L0 = Layer0.getInstance(graph);
877 String cpName = URIStringUtils.escape( graph.<String>getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) );
878 for(ConnectionPoint cp : conn.connectionPoints) {
879 if(cp == inf) continue;
880 Terminal t = (Terminal)cp;
881 result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation));
892 final Collection<InterfaceResolution> interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type));
893 if(interfaces != null) return interfaces;
897 return BUILTIN_STRUCTURAL_CPS;
901 static class InterfacePathRequest extends VariableRead<Collection<InterfaceResolution>> {
903 public InterfacePathRequest(Variable variable) {
908 public Collection<InterfaceResolution> perform(ReadGraph graph) throws DatabaseException {
909 return computeInterfacePaths(graph, variable);
914 public static final Collection<InterfaceResolution> BUILTIN_STRUCTURAL_CPS = new ArrayList<InterfaceResolution>();
916 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
917 public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
918 return CompileStructuralValueRequest.compileAndEvaluate(graph, context);
921 public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException {
922 SCLContext sclContext = SCLContext.getCurrent();
923 Object oldGraph = sclContext.get("graph");
925 Function1<Variable,Object> exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) {
926 protected String getExpressionText(ReadGraph graph) throws DatabaseException {
930 TransientCacheListener.<Function1<Variable,Object>>instance());
931 sclContext.put("graph", graph);
932 return exp.apply(context);
933 } catch (DatabaseException e) {
934 throw (DatabaseException)e;
935 } catch (Throwable t) {
936 throw new DatabaseException(t);
938 sclContext.put("graph", oldGraph);
942 static abstract class InterfacePathProperty extends LazyPropertyVariable {
944 public InterfacePathProperty(Variable parent) {
945 super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY);
949 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
950 return getValue(graph);
955 static abstract class GraphMap<Value> {
957 abstract Value get(ReadGraph graph, String key) throws DatabaseException;