Procedural Values
It is possible to define procedural values in the graph and compute their values using graph interface.
Currently the methods for computing the values are:
- <T> T getRelatedValue2(Resource subject, Resource relation) throws DatabaseException;
- <T> T getPossibleRelatedValue2(Resource subject, Resource relation) throws DatabaseException;
- <T> T getRelatedValue2(Resource subject, Resource relation, Object context) throws DatabaseException;
- <T> T getPossibleRelatedValue2(Resource subject, Resource relation, Object context) throws DatabaseException;
- <T> T getRelatedValue2(Resource subject, Resource relation, Binding binding) throws DatabaseException;
- <T> T getPossibleRelatedValue2(Resource subject, Resource relation, Binding binding) throws DatabaseException;
- <T> T getRelatedValue2(Resource subject, Resource relation, Object context, Binding binding) throws DatabaseException;
- <T> T getPossibleRelatedValue2(Resource subject, Resource relation, Object context, Binding binding) throws DatabaseException;
These methods work like getRelatedValue and getPossibleRelatedValue -methods. They follow the given relation from the given subject and then determine the value based on the resource found. If the resource is a literal, then they work exactly like getRelatedValue and getPossibleRelatedValue. They however extend the old functionality in two ways:
- If the found resource is an instance of ExternalValue, then the URI of the resource is used to find a value that is declared using extensions and Java annotations.
- If the found resource is an instance of Value, the mechanism first finds the property ConvertsToValueWith of the value and uses it compute the value.
These two mechanisms are detailed below.
External values
External values are resources in the graph with type ExternalValue. They must have URIs. Let's consider for example
SEL.Functions.inputModifier : L0.ExternalValue
defined in SelectionView -ontology.
The definitions of the values are declared in the extension point org.simantics.scl.reflection.binding like this
<extension point="org.simantics.scl.reflection.binding"> <namespace path="http://www.simantics.org/SelectionView-0.0/Functions"> <externalClass className="org.simantics.db.Resource"/> <externalClass className="org.simantics.db.ReadGraph"/> <externalClass className="org.simantics.db.WriteGraph"/> <externalClass className="org.simantics.db.layer0.variable.Variable"/> <class className="org.simantics.selectionview.function.All"/> </namespace> </extension>
The value itself is defined as:
public class All { @SCLValue(type = "WriteGraph -> Variable -> a -> b -> String") public static String inputModifier(WriteGraph graph, Variable variable, Object value, Object _binding) throws DatabaseException { ... } }
Any static method or field can be declared an external value with @SCLValue annotation. The SCL -type of the value is given as an attribute to the annotation. By default the method name and resource name are matched, but the method name can be overrided in the annotation with name attribute.
Contextual values
External values can be used to define complex constants, in particular functions. Contextual values extend the functionality so that the value may depend on the other properties of the original subject resource that was used for finding the value resource. In some cases, even more needs to be known about the context of the computation than just a resource. Therefore some of the getRelatedValue2 -methods take a context as a parameter. If it is not given, the default context is the subject resource.
A contextual value is defined as a resource with type Value and properties ConvertsToValueWith. For example:
L0.List <T L0.Value L0.HasDescription """Represents a list of resources that may contain repetitions.""" L0.HasValueType "[Resource]" @L0.assert L0.ConvertsToValueWith L0.Functions.listResources : L0.ExternalValue
The conversion function must have type
ReadGraph => Resource -> Context -> Result
The second parameter is the resource of the value itself (in this case the linked list) and the context type can be any type. Result type must be the type annotated with HasValueType.
Value types
Types of the values must be annotated with relation HasValueType. The type is an SCL type in a string format. A relation may require that its range has a certain value type using RequiresValueType -property.