From ada96685970d938b68b28085e51610187401b8a9 Mon Sep 17 00:00:00 2001 From: Reino Ruusu Date: Mon, 3 Oct 2016 17:39:33 +0300 Subject: [PATCH] Improve Databoard's dynamically typed data capabilities. refs #6738 Change-Id: Iddbcf7e875aefa1bc70430b918cef3656ad97501 --- .../databoard/adapter/AdapterFactory.java | 24 ++++++ .../binding/reflection/BindingRequest.java | 6 +- .../reflection/ClassBindingFactory.java | 74 ++++++++++++------- .../org.simantics.scl.runtime/scl/Prelude.scl | 3 + 4 files changed, 78 insertions(+), 29 deletions(-) diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/adapter/AdapterFactory.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/adapter/AdapterFactory.java index 0c07958d5..2dc51e402 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/adapter/AdapterFactory.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/adapter/AdapterFactory.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Map; import org.apache.commons.collections.map.ReferenceMap; +import org.simantics.databoard.Bindings; import org.simantics.databoard.Units; import org.simantics.databoard.binding.ArrayBinding; import org.simantics.databoard.binding.Binding; @@ -854,6 +855,29 @@ public class AdapterFactory { return result; } + if (domain instanceof VariantBinding && !(range instanceof VariantBinding)) + { + // Make a recursive adaptation from a variant source + final VariantBinding domainBinding = (VariantBinding)domain; + final Binding rangeBinding = range; + AbstractAdapter result = new AbstractAdapter() { + @Override + public Object adapt(Object obj) throws AdaptException { + try { + Object value = domainBinding.getContent(obj); + Binding contentBinding = domainBinding.getContentBinding(obj); + AbstractAdapter adapter = (AbstractAdapter) getAdapter(contentBinding, rangeBinding, typeAdapter, mustClone); + return adapter.adapt(value); + } catch (BindingException | AdapterConstructionException e) { + throw new AdaptException(e); + } + } + }; + result.clones = mustClone; + addToCache(req, result); + return result; + } + if (range instanceof VariantBinding && !(domain instanceof VariantBinding)) { // Default to just wrapping the domain type diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java index 593eb308b..56cbe61dd 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java @@ -17,7 +17,7 @@ public class BindingRequest { { Annotation[] annotations = ClassBindingFactory.getFieldAnnotations(field); Class fieldClass = field.getType(); - return new BindingRequest(fieldClass, annotations); + return new BindingRequest(fieldClass, annotations); } /** Requested class */ @@ -33,8 +33,8 @@ public class BindingRequest { public final String signature; // eg. Ljava/util/Map; public final String descriptor; //eg. Ljava/util/Map; - public BindingRequest componentRequest; - public Binding componentBinding; + public BindingRequest[] componentRequests; + public Binding[] componentBindings; transient int hash; diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/ClassBindingFactory.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/ClassBindingFactory.java index 081e8b1ec..94d3ed5f6 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/ClassBindingFactory.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/ClassBindingFactory.java @@ -74,6 +74,7 @@ import org.simantics.databoard.type.DoubleType; import org.simantics.databoard.type.FloatType; import org.simantics.databoard.type.IntegerType; import org.simantics.databoard.type.LongType; +import org.simantics.databoard.type.MapType; import org.simantics.databoard.type.OptionalType; import org.simantics.databoard.type.RecordType; import org.simantics.databoard.type.StringType; @@ -391,15 +392,16 @@ public class ClassBindingFactory { lengths[i] = org.simantics.databoard.util.Range.valueOf(strs[i]); } - if ( binding.componentBinding==null && request.componentBinding!=null ) binding.componentBinding = request.componentBinding; + if ( binding.componentBinding==null && request.componentBindings!=null ) binding.componentBinding = request.componentBindings[0]; if ( binding.componentBinding == null) { - BindingRequest componentRequest = request.componentRequest; - if (componentClass!=null && componentRequest==null) { + BindingRequest componentRequest = request.componentRequests != null ? request.componentRequests[0] : null; + if (componentRequest==null) { + if (componentClass==null) { + componentClass = Object.class; + // throw new BindingConstructionException("Cannot determine array component type"); + } componentRequest = new BindingRequest(componentClass, componentAnnotations); } - if (componentRequest==null) { - throw new BindingConstructionException("Cannot determine array component type"); - } inprogress.put(request, binding); binding.componentBinding = construct( componentRequest ); @@ -426,44 +428,64 @@ public class ClassBindingFactory { Arguments argumentsAnnotation = request.getAnnotation(Arguments.class); Annotation[] componentAnnotations = request.dropAnnotations( 2 ); + Class[] arguments = argumentsAnnotation != null ? argumentsAnnotation.value() : null; BindingRequest keyRequest = null; BindingRequest valueRequest = null; + + Binding keyBinding = null; + Binding valueBinding = null; - if (binding.getKeyBinding() == null) { - Class keyClass = argumentsAnnotation.value()[0]; + if (binding.getKeyBinding() != null) { + keyBinding = binding.getKeyBinding(); + } + else if (request.componentBindings != null) { + keyBinding = request.componentBindings[0]; + } + else if (request.componentRequests != null) { + keyRequest = request.componentRequests[0]; + } + else { + Class keyClass = arguments != null && arguments.length >= 1 ? arguments[0] : null; if (keyClass==null) { - throw new BindingConstructionException("Cannot determine key class, use @Arguments annotation"); + keyClass = Object.class; + //throw new BindingConstructionException("Cannot determine key class, use @Arguments annotation"); } keyRequest = new BindingRequest(keyClass, componentAnnotations); } - else { - binding.type().keyType = binding.getKeyBinding().type(); - } - if (binding.getValueBinding() == null) { - Class valueClass = argumentsAnnotation.value()[1]; + if (binding.getValueBinding() != null) { + valueBinding = binding.getValueBinding(); + } + else if (request.componentBindings != null) { + valueBinding = request.componentBindings[1]; + } + else if (request.componentRequests != null) { + valueRequest = request.componentRequests[1]; + } + else { + Class valueClass = arguments != null && arguments.length >= 2 ? arguments[1] : null; if (valueClass==null) { - throw new BindingConstructionException("Cannot determine value class, use @Arguments annotation"); + valueClass = Object.class; + //throw new BindingConstructionException("Cannot determine value class, use @Arguments annotation"); } valueRequest = new BindingRequest(valueClass, componentAnnotations); } - else { - binding.type().valueType = binding.getValueBinding().type(); - } - + inprogress.put(request, result); if (keyRequest!=null) { - Binding keyBinding = construct( keyRequest ); - binding.type().keyType = keyBinding.type(); - binding.setKeyBinding(keyBinding); + keyBinding = construct( keyRequest ); } if (valueRequest!=null) { - Binding valueBinding = construct( valueRequest ); - binding.type().valueType = valueBinding.type(); - binding.setValueBinding(valueBinding); + valueBinding = construct( valueRequest ); } - inprogress.remove(request); + inprogress.remove(request); + + MapType type = binding.type(); + type.keyType = keyBinding.type(); + type.valueType = valueBinding.type(); + binding.setKeyBinding( keyBinding ); + binding.setValueBinding( valueBinding ); } /// Optional diff --git a/bundles/org.simantics.scl.runtime/scl/Prelude.scl b/bundles/org.simantics.scl.runtime/scl/Prelude.scl index 84f8b91b6..4c20c99b5 100644 --- a/bundles/org.simantics.scl.runtime/scl/Prelude.scl +++ b/bundles/org.simantics.scl.runtime/scl/Prelude.scl @@ -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 -- 2.43.2