Repository: brooklyn-server
Updated Branches:
  refs/heads/master 007c4341f -> 33d39242e


UpdateMap: support configuring ‘producer’


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

Branch: refs/heads/master
Commit: af44b6d4bbe363b87d0c601f6842d5000cd7dba0
Parents: 092edf1
Author: Aled Sage <aled.s...@gmail.com>
Authored: Thu Aug 3 13:15:08 2017 +0100
Committer: Aled Sage <aled.s...@gmail.com>
Committed: Thu Aug 3 15:53:44 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/enricher/stock/UpdatingMap.java    |  12 +-
 .../enricher/stock/UpdatingMapTest.java         | 126 +++++++++++++++++++
 2 files changed, 135 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/af44b6d4/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java 
b/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
index 6945d50..c74423e 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.enricher.stock;
 import java.util.Map;
 
 import org.apache.brooklyn.api.catalog.Catalog;
+import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Sensor;
@@ -64,12 +65,15 @@ public class UpdatingMap<S,TKey,TVal> extends 
AbstractEnricher implements Sensor
 
     private static final Logger LOG = 
LoggerFactory.getLogger(UpdatingMap.class);
 
+    public static final ConfigKey<Entity> PRODUCER = 
ConfigKeys.newConfigKey(Entity.class,
+            "enricher.producer");
+
     @SetFromFlag("fromSensor")
     public static final ConfigKey<Sensor<?>> SOURCE_SENSOR = 
ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.sourceSensor");
     @SetFromFlag("targetSensor")
     public static final ConfigKey<Sensor<?>> TARGET_SENSOR = 
ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.targetSensor");
     @SetFromFlag("key")
-    public static final ConfigKey<?> KEY_IN_TARGET_SENSOR = 
ConfigKeys.newConfigKey(Object.class, "enricher.updatingMap.keyInTargetSensor",
+    public static final ConfigKey<Object> KEY_IN_TARGET_SENSOR = 
ConfigKeys.newConfigKey(Object.class, "enricher.updatingMap.keyInTargetSensor",
         "Key to update in the target sensor map, defaulting to the name of the 
source sensor");
     @SetFromFlag("computing")
     public static final ConfigKey<Function<?, ?>> COMPUTING = 
ConfigKeys.newConfigKey(new TypeToken<Function<?,?>>() {}, 
"enricher.updatingMap.computing");
@@ -77,6 +81,7 @@ public class UpdatingMap<S,TKey,TVal> extends 
AbstractEnricher implements Sensor
     public static final ConfigKey<Boolean> REMOVING_IF_RESULT_IS_NULL = 
ConfigKeys.newBooleanConfigKey("enricher.updatingMap.removingIfResultIsNull", 
         "Whether the key in the target map is removed if the result if the 
computation is null");
 
+    protected Entity producer;
     protected AttributeSensor<S> sourceSensor;
     protected AttributeSensor<Map<TKey,TVal>> targetSensor;
     protected TKey key;
@@ -112,13 +117,14 @@ public class UpdatingMap<S,TKey,TVal> extends 
AbstractEnricher implements Sensor
     @Override
     public void setEntity(EntityLocal entity) {
         super.setEntity(entity);
+        this.producer = getConfig(PRODUCER) == null ? entity: 
getConfig(PRODUCER);
         this.sourceSensor = (AttributeSensor<S>) 
getRequiredConfig(SOURCE_SENSOR);
         this.targetSensor = (AttributeSensor<Map<TKey,TVal>>) 
getRequiredConfig(TARGET_SENSOR);
         this.key = (TKey) getConfig(KEY_IN_TARGET_SENSOR);
         this.computing = (Function) getRequiredConfig(COMPUTING);
         this.removingIfResultIsNull = getConfig(REMOVING_IF_RESULT_IS_NULL);
 
-        subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", 
true), entity, sourceSensor, this);
+        subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", 
true), producer, sourceSensor, this);
     }
     
     @Override
@@ -132,7 +138,7 @@ public class UpdatingMap<S,TKey,TVal> extends 
AbstractEnricher implements Sensor
     @SuppressWarnings("unchecked")
     protected void onUpdated() {
         try {
-            Object v = computing.apply(entity.getAttribute(sourceSensor));
+            Object v = computing.apply(producer.getAttribute(sourceSensor));
             if (v == null && !Boolean.FALSE.equals(removingIfResultIsNull)) {
                 v = Entities.REMOVE;
             }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/af44b6d4/core/src/test/java/org/apache/brooklyn/enricher/stock/UpdatingMapTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/enricher/stock/UpdatingMapTest.java 
b/core/src/test/java/org/apache/brooklyn/enricher/stock/UpdatingMapTest.java
new file mode 100644
index 0000000..801d4fa
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/enricher/stock/UpdatingMapTest.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.enricher.stock;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.EnricherSpec;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
+import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.entity.stock.BasicApplication;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+
+public class UpdatingMapTest extends BrooklynAppUnitTestSupport {
+
+    @Test
+    public void testUpdateServiceNotUpIndicator() throws Exception {
+        AttributeSensor<Object> extraIsUpSensor = 
Sensors.newSensor(Object.class, "extraIsUp");
+        
+        Entity entity = 
app.createAndManageChild(EntitySpec.create(BasicApplication.class)
+                .enricher(EnricherSpec.create(UpdatingMap.class)
+                        .configure(UpdatingMap.SOURCE_SENSOR.getName(), 
extraIsUpSensor.getName())
+                        .configure(UpdatingMap.TARGET_SENSOR, 
ServiceStateLogic.SERVICE_NOT_UP_INDICATORS)
+                        .configure(UpdatingMap.COMPUTING, 
Functions.forMap(MutableMap.of(true, null, false, "valIsFalse"), 
"myDefault"))));
+
+        assertMapSensorContainsEventually(entity, 
ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, ImmutableMap.of("extraIsUp", 
"myDefault"));
+        
+        entity.sensors().set(extraIsUpSensor, true);
+        assertMapSensorNotContainsKeysEventually(entity, 
ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, ImmutableList.of("extraIsUp"));
+
+        app.start(ImmutableList.<Location>of());
+        
+        EntityAsserts.assertAttributeEqualsEventually(entity, 
Attributes.SERVICE_UP, true);
+        EntityAsserts.assertAttributeEqualsContinually(entity, 
Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        
+        entity.sensors().set(extraIsUpSensor, false);
+        EntityAsserts.assertAttributeEqualsEventually(entity, 
ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, ImmutableMap.of("extraIsUp", 
"valIsFalse"));
+        EntityAsserts.assertAttributeEqualsEventually(entity, 
Attributes.SERVICE_UP, false);
+
+        entity.sensors().set(extraIsUpSensor, true);
+        EntityAsserts.assertAttributeEqualsEventually(entity, 
ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, ImmutableMap.of());
+        EntityAsserts.assertAttributeEqualsEventually(entity, 
Attributes.SERVICE_UP, true);
+    }
+    
+    @Test
+    @SuppressWarnings("serial")
+    public void testUpdateMapUsingDifferentProducer() throws Exception {
+        AttributeSensor<Object> mySensor = Sensors.newSensor(Object.class, 
"mySensor");
+        AttributeSensor<Map<String,Object>> mapSensor = Sensors.newSensor(
+                new TypeToken<Map<String,Object>>() {},
+                "mapSensor");
+        
+        Entity producer = 
app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+        Entity entity = 
app.createAndManageChild(EntitySpec.create(BasicApplication.class)
+                .enricher(EnricherSpec.create(UpdatingMap.class)
+                        .configure(UpdatingMap.PRODUCER, producer)
+                        .configure(UpdatingMap.SOURCE_SENSOR.getName(), 
mySensor.getName())
+                        .configure(UpdatingMap.TARGET_SENSOR, mapSensor)
+                        .configure(UpdatingMap.KEY_IN_TARGET_SENSOR, "myKey")
+                        .configure(UpdatingMap.COMPUTING, 
Functions.forMap(MutableMap.of("v1", "valIsV1", "v2", "valIsV2"), 
"myDefault"))));
+
+        EntityAsserts.assertAttributeEqualsEventually(entity, mapSensor, 
ImmutableMap.of("myKey", "myDefault"));
+        
+        producer.sensors().set(mySensor, "v1");
+        EntityAsserts.assertAttributeEqualsEventually(entity, mapSensor, 
ImmutableMap.of("myKey", "valIsV1"));
+    }
+    
+    private void assertMapSensorContainsEventually(Entity entity, 
AttributeSensor<? extends Map<?, ?>> mapSensor, Map<?, ?> expected) {
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                Map<?, ?> actual = entity.sensors().get(mapSensor);
+                String errMsg = "actual="+actual+"; expected="+expected;
+                for (Map.Entry<?,?> entry : expected.entrySet()) {
+                    assertTrue(actual.containsKey(entry.getKey()), errMsg);
+                    assertEquals(actual.get(entry.getKey()), entry.getValue(), 
errMsg);
+                }
+            }});
+    }
+    
+    private void assertMapSensorNotContainsKeysEventually(Entity entity, 
AttributeSensor<? extends Map<?, ?>> mapSensor, Iterable<?> keys) {
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                Map<?, ?> actual = entity.sensors().get(mapSensor);
+                String errMsg = "actual="+actual+"; notExpected="+keys;
+                for (Object key : keys) {
+                    assertFalse(actual.containsKey(key), errMsg);
+                }
+            }});
+    }
+}

Reply via email to