This is an automated email from the ASF dual-hosted git repository.

iuliana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git


The following commit(s) were added to refs/heads/master by this push:
     new 529983a  add support and docs for coercing and resolving WrappedValue 
instances
     new 71ec87d  Merge pull request #1120 from 
ahgittin/wrapped-values-resolution
529983a is described below

commit 529983af68fe4bafa82c64478559b1a4bf6d900c
Author: Alex Heneveld <[email protected]>
AuthorDate: Thu Oct 29 12:22:11 2020 +0000

    add support and docs for coercing and resolving WrappedValue instances
---
 .../core/resolve/jackson/WrappedValue.java         | 13 ++++--
 .../jackson/WrappedValuesSerialization.java        | 18 ---------
 .../brooklyn/util/core/flags/TypeCoercions.java    | 47 ++++++++++++++++++++++
 .../brooklyn/util/core/task/DeferredSupplier.java  |  4 +-
 .../jackson/WrappedValuesSerializationTest.java    | 42 +++++++++++++++++++
 5 files changed, 101 insertions(+), 23 deletions(-)

diff --git 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValue.java 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValue.java
index a5f22d9..666aa00 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValue.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValue.java
@@ -21,13 +21,20 @@ package org.apache.brooklyn.core.resolve.jackson;
 import com.google.common.base.Preconditions;
 import java.util.Objects;
 import java.util.function.Supplier;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
 
 /**
  * Wraps a value which might be constant or might come from a supplier.
  * The pattern where fields are of this type is used to assist with 
(de)serialization
  * where values might come from a DSL.
+ *
+ * This will be unwrapped using {@link 
org.apache.brooklyn.util.core.flags.TypeCoercions}
+ * if it contains a value (unless a WrappedValue is requested), but not if it 
uses a supplier.
+ * Any object can be coerced to a {@link WrappedValue} using {@link 
org.apache.brooklyn.util.core.flags.TypeCoercions}.
+ *
+ * It will always be unwrapped (attempted) using {@link 
org.apache.brooklyn.util.core.task.Tasks#resolving(Object)}.
  */
-public class WrappedValue<T> implements Supplier<T> {
+public class WrappedValue<T> implements Supplier<T>, 
com.google.common.base.Supplier<T>, DeferredSupplier<T> {
     final static WrappedValue<?> NULL_WRAPPED_VALUE = new WrappedValue<>(null, 
false);
     final T value;
     final Supplier<T> supplier;
@@ -75,14 +82,14 @@ public class WrappedValue<T> implements Supplier<T> {
 
     public static <T> WrappedValue<T> of(Object x) {
         if (x instanceof Supplier) return ofSupplier((Supplier<T>)x);
-        if (x instanceof com.google.common.base.Supplier) return 
ofSupplier((com.google.common.base.Supplier<T>)x);
+        if (x instanceof com.google.common.base.Supplier) return 
ofGuavaSupplier((com.google.common.base.Supplier<T>)x);
         return new WrappedValue<>(x, false);
     }
     public static <T> WrappedValue<T> ofConstant(T x) {
         return new WrappedValue<>(x, false);
     }
     public static <T> WrappedValue<T> ofSupplier(Supplier<T> x) { return new 
WrappedValue<>(x, true); }
-    public static <T> WrappedValue<T> 
ofSupplier(com.google.common.base.Supplier<T> x) { return new 
WrappedValue<>(new GuavaSupplierAsJavaSupplier<>( 
(com.google.common.base.Supplier<T>)x ), true); }
+    public static <T> WrappedValue<T> 
ofGuavaSupplier(com.google.common.base.Supplier<T> x) { return new 
WrappedValue<>(new GuavaSupplierAsJavaSupplier<>( 
(com.google.common.base.Supplier<T>)x ), true); }
     public static <T> WrappedValue<T> ofNull() { return 
(WrappedValue<T>)NULL_WRAPPED_VALUE; }
 
     public T get() {
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java
 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java
index 1d09f25..42a2702 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerialization.java
@@ -67,10 +67,6 @@ public class WrappedValuesSerialization {
                 TokenBuffer b = new TokenBuffer(p, ctxt);
                 b.copyCurrentStructure(p);
                 try {
-//                        // could do this first for primitives, but no need 
as the object serializer below will do the same
-//                        TreeNode v = 
b.asParserOnFirstToken().readValueAsTree();
-//                        if (v instanceof ValueNode) return 
((ValueNode)v).asText();  // this makes strings for everything; would need to 
do all the subtypes of ValueNode
-
                     // this should work for primitives, objects, and suppliers 
(which will declare type)
                     // only time it won't is where generics are used to drop 
the type declaration during serialization
                     JavaType genericType = getGenericType(typeDeserializer);
@@ -84,17 +80,6 @@ public class WrappedValuesSerialization {
                 // fall back to just using object
                 try {
                     return 
ctxt.findRootValueDeserializer(ctxt.constructType(Object.class)).deserialize(b.asParserOnFirstToken(),
 ctxt);
-                    // above should be sufficient, but if not we could try the 
below:
-//                    Object result 
ctxt.findNonContextualValueDeserializer(ctxt.constructType(Object.class)).deserialize(b.asParserOnFirstToken(),
 ctxt);
-//                    try {
-//                        if (result instanceof Map) {
-//                            // if we got a map, try reading it as typed
-//                            return 
ctxt.findRootValueDeserializer(ctxt.constructType(Object.class)).deserialize(b.asParserOnFirstToken(),
 ctxt);
-//                        }
-//                    } catch (Exception e) {
-//                        exceptions.add(e);
-//                    }
-//                    return result;
                 } catch (Exception e) {
                     exceptions.add(e);
                 }
@@ -220,9 +205,6 @@ public class WrappedValuesSerialization {
             .registerModule(new SimpleModule()
                 .addSerializer(WrappedValue.class, new 
WrappedValueSerializer())
                 .addDeserializer(WrappedValue.class, new 
WrappedValueDeserializer())
-//                .setDeserializerModifier(new 
ConfigurableBeanDeserializerModifier()
-//                        
.addPostConstructFunction(WrappedValuesSerialization::ensureWrappedValuesInitialized)
-//                )
             );
     }
 
diff --git 
a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java 
b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
index 536ae66..0049c96 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Sensor;
 import org.apache.brooklyn.core.internal.BrooklynInitialization;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.resolve.jackson.WrappedValue;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.util.JavaGroovyEquivalents;
 import org.apache.brooklyn.util.core.ClassLoaderUtils;
@@ -269,6 +270,16 @@ public class TypeCoercions {
         
         public BrooklynCommonAdaptorTypeCoercions(TypeCoercerExtensible 
coercer) { super(coercer); }
 
+        public CommonAdaptorTypeCoercions registerAllAdapters() {
+            super.registerAllAdapters();
+            registerWrappedValueAdapters();
+
+            //these are deliberately not included here, but added by routines 
which need them
+            // registerInstanceForClassnameAdapter
+
+            return this;
+        }
+
         @SuppressWarnings("rawtypes")
         @Override
         public void registerClassForNameAdapters() {
@@ -307,6 +318,42 @@ public class TypeCoercions {
                 }
             });
         }
+
+        public void registerWrappedValueAdapters() {
+            registerAdapter("10-unwrap-wrapped-value", new TryCoercer() {
+                        @Override
+                        public <T> Maybe<T> tryCoerce(Object input, 
TypeToken<T> type) {
+                            if (!(input instanceof WrappedValue)) {
+                                return null;
+                            }
+                            if 
(WrappedValue.class.isAssignableFrom(type.getRawType())) {
+                                // don't unwrap if a wrapped value is wanted 
(won't come here anyway)
+                                return null;
+                            }
+                            WrappedValue<?> w = (WrappedValue<?>) input;
+                            if (w.getSupplier()!=null) {
+                                // don't unwrap if it is a supplier
+                                return null;
+                            }
+                            return (Maybe) Maybe.of(((WrappedValue<?>) 
input).get());
+                        }
+                    });
+            registerAdapter("99-wrap-to-wrapped-value", new TryCoercer() {
+                @Override
+                public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> type) 
{
+                    if (!WrappedValue.class.equals(type.getRawType())) {
+                        // only applies if a WrappedValue is wanted
+                        return null;
+                    }
+                    if (input instanceof WrappedValue) {
+                        // already wrapped (won't come here anyway, unless 
possibly thing _in_ the wrapped value needs generic coercion)
+                        return null;
+                    }
+                    // note, generics on type are not respected
+                    return Maybe.of( (T) WrappedValue.ofConstant(input) );
+                }
+            });
+        }
     }
 
     public static TypeCoercer asTypeCoercer() {
diff --git 
a/core/src/main/java/org/apache/brooklyn/util/core/task/DeferredSupplier.java 
b/core/src/main/java/org/apache/brooklyn/util/core/task/DeferredSupplier.java
index 4a19a74..1a617ad 100644
--- 
a/core/src/main/java/org/apache/brooklyn/util/core/task/DeferredSupplier.java
+++ 
b/core/src/main/java/org/apache/brooklyn/util/core/task/DeferredSupplier.java
@@ -22,8 +22,8 @@ import com.google.common.base.Supplier;
 
 /**
  * A class that supplies objects of a single type. When used as a ConfigKey 
value,
- * the evaluation is deferred until getConfig() is called. The returned value 
will then
- * be coerced to the correct type. 
+ * the evaluation is deferred until getConfig() or {@link 
Tasks#resolving(Object)} is called.
+ * The returned value will then be coerced to the correct type.
  * 
  * Subsequent calls to getConfig will result in further calls to 
deferredProvider.get(), 
  * rather than reusing the result. If you want to reuse the result, consider 
instead 
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java
 
b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java
index 25aec9a..fe1b16b 100644
--- 
a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/WrappedValuesSerializationTest.java
@@ -22,6 +22,13 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.function.Supplier;
 import 
org.apache.brooklyn.core.resolve.jackson.WrappedValue.WrappedValuesInitialized;
 import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import 
org.apache.brooklyn.util.core.flags.TypeCoercions.BrooklynCommonAdaptorTypeCoercions;
+import org.apache.brooklyn.util.core.task.BasicExecutionContext;
+import org.apache.brooklyn.util.core.task.BasicExecutionManager;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -116,4 +123,39 @@ public class WrappedValuesSerializationTest implements 
MapperTestFixture {
         Assert.assertEquals(b2.x.get().x.get(), "hello");
     }
 
+    @Test
+    public void testWrappedValueCoercion() throws Exception {
+        ObjectWithWrappedValueString a = new ObjectWithWrappedValueString();
+
+        a.x = WrappedValue.of("hello");
+        Assert.assertEquals(TypeCoercions.coerce(a.x, String.class), "hello");
+        Assert.assertEquals(TypeCoercions.coerce(a.x, Object.class), a.x);
+        Assert.assertEquals(TypeCoercions.coerce(a.x, WrappedValue.class), 
a.x);
+
+        a.x = WrappedValue.ofSupplier((Supplier) () -> "hello");
+        Asserts.assertNotPresent(TypeCoercions.tryCoerce(a.x, String.class));
+    }
+
+    @Test
+    public void testWrappedValueResolution() throws Exception {
+        ObjectWithWrappedValueString a = new ObjectWithWrappedValueString();
+
+        a.x = WrappedValue.of("hello");
+        Assert.assertEquals(resolve(a.x, String.class).get(), "hello");
+        Assert.assertEquals(resolve(a.x, Object.class).get(), "hello");
+        Assert.assertEquals(resolve(a.x, WrappedValue.class).get().get(), 
"hello");
+
+        a.x = WrappedValue.ofSupplier((Supplier) () -> "hello");
+        Asserts.assertEquals(resolve(a.x, String.class).get(), "hello");
+        Asserts.assertEquals(resolve(a.x, Object.class).get(), "hello");
+        Asserts.assertEquals(resolve(a.x, WrappedValue.class).get().get(), 
"hello");
+    }
+
+    protected <T> Maybe<T> resolve(Object o, Class<T> type) {
+        BasicExecutionManager execManager = new 
BasicExecutionManager("test-context-"+ JavaClassNames.niceClassAndMethod());
+        BasicExecutionContext execContext = new 
BasicExecutionContext(execManager);
+
+        return 
Tasks.resolving(o).as(type).context(execContext).deep().getMaybe();
+    }
+
 }

Reply via email to