SensorPropagatingEnricher: support propagating as different sensor
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/39c08cb5 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/39c08cb5 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/39c08cb5 Branch: refs/heads/0.5.0 Commit: 39c08cb5c1f233a347fcbe629bc85b3648cb01e9 Parents: 7358417 Author: Aled Sage <[email protected]> Authored: Wed Apr 24 10:54:04 2013 +0100 Committer: Aled Sage <[email protected]> Committed: Thu Apr 25 11:15:19 2013 +0100 ---------------------------------------------------------------------- .../basic/SensorPropagatingEnricher.java | 56 ++++++++--- .../SensorPropagatingEnricherTest.groovy | 41 -------- .../enricher/SensorPropagatingEnricherTest.java | 98 ++++++++++++++++++++ 3 files changed, 141 insertions(+), 54 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/39c08cb5/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java b/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java index 899dc61..068cc9a 100644 --- a/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java +++ b/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java @@ -1,7 +1,7 @@ package brooklyn.enricher.basic; -import java.util.Arrays; import java.util.Collection; +import java.util.Map; import java.util.Set; import org.slf4j.Logger; @@ -14,6 +14,8 @@ import brooklyn.event.Sensor; import brooklyn.event.SensorEvent; import brooklyn.event.SensorEventListener; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -24,9 +26,13 @@ public class SensorPropagatingEnricher extends AbstractEnricher implements Senso /** the entity to listen to */ private final Entity source; - /** the sensors to listen to */ - private final Set<Sensor<?>> sensors = Sets.newLinkedHashSet(); + /** the sensors to listen to */ + private final Set<Sensor<?>> sensors; + + /** the sensors to listen to */ + private final Map<Sensor<?>, Sensor<?>> sensorAlternatives; + public static SensorPropagatingEnricher newInstanceListeningToAllSensors(Entity source) { return newInstanceListeningToAllSensorsBut(source); } @@ -44,12 +50,24 @@ public class SensorPropagatingEnricher extends AbstractEnricher implements Senso return new SensorPropagatingEnricher(source, includes); } + public static SensorPropagatingEnricher newInstanceListeningTo(Entity source, Map<? extends Sensor<?>, ? extends Sensor<?>> sensors) { + return new SensorPropagatingEnricher(source, sensors); + } + public SensorPropagatingEnricher(Entity source, Sensor<?>... sensors) { - this(source, Arrays.asList(sensors)); + this(source, ImmutableList.copyOf(sensors)); } + public SensorPropagatingEnricher(Entity source, Collection<Sensor<?>> sensors) { this.source = source; - this.sensors.addAll(sensors); + this.sensors = ImmutableSet.copyOf(sensors); + this.sensorAlternatives = ImmutableMap.of(); + } + + public SensorPropagatingEnricher(Entity source, Map<? extends Sensor<?>, ? extends Sensor<?>> sensors) { + this.source = source; + this.sensors = ImmutableSet.copyOf(sensors.keySet()); + this.sensorAlternatives = ImmutableMap.copyOf(sensors); } public void setEntity(EntityLocal entity) { @@ -59,16 +77,23 @@ public class SensorPropagatingEnricher extends AbstractEnricher implements Senso } } - public void onEvent(SensorEvent event) { - if (log.isTraceEnabled()) log.trace("policy {} got {}, propagating via {}", new Object[] {this, event, entity}); - //just propagate upwards + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void onEvent(SensorEvent<Object> event) { + // propagate upwards + Sensor<?> sourceSensor = event.getSensor(); + Sensor<?> destinationSensor = getDestinationSensor(sourceSensor); + + if (log.isTraceEnabled()) log.trace("policy {} got {}, propagating via {}{}", + new Object[] {this, event, entity, (sourceSensor == destinationSensor ? "" : " (as "+destinationSensor+")")}); + if (event.getSensor() instanceof AttributeSensor) { - entity.setAttribute((AttributeSensor)event.getSensor(), event.getValue()); + entity.setAttribute((AttributeSensor)destinationSensor, event.getValue()); } else { - entity.emit(event.getSensor(), event.getValue()); + entity.emit((Sensor)destinationSensor, event.getValue()); } } - + /** useful post-addition to emit current values */ public void emitAllAttributes() { emitAllAttributes(false); @@ -77,8 +102,9 @@ public class SensorPropagatingEnricher extends AbstractEnricher implements Senso public void emitAllAttributes(boolean includeNullValues) { for (Sensor s: sensors) { if (s instanceof AttributeSensor) { + AttributeSensor destinationSensor = (AttributeSensor<?>) getDestinationSensor(s); Object v = source.getAttribute((AttributeSensor)s); - if (v!=null || includeNullValues) entity.setAttribute((AttributeSensor)s, v); + if (v != null || includeNullValues) entity.setAttribute(destinationSensor, v); } } } @@ -88,5 +114,9 @@ public class SensorPropagatingEnricher extends AbstractEnricher implements Senso host.addEnricher(this); emitAllAttributes(); return this; - } + } + + private Sensor<?> getDestinationSensor(Sensor<?> sourceSensor) { + return sensorAlternatives.containsKey(sourceSensor) ? sensorAlternatives.get(sourceSensor): sourceSensor; + } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/39c08cb5/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.groovy ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.groovy b/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.groovy deleted file mode 100644 index c4615d9..0000000 --- a/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.groovy +++ /dev/null @@ -1,41 +0,0 @@ -package brooklyn.enricher - -import org.testng.Assert -import org.testng.annotations.Test - -import brooklyn.enricher.basic.SensorPropagatingEnricher -import brooklyn.entity.basic.ApplicationBuilder -import brooklyn.entity.proxying.EntitySpecs -import brooklyn.event.SensorEvent -import brooklyn.event.SensorEventListener -import brooklyn.test.TestUtils -import brooklyn.test.entity.TestApplication -import brooklyn.test.entity.TestEntity - -class SensorPropagatingEnricherTest { - - @Test - public void testPropagation() { - TestApplication app = ApplicationBuilder.newManagedApp(TestApplication.class); - TestEntity entity = app.createAndManageChild(EntitySpecs.spec(TestEntity.class)); - - app.addEnricher(SensorPropagatingEnricher.newInstanceListeningToAllSensorsBut(entity, TestEntity.SEQUENCE)) - - //name propagated - entity.setAttribute(TestEntity.NAME, "foo") - TestUtils.executeUntilSucceeds { Assert.assertEquals(app.getAttribute(TestEntity.NAME), "foo") } - - //sequence not picked up - entity.setAttribute(TestEntity.SEQUENCE, 2) - Thread.sleep(100) - Assert.assertEquals(app.getAttribute(TestEntity.SEQUENCE), null) - - //notif propagated - int notif = 0; - app.subscribe(app, TestEntity.MY_NOTIF, { SensorEvent evt -> notif = evt.value } as SensorEventListener) - entity.emit(TestEntity.MY_NOTIF, 7) - TestUtils.executeUntilSucceeds { Assert.assertEquals(notif, 7) } - } - - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/39c08cb5/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.java b/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.java new file mode 100644 index 0000000..27cb601 --- /dev/null +++ b/core/src/test/java/brooklyn/enricher/SensorPropagatingEnricherTest.java @@ -0,0 +1,98 @@ +package brooklyn.enricher; + +import java.util.concurrent.atomic.AtomicReference; + +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.enricher.basic.SensorPropagatingEnricher; +import brooklyn.entity.basic.ApplicationBuilder; +import brooklyn.entity.basic.Entities; +import brooklyn.entity.proxying.EntitySpecs; +import brooklyn.event.SensorEvent; +import brooklyn.event.SensorEventListener; +import brooklyn.event.basic.BasicAttributeSensor; +import brooklyn.test.Asserts; +import brooklyn.test.EntityTestUtils; +import brooklyn.test.entity.TestApplication; +import brooklyn.test.entity.TestEntity; +import brooklyn.util.MutableMap; +import brooklyn.util.javalang.AtomicReferences; + +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableMap; + +public class SensorPropagatingEnricherTest { + + private TestApplication app; + private TestEntity entity; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + app = ApplicationBuilder.newManagedApp(TestApplication.class); + entity = app.createAndManageChild(EntitySpecs.spec(TestEntity.class)); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (app != null) Entities.destroyAll(app); + } + + @Test + public void testPropagatesSpecificSensor() { + app.addEnricher(SensorPropagatingEnricher.newInstanceListeningTo(entity, TestEntity.NAME)); + + // name propagated + entity.setAttribute(TestEntity.NAME, "foo"); + EntityTestUtils.assertAttributeEqualsEventually(app, TestEntity.NAME, "foo"); + + // sequence not propagated + entity.setAttribute(TestEntity.SEQUENCE, 2); + EntityTestUtils.assertAttributeEqualsContinually(MutableMap.of("timeout", 100), app, TestEntity.SEQUENCE, null); + } + + @Test + public void testPropagatesAllSensors() { + app.addEnricher(SensorPropagatingEnricher.newInstanceListeningToAllSensors(entity)); + + // all attributes propagated + entity.setAttribute(TestEntity.NAME, "foo"); + entity.setAttribute(TestEntity.SEQUENCE, 2); + + EntityTestUtils.assertAttributeEqualsEventually(app, TestEntity.NAME, "foo"); + EntityTestUtils.assertAttributeEqualsEventually(app, TestEntity.SEQUENCE, 2); + + // notification-sensor propagated + final AtomicReference<Integer> notif = new AtomicReference<Integer>(); + app.subscribe(app, TestEntity.MY_NOTIF, new SensorEventListener<Integer>() { + @Override public void onEvent(SensorEvent<Integer> event) { + notif.set(event.getValue()); + }}); + entity.emit(TestEntity.MY_NOTIF, 7); + Asserts.eventually(AtomicReferences.supplier(notif), Predicates.equalTo(7)); + } + + @Test + public void testPropagatesAllBut() { + app.addEnricher(SensorPropagatingEnricher.newInstanceListeningToAllSensorsBut(entity, TestEntity.SEQUENCE)) ; + + // name propagated + entity.setAttribute(TestEntity.NAME, "foo"); + EntityTestUtils.assertAttributeEqualsEventually(app, TestEntity.NAME, "foo"); + + // sequence not propagated + entity.setAttribute(TestEntity.SEQUENCE, 2); + EntityTestUtils.assertAttributeEqualsContinually(MutableMap.of("timeout", 100), app, TestEntity.SEQUENCE, null); + } + + @Test + public void testPropagatingAsDifferentSensor() { + final BasicAttributeSensor<String> ANOTHER_ATTRIBUTE = new BasicAttributeSensor<String>(String.class, "another.attribute", ""); + app.addEnricher(SensorPropagatingEnricher.newInstanceListeningTo(entity, ImmutableMap.of(TestEntity.NAME, ANOTHER_ATTRIBUTE))); + + // name propagated as different attribute + entity.setAttribute(TestEntity.NAME, "foo"); + EntityTestUtils.assertAttributeEqualsEventually(app, ANOTHER_ATTRIBUTE, "foo"); + } +}
