Coerce aggregated values, might be coming from string sources

Caller code expects values to be in the sensor type, coerce the values before 
returning them. String values could be inserted - for example from 
BrooklynEntityMirror.


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/2a6d9fd5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/2a6d9fd5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/2a6d9fd5

Branch: refs/heads/master
Commit: 2a6d9fd566f90a4fb8e6f67815d9e50f7bb78e63
Parents: ff31a41
Author: Svetoslav Neykov <[email protected]>
Authored: Tue Apr 21 17:10:16 2015 +0300
Committer: Svetoslav Neykov <[email protected]>
Committed: Wed Apr 22 14:50:00 2015 +0300

----------------------------------------------------------------------
 .../basic/AbstractMultipleSensorAggregator.java | 22 +++++++++++--
 .../entity/basic/ServiceStateLogicTest.java     | 34 +++++++++++++++++++-
 2 files changed, 53 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2a6d9fd5/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
 
b/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
index b40c234..793d8a9 100644
--- 
a/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
+++ 
b/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
@@ -20,8 +20,10 @@ package brooklyn.enricher.basic;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,6 +35,7 @@ import brooklyn.event.Sensor;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.flags.TypeCoercions;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
@@ -138,11 +141,26 @@ public abstract class AbstractMultipleSensorAggregator<U> 
extends AbstractAggreg
         onUpdated();
     }
 
-    @SuppressWarnings("unchecked")
     public <T> Map<Entity,T> getValues(Sensor<T> sensor) {
+        Map<Entity, T> valuesCopy = copyValues(sensor);
+        return coerceValues(valuesCopy, sensor.getType());
+    }
+
+    private <T> Map<Entity, T> coerceValues(Map<Entity, T> values, Class<? 
super T> type) {
+        Map<Entity, T> typedValues = MutableMap.of();
+        for (Entry<Entity, T> entry : values.entrySet()) {
+            @SuppressWarnings("unchecked")
+            T typedValue = (T) TypeCoercions.coerce(entry.getValue(), type);
+            typedValues.put(entry.getKey(), typedValue);
+        }
+        return typedValues;
+    }
+
+    private <T> Map<Entity, T> copyValues(Sensor<T> sensor) {
         synchronized (values) {
+            @SuppressWarnings("unchecked")
             Map<Entity, T> sv = (Map<Entity, T>) values.get(sensor.getName());
-            if (sv==null) return ImmutableMap.of();
+            //use MutableMap because of potentially null values
             return MutableMap.copyOf(sv).asUnmodifiable();
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2a6d9fd5/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java 
b/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java
index 00dd322..d30b05a 100644
--- a/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java
@@ -24,16 +24,22 @@ import org.testng.annotations.Test;
 
 import brooklyn.entity.BrooklynAppUnitTestSupport;
 import brooklyn.entity.Entity;
+import brooklyn.entity.Group;
+import 
brooklyn.entity.basic.EntitySubscriptionTest.RecordingSensorEventListener;
 import brooklyn.entity.basic.QuorumCheck.QuorumChecks;
 import 
brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
 import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
 import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
+import brooklyn.entity.group.DynamicCluster;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.Sensors;
 import brooklyn.location.Location;
+import brooklyn.location.basic.SimulatedLocation;
 import brooklyn.policy.Enricher;
 import brooklyn.test.EntityTestUtils;
 import brooklyn.test.entity.TestEntity;
+import brooklyn.test.entity.TestEntityImpl.TestEntityWithoutEnrichers;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.time.Duration;
 
@@ -240,7 +246,33 @@ public class ServiceStateLogicTest extends 
BrooklynAppUnitTestSupport {
         assertAttributeEquals(entity, Attributes.SERVICE_UP, true);
         assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, 
Lifecycle.RUNNING);
     }
-        
+
+    @Test
+    public void testQuorumWithStringStates() {
+        final DynamicCluster cluster = 
app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
+                .configure(DynamicCluster.MEMBER_SPEC, 
EntitySpec.create(TestEntityWithoutEnrichers.class))
+                .configure(DynamicCluster.INITIAL_SIZE, 1));
+
+        RecordingSensorEventListener r = new RecordingSensorEventListener();
+        app.subscribe(cluster, Attributes.SERVICE_STATE_ACTUAL, r);
+
+        cluster.start(ImmutableList.of(new SimulatedLocation()));
+        EntityTestUtils.assertGroupSizeEqualsEventually(cluster, 1);
+
+        //manually set state to healthy as enrichers are disabled
+        EntityInternal child = (EntityInternal) 
cluster.getMembers().iterator().next();
+        child.setAttribute(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        child.setAttribute(Attributes.SERVICE_UP, Boolean.TRUE);
+
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, 
Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+
+        //set untyped service state, the quorum check should be able to handle 
coercion
+        AttributeSensor<Object> stateSensor = Sensors.newSensor(Object.class, 
Attributes.SERVICE_STATE_ACTUAL.getName());
+        child.setAttribute(stateSensor, "running");
+
+        EntityTestUtils.assertAttributeEqualsContinually(cluster, 
Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+    }
+
     private static <T> void assertAttributeEqualsEventually(Entity x, 
AttributeSensor<T> sensor, T value) {
         try {
             
EntityTestUtils.assertAttributeEqualsEventually(ImmutableMap.of("timeout", 
Duration.seconds(3)), x, sensor, value);

Reply via email to