X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.structural2%2Fsrc%2Forg%2Fsimantics%2Fstructural2%2FFunctions.java;h=8bf4e3df68b6ac62dc30b2575ddb3eb75b1b9bf2;hp=70b9ab03942b400eb16604ff5e93d354618489ae;hb=45ddae414b7f632d52546c3c46b0f6d2b4ab37af;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java b/bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java index 70b9ab039..8bf4e3df6 100644 --- a/bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java +++ b/bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java @@ -1,847 +1,942 @@ -package org.simantics.structural2; - - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.simantics.databoard.Bindings; -import org.simantics.databoard.Datatypes; -import org.simantics.databoard.adapter.AdaptException; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.error.BindingException; -import org.simantics.databoard.binding.error.DatatypeConstructionException; -import org.simantics.databoard.type.Datatype; -import org.simantics.databoard.util.URIStringUtils; -import org.simantics.db.Issue; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Statement; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.issue.StandardIssue; -import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; -import org.simantics.db.common.procedure.adapter.TransientCacheListener; -import org.simantics.db.common.request.ObjectsWithType; -import org.simantics.db.common.request.ResourceRead; -import org.simantics.db.common.uri.UnescapedChildMapOfResource; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.function.All; -import org.simantics.db.layer0.function.StandardChildDomainChildren; -import org.simantics.db.layer0.request.PossibleModel; -import org.simantics.db.layer0.request.PropertyInfo; -import org.simantics.db.layer0.request.PropertyInfoRequest; -import org.simantics.db.layer0.request.VariableRead; -import org.simantics.db.layer0.variable.AbstractChildVariable; -import org.simantics.db.layer0.variable.AbstractPropertyVariable; -import org.simantics.db.layer0.variable.LazyPropertyVariable; -import org.simantics.db.layer0.variable.NodeSupport; -import org.simantics.db.layer0.variable.StandardGraphChildVariable; -import org.simantics.db.layer0.variable.StandardGraphPropertyVariable; -import org.simantics.db.layer0.variable.ValueAccessor; -import org.simantics.db.layer0.variable.ValueAccessorWithBinding; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.VariableMap; -import org.simantics.db.layer0.variable.VariableMapImpl; -import org.simantics.db.layer0.variable.VariableNode; -import org.simantics.issues.common.IssueUtils; -import org.simantics.layer0.Layer0; -import org.simantics.scl.reflection.annotations.SCLValue; -import org.simantics.scl.runtime.SCLContext; -import org.simantics.scl.runtime.function.Function1; -import org.simantics.simulation.ontology.SimulationResource; -import org.simantics.simulator.variable.NodeManager; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.structural2.procedural.Component; -import org.simantics.structural2.procedural.ConnectionPoint; -import org.simantics.structural2.procedural.Interface; -import org.simantics.structural2.procedural.SubstructureElement; -import org.simantics.structural2.procedural.Terminal; -import org.simantics.structural2.queries.ConnectionComponents; -import org.simantics.structural2.queries.ConnectionJoinComponents; -import org.simantics.structural2.queries.ConnectionPointMapOfResource; -import org.simantics.structural2.queries.PossibleConnectionPointInfo; -import org.simantics.structural2.scl.CompileStructuralValueRequest; -import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest; -import org.simantics.structural2.variables.Connection; -import org.simantics.structural2.variables.ConnectionBrowser; -import org.simantics.structural2.variables.StandardProceduralChildVariable; -import org.simantics.structural2.variables.VariableConnectionPointDescriptor; -import org.simantics.utils.datastructures.MapList; - -import gnu.trove.map.hash.THashMap; -import gnu.trove.set.hash.THashSet; - -public class Functions { - - @SCLValue(type="ValueAccessor") - public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() { - - public Binding getBinding() { - return Bindings.STRING; - } - - @Override - public void setValue(WriteGraph graph, Variable context, Object value) - throws DatabaseException { - if(value == null) { - if(getValue(graph, context) != null) - clearExpression(graph, context); - return; - } - - // Get all necessary data - String expression = (String)value; - Variable parent = context.getParent(graph); - if(!(parent instanceof AbstractPropertyVariable)) return; - AbstractPropertyVariable property = (AbstractPropertyVariable)parent; - Resource propertyResource = property.getRepresents(graph); - if(propertyResource == null) return; - Resource container = property.getContainerResource(graph); - if(container == null) return; - Resource predicate = property.getPossiblePredicateResource(graph); - if(predicate == null) return; - Statement stat = graph.getPossibleStatement(container, predicate); - StructuralResource2 STR = StructuralResource2.getInstance(graph); - - // Write - boolean createNew = false; - if(stat.isAsserted(container)) - createNew = true; - else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) { - graph.deny(propertyResource); - createNew = true; - } - Layer0 L0 = Layer0.getInstance(graph); - if(createNew) { - propertyResource = graph.newResource(); - graph.claim(container, predicate, propertyResource); - graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue); - } - graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING); - } - - private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException { - Variable parent = context.getParent(graph); - if(!(parent instanceof AbstractPropertyVariable)) return; - AbstractPropertyVariable property = (AbstractPropertyVariable)parent; - Resource container = property.getContainerResource(graph); - if(container == null) return; - Resource predicate = property.getPossiblePredicateResource(graph); - if(predicate == null) return; - graph.deny(container, predicate); - } - - @Override - public Object getValue(ReadGraph graph, Variable context) - throws DatabaseException { - Variable parent = context.getParent(graph); - if(!(parent instanceof AbstractPropertyVariable)) - return null; - AbstractPropertyVariable property = (AbstractPropertyVariable)parent; - Resource propertyResource = property.getPossibleRepresents(graph); - if(propertyResource == null) return null; - StructuralResource2 STR = StructuralResource2.getInstance(graph); - if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) - return null; - Layer0 L0 = Layer0.getInstance(graph); - return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression); - } - - }; - - static class ConnectionImpl implements Connection { - - final private StandardGraphPropertyVariable connectionPoint; - - public ConnectionImpl(StandardGraphPropertyVariable connectionPoint) { - this.connectionPoint = connectionPoint; - } - - @Override - public Collection getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException { - Set result = new THashSet(); - for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) { - result.add(desc.getVariable(graph)); - } - return result; - } - - @Override - public Collection getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException { - Set result = new THashSet(); - for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) { - result.add(desc.getURI(graph)); - } - return result; - } - - @Override - public Collection getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException { - return ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType); - } - - } - - @SCLValue(type="ValueAccessor") - public static final ValueAccessor connectionValueAccessor = new ValueAccessor() { - - @Override - public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException { - throw new UnsupportedOperationException(); - } - - public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException { - throw new UnsupportedOperationException(); - } - - public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { - try { - Object value = getValue(graph, context); - Binding srcBinding = Bindings.OBJECT.getContentBinding(value); - return Bindings.adapt(value, srcBinding, binding); - } catch (AdaptException e) { - throw new DatabaseException(e); - } catch (BindingException e) { - throw new DatabaseException(e); - } - } - - @Override - public Object getValue(ReadGraph graph, Variable context) throws DatabaseException { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - return new ConnectionImpl(variable); - } - - @Override - public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException { - try { - return Datatypes.getDatatype(Connection.class); - } catch (DatatypeConstructionException e) { - throw new DatabaseException(e); - } - } - - }; - - - @SCLValue(type = "VariableMap") - public static VariableMap structuralChildDomainProperties = new VariableMapImpl() { - - public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException { - - Map connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.>instance()); - Resource cp = connectionPoints.get(name); - if(cp == null) return null; - else return new StandardGraphPropertyVariable(graph, variable, cp); - - } - - public Map collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map map, boolean needSynchronized) throws DatabaseException { - - if(graph.isImmutable(context)) { - - Map cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.>instance()); - if(cps.size() == 0) return map; - - if(map == null) map = new THashMap(cps.size()); - - for(Map.Entry entry : cps.entrySet()) { - String name = entry.getKey(); - Resource cp = entry.getValue(); - if(needSynchronized && !graph.isInstanceOf(cp, STR.SynchronizedConnectionRelation)) continue; - map.put(name, new StandardGraphPropertyVariable(graph, variable, cp)); - } - - return map; - - } else { - - Collection predicates = graph.getPredicates(context); - - for(Resource predicate : predicates) { - - PropertyInfo info = graph.isImmutable(predicate) ? - graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.instance()) : - graph.syncRequest(new PossibleConnectionPointInfo(predicate)); - - if(info != null) { - if(map == null) map = new THashMap(4); - if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue; - map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate)); - } - - } - - return map; - - } - - } - - @Override - public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - final StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name); - if(cp != null) return cp; - return All.getStandardChildDomainPropertyVariable(graph, context, name); - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - StructuralResource2 STR = StructuralResource2.getInstance(graph); - map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false); - return All.getStandardChildDomainPropertyVariables(graph, context, map); - } - - public Map getVariables(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { - if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) { - return All.getStandardChildDomainPropertyVariables(graph, context, classification, map); - } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) { - StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true); - } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) { - StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false); - } - return super.getVariables(graph, context, classification, map); - } - - }; - - static class StructuralChildMapOfResource extends ResourceRead> { - - public StructuralChildMapOfResource(Resource resource) { - super(resource); - } - - @Override - public Map perform(ReadGraph graph) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource type = graph.getPossibleType(resource, STR.Component); - if(type != null) { - Resource definition = graph.getPossibleObject(type, STR.IsDefinedBy); - if(definition != null) { - Map map = graph.syncRequest(new UnescapedChildMapOfResource(definition)); - if (!map.isEmpty()) - return map; - } - } - Map directChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource)); - return directChildren; - } - - } - - static class StructuralChildMapOfResourceT extends ResourceRead> { - - public StructuralChildMapOfResourceT(Resource resource) { - super(resource); - } - - @Override - public Map perform(ReadGraph graph) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy); - if(definition != null) { - Map map = graph.syncRequest(new UnescapedChildMapOfResource(definition)); - if (!map.isEmpty()) - return map; - } - return Collections.emptyMap(); - } - - } - - static class StructuralRunChildMapOfResource extends ResourceRead> { - - public StructuralRunChildMapOfResource(Resource resource) { - super(resource); - } - - public Map fromContext(ReadGraph graph, Resource context) throws DatabaseException { - return graph.sync(new StructuralChildMapOfResource(context)); - } - - @Override - public Map perform(ReadGraph graph) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - SimulationResource SIMU = SimulationResource.getInstance(graph); - Resource model = graph.sync(new PossibleModel(resource)); - if(graph.isInstanceOf(model, L0.RVIContext)) { - return fromContext(graph, model); - } - Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration); - if(configuration != null) { - if(graph.isInstanceOf(configuration, L0.RVIContext)) { - return fromContext(graph, configuration); - } - } - - return Collections.emptyMap(); - - } - - } - - private static class SubstructureRequest extends VariableRead> { - public SubstructureRequest(Variable context) { - super(context); - } - - @Override - public List perform(ReadGraph graph) { - try { - Resource type = variable.getPossibleType(graph); - if(type == null) - return null; - return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable); - } catch (Throwable t) { - t.printStackTrace(); - return null; - } - } - } - - public static List getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - final Resource type = context.getPossibleType(graph); - if(type != null) { - if(graph.isInstanceOf(type, STR.ProceduralComponentType)) { - return graph.syncRequest(new SubstructureRequest(context)); - } - } - return null; - } - - public static Map getProcedural(ReadGraph graph, Variable context, List elements, Map map) throws DatabaseException { - - if(map == null) map = new THashMap(); - - MapList conns = new MapList(); - for(SubstructureElement sub : elements) { - if(sub instanceof org.simantics.structural2.procedural.Connection) { - org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub; - for(ConnectionPoint cp : conn.connectionPoints) { - if(cp instanceof Terminal) { - Terminal t = (Terminal)cp; - conns.add(t.component, conn); - } - } - } - } - - Map proceduralChildren = new THashMap(); - for(SubstructureElement sub : elements) { - if(sub instanceof Component) { - Component comp = (Component)sub; - proceduralChildren.put(comp.name, comp); - } - } - - Collection nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context); - Set used = new HashSet(nodeChildren.size()); - for(Object nodeChild : nodeChildren) { - @SuppressWarnings("rawtypes") - NodeSupport support = ((AbstractChildVariable)context).node.support; - @SuppressWarnings("rawtypes") - NodeManager manager = support.manager; - @SuppressWarnings("unchecked") - String name = manager.getName(nodeChild); - used.add(name); - Component proceduralChild = proceduralChildren.get(name); - if(proceduralChild != null) { - map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name))); - } - } - - for(Map.Entry entry : proceduralChildren.entrySet()) { - String name = entry.getKey(); - if(used.contains(name)) continue; - Component proceduralChild = entry.getValue(); - map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name))); - } - - return map; - - } - - private static class ProceduralSubstructureRequest extends VariableRead> { - - public ProceduralSubstructureRequest(Variable variable) { - super(variable); - } - - @Override - public Map perform(ReadGraph graph) - throws DatabaseException { - List elements = getProceduralDesc(graph, variable); - if(elements != null) - return getProcedural(graph, variable, elements, null); - else - return null; - } - } - - - @SCLValue(type = "VariableMap") - public static VariableMap structuralChildDomainChildren = new VariableMapImpl() { - - @Override - public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - - final Resource type = context.getPossibleType(graph); - if(type != null) { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - if(graph.isInstanceOf(type, STR.ProceduralComponentType)) { - Map map = graph.syncRequest(new ProceduralSubstructureRequest(context), - TransientCacheListener.>instance()); - if(map != null) return map.get(name); - } - } - - Resource represents = context.getPossibleRepresents(graph); - if(represents == null) { - Map children = graph.syncRequest(new StructuralChildMapOfResourceT(type)); - Resource child = children.get(name); - return All.getStandardChildDomainChildVariable(graph, context, child, name); - } - Map children = graph.syncRequest(new StructuralChildMapOfResource(represents)); - Resource child = children.get(name); - return All.getStandardChildDomainChildVariable(graph, context, child, name); - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - - final Resource type = context.getPossibleType(graph); - if(type != null) { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - if(graph.isInstanceOf(type, STR.ProceduralComponentType)) { - Map mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context), - TransientCacheListener.>instance()); - if(mapPrime != null) { - if(map != null) { - map.putAll(mapPrime); - return map; - } - else - return mapPrime; - } - } - } - Resource represents = context.getPossibleRepresents(graph); - if(represents == null) { - Map children = graph.syncRequest(new StructuralChildMapOfResourceT(type)); - return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map); - } - Map children = graph.syncRequest(new StructuralChildMapOfResource(represents)); - return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map); - } - - }; - - @SCLValue(type = "VariableMap") - public static VariableMap structuralRunDomainChildren = new VariableMapImpl() { - - @Override - public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { - Map children = graph.syncRequest(new StructuralRunChildMapOfResource(context.getRepresents(graph))); - Resource child = children.get(name); - return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name); - } - - @Override - public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - Map children = graph.syncRequest(new StructuralRunChildMapOfResource(variable.resource)); - return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map); - } - - }; - - @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]") - public static List connectionExtension(ReadGraph graph, List rs) throws DatabaseException { - - StructuralResource2 STR = StructuralResource2.getInstance(graph); - HashSet extension = new HashSet(8); - for(Resource r : rs) { - if(graph.isInstanceOf(r, STR.Connection)) { - extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.>instance())); - } - if(graph.isInstanceOf(r, STR.ConnectionJoin)) { - extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.>instance())); - } - } - - HashSet components = new HashSet(8); - for(Resource r : extension) { - components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component))); - } - - if(!extension.isEmpty()) { - ArrayList result = new ArrayList(rs.size() + extension.size()); - result.addAll(rs); - result.addAll(extension); - result.addAll(components); - rs = result; - } - - return rs; - - } - - @SCLValue(type = "ReadGraph -> Resource -> [Issue]") - public static List connectionValidator(ReadGraph graph, Resource component) throws DatabaseException { - - if(!graph.hasStatement(component)) return Collections.emptyList(); - - ArrayList result = new ArrayList(); - - Layer0 L0 = Layer0.getInstance(graph); - StructuralResource2 sr = StructuralResource2.getInstance(graph); - - Resource type = graph.getSingleType(component, sr.Component); - - Set requiredConnections = new HashSet(); - for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) { - Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN); - if(required != null && required) - requiredConnections.add(connectionRelation); - } - - Set connections = new HashSet(); - - for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) { - connections.add(stm.getPredicate()); - connections.addAll(graph.getSuperrelations(stm.getPredicate())); - } - - for(Resource req : requiredConnections) { - if(!connections.contains(req)) { - result.add(new StandardIssue(sr.ConnectionConstraint_ErrorIssue, component, req)); - } - } - - return result; - - } - - @SCLValue(type = "ReadGraph -> Resource -> Variable -> String") - public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException { - List contexts = IssueUtils.getContextsForProperty(graph, property); - String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName); - return "'" + attributeName + "' should be connected."; - } - - public static class InterfacePathMap extends VariableRead>> { - - public InterfacePathMap(Variable context) { - super(context); - } - - @Override - public GraphMap> perform(ReadGraph graph) throws DatabaseException { - - return new GraphMap>() { - - @Override - Map get(ReadGraph graph, String key) throws DatabaseException { - - Variable child = variable.getChild(graph, key); - - Map childMap = new THashMap(); - Collection paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath"); - if(paths != null) { - for(InterfaceResolution r : paths) { - childMap.put(r.interfaceName, r); - } - } - return childMap; - - } - - }; - - } - - } - - public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException { - - GraphMap> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.>>instance()); - Map childMap = map.get(graph, component); - if(childMap == null) return ""; - - PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.instance()); - - InterfaceResolution match = childMap.get(info.name); - if(match != null) { - String comp = URIStringUtils.escape(component); - Variable newContext = context.getChild(graph, component); - return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint); - } else { - return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name); - } - - } - - public static class InterfaceResolution { - - public Resource interfaceConnectionPoint; - public String interfaceName; - public String componentName; - public Resource connectionPoint; - - public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) { - this.interfaceConnectionPoint = interfaceConnectionPoint; - this.interfaceName = interfaceName; - this.componentName = componentName; - this.connectionPoint = connectionPoint; - } - - } - - public static Collection computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException { - - StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource type = variable.getPossibleType(graph); - if(type != null) { - if(graph.isInstanceOf(type, STR.ProceduralComponentType)) { - ArrayList result = new ArrayList(); - List elements = getProceduralDesc(graph, variable); - if(elements != null) { - for(SubstructureElement e : elements) { - if(e instanceof org.simantics.structural2.procedural.Connection) { - org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e; - Interface inf = null; - for(ConnectionPoint cp : conn.connectionPoints) { - if(cp instanceof Interface) { - if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection."); - inf = (Interface)cp; - } - } - if(inf != null && conn.connectionPoints.size() > 1) { - Layer0 L0 = Layer0.getInstance(graph); - String cpName = URIStringUtils.escape( graph.getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) ); - for(ConnectionPoint cp : conn.connectionPoints) { - if(cp == inf) continue; - Terminal t = (Terminal)cp; - result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation)); - } - } - } - } - } - - return result; - - } - - final Collection interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type)); - if(interfaces != null) return interfaces; - - } - - return BUILTIN_STRUCTURAL_CPS; - - } - - static class InterfacePathRequest extends VariableRead> { - - public InterfacePathRequest(Variable variable) { - super(variable); - } - - @Override - public Collection perform(ReadGraph graph) throws DatabaseException { - return computeInterfacePaths(graph, variable); - } - - } - - static class DefinedUCInterfaceMap extends ResourceRead> { - - public DefinedUCInterfaceMap(Resource resource) { - super(resource); - } - - @Override - public Collection perform(ReadGraph graph) - throws DatabaseException { - - StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource definition = graph.getPossibleObject(resource, STR.IsDefinedBy); - if(definition != null) { - Collection result = new ArrayList(); - Layer0 L0 = Layer0.getInstance(graph); - for(Resource cp : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, STR.ConnectionRelation))) { - String cpName = graph.getRelatedValue(cp, L0.HasName, Bindings.STRING); - for(Resource conn : graph.getObjects(cp, STR.IsBoundBy)) { - Statement stm = graph.getPossibleStatement(conn, STR.Connects); - if(stm == null) continue; - Resource component = stm.getObject(); - String componentName = graph.getRelatedValue(component, L0.HasName, Bindings.STRING); - result.add(new InterfaceResolution(cp, cpName, componentName, graph.getInverse(stm.getPredicate()))); - } - } - return result; - } - return null; - } - - } - - public static final Collection BUILTIN_STRUCTURAL_CPS = new ArrayList(); - - @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") - public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { - return CompileStructuralValueRequest.compileAndEvaluate(graph, context); - } - - public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException { - SCLContext sclContext = SCLContext.getCurrent(); - Object oldGraph = sclContext.get("graph"); - try { - Function1 exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) { - protected String getExpressionText(ReadGraph graph) throws DatabaseException { - return expression; - } - }, - TransientCacheListener.>instance()); - sclContext.put("graph", graph); - return exp.apply(context); - } catch (DatabaseException e) { - throw (DatabaseException)e; - } catch (Throwable t) { - throw new DatabaseException(t); - } finally { - sclContext.put("graph", oldGraph); - } - } - - static abstract class InterfacePathProperty extends LazyPropertyVariable { - - public InterfacePathProperty(Variable parent) { - super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY); - } - - @Override - public T getValue(ReadGraph graph, Binding binding) throws DatabaseException { - return getValue(graph); - } - - } - - static abstract class GraphMap { - - abstract Value get(ReadGraph graph, String key) throws DatabaseException; - - } - -} +package org.simantics.structural2; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.Datatypes; +import org.simantics.databoard.adapter.AdaptException; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.binding.error.DatatypeConstructionException; +import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.util.URIStringUtils; +import org.simantics.db.Issue; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.issue.StandardIssue; +import org.simantics.db.common.primitiverequest.IsInstanceOf; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.PossibleObjectWithType; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.common.request.TernaryRead; +import org.simantics.db.common.uri.UnescapedChildMapOfResource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.function.All; +import org.simantics.db.layer0.function.StandardChildDomainChildren; +import org.simantics.db.layer0.request.PropertyInfo; +import org.simantics.db.layer0.request.PropertyInfoRequest; +import org.simantics.db.layer0.request.VariableRead; +import org.simantics.db.layer0.variable.AbstractChildVariable; +import org.simantics.db.layer0.variable.AbstractPropertyVariable; +import org.simantics.db.layer0.variable.LazyPropertyVariable; +import org.simantics.db.layer0.variable.NodeSupport; +import org.simantics.db.layer0.variable.StandardGraphChildVariable; +import org.simantics.db.layer0.variable.StandardGraphPropertyVariable; +import org.simantics.db.layer0.variable.ValueAccessor; +import org.simantics.db.layer0.variable.ValueAccessorWithBinding; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.VariableMap; +import org.simantics.db.layer0.variable.VariableMapImpl; +import org.simantics.db.layer0.variable.VariableNode; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.service.CollectionSupport; +import org.simantics.issues.common.IssueUtils; +import org.simantics.layer0.Layer0; +import org.simantics.scl.reflection.annotations.SCLValue; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function1; +import org.simantics.scl.runtime.tuple.Tuple2; +import org.simantics.simulation.ontology.SimulationResource; +import org.simantics.simulator.variable.NodeManager; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.structural2.procedural.Component; +import org.simantics.structural2.procedural.ConnectionPoint; +import org.simantics.structural2.procedural.Interface; +import org.simantics.structural2.procedural.SubstructureElement; +import org.simantics.structural2.procedural.Terminal; +import org.simantics.structural2.queries.ConnectionComponents; +import org.simantics.structural2.queries.ConnectionJoinComponents; +import org.simantics.structural2.queries.ConnectionPointMapOfResource; +import org.simantics.structural2.queries.PossibleConnectionPointInfo; +import org.simantics.structural2.scl.CompileStructuralValueRequest; +import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest; +import org.simantics.structural2.utils.StructuralUtils.StructuralComponentClass; +import org.simantics.structural2.variables.Connection; +import org.simantics.structural2.variables.StandardProceduralChildVariable; +import org.simantics.utils.datastructures.MapList; + +import gnu.trove.map.hash.THashMap; + +public class Functions { + + @SCLValue(type="ValueAccessor") + public static final ValueAccessor expressionValueAccessor = new ValueAccessorWithBinding() { + + public Binding getBinding() { + return Bindings.STRING; + } + + @Override + public void setValue(WriteGraph graph, Variable context, Object value) + throws DatabaseException { + if(value == null) { + if(getValue(graph, context) != null) + clearExpression(graph, context); + return; + } + + // Get all necessary data + String expression = (String)value; + Variable parent = context.getParent(graph); + if(!(parent instanceof AbstractPropertyVariable)) return; + AbstractPropertyVariable property = (AbstractPropertyVariable)parent; + Resource propertyResource = property.getRepresents(graph); + if(propertyResource == null) return; + Resource container = property.getContainerResource(graph); + if(container == null) return; + Resource predicate = property.getPossiblePredicateResource(graph); + if(predicate == null) return; + Statement stat = graph.getPossibleStatement(container, predicate); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + // Write + boolean createNew = false; + if(stat.isAsserted(container)) + createNew = true; + else if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) { + graph.deny(propertyResource); + createNew = true; + } + Layer0 L0 = Layer0.getInstance(graph); + if(createNew) { + propertyResource = graph.newResource(); + graph.claim(container, predicate, propertyResource); + graph.claim(propertyResource, L0.InstanceOf, STR.SCLValue); + } + graph.claimLiteral(propertyResource, L0.SCLValue_expression, expression, Bindings.STRING); + } + + private void clearExpression(WriteGraph graph, Variable context) throws DatabaseException { + Variable parent = context.getParent(graph); + if(!(parent instanceof AbstractPropertyVariable)) return; + AbstractPropertyVariable property = (AbstractPropertyVariable)parent; + Resource container = property.getContainerResource(graph); + if(container == null) return; + Resource predicate = property.getPossiblePredicateResource(graph); + if(predicate == null) return; + graph.deny(container, predicate); + } + + @Override + public Object getValue(ReadGraph graph, Variable context) + throws DatabaseException { + Variable parent = context.getParent(graph); + if(!(parent instanceof AbstractPropertyVariable)) + return null; + AbstractPropertyVariable property = (AbstractPropertyVariable)parent; + Resource propertyResource = property.getPossibleRepresents(graph); + if(propertyResource == null) return null; + StructuralResource2 STR = StructuralResource2.getInstance(graph); + if(!graph.isInstanceOf(propertyResource, STR.SCLValue)) + return null; + Layer0 L0 = Layer0.getInstance(graph); + return graph.getPossibleRelatedValue(propertyResource, L0.SCLValue_expression); + } + + }; + + @SCLValue(type="ValueAccessor") + public static final ValueAccessor connectionValueAccessor = new ValueAccessor() { + + @Override + public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException { + throw new UnsupportedOperationException(); + } + + public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException { + throw new UnsupportedOperationException(); + } + + public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { + try { + Object value = getValue(graph, context); + Binding srcBinding = Bindings.OBJECT.getContentBinding(value); + return Bindings.adapt(value, srcBinding, binding); + } catch (AdaptException e) { + throw new DatabaseException(e); + } catch (BindingException e) { + throw new DatabaseException(e); + } + } + + @Override + public Object getValue(ReadGraph graph, Variable context) throws DatabaseException { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + return new ConnectionImpl(context.getParent(graph), variable.property.predicate); + } + + @Override + public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException { + try { + return Datatypes.getDatatype(Connection.class); + } catch (DatatypeConstructionException e) { + throw new DatabaseException(e); + } + } + + }; + + + @SCLValue(type = "VariableMap") + public static VariableMap structuralChildDomainProperties = new VariableMapImpl() { + + public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException { + + Map connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.>instance()); + PropertyInfo cp = connectionPoints.get(name); + if(cp == null) return null; + else return new StandardGraphPropertyVariable(graph, variable, cp.predicate); + + } + + public Map collectConnectionPointsFromContext(ReadGraph graph, StructuralResource2 STR, Variable variable, Resource context, Map map, boolean needSynchronized) throws DatabaseException { + + if(graph.isImmutable(context)) { + + Map cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.>instance()); + if(cps.size() == 0) return map; + + if(map == null) map = new THashMap(cps.size()); + + for(Map.Entry entry : cps.entrySet()) { + String name = entry.getKey(); + PropertyInfo cp = entry.getValue(); + if(needSynchronized && !graph.isInstanceOf(cp.predicate, STR.SynchronizedConnectionRelation)) continue; + map.put(name, new StandardGraphPropertyVariable(graph, variable, cp.predicate)); + } + + return map; + + } else { + + Collection predicates = graph.getPredicates(context); + + for(Resource predicate : predicates) { + + PropertyInfo info = graph.isImmutable(predicate) ? + graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.instance()) : + graph.syncRequest(new PossibleConnectionPointInfo(predicate)); + + if(info != null) { + if(map == null) map = new THashMap(4); + if(needSynchronized && !graph.isInstanceOf(predicate, STR.SynchronizedConnectionRelation)) continue; + map.put(info.name, new StandardGraphPropertyVariable(graph, variable, predicate)); + } + + } + + return map; + + } + + } + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + final StandardGraphChildVariable variable = (StandardGraphChildVariable)context; + Variable cp = getPossibleConnectionPointFromContext(graph, variable, variable.resource, name); + if(cp != null) return cp; + return All.getStandardChildDomainPropertyVariable(graph, context, name); + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + StandardGraphChildVariable variable = (StandardGraphChildVariable)context; + StructuralResource2 STR = StructuralResource2.getInstance(graph); + map = collectConnectionPointsFromContext(graph, STR, variable, variable.resource, map, false); + return All.getStandardChildDomainPropertyVariables(graph, context, map); + } + + public Map getVariables(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { + if (StructuralResource2.URIs.SynchronizedRelation.equals(classification)) { + return All.getStandardChildDomainPropertyVariables(graph, context, classification, map); + } else if (StructuralResource2.URIs.SynchronizedConnectionRelation.equals(classification)) { + StandardGraphChildVariable variable = (StandardGraphChildVariable)context; + return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, true); + } else if(StructuralResource2.URIs.ConnectionRelation.equals(classification)) { + StandardGraphChildVariable variable = (StandardGraphChildVariable)context; + return collectConnectionPointsFromContext(graph, StructuralResource2.getInstance(graph), variable, variable.resource, map, false); + } + return super.getVariables(graph, context, classification, map); + } + + }; + + static class StructuralRunContext extends ResourceRead { + + public StructuralRunContext(Resource resource) { + super(resource); + } + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + SimulationResource SIMU = SimulationResource.getInstance(graph); + Resource model = graph.sync(new PossibleIndexRoot(resource)); + if(graph.isInstanceOf(model, L0.RVIContext)) { + return model; + } + Resource configuration = graph.getPossibleObject(model, SIMU.HasConfiguration); + if(configuration != null) { + if(graph.isInstanceOf(configuration, L0.RVIContext)) { + return configuration; + } + } + + return null; + + } + + } + + private static class SubstructureRequest extends VariableRead> { + public SubstructureRequest(Variable context) { + super(context); + } + + @Override + public List perform(ReadGraph graph) { + try { + Resource type = variable.getPossibleType(graph); + if(type == null) + return null; + return CompileProceduralComponentTypeRequest.compileAndEvaluate(graph, type, variable); + } catch (Throwable t) { + t.printStackTrace(); + return null; + } + } + } + + public static List getProceduralDesc(ReadGraph graph, final Variable context) throws DatabaseException { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Variable config = Variables.getConfigurationVariable(graph, context); + final Resource type = config.getPossibleType(graph); + if(type != null) { + if(graph.isInstanceOf(type, STR.ProceduralComponentType)) { + return graph.syncRequest(new SubstructureRequest(config)); + } + } + return null; + } + + public static Map getProcedural(ReadGraph graph, Variable context, List elements, Map map) throws DatabaseException { + + if(map == null) map = new THashMap(); + + MapList conns = new MapList(); + for(SubstructureElement sub : elements) { + if(sub instanceof org.simantics.structural2.procedural.Connection) { + org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)sub; + for(ConnectionPoint cp : conn.connectionPoints) { + if(cp instanceof Terminal) { + Terminal t = (Terminal)cp; + conns.add(t.component, conn); + } + } + } + } + + Map proceduralChildren = new THashMap(); + for(SubstructureElement sub : elements) { + if(sub instanceof Component) { + Component comp = (Component)sub; + proceduralChildren.put(comp.name, comp); + } + } + + Collection nodeChildren = All.getPossibleNodeChildren(graph, (AbstractChildVariable)context); + Set used = new HashSet(nodeChildren.size()); + for(Object nodeChild : nodeChildren) { + @SuppressWarnings("rawtypes") + NodeSupport support = ((AbstractChildVariable)context).node.support; + @SuppressWarnings("rawtypes") + NodeManager manager = support.manager; + @SuppressWarnings("unchecked") + String name = manager.getName(nodeChild); + used.add(name); + Component proceduralChild = proceduralChildren.get(name); + if(proceduralChild != null) { + map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, new VariableNode(support, nodeChild), proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name))); + } + } + + for(Map.Entry entry : proceduralChildren.entrySet()) { + String name = entry.getKey(); + if(used.contains(name)) continue; + Component proceduralChild = entry.getValue(); + map.put(proceduralChild.name, new StandardProceduralChildVariable(graph, context, null, proceduralChild.name, proceduralChild.type, proceduralChild.properties, conns.getValues(proceduralChild.name))); + } + + return map; + + } + + private static class ProceduralSubstructureRequest extends VariableRead> { + + public ProceduralSubstructureRequest(Variable variable) { + super(variable); + } + + @Override + public Map perform(ReadGraph graph) + throws DatabaseException { + List elements = getProceduralDesc(graph, variable); + if(elements != null) + return getProcedural(graph, variable, elements, null); + else + return null; + } + } + + public static class StructuralTypeOverrideMap extends ResourceRead> { + + protected StructuralTypeOverrideMap(Resource composite) { + super(composite); + } + + @Override + public Map perform(ReadGraph graph) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + CollectionSupport cs = graph.getService(CollectionSupport.class); + + Map result = null; + + for(Resource override : graph.getObjects(resource, STR.HasTypeOverride)) { + Resource original = graph.getSingleObject(override, STR.TypeOverride_HasOriginalType); + Resource replacement = graph.getSingleObject(override, STR.TypeOverride_HasReplacementType); + if(result == null) result = cs.createMap(Resource.class); + result.put(original, replacement); + } + + if(result == null) return Collections.emptyMap(); + + return result; + + } + + } + + public static class StructuralOverrideData { + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actualRepresents == null) ? 0 : actualRepresents.hashCode()); + result = prime * result + ((actualType == null) ? 0 : actualType.hashCode()); + result = prime * result + ((overrideType == null) ? 0 : overrideType.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + StructuralOverrideData other = (StructuralOverrideData) obj; + if (actualRepresents == null) { + if (other.actualRepresents != null) + return false; + } else if (!actualRepresents.equals(other.actualRepresents)) + return false; + if (actualType == null) { + if (other.actualType != null) + return false; + } else if (!actualType.equals(other.actualType)) + return false; + if (overrideType == null) { + if (other.overrideType != null) + return false; + } else if (!overrideType.equals(other.overrideType)) + return false; + return true; + } + Resource actualRepresents; + Resource actualType; + Resource overrideType; + public StructuralOverrideData(Resource actualRepresents, Resource actualType, Resource overrideType) { + this.actualRepresents = actualRepresents; + this.actualType = actualType; + this.overrideType = overrideType; + } + + public static StructuralOverrideData compute(ReadGraph graph, Variable context) throws DatabaseException { + return graph.syncRequest(new StructuralOverrideDataRequest(context)); + } + + public Resource type() { + if(overrideType != null) + return overrideType; + return actualType; + } + + public Resource represents() { + return actualRepresents; + } + + } + + private static class StructuralOverrideDataWalkRequest + extends TernaryRead { + + public StructuralOverrideDataWalkRequest(Variable component, Resource actualRepresents, Resource actualType) { + super(component, actualRepresents, actualType); + } + + @Override + public StructuralOverrideData perform(ReadGraph graph) throws DatabaseException { + Variable component = parameter; + Resource actualRepresents = parameter2; + Resource actualType = parameter3; +// System.err.println(component.getURI(graph)); + Resource represents = component.getPossibleRepresents(graph); + if (represents != null) { + Layer0 L0 = Layer0.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource container = graph + .syncRequest(new PossibleObjectWithType(represents, L0.PartOf, STR.Composite)); + if (container != null) { + Map overrides = graph.syncRequest(new StructuralTypeOverrideMap(container), TransientCacheListener.instance()); + Resource override = overrides.get(actualType); + if (override != null) { + return new StructuralOverrideData(actualRepresents, actualType, override); + } + } + } + Variable parent = component.getParent(graph); + if (parent == null) + return new StructuralOverrideData(actualRepresents, actualType, null); + else + return graph.syncRequest(new StructuralOverrideDataWalkRequest(parent, represents, actualType), TransientCacheListener.instance()); + } + + } + + public static class StructuralOverrideDataRequest extends VariableRead { + + public StructuralOverrideDataRequest(Variable component) { + super(component); + } + + @Override + public StructuralOverrideData perform(ReadGraph graph) throws DatabaseException { + + Resource represents = variable.getPossibleRepresents(graph); + if(represents == null) { + String uri = variable.getPossiblePropertyValue(graph, "typeURI"); + if(uri != null) { + Resource actualType = graph.syncRequest(new org.simantics.db.common.primitiverequest.Resource(uri), TransientCacheAsyncListener.instance()); + if (graph.syncRequest(new IsInstanceOf(actualType, StructuralResource2.getInstance(graph).ReplaceableDefinedComponentType), TransientCacheListener.instance()) ) { + return graph.syncRequest(new StructuralOverrideDataWalkRequest(variable, null, actualType), TransientCacheListener.instance()); + } else { + // can not have replaceable type + return null; + } + } + throw new DatabaseException("No type for " + variable.getURI(graph)); + } else { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource possibleType = graph.getPossibleType(represents, STR.Component); + if (possibleType == null) { + possibleType = graph.getPossibleType(represents, Layer0.getInstance(graph).Entity); + if (possibleType == null) + return null; + } + if (graph.syncRequest(new IsInstanceOf(possibleType, STR.ReplaceableDefinedComponentType), TransientCacheListener.instance()) ) { + return graph.syncRequest(new StructuralOverrideDataWalkRequest(variable, represents, possibleType), TransientCacheListener.instance()); + } else { + return null; + } + } + + } + + } + + + private static class StructureTypeAndChildMapRequest extends ResourceRead { + + protected StructureTypeAndChildMapRequest(Resource resource) { + super(resource); + } + + @Override + public Tuple2 perform(ReadGraph graph) throws DatabaseException { + StructuralComponentClass clazz = StructuralComponentClass.get(graph, resource); + if (StructuralComponentClass.DEFINED.equals(clazz)) { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource def = graph.getSingleObject(resource, STR.IsDefinedBy); + Map children = graph.syncRequest(new UnescapedChildMapOfResource(def), TransientCacheListener.instance()); + return new Tuple2(clazz, children); + } + return new Tuple2(clazz, null); + } + + } + + @SCLValue(type = "VariableMap") + public static VariableMap structuralChildDomainChildren = new VariableMapImpl() { + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource type = context.getPossibleType(graph, STR.Component); + if(type == null) return null; + + Tuple2 result = graph.syncRequest(new StructureTypeAndChildMapRequest(type), TransientCacheListener.instance()); + StructuralComponentClass clazz = (StructuralComponentClass) result.c0; + + if(StructuralComponentClass.PROCEDURAL.equals(clazz)) { + Map map = graph.syncRequest(new ProceduralSubstructureRequest(context), + TransientCacheListener.>instance()); + if(map != null) return map.get(name); + return null; + } else if (StructuralComponentClass.DEFINED.equals(clazz)) { + Map children = (Map) result.c1; + Resource child = children.get(name); + if(child == null) return null; + return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name); + } else { + Resource represents = context.getPossibleRepresents(graph); + if(represents == null) return null; + Map children = graph.syncRequest(new UnescapedChildMapOfResource(represents), TransientCacheListener.instance()); + Resource child = children.get(name); + return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name); + } + + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + + Resource type = context.getPossibleType(graph); + if(type == null) return null; + + StructuralComponentClass clazz = StructuralComponentClass.get(graph, type); + if(StructuralComponentClass.PROCEDURAL.equals(clazz)) { + Map mapPrime = graph.syncRequest(new ProceduralSubstructureRequest(context), + TransientCacheListener.>instance()); + if(mapPrime != null) { + if(map != null) { + map.putAll(mapPrime); + return map; + } + else + return mapPrime; + } + return map; + } else if (StructuralComponentClass.DEFINED.equals(clazz)) { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource def = graph.getSingleObject(type, STR.IsDefinedBy); + Map children = graph.syncRequest(new UnescapedChildMapOfResource(def), TransientCacheListener.instance()); + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map); + } else { + Resource represents = context.getPossibleRepresents(graph); + if(represents == null) return null; + Map children = graph.syncRequest(new UnescapedChildMapOfResource(represents)); + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map); + } + + } + + }; + + @SCLValue(type = "VariableMap") + public static VariableMap structuralRunDomainChildren = new VariableMapImpl() { + + @Override + public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException { + Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph))); + if(ctx == null) return null; + Map children = graph.syncRequest(new UnescapedChildMapOfResource(ctx)); + Resource child = children.get(name); + return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, child, name); + } + + @Override + public Map getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + Resource ctx = graph.syncRequest(new StructuralRunContext(context.getRepresents(graph))); + if(ctx == null) return map; + Map children = graph.syncRequest(new UnescapedChildMapOfResource(ctx)); + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, children, map); + } + + }; + + @SCLValue(type = "ReadGraph -> [Resource] -> [Resource]") + public static List connectionExtension(ReadGraph graph, List rs) throws DatabaseException { + + StructuralResource2 STR = StructuralResource2.getInstance(graph); + HashSet extension = new HashSet(8); + for(Resource r : rs) { + if(graph.isInstanceOf(r, STR.Connection)) { + extension.addAll(graph.syncRequest(new ConnectionComponents(r), TransientCacheListener.>instance())); + } + if(graph.isInstanceOf(r, STR.ConnectionJoin)) { + extension.addAll(graph.syncRequest(new ConnectionJoinComponents(r), TransientCacheListener.>instance())); + } + } + + HashSet components = new HashSet(8); + for(Resource r : extension) { + components.addAll(graph.sync(new ObjectsWithType(r, STR.Connects, STR.Component))); + } + + if(!extension.isEmpty()) { + ArrayList result = new ArrayList(rs.size() + extension.size()); + result.addAll(rs); + result.addAll(extension); + result.addAll(components); + rs = result; + } + + return rs; + + } + + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") + public static List connectionValidator(ReadGraph graph, Resource component) throws DatabaseException { + + if(!graph.hasStatement(component)) return Collections.emptyList(); + + ArrayList result = new ArrayList(); + + Layer0 L0 = Layer0.getInstance(graph); + StructuralResource2 sr = StructuralResource2.getInstance(graph); + + Resource type = graph.getSingleType(component, sr.Component); + + Set requiredConnections = new HashSet(); + for(Resource connectionRelation : graph.sync(new ObjectsWithType(type, L0.ConsistsOf, sr.ConnectionRelation))) { + Boolean required = graph.getPossibleRelatedValue(connectionRelation, sr.ConnectionRelation_connectionRequired, Bindings.BOOLEAN); + if(required != null && required) + requiredConnections.add(connectionRelation); + } + + Set connections = new HashSet(); + + for(Statement stm : graph.getStatements(component, sr.IsConnectedTo)) { + connections.add(stm.getPredicate()); + connections.addAll(graph.getSuperrelations(stm.getPredicate())); + } + + for(Resource req : requiredConnections) { + if(!connections.contains(req)) { + result.add(new StandardIssue(sr.ConnectionValidationConstraint_ErrorIssue, component, req)); + } + } + + return result; + + } + + @SCLValue(type = "ReadGraph -> Resource -> Variable -> String") + public static String connectionIssueDescription(ReadGraph graph, Resource converter, Variable property) throws DatabaseException { + List contexts = IssueUtils.getContextsForProperty(graph, property); + String attributeName = graph.getRelatedValue(contexts.get(1), Layer0.getInstance(graph).HasName); + return "'" + attributeName + "' should be connected."; + } + + public static class InterfacePathMap extends VariableRead>> { + + public InterfacePathMap(Variable context) { + super(context); + } + + @Override + public GraphMap> perform(ReadGraph graph) throws DatabaseException { + + return new GraphMap>() { + + @Override + Map get(ReadGraph graph, String key) throws DatabaseException { + + Variable child = variable.getChild(graph, key); + + Map childMap = new THashMap(); + Collection paths = computeInterfacePaths(graph, child);//child.getPossiblePropertyValue(graph, "proceduralConnectionPointPath"); + if(paths != null) { + for(InterfaceResolution r : paths) { + childMap.put(r.interfaceName, r); + } + } + return childMap; + + } + + }; + + } + + } + + public static String resolveInterfacePath(ReadGraph graph, Variable context, String component, Resource relation) throws DatabaseException { + + GraphMap> map = graph.syncRequest(new InterfacePathMap(context), TransientCacheListener.>>instance()); + Map childMap = map.get(graph, component); + if(childMap == null) return ""; + + PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheListener.instance()); + + InterfaceResolution match = childMap.get(info.name); + if(match != null) { + String comp = URIStringUtils.escape(component); + Variable newContext = context.getChild(graph, component); + return "/" + comp + resolveInterfacePath(graph, newContext, match.componentName, match.connectionPoint); + } else { + return "/" + URIStringUtils.escape(component) + "#" + URIStringUtils.escape(info.name); + } + + } + + public static class InterfaceResolution { + + public Resource interfaceConnectionPoint; + public String interfaceName; + public String componentName; + public Resource connectionPoint; + + public InterfaceResolution(Resource interfaceConnectionPoint, String interfaceName, String componentName, Resource connectionPoint) { + this.interfaceConnectionPoint = interfaceConnectionPoint; + this.interfaceName = interfaceName; + this.componentName = componentName; + this.connectionPoint = connectionPoint; + } + + } + + public static Collection computeInterfacePaths(ReadGraph graph, Variable variable) throws DatabaseException { + + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource type = variable.getPossibleType(graph); + if(type != null) { + if(graph.isInstanceOf(type, STR.ProceduralComponentType)) { + ArrayList result = new ArrayList(); + List elements = getProceduralDesc(graph, variable); + if(elements != null) { + for(SubstructureElement e : elements) { + if(e instanceof org.simantics.structural2.procedural.Connection) { + org.simantics.structural2.procedural.Connection conn = (org.simantics.structural2.procedural.Connection)e; + Interface inf = null; + for(ConnectionPoint cp : conn.connectionPoints) { + if(cp instanceof Interface) { + if(inf != null) throw new DatabaseException("Multiple interfaces referenced in procedural connection."); + inf = (Interface)cp; + } + } + if(inf != null && conn.connectionPoints.size() > 1) { + Layer0 L0 = Layer0.getInstance(graph); + String cpName = URIStringUtils.escape( graph.getRelatedValue(inf.relation, L0.HasName, Bindings.STRING) ); + for(ConnectionPoint cp : conn.connectionPoints) { + if(cp == inf) continue; + Terminal t = (Terminal)cp; + result.add(new InterfaceResolution(inf.relation, cpName, t.component, t.relation)); + } + } + } + } + } + + return result; + + } + + final Collection interfaces = graph.syncRequest(new DefinedUCInterfaceMap(type), TransientCacheListener.instance()); + if(interfaces != null) return interfaces; + + } + + return BUILTIN_STRUCTURAL_CPS; + + } + + static class InterfacePathRequest extends VariableRead> { + + public InterfacePathRequest(Variable variable) { + super(variable); + } + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + return computeInterfacePaths(graph, variable); + } + + } + + public static final Collection BUILTIN_STRUCTURAL_CPS = new ArrayList(); + + @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") + public static Object computeExpression(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { + return CompileStructuralValueRequest.compileAndEvaluate(graph, context); + } + + public static Object computeExpressionInContext(ReadGraph graph, Variable context, final String expression) throws DatabaseException { + SCLContext sclContext = SCLContext.getCurrent(); + Object oldGraph = sclContext.get("graph"); + try { + Function1 exp = graph.syncRequest(new CompileStructuralValueRequest(graph, context) { + protected String getExpressionText(ReadGraph graph) throws DatabaseException { + return expression; + } + }, + TransientCacheListener.instance()); + sclContext.put("graph", graph); + return exp.apply(context); + } catch (DatabaseException e) { + throw (DatabaseException)e; + } catch (Throwable t) { + throw new DatabaseException(t); + } finally { + sclContext.put("graph", oldGraph); + } + } + + static abstract class InterfacePathProperty extends LazyPropertyVariable { + + public InterfacePathProperty(Variable parent) { + super(parent, "proceduralConnectionPointPath", Bindings.STRING_ARRAY); + } + + @Override + public T getValue(ReadGraph graph, Binding binding) throws DatabaseException { + return getValue(graph); + } + + } + + static abstract class GraphMap { + + abstract Value get(ReadGraph graph, String key) throws DatabaseException; + + } + +}