Improve Databoard's dynamically typed data capabilities. 17/117/1
authorReino Ruusu <reino.ruusu@vtt.fi>
Mon, 3 Oct 2016 14:39:33 +0000 (17:39 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Tue, 4 Oct 2016 12:33:08 +0000 (15:33 +0300)
refs #6738

Change-Id: Iddbcf7e875aefa1bc70430b918cef3656ad97501

bundles/org.simantics.databoard/src/org/simantics/databoard/adapter/AdapterFactory.java
bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java
bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/ClassBindingFactory.java
bundles/org.simantics.scl.runtime/scl/Prelude.scl

index 0c07958d580e7e7b9707b044e79e84c761583238..2dc51e402eee7300db0f8aea4dd898ff5168c905 100644 (file)
@@ -15,6 +15,7 @@ import java.util.ArrayList;
 import java.util.Map;\r
 \r
 import org.apache.commons.collections.map.ReferenceMap;\r
+import org.simantics.databoard.Bindings;\r
 import org.simantics.databoard.Units;\r
 import org.simantics.databoard.binding.ArrayBinding;\r
 import org.simantics.databoard.binding.Binding;\r
@@ -854,6 +855,29 @@ public class AdapterFactory {
                return result;
        }\r
        \r
+       if (domain instanceof VariantBinding && !(range instanceof VariantBinding))\r
+       {\r
+               // Make a recursive adaptation from a variant source\r
+               final VariantBinding domainBinding = (VariantBinding)domain;\r
+               final Binding rangeBinding = range;\r
+               AbstractAdapter result = new AbstractAdapter() {\r
+                               @Override\r
+                               public Object adapt(Object obj) throws AdaptException {\r
+                                       try {\r
+                                               Object value = domainBinding.getContent(obj);\r
+                                               Binding contentBinding = domainBinding.getContentBinding(obj);\r
+                                               AbstractAdapter adapter = (AbstractAdapter) getAdapter(contentBinding, rangeBinding, typeAdapter, mustClone);\r
+                                               return adapter.adapt(value);\r
+                                       } catch (BindingException | AdapterConstructionException e) {\r
+                                               throw new AdaptException(e);\r
+                                       }\r
+                               }\r
+               };\r
+               result.clones = mustClone;\r
+               addToCache(req, result);\r
+               return result;                  \r
+       }\r
+       \r
        if (range instanceof VariantBinding && !(domain instanceof VariantBinding))\r
        {\r
                // Default to just wrapping the domain type\r
index 593eb308b17cd3bce06602ef40e7605c58e0e153..56cbe61dd2116bd38101d87b794a677907b56e60 100644 (file)
@@ -17,7 +17,7 @@ public class BindingRequest {
        {\r
        Annotation[] annotations = ClassBindingFactory.getFieldAnnotations(field);\r
        Class<?> fieldClass = field.getType(); \r
-       return new BindingRequest(fieldClass, annotations);             \r
+       return new BindingRequest(fieldClass, annotations);\r
        }\r
        \r
        /** Requested class */\r
@@ -33,8 +33,8 @@ public class BindingRequest {
     public final String signature; // eg. Ljava/util/Map;\r
     public final String descriptor; //eg. Ljava/util/Map<I;I>;\r
     \r
-    public BindingRequest componentRequest;\r
-    public Binding componentBinding;\r
+    public BindingRequest[] componentRequests;\r
+    public Binding[] componentBindings;\r
     \r
     transient int hash;\r
 \r
index 081e8b1ecbdb4547f5f1a22c9620db43c8f0d5e1..94d3ed5f6d4f323950cfec22df2095193d9e8a13 100644 (file)
@@ -74,6 +74,7 @@ import org.simantics.databoard.type.DoubleType;
 import org.simantics.databoard.type.FloatType;\r
 import org.simantics.databoard.type.IntegerType;\r
 import org.simantics.databoard.type.LongType;\r
+import org.simantics.databoard.type.MapType;\r
 import org.simantics.databoard.type.OptionalType;\r
 import org.simantics.databoard.type.RecordType;\r
 import org.simantics.databoard.type.StringType;\r
@@ -391,15 +392,16 @@ public class ClassBindingFactory {
                                lengths[i] = org.simantics.databoard.util.Range.valueOf(strs[i]);                               \r
                }\r
                \r
-               if ( binding.componentBinding==null && request.componentBinding!=null ) binding.componentBinding = request.componentBinding;\r
+               if ( binding.componentBinding==null && request.componentBindings!=null ) binding.componentBinding = request.componentBindings[0];\r
                if ( binding.componentBinding == null) {\r
-                       BindingRequest componentRequest = request.componentRequest;\r
-                               if (componentClass!=null && componentRequest==null) {\r
+                       BindingRequest componentRequest = request.componentRequests != null ? request.componentRequests[0] : null;\r
+                               if (componentRequest==null) {\r
+                                       if (componentClass==null) {\r
+                                               componentClass = Object.class;\r
+                                       // throw new BindingConstructionException("Cannot determine array component type");\r
+                                       }\r
                                        componentRequest = new BindingRequest(componentClass, componentAnnotations);                    \r
                                }\r
-                               if (componentRequest==null) {\r
-                               throw new BindingConstructionException("Cannot determine array component type");\r
-                       }\r
                                \r
                                inprogress.put(request, binding);\r
                                binding.componentBinding = construct( componentRequest );\r
@@ -426,44 +428,64 @@ public class ClassBindingFactory {
                \r
                        Arguments argumentsAnnotation = request.getAnnotation(Arguments.class);\r
                        Annotation[] componentAnnotations = request.dropAnnotations( 2 );\r
+                Class<?>[] arguments = argumentsAnnotation != null ? argumentsAnnotation.value() : null;\r
 \r
                 BindingRequest keyRequest = null;\r
                 BindingRequest valueRequest = null;\r
+                \r
+                Binding keyBinding = null;\r
+                Binding valueBinding = null;\r
                        \r
-                       if (binding.getKeyBinding() == null) {\r
-                               Class<?> keyClass = argumentsAnnotation.value()[0];\r
+                       if (binding.getKeyBinding() != null) {\r
+                           keyBinding = binding.getKeyBinding();\r
+                       }\r
+                       else if (request.componentBindings != null) {\r
+                               keyBinding = request.componentBindings[0];\r
+                       }\r
+                       else if (request.componentRequests != null) {\r
+                               keyRequest = request.componentRequests[0];\r
+                       }\r
+                       else {\r
+                               Class<?> keyClass = arguments != null && arguments.length >= 1 ? arguments[0] : null;\r
                     if (keyClass==null) {\r
-                       throw new BindingConstructionException("Cannot determine key class, use @Arguments annotation");\r
+                       keyClass = Object.class;\r
+                       //throw new BindingConstructionException("Cannot determine key class, use @Arguments annotation");\r
                     }\r
                     keyRequest = new BindingRequest(keyClass, componentAnnotations);\r
                        }\r
-                       else {\r
-                               binding.type().keyType = binding.getKeyBinding().type();                                \r
-                       }\r
                        \r
-                       if (binding.getValueBinding() == null) {\r
-                               Class<?> valueClass = argumentsAnnotation.value()[1];\r
+                       if (binding.getValueBinding() != null) {\r
+                    valueBinding = binding.getValueBinding();\r
+                       }\r
+                       else if (request.componentBindings != null) {\r
+                               valueBinding = request.componentBindings[1];\r
+                       }\r
+                       else if (request.componentRequests != null) {\r
+                               valueRequest = request.componentRequests[1];\r
+                       }\r
+                       else {\r
+                               Class<?> valueClass = arguments != null && arguments.length >= 2 ? arguments[1] : null;\r
                     if (valueClass==null) {\r
-                       throw new BindingConstructionException("Cannot determine value class, use @Arguments annotation");\r
+                       valueClass = Object.class;\r
+                       //throw new BindingConstructionException("Cannot determine value class, use @Arguments annotation");\r
                     }\r
                     valueRequest = new BindingRequest(valueClass, componentAnnotations);\r
                        }\r
-                       else {\r
-                               binding.type().valueType = binding.getValueBinding().type();                            \r
-                       }\r
-                                \r
+                       \r
                        inprogress.put(request, result);\r
                        if (keyRequest!=null) {\r
-                               Binding keyBinding = construct( keyRequest );\r
-                               binding.type().keyType = keyBinding.type();\r
-                               binding.setKeyBinding(keyBinding);\r
+                               keyBinding = construct( keyRequest );\r
                        }\r
                        if (valueRequest!=null) {\r
-                               Binding valueBinding = construct( valueRequest );\r
-                               binding.type().valueType = valueBinding.type();\r
-                               binding.setValueBinding(valueBinding);\r
+                               valueBinding = construct( valueRequest );\r
                        }\r
-                       inprogress.remove(request);\r
+                inprogress.remove(request);\r
+                \r
+                MapType type = binding.type();\r
+                type.keyType = keyBinding.type();\r
+                type.valueType = valueBinding.type();\r
+                       binding.setKeyBinding( keyBinding );\r
+                       binding.setValueBinding( valueBinding );\r
             }\r
                \r
                /// Optional\r
index 84f8b91b6ef97751ea1f0a00b053ece6e2e8be63..4c20c99b52dfe03528542ab582934a9fe7185ec3 100644 (file)
@@ -2294,6 +2294,9 @@ importJava "org.simantics.databoard.binding.mutable.Variant" where
     @JavaName getComponent
     variantComponent :: Variant -> ChildReference -> Variant
 
+variant :: Serializable a => a -> Variant
+variant v = variantOfWithBinding binding v
+
 variantValue :: Serializable a => Variant -> a
 variantValue v = variantValue_ v binding