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;
72 import org.simantics.structural2.utils.StructuralUtils.StructuralComponentClass;
73 import org.simantics.structural2.variables.Connection;
74 import org.simantics.structural2.variables.StandardProceduralChildVariable;
75 import org.simantics.utils.datastructures.MapList;
76 import org.simantics.utils.datastructures.Pair;
78 import gnu.trove.map.hash.THashMap;
80 public class Functions {
82 @SCLValue(type="ValueAccessor")
83 public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() {
85 public Binding getBinding() {
86 return Bindings.STRING;
90 public void setValue(WriteGraph graph, Variable context, Object value)
91 throws DatabaseException {
93 if(getValue(graph, context) != null)
94 clearExpression(graph, context);
98 // Get all necessary data
99 String expression = (String)value;
100 Variable parent = context.getParent(graph);
101 if(!(parent instanceof AbstractPropertyVariable)) return;
102 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
103 Resource propertyResource = property.getRepresents(graph);
104 if(propertyResource == null) return;
105 Resource container = property.getContainerResource(graph);
106 if(container == null) return;
107 Resource predicate = property.getPossiblePredicateResource(graph);
108 if(predicate == null) return;
109 Statement stat = graph.getPossibleStatement(container, predicate);
110 StructuralResource2 STR = StructuralResource2.getInstance(graph);
113 boolean createNew = false;
114 if(stat.isAsserted(container))
116 else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) {
117 graph.deny(propertyResource);
120 Layer0 L0 = Layer0.getInstance(graph);
122 propertyResource = graph.newResource();
123 graph.claim(container, predicate, propertyResource);
124 graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue);
126 graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING);
129 private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException {
130 Variable parent = context.getParent(graph);
131 if(!(parent instanceof AbstractPropertyVariable)) return;
132 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
133 Resource container = property.getContainerResource(graph);
134 if(container == null) return;
135 Resource predicate = property.getPossiblePredicateResource(graph);
136 if(predicate == null) return;
137 graph.deny(container, predicate);
141 public Object getValue(ReadGraph graph, Variable context)
142 throws DatabaseException {
143 Variable parent = context.getParent(graph);
144 if(!(parent instanceof AbstractPropertyVariable))
146 AbstractPropertyVariable property = (AbstractPropertyVariable)parent;
147 Resource propertyResource = property.getPossibleRepresents(graph);
148 if(propertyResource == null) return null;
149 StructuralResource2 STR = StructuralResource2.getInstance(graph);
150 if(!graph.isInstanceOf(propertyResource, STR.SCLValue))
152 Layer0 L0 = Layer0.getInstance(graph);
153 return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression);
158 @SCLValue(type="ValueAccessor")
159 public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {
162 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
163 throw new UnsupportedOperationException();
166 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
167 throw new UnsupportedOperationException();
170 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
172 Object value = getValue(graph, context);
173 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
174 return Bindings.adapt(value, srcBinding, binding);
175 } catch (AdaptException e) {
176 throw new DatabaseException(e);
177 } catch (BindingException e) {
178 throw new DatabaseException(e);
183 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
184 StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
185 return new ConnectionImpl(variable.property.predicate);
189 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
191 return Datatypes.getDatatype(Connection.class);
192 } catch (DatatypeConstructionException e) {
193 throw new DatabaseException(e);
200 @SCLValue(type = "VariableMap")
201 public static VariableMap structuralChildDomainProperties = new VariableMapImpl() {
203 public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
205 Map<String, PropertyInfo> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
206 PropertyInfo cp = connectionPoints.get(name);
207 if(cp == null) return null;
208 else return new StandardGraphPropertyVariable(graph, variable, cp.predicate);
212 public Map<String, Variable> collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map<String, Variable> map, boolean needSynchronized) throws DatabaseException {
214 if(graph.isImmutable(context)) {
216 Map<String, PropertyInfo> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
217 if(cps.size() == 0) return map;
219 if(map == null) map = new THashMap<String,Variable>(cps.size());
221 for(Map.Entry<String, PropertyInfo> entry : cps.entrySet()) {
222 String name = entry.getKey();
223 PropertyInfo cp = entry.getValue();
224 if(needSynchronized && !graph.isInstanceOf(cp.predicate, STR.SynchronizedConnectionRelation)) continue;
225 map.put(name, new StandardGraphPropertyVariable(graph, variable, cp.predicate));
232 Collection<Resource> predicates = graph.getPredicates(context);
234 for(Resource predicate : predicates) {
236 PropertyInfo info = graph.isImmutable(predicate) ?
237 graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
238 graph.syncRequest(new PossibleConnectionPointInfo(predicate));
241 if(map == null) map = new THashMap<String,Variable>(4);
242 if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue;
243 map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate));
255 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
256 final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
257 Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name);
258 if(cp != null) return cp;
259 return All.getStandardChildDomainPropertyVariable(graph, context, name);
263 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
264 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
265 StructuralResource2 STR = StructuralResource2.getInstance(graph);
266 map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false);
267 return All.getStandardChildDomainPropertyVariables(graph, context, map);
270 public Map<String,Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String,Variable> map) throws DatabaseException {
271 if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) {
272 return All.getStandardChildDomainPropertyVariables(graph, context, classification, map);
273 } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) {
274 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
275 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true);
276 } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) {
277 StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
278 return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false);
280 return super.getVariables(graph, context, classification, map);
285 /*public static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {
287 public StructuralChildMapOfResource(Resource resource) {
292 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
293 StructuralResource2 STR = StructuralResource2.getInstance(graph);
294 Resource type = graph.getPossibleType(resource, STR.Component);
296 Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy);
297 if(definition != null) {
298 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
303 Map<String, Resource> directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));
304 return directChildren;
309 /*public static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {
311 public StructuralChildMapOfResourceT(Resource type) {
316 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
317 StructuralResource2 STR = StructuralResource2.getInstance(graph);
318 Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy);
319 if(definition != null) {
320 Map<String, Resource> map = graph.syncRequest(new UnescapedChildMapOfResource(definition));
324 return Collections.emptyMap();
329 /*static class StructuralRunChildMapOfResource extends ResourceRead<Map<String, Resource>> {
331 public StructuralRunChildMapOfResource(Resource resource) {
335 public Map<String, Resource> fromContext(ReadGraph graph, Resource context) throws DatabaseException {
336 return graph.sync(new StructuralChildMapOfResource(context));
340 public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {
342 Layer0 L0 = Layer0.getInstance(graph);
343 SimulationResource SIMU = SimulationResource.getInstance(graph);
344 Resource model = graph.sync(new PossibleIndexRoot(resource));
345 if(graph.isInstanceOf(model, L0.RVIContext)) {
346 return fromContext(graph, model);
348 Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
349 if(configuration != null) {
350 if(graph.isInstanceOf(configuration, L0.RVIContext)) {
351 return fromContext(graph, configuration);
355 return Collections.emptyMap();
361 static class StructuralRunContext extends ResourceRead<Resource> {
363 public StructuralRunContext(Resource resource) {
368 public Resource perform(ReadGraph graph) throws DatabaseException {
370 Layer0 L0 = Layer0.getInstance(graph);
371 SimulationResource SIMU = SimulationResource.getInstance(graph);
372 Resource model = graph.sync(new PossibleIndexRoot(resource));
373 if(graph.isInstanceOf(model, L0.RVIContext)) {
376 Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration);
377 if(configuration != null) {
378 if(graph.isInstanceOf(configuration, L0.RVIContext)) {
379 return configuration;
389 private static class SubstructureRequest extends VariableRead<List<SubstructureElement>> {
390 public SubstructureRequest(Variable context) {
395 public List<SubstructureElement> perform(ReadGraph graph) {
397 Resource type = variable.getPossibleType(graph);
400 return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable);
401 } catch (Throwable t) {
408 public static List<SubstructureElement> getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException {
409 StructuralResource2 STR = StructuralResource2.getInstance(graph);
410 final Resource type = context.getPossibleType(graph);
412 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
413 return graph.syncRequest(new SubstructureRequest(context));
419 public static Map<String,Variable> getProcedural(ReadGraph graph, Variable context, List<SubstructureElement> elements, Map<String,Variable> map) throws DatabaseException {
421 if(map == null) map = new THashMap<String,Variable>();
423 MapList<String,org.simantics.structural2.procedural.Connection> conns = new MapList<String,org.simantics.structural2.procedural.Connection>();
424 for(SubstructureElement sub : elements) {
425 if(sub instanceof org.simantics.structural2.procedural.Connection) {
426 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub;
427 for(ConnectionPoint cp : conn.connectionPoints) {
428 if(cp instanceof Terminal) {
429 Terminal t = (Terminal)cp;
430 conns.add(t.component, conn);
436 Map<String,Component> proceduralChildren = new THashMap<String, Component>();
437 for(SubstructureElement sub : elements) {
438 if(sub instanceof Component) {
439 Component comp = (Component)sub;
440 proceduralChildren.put(comp.name, comp);
444 Collection<Object> nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context);
445 Set<String> used = new HashSet<String>(nodeChildren.size());
446 for(Object nodeChild : nodeChildren) {
447 @SuppressWarnings("rawtypes")
448 NodeSupport support = ((AbstractChildVariable)context).node.support;
449 @SuppressWarnings("rawtypes")
450 NodeManager manager = support.manager;
451 @SuppressWarnings("unchecked")
452 String name = manager.getName(nodeChild);
454 Component proceduralChild = proceduralChildren.get(name);
455 if(proceduralChild != null) {
456 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
460 for(Map.Entry<String, Component> entry : proceduralChildren.entrySet()) {
461 String name = entry.getKey();
462 if(used.contains(name)) continue;
463 Component proceduralChild = entry.getValue();
464 map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name)));
471 private static class ProceduralSubstructureRequest extends VariableRead<Map<String,Variable>> {
473 public ProceduralSubstructureRequest(Variable variable) {
478 public Map<String, Variable> perform(ReadGraph graph)
479 throws DatabaseException {
480 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
482 return getProcedural(graph, variable, elements, null);
488 public static class StructuralTypeOverrideMap extends ResourceRead<Map<Resource,Resource>> {
490 protected StructuralTypeOverrideMap(Resource composite) {
495 public Map<Resource, Resource> perform(ReadGraph graph) throws DatabaseException {
497 Layer0 L0 = Layer0.getInstance(graph);
499 StructuralResource2 STR = StructuralResource2.getInstance(graph);
501 CollectionSupport cs = graph.getService(CollectionSupport.class);
503 Map<Resource,Resource> result = null;
505 for(Resource override : graph.getObjects(resource, STR.HasTypeOverride)) {
506 Resource original = graph.getSingleObject(override, STR.TypeOverride_HasOriginalType);
507 Resource replacement = graph.getSingleObject(override, STR.TypeOverride_HasReplacementType);
508 if(result == null) result = cs.createMap(Resource.class);
509 result.put(original, replacement);
512 if(result == null) return Collections.emptyMap();
520 public static class StructuralOverrideData {
522 public int hashCode() {
523 final int prime = 31;
525 result = prime * result + ((actualRepresents == null) ? 0 : actualRepresents.hashCode());
526 result = prime * result + ((actualType == null) ? 0 : actualType.hashCode());
527 result = prime * result + ((overrideType == null) ? 0 : overrideType.hashCode());
531 public boolean equals(Object obj) {
536 if (getClass() != obj.getClass())
538 StructuralOverrideData other = (StructuralOverrideData) obj;
539 if (actualRepresents == null) {
540 if (other.actualRepresents != null)
542 } else if (!actualRepresents.equals(other.actualRepresents))
544 if (actualType == null) {
545 if (other.actualType != null)
547 } else if (!actualType.equals(other.actualType))
549 if (overrideType == null) {
550 if (other.overrideType != null)
552 } else if (!overrideType.equals(other.overrideType))
556 Resource actualRepresents;
558 Resource overrideType;
559 public StructuralOverrideData(Resource actualRepresents, Resource actualType, Resource overrideType) {
560 this.actualRepresents = actualRepresents;
561 this.actualType = actualType;
562 this.overrideType = overrideType;
565 public static StructuralOverrideData compute(ReadGraph graph, Variable context) throws DatabaseException {
566 return graph.syncRequest(new StructuralOverrideDataRequest(context));
569 public Resource type() {
570 if(overrideType != null)
575 public Resource represents() {
576 return actualRepresents;
581 public static class StructuralOverrideDataRequest extends VariableRead<StructuralOverrideData> {
583 public StructuralOverrideDataRequest(Variable component) {
587 public StructuralOverrideData walk(ReadGraph graph, Variable component, Resource actualRepresents, Resource actualType) throws DatabaseException {
588 System.err.println("walk: " + component.getURI(graph));
589 Resource represents = component.getPossibleRepresents(graph);
590 if(represents != null) {
591 Layer0 L0 = Layer0.getInstance(graph);
592 StructuralResource2 STR = StructuralResource2.getInstance(graph);
593 Resource container = graph.syncRequest(new PossibleObjectWithType(represents, L0.PartOf, STR.Composite));
594 if(container != null) {
595 Map<Resource,Resource> overrides = graph.syncRequest(new StructuralTypeOverrideMap(container));
596 if(!overrides.isEmpty()) {
597 System.err.println("Check overrides for " + graph.getPossibleURI(actualType));
598 for(Resource r : overrides.keySet()) {
599 System.err.println("-available OR: " + graph.getPossibleURI(r) + " = > " + graph.getPossibleURI(overrides.get(r)));
602 Resource override = overrides.get(actualType);
603 if(override != null) {
604 System.err.println("Override! " + graph.getPossibleURI(actualType) + " = > " + graph.getPossibleURI(override));
605 return new StructuralOverrideData(actualRepresents, actualType, override);
609 Variable parent = component.getParent(graph);
610 if(parent == null) return new StructuralOverrideData(actualRepresents, actualType, null);
611 else return walk(graph, parent, represents, actualType);
615 public StructuralOverrideData perform(ReadGraph graph) throws DatabaseException {
617 if(variable.getURI(graph).endsWith("/Alternative/Panel2"))
618 System.err.println("walk1: " + variable.getURI(graph));
620 Resource represents = variable.getPossibleRepresents(graph);
621 if(represents == null) {
622 String uri = variable.getPossiblePropertyValue(graph, "typeURI");
624 Resource actualType = graph.syncRequest(new org.simantics.db.common.primitiverequest.Resource(uri), TransientCacheAsyncListener.<Resource>instance());
625 return walk(graph, variable, null, actualType);
627 throw new DatabaseException("No type for " + variable.getURI(graph));
629 return walk(graph, variable, represents, graph.getPossibleType(represents, Layer0.getInstance(graph).Entity));
637 @SCLValue(type = "VariableMap")
638 public static VariableMap structuralChildDomainChildren = new VariableMapImpl() {
640 // private Variable childWithTypeOverrides(ReadGraph graph, Variable parent, Resource child, String name) throws DatabaseException {
641 // return All.getStandardChildDomainChildVariable(graph, parent, child, name);
644 // private Map<String, Variable> childrenWithTypeOverrides(ReadGraph graph, Variable parent, Map<String, Resource> children, Map<String, Variable> map) throws DatabaseException {
645 // return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, parent, children, map);
649 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
651 System.err.println("foobar1: " + context.getURI(graph));
653 Resource type = context.getPossibleType(graph);
654 if(type == null) return null;
656 StructuralComponentClass clazz = StructuralComponentClass.get(graph, type);
657 if(StructuralComponentClass.PROCEDURAL.equals(clazz)) {
658 Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),
659 TransientCacheListener.<Map<String,Variable>>instance());
660 if(map != null) return map.get(name);
662 } else if (StructuralComponentClass.DEFINED.equals(clazz)) {
663 StructuralResource2 STR = StructuralResource2.getInstance(graph);
664 Resource def = graph.getSingleObject(type, STR.IsDefinedBy);
665 Map<String, Resource> children = graph.getChildren(def);
666 Resource child = children.get(name);
667 if(child == null) return null;
668 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
670 Resource represents = context.getPossibleRepresents(graph);
671 if(represents == null) return null;
672 Map<String, Resource> children = graph.getChildren(represents);
673 Resource child = children.get(name);
674 if(child == null) return null;
675 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
678 // StructuralOverrideData od = StructuralOverrideData.compute(graph, context);
679 // if(od.type() != null) {
680 // StructuralResource2 STR = StructuralResource2.getInstance(graph);
681 // if(graph.isInstanceOf(od.type(), STR.ProceduralComponentType)) {
682 // Map<String,Variable> map = graph.syncRequest(new ProceduralSubstructureRequest(context),
683 // TransientCacheListener.<Map<String,Variable>>instance());
684 // if(map != null) return map.get(name);
688 // Resource type = context.getPossibleType(graph, baseType);
690 // Resource represents = od.represents();
691 // if(represents == null) {
692 // Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(od.type()));
693 // Resource child = children.get(name);
694 // return childWithTypeOverrides(graph, context, child, name);
696 // Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));
697 // Resource child = children.get(name);
698 // return childWithTypeOverrides(graph, context, child, name);
703 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
705 System.err.println("foobar2: " + context.getURI(graph));
707 Resource type = context.getPossibleType(graph);
708 if(type == null) return null;
710 StructuralComponentClass clazz = StructuralComponentClass.get(graph, type);
711 if(StructuralComponentClass.PROCEDURAL.equals(clazz)) {
712 Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),
713 TransientCacheListener.<Map<String,Variable>>instance());
714 if(mapPrime != null) {
716 map.putAll(mapPrime);
723 } else if (StructuralComponentClass.DEFINED.equals(clazz)) {
724 StructuralResource2 STR = StructuralResource2.getInstance(graph);
725 Resource def = graph.getSingleObject(type, STR.IsDefinedBy);
726 Map<String, Resource> children = graph.getChildren(def);
727 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
729 Resource represents = context.getPossibleRepresents(graph);
730 if(represents == null) return null;
731 Map<String, Resource> children = graph.getChildren(represents);
732 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
736 // StructuralOverrideData od = StructuralOverrideData.compute(graph, context);
737 // if(od.type() != null) {
738 // StructuralResource2 STR = StructuralResource2.getInstance(graph);
739 // if(graph.isInstanceOf(od.type(), STR.ProceduralComponentType)) {
740 // Map<String,Variable> mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context),
741 // TransientCacheListener.<Map<String,Variable>>instance());
742 // if(mapPrime != null) {
744 // map.putAll(mapPrime);
753 // Resource represents = od.represents();
754 // if(represents == null) {
755 // Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResourceT(od.type()));
756 // return childrenWithTypeOverrides(graph, context, children, map);
758 // Map<String, Resource> children = graph.syncRequest(new StructuralChildMapOfResource(represents));
759 // return childrenWithTypeOverrides(graph, context, children, map);
765 @SCLValue(type = "VariableMap")
766 public static VariableMap structuralRunDomainChildren = new VariableMapImpl() {
769 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
770 Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph)));
771 if(ctx == null) return null;
772 Map<String, Resource> children = graph.getChildren(ctx);
773 Resource child = children.get(name);
774 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name);
778 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
779 Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph)));
780 if(ctx == null) return map;
781 Map<String, Resource> children = graph.getChildren(ctx);
782 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map);
787 @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]")
788 public static List<Resource> connectionExtension(ReadGraph graph, List<Resource> rs) throws DatabaseException {
790 StructuralResource2 STR = StructuralResource2.getInstance(graph);
791 HashSet<Resource> extension = new HashSet<Resource>(8);
792 for(Resource r : rs) {
793 if(graph.isInstanceOf(r, STR.Connection)) {
794 extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
796 if(graph.isInstanceOf(r, STR.ConnectionJoin)) {
797 extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.<Collection<Resource>>instance()));
801 HashSet<Resource> components = new HashSet<Resource>(8);
802 for(Resource r : extension) {
803 components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component)));
806 if(!extension.isEmpty()) {
807 ArrayList<Resource> result = new ArrayList<Resource>(rs.size() + extension.size());
809 result.addAll(extension);
810 result.addAll(components);
818 @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
819 public static List<Issue> connectionValidator(ReadGraph graph, Resource component) throws DatabaseException {
821 if(!graph.hasStatement(component)) return Collections.emptyList();
823 ArrayList<Issue> result = new ArrayList<Issue>();
825 Layer0 L0 = Layer0.getInstance(graph);
826 StructuralResource2 sr = StructuralResource2.getInstance(graph);
828 Resource type = graph.getSingleType(component, sr.Component);
830 Set<Resource> requiredConnections = new HashSet<Resource>();
831 for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) {
832 Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN);
833 if(required != null && required)
834 requiredConnections.add(connectionRelation);
837 Set<Resource> connections = new HashSet<Resource>();
839 for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) {
840 connections.add(stm.getPredicate());
841 connections.addAll(graph.getSuperrelations(stm.getPredicate()));
844 for(Resource req : requiredConnections) {
845 if(!connections.contains(req)) {
846 result.add(new StandardIssue(sr.ConnectionConstraint_ErrorIssue, component, req));
854 @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
855 public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
856 List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);
857 String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName);
858 return "'" + attributeName + "' should be connected.";
861 public static class InterfacePathMap extends VariableRead<GraphMap<Map<String,InterfaceResolution>>> {
863 public InterfacePathMap(Variable context) {
868 public GraphMap<Map<String,InterfaceResolution>> perform(ReadGraph graph) throws DatabaseException {
870 return new GraphMap<Map<String,InterfaceResolution>>() {
873 Map<String, InterfaceResolution> get(ReadGraph graph, String key) throws DatabaseException {
875 Variable child = variable.getChild(graph, key);
877 Map<String,InterfaceResolution> childMap = new THashMap<String,InterfaceResolution>();
878 Collection<InterfaceResolution> paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath");
880 for(InterfaceResolution r : paths) {
881 childMap.put(r.interfaceName, r);
894 public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException {
896 GraphMap<Map<String,InterfaceResolution>> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.<GraphMap<Map<String,InterfaceResolution>>>instance());
897 Map<String,InterfaceResolution> childMap = map.get(graph, component);
898 if(childMap == null) return "";
900 PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.<PropertyInfo>instance());
902 InterfaceResolution match = childMap.get(info.name);
904 String comp = URIStringUtils.escape(component);
905 Variable newContext = context.getChild(graph, component);
906 return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint);
908 return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name);
913 public static class InterfaceResolution {
915 public Resource interfaceConnectionPoint;
916 public String interfaceName;
917 public String componentName;
918 public Resource connectionPoint;
920 public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) {
921 this.interfaceConnectionPoint = interfaceConnectionPoint;
922 this.interfaceName = interfaceName;
923 this.componentName = componentName;
924 this.connectionPoint = connectionPoint;
929 public static Collection<InterfaceResolution> computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException {
931 StructuralResource2 STR = StructuralResource2.getInstance(graph);
932 Resource type = variable.getPossibleType(graph);
934 if(graph.isInstanceOf(type, STR.ProceduralComponentType)) {
935 ArrayList<InterfaceResolution> result = new ArrayList<InterfaceResolution>();
936 List<SubstructureElement> elements = getProceduralDesc(graph, variable);
937 if(elements != null) {
938 for(SubstructureElement e : elements) {
939 if(e instanceof org.simantics.structural2.procedural.Connection) {
940 org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e;
941 Interface inf = null;
942 for(ConnectionPoint cp : conn.connectionPoints) {
943 if(cp instanceof Interface) {
944 if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection.");
948 if(inf != null && conn.connectionPoints.size() > 1) {
949 Layer0 L0 = Layer0.getInstance(graph);
950 String cpName = URIStringUtils.escape( graph.<String>getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) );
951 for(ConnectionPoint cp : conn.connectionPoints) {
952 if(cp == inf) continue;
953 Terminal t = (Terminal)cp;
954 result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation));
965 final Collection<InterfaceResolution> interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type));
966 if(interfaces != null) return interfaces;
970 return BUILTIN_STRUCTURAL_CPS;
974 static class InterfacePathRequest extends VariableRead<Collection<InterfaceResolution>> {
976 public InterfacePathRequest(Variable variable) {
981 public Collection<InterfaceResolution> perform(ReadGraph graph) throws DatabaseException {
982 return computeInterfacePaths(graph, variable);
987 public static final Collection<InterfaceResolution> BUILTIN_STRUCTURAL_CPS = new ArrayList<InterfaceResolution>();
989 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
990 public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
991 return CompileStructuralValueRequest.compileAndEvaluate(graph, context);
994 public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException {
995 SCLContext sclContext = SCLContext.getCurrent();
996 Object oldGraph = sclContext.get("graph");
998 Function1<Variable,Object> exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) {
999 protected String getExpressionText(ReadGraph graph) throws DatabaseException {
1003 TransientCacheListener.<Function1<Variable,Object>>instance());
1004 sclContext.put("graph", graph);
1005 return exp.apply(context);
1006 } catch (DatabaseException e) {
1007 throw (DatabaseException)e;
1008 } catch (Throwable t) {
1009 throw new DatabaseException(t);
1011 sclContext.put("graph", oldGraph);
1015 static abstract class InterfacePathProperty extends LazyPropertyVariable {
1017 public InterfacePathProperty(Variable parent) {
1018 super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY);
1022 public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
1023 return getValue(graph);
1028 static abstract class GraphMap<Value> {
1030 abstract Value get(ReadGraph graph, String key) throws DatabaseException;