package org.simantics.db.layer0.variable; import java.util.Map; import org.simantics.databoard.Bindings; import org.simantics.databoard.adapter.AdaptException; import org.simantics.databoard.adapter.Adapter; import org.simantics.databoard.adapter.AdapterConstructionException; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.type.Datatype; import org.simantics.db.Resource; import org.simantics.db.Statement; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.EnumerationMap; import org.simantics.db.common.request.IsEnumeratedValue; import org.simantics.db.common.utils.CommonDBUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.RuntimeDatabaseException; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.layer0.Layer0; import org.simantics.scl.runtime.function.Function4; import org.simantics.scl.runtime.function.FunctionImpl4; public class VariableUtils { final private static Binding datatype_binding = Bindings.getBindingUnchecked(Datatype.class); public static Function4 defaultInputModifier = new FunctionImpl4() { public String apply(WriteGraph graph, Variable variable, Object value, Object _binding) { try { return safeApply(graph, variable, value, _binding); } catch (DatabaseException e) { throw new RuntimeDatabaseException(e); } } public String safeApply(WriteGraph graph, Variable variable, Object value, Object _binding) throws DatabaseException { Binding binding = (Binding)_binding; Variable parent = variable.getParent(graph); Resource property = variable.getPossiblePredicateResource(graph); Resource container = parent.getPossibleRepresents(graph); if(container == null) return null; if(property == null) return null; CommonDBUtils.selectClusterSet(graph, container); Statement object = graph.getPossibleStatement(container, property); if(object == null) return null; Resource objectResource = object.getObject(); if(graph.sync(new IsEnumeratedValue(objectResource))) { Layer0 L0 = Layer0.getInstance(graph); Resource type = graph.getSingleObject(objectResource, L0.PartOf); Map enumMap = graph.syncRequest(new EnumerationMap(type)); Resource newLiteral = enumMap.get(value); graph.deny(container, property, objectResource); graph.claim(container, property, newLiteral); return null; } Layer0 L0 = Layer0.getInstance(graph); Statement dt = graph.getPossibleStatement(objectResource, L0.HasDataType); if (dt == null) { throw new DatabaseException("Can't write variable " + variable.getURI(graph) + " since its literal resource " + objectResource + " does not contain a datatype statement"); } boolean needsCustomDatatype = !dt.isAsserted(objectResource); Datatype correctDatatype = graph.getValue(dt.getObject(), datatype_binding); Binding correctBinding = Bindings.getBinding(correctDatatype); try { Adapter adapter = Bindings.getTypeAdapter(binding, correctBinding); Object correctValue = adapter.adapt(value); if (correctValue == value) { // Adapter is passthrough, i.e. the specified binding can be // considered correct for the value. correctBinding = binding; } value = correctValue; } catch (AdapterConstructionException e) { throw new DatabaseException("Can't adapt values from source datatype '" + binding.type().toSingleLineString() + "' to target '" + correctDatatype.toSingleLineString() + "'"); } catch (AdaptException e) { throw new DatabaseException("Can't adapt value " + value + " from source datatype '" + binding.type().toSingleLineString() + "' to target '" + correctDatatype.toSingleLineString() + "'"); } if (object.isAsserted(container)) { String sclType = needsCustomDatatype ? Layer0Utils.getSCLType(correctDatatype) : null; Resource type = graph.getPossibleType(objectResource, L0.Literal); objectResource = graph.newResource(); graph.claim(objectResource, L0.InstanceOf, null, type); graph.claim(container, property, objectResource); if(needsCustomDatatype) { graph.addLiteral(objectResource, L0.HasDataType, L0.HasDataType_Inverse, L0.DataType, correctDatatype, datatype_binding); graph.addLiteral(objectResource, L0.HasValueType, L0.HasValueType_Inverse, L0.String, sclType, Bindings.STRING); } } graph.claimValue(objectResource, value, correctBinding); return null; } }; public static String unnamedResourceName(Resource resource) { return "r" + resource.getResourceId(); } }