]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java
StructuralUtils.isImmutable now takes L0.readOnly of input into account
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / util / Layer0Utils.java
index ee97fdb5827a723d8f1e86520d0343a81dbaee7f..ad8676f813bdb83d4da1adde8aed547c31541ddb 100644 (file)
@@ -71,9 +71,9 @@ import org.simantics.db.common.primitiverequest.PossibleRelatedValue;
 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
 import org.simantics.db.common.request.DelayedWriteRequest;
 import org.simantics.db.common.request.ObjectsWithType;
-import org.simantics.db.common.request.PossibleChild;
 import org.simantics.db.common.request.PossibleIndexRoot;
 import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.utils.CommonDBUtils;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.event.ChangeListener;
 import org.simantics.db.exception.CancelTransactionException;
@@ -115,9 +115,7 @@ import org.simantics.graph.representation.PrettyPrintTG;
 import org.simantics.graph.representation.TransferableGraph1;
 import org.simantics.layer0.Layer0;
 import org.simantics.operation.Layer0X;
-import org.simantics.scl.compiler.environment.Environments;
 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
-import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
 import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.osgi.SCLOsgi;
 import org.simantics.scl.runtime.function.Function;
@@ -129,8 +127,6 @@ public class Layer0Utils {
        @SuppressWarnings("rawtypes")
        public static final ThreadLocal SCL_GRAPH = new ThreadLocal();
 
-       final public static Binding datatype_binging = Bindings.getBindingUnchecked(Datatype.class);
-
        public static Resource literal(WriteGraph g, String value) throws DatabaseException {
                Layer0 L0 = Layer0.getInstance(g);
                Resource r = g.newResource();
@@ -272,7 +268,7 @@ public class Layer0Utils {
                Resource range = graph.getPossibleObject(property, L0.HasRange);
                if(range != null && !L0.Value.equals(range)) return range;
 
-               Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
+               Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, Bindings.DATATYPE);
                if(requiredDataType != null) return getLiteralType(graph, requiredDataType);
 
                String requiredValueType = graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
@@ -355,13 +351,9 @@ public class Layer0Utils {
                throw new IllegalArgumentException("Unable to convert datatype into SCL type: " + type);
        }
 
-
+       @Deprecated
        public static Type getSCLType(ReadGraph graph, RuntimeEnvironment runtimeEnvironment, String typeText) throws DatabaseException {
-        try {
-                       return Environments.getType(runtimeEnvironment.getEnvironment(), typeText);
-               } catch (SCLExpressionCompilationException e) {
-                       throw new DatabaseException(e);
-               }
+           return CommonDBUtils.getSCLType(graph, runtimeEnvironment, typeText);
        }
 
        public static Type getSCLType(ReadGraph graph, Variable property) throws DatabaseException {
@@ -388,7 +380,7 @@ public class Layer0Utils {
                Layer0 L0 = Layer0.getInstance(graph);
                Layer0X L0X = Layer0X.getInstance(graph);
 
-               Datatype literalDatatype = graph.getPossibleRelatedValue(value, L0.HasDataType, datatype_binging);
+               Datatype literalDatatype = graph.getPossibleRelatedValue(value, L0.HasDataType, Bindings.DATATYPE);
                if(literalDatatype != null) return getSCLType(literalDatatype);
 
                String literalValueType = graph.getPossibleRelatedValue(value, L0.HasValueType, Bindings.STRING);
@@ -396,7 +388,7 @@ public class Layer0Utils {
 
                if(predicate != null) {
 
-                       Datatype requiredDataType = graph.getPossibleRelatedValue(predicate, L0X.RequiresDataType, datatype_binging);
+                       Datatype requiredDataType = graph.getPossibleRelatedValue(predicate, L0X.RequiresDataType, Bindings.DATATYPE);
                        if(requiredDataType != null) return getSCLType(requiredDataType);
 
                        throw new DatabaseException("Unidentified literal data type for property " + NameUtils.getURIOrSafeNameInternal(graph, predicate));
@@ -414,26 +406,30 @@ public class Layer0Utils {
        }
 
        public static Datatype getPossibleDatatype(ReadGraph graph, Variable variable) throws DatabaseException {
+               return getPossibleDatatype(graph, variable, null, true);
+       }
 
+       private static Datatype getPossibleDatatype(ReadGraph graph, Variable variable, PropertyInfo info, boolean checkPropertyDatatype) throws DatabaseException {
                Layer0 L0 = Layer0.getInstance(graph);
                Layer0X L0X = Layer0X.getInstance(graph);
 
                Resource property = variable.getPossiblePredicateResource(graph);
-               if(property != null) {
-//                     Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
-                       Datatype requiredDataType = graph.syncRequest(new PossibleRelatedValue<Datatype>(property, L0X.RequiresDataType, datatype_binging));
+               if(checkPropertyDatatype && property != null) {
+                       Datatype requiredDataType = graph.syncRequest(new PossibleRelatedValue<Datatype>(property, L0X.RequiresDataType, Bindings.DATATYPE));
                        if(requiredDataType != null) return requiredDataType;
                }
 
                Resource literal = variable.getPossibleRepresents(graph);
                if(literal != null) {
-                   Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), datatype_binging);
-                   if(literalDatatype != null) return literalDatatype;
+                       Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), Bindings.DATATYPE);
+                       if(literalDatatype != null) return literalDatatype;
                }
 
                if(property != null) {
 
-                       String requiredValueType = graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
+                       String requiredValueType = info != null
+                                       ? info.requiredValueType
+                                       : graph.getPossibleRelatedValue(property, L0.RequiresValueType, Bindings.STRING);
                        if(requiredValueType != null) {
                                Datatype datatype = getPossibleDatatypeForValueType(requiredValueType);
                                if(datatype != null) return datatype;
@@ -455,7 +451,6 @@ public class Layer0Utils {
                }
 
                return null;
-
        }
 
        private static Datatype getPossibleDatatypeForValueType(String requiredValueType) throws DatabaseException {
@@ -468,11 +463,9 @@ public class Layer0Utils {
                        arrayType = requiredValueType.substring(1, requiredValueType.length()-1);
                }
 
-               if(arrayType != null) {
-                       Datatype arrayDataType = getArrayDataTypeForType(arrayType);
-                       if(arrayDataType != null)
-                               return arrayDataType;
-               }
+               Datatype arrayDataType = getDatatypeForType(arrayType != null ? arrayType : requiredValueType, arrayType != null);
+               if(arrayDataType != null)
+                       return arrayDataType;
 
                Datatype dt = Datatypes.getDatatype(requiredValueType);
                if(dt != null) return dt;
@@ -483,18 +476,19 @@ public class Layer0Utils {
                        return null;
                }
 
-
        }
 
-       private static Datatype getArrayDataTypeForType(String type) {
-               if("Double".equals(type)) return Datatypes.DOUBLE_ARRAY;
-               else if("String".equals(type)) return Datatypes.STRING_ARRAY;
-               else if("Integer".equals(type)) return Datatypes.INTEGER_ARRAY;
-               else if("Long".equals(type)) return Datatypes.LONG_ARRAY;
-               else if("Float".equals(type)) return Datatypes.FLOAT_ARRAY;
-               else if("Byte".equals(type)) return Datatypes.BYTE_ARRAY;
-               else if("Boolean".equals(type)) return Datatypes.BOOLEAN_ARRAY;
-               else if("Variant".equals(type)) return Datatypes.VARIANT_ARRAY;
+       private static Datatype getDatatypeForType(String type, boolean isArray) {
+               switch (type) {
+                       case "Double":  return isArray ? Datatypes.DOUBLE_ARRAY  : Datatypes.DOUBLE;
+                       case "String":  return isArray ? Datatypes.STRING_ARRAY  : Datatypes.STRING;
+                       case "Integer": return isArray ? Datatypes.INTEGER_ARRAY : Datatypes.INTEGER;
+                       case "Long":    return isArray ? Datatypes.LONG_ARRAY    : Datatypes.LONG;
+                       case "Float":   return isArray ? Datatypes.FLOAT_ARRAY   : Datatypes.FLOAT;
+                       case "Byte":    return isArray ? Datatypes.BYTE_ARRAY    : Datatypes.BYTE;
+                       case "Boolean": return isArray ? Datatypes.BOOLEAN_ARRAY : Datatypes.BOOLEAN;
+                       case "Variant": return isArray ? Datatypes.VARIANT_ARRAY : Datatypes.VARIANT;
+               }
                return null;
        }
 
@@ -507,8 +501,6 @@ public class Layer0Utils {
                }
 
                Datatype type = getDatatype(graph, variable);
-               if (type == null)
-                       throw new DatabaseException("No datatype available for variable " + variable.getURI(graph));
                return Bindings.getBinding(type);
 
        }
@@ -516,12 +508,13 @@ public class Layer0Utils {
        public static Binding getPossibleDefaultBinding(ReadGraph graph, Variable variable) throws DatabaseException {
 
                Resource property = variable.getPossiblePredicateResource(graph);
+               PropertyInfo info = null;
                if(property != null) {
-                       PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance());
+                       info = graph.syncRequest(new PropertyInfoRequest(property), TransientCacheAsyncListener.<PropertyInfo>instance());
                        if(info.defaultBinding != null) return info.defaultBinding;
                }
 
-               Datatype type = getPossibleDatatype(graph, variable);
+               Datatype type = getPossibleDatatype(graph, variable, info, false);
                if (type == null) return null;
 
                return Bindings.getBinding(type);
@@ -553,7 +546,7 @@ public class Layer0Utils {
                if(literal == null)
                    return "";
 
-               Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), datatype_binging);
+               Datatype literalDatatype = graph.getPossibleRelatedValue2(literal, L0.HasDataType, new StandardGraphPropertyVariable(graph, variable, null, literal, L0.HasDataType), Bindings.DATATYPE);
                if(literalDatatype != null) {
                        String unit = getPossibleUnit(literalDatatype);
                        if(unit != null) return unit;
@@ -562,7 +555,7 @@ public class Layer0Utils {
                Resource property = variable.getPossiblePredicateResource(graph);
                if(property != null) {
 
-                       Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, datatype_binging);
+                       Datatype requiredDataType = graph.getPossibleRelatedValue(property, L0X.RequiresDataType, Bindings.DATATYPE);
                        if(requiredDataType != null) {
                                String unit = getPossibleUnit(requiredDataType);
                                if(unit != null) return unit;
@@ -647,15 +640,14 @@ public class Layer0Utils {
                return graph.getPossibleResource(graph.getURI(root) + suffix);
        }
 
+       @Deprecated
        public static Resource getPossibleChild(ReadGraph graph, Resource resource, String name) throws DatabaseException {
-               return graph.sync(new PossibleChild(resource, name));
+               return CommonDBUtils.getPossibleChild(graph, resource, name);
        }
 
+       @Deprecated
        public static Resource getPossibleChild(ReadGraph graph, Resource resource, Resource type, String name) throws DatabaseException {
-               Resource child = graph.sync(new PossibleChild(resource, name));
-               if(child == null) return null;
-               if(!graph.isInstanceOf(child, type)) return null;
-               return child;
+               return CommonDBUtils.getPossibleChild(graph, resource, type, name);
        }
 
        public static RelationContext relationContext(ReadGraph graph, Resource subject, Resource predicate) throws DatabaseException {
@@ -927,6 +919,27 @@ public class Layer0Utils {
                return stm != null && stm.isAsserted(subject);
        }
 
+       /*
+        * Works around problems in WriteGraph methods with similar signature. 
+        * Especially handles better some cases with existing literals.
+        * 
+        */
+       public static void claimLiteral(WriteGraph graph, Resource r, Resource p, Resource i, Resource t, Object value, Binding binding) throws DatabaseException {
+           Statement stm = graph.getPossibleStatement(r, p);
+           if(stm != null && !stm.isAsserted(r)) {
+               if(graph.isInstanceOf(stm.getObject(), t)) {
+                   // Existing statement is compatible, reuse the literal
+                   graph.claimValue(stm.getObject(), value, binding);
+                   return;
+               } else {
+                   // Existing statement is incompatible - remove it
+                   graph.deny(stm);
+               }
+           }
+           // Create new statement
+           graph.claimLiteral(r, p, i, t, value, binding);
+       }
+       
        public static void setExpression(WriteGraph graph, Variable context, String text, Resource expressionValueType) throws DatabaseException {
                
                Resource value = context.getRepresents(graph);
@@ -1189,6 +1202,10 @@ public class Layer0Utils {
 
     }
 
+    public static boolean isMarkedReadOnly(ReadGraph graph, Resource r) throws DatabaseException {
+        return Boolean.TRUE.equals( graph.getPossibleRelatedValue(r, graph.<Layer0>l0().readOnly, Bindings.BOOLEAN) );
+    }
+
     private static TransferableGraph1 makeTG(ReadGraph graph, Resource r) throws DatabaseException {
 
        SimanticsClipboardImpl cp = new SimanticsClipboardImpl();
@@ -1366,6 +1383,41 @@ public class Layer0Utils {
        return result;
     }
 
+    public static Resource possibleObjectForType(ReadGraph graph, Resource type, Resource relation) throws DatabaseException {
+        PropertyInfo pi = graph.syncRequest(new PropertyInfoRequest(relation));
+        return possibleObjectForType(graph, type, relation, pi.isFunctional);
+    }
+
+    public static Resource possibleObjectForType(ReadGraph graph, Resource type, Resource relation, boolean functional) throws DatabaseException {
+        if(functional) {
+            Layer0 L0 = Layer0.getInstance(graph);
+            Resource result = graph.getPossibleObject(type, relation);
+            if(result != null)
+                return result;
+            for(Resource su : graph.getObjects(L0.Inherits, type)) {
+                Resource r = possibleObjectForType(graph, su, relation, functional);
+                if(r != null) {
+                    if(result != null)
+                        return null;
+                    result = r;
+                }
+            }
+            return result;
+        } else {
+            Set<Resource> found = objectsForTypeNonFunctional(graph, type, relation, new HashSet<>());
+            return found.size() == 1 ? found.iterator().next() : null;
+        }
+    }
+
+    private static Set<Resource> objectsForTypeNonFunctional(ReadGraph graph, Resource type, Resource relation, Set<Resource> found) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        found.addAll(graph.getObjects(type, relation));
+        for(Resource su : graph.getObjects(L0.Inherits, type)) {
+            objectsForTypeNonFunctional(graph, su, relation, found);
+        }
+        return found;
+    }
+
     public static Resource getPossiblePredicateByNameFromType(ReadGraph graph, Resource type, String name) throws DatabaseException {
        Map<String,Resource> domain = getDomainOf(graph, type);
        return domain.get(name);