1 package org.simantics.db.layer0.variable;
\r
3 import java.util.Map;
\r
5 import org.simantics.databoard.Bindings;
\r
6 import org.simantics.databoard.adapter.AdaptException;
\r
7 import org.simantics.databoard.adapter.Adapter;
\r
8 import org.simantics.databoard.adapter.AdapterConstructionException;
\r
9 import org.simantics.databoard.binding.Binding;
\r
10 import org.simantics.databoard.type.Datatype;
\r
11 import org.simantics.db.Resource;
\r
12 import org.simantics.db.Statement;
\r
13 import org.simantics.db.WriteGraph;
\r
14 import org.simantics.db.common.request.EnumerationMap;
\r
15 import org.simantics.db.common.request.IsEnumeratedValue;
\r
16 import org.simantics.db.common.utils.CommonDBUtils;
\r
17 import org.simantics.db.exception.DatabaseException;
\r
18 import org.simantics.db.exception.RuntimeDatabaseException;
\r
19 import org.simantics.db.layer0.util.Layer0Utils;
\r
20 import org.simantics.layer0.Layer0;
\r
21 import org.simantics.scl.runtime.function.Function4;
\r
22 import org.simantics.scl.runtime.function.FunctionImpl4;
\r
24 public class VariableUtils {
\r
26 final private static Binding datatype_binding = Bindings.getBindingUnchecked(Datatype.class);
\r
28 public static Function4<WriteGraph, Variable, Object, Object, String> defaultInputModifier = new FunctionImpl4<WriteGraph, Variable, Object, Object, String>() {
\r
30 public String apply(WriteGraph graph, Variable variable, Object value, Object _binding) {
\r
32 return safeApply(graph, variable, value, _binding);
\r
33 } catch (DatabaseException e) {
\r
34 throw new RuntimeDatabaseException(e);
\r
38 public String safeApply(WriteGraph graph, Variable variable, Object value, Object _binding) throws DatabaseException {
\r
40 Binding binding = (Binding)_binding;
\r
42 Variable parent = variable.getParent(graph);
\r
43 Resource property = variable.getPossiblePredicateResource(graph);
\r
44 Resource container = parent.getPossibleRepresents(graph);
\r
45 if(container == null) return null;
\r
46 if(property == null) return null;
\r
48 CommonDBUtils.selectClusterSet(graph, container);
\r
50 Statement object = graph.getPossibleStatement(container, property);
\r
51 if(object == null) return null;
\r
53 Resource objectResource = object.getObject();
\r
54 if(graph.sync(new IsEnumeratedValue(objectResource))) {
\r
56 Layer0 L0 = Layer0.getInstance(graph);
\r
57 Resource type = graph.getSingleObject(objectResource, L0.PartOf);
\r
59 Map<String, Resource> enumMap = graph.syncRequest(new EnumerationMap(type));
\r
60 Resource newLiteral = enumMap.get(value);
\r
61 graph.deny(container, property, objectResource);
\r
62 graph.claim(container, property, newLiteral);
\r
68 Layer0 L0 = Layer0.getInstance(graph);
\r
69 Statement dt = graph.getPossibleStatement(objectResource, L0.HasDataType);
\r
71 throw new DatabaseException("Can't write variable " + variable.getURI(graph) + " since its literal resource " + objectResource + " does not contain a datatype statement");
\r
74 boolean needsCustomDatatype = !dt.isAsserted(objectResource);
\r
75 Datatype correctDatatype = graph.getValue(dt.getObject(), datatype_binding);
\r
76 Binding correctBinding = Bindings.getBinding(correctDatatype);
\r
79 Adapter adapter = Bindings.getTypeAdapter(binding, correctBinding);
\r
80 Object correctValue = adapter.adapt(value);
\r
81 if (correctValue == value) {
\r
82 // Adapter is passthrough, i.e. the specified binding can be
\r
83 // considered correct for the value.
\r
84 correctBinding = binding;
\r
86 value = correctValue;
\r
87 } catch (AdapterConstructionException e) {
\r
88 throw new DatabaseException("Can't adapt values from source datatype '" + binding.type().toSingleLineString() + "' to target '" + correctDatatype.toSingleLineString() + "'");
\r
89 } catch (AdaptException e) {
\r
90 throw new DatabaseException("Can't adapt value " + value + " from source datatype '" + binding.type().toSingleLineString() + "' to target '" + correctDatatype.toSingleLineString() + "'");
\r
93 if (object.isAsserted(container)) {
\r
94 String sclType = needsCustomDatatype ? Layer0Utils.getSCLType(correctDatatype) : null;
\r
96 Resource type = graph.getPossibleType(objectResource, L0.Literal);
\r
97 objectResource = graph.newResource();
\r
98 graph.claim(objectResource, L0.InstanceOf, null, type);
\r
99 graph.claim(container, property, objectResource);
\r
100 if(needsCustomDatatype) {
\r
101 graph.addLiteral(objectResource, L0.HasDataType, L0.HasDataType_Inverse, L0.DataType, correctDatatype, datatype_binding);
\r
102 graph.addLiteral(objectResource, L0.HasValueType, L0.HasValueType_Inverse, L0.String, sclType, Bindings.STRING);
\r
106 graph.claimValue(objectResource, value, correctBinding);
\r