You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/08/30 01:01:05 UTC
[05/26] git commit: refactor Enrichers.builder() types to give
correct generics for published sensor
refactor Enrichers.builder() types to give correct generics for published sensor
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/3c714ed1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/3c714ed1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/3c714ed1
Branch: refs/heads/master
Commit: 3c714ed12259c3909f0244f83f504e6a62be7bdb
Parents: 141751b
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Aug 6 22:09:15 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Aug 27 02:07:48 2014 -0400
----------------------------------------------------------------------
.../main/java/brooklyn/enricher/Enrichers.java | 132 ++++++++++---------
.../java/brooklyn/enricher/EnrichersTest.java | 55 +++++++-
2 files changed, 115 insertions(+), 72 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3c714ed1/core/src/main/java/brooklyn/enricher/Enrichers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/Enrichers.java b/core/src/main/java/brooklyn/enricher/Enrichers.java
index 6ddc780..0d3a0d5 100644
--- a/core/src/main/java/brooklyn/enricher/Enrichers.java
+++ b/core/src/main/java/brooklyn/enricher/Enrichers.java
@@ -56,8 +56,8 @@ public class Enrichers {
private Enrichers() {}
- public static InitialBuilder<?> builder() {
- return new ConcreteInitialBuilder();
+ public static InitialBuilder builder() {
+ return new InitialBuilder();
}
public abstract static class Builder<B extends Builder<B>> {
@@ -67,36 +67,46 @@ public class Enrichers {
}
}
- public abstract static class InitialBuilder<B extends InitialBuilder<B>> extends Builder<B> {
- public PropagatorBuilder<?> propagating(Map<? extends Sensor<?>, ? extends Sensor<?>> vals) {
- return new ConcretePropagatorBuilder(vals);
+ protected abstract static class AbstractInitialBuilder<B extends AbstractInitialBuilder<B>> extends Builder<B> {
+ public PropagatorBuilder propagating(Map<? extends Sensor<?>, ? extends Sensor<?>> vals) {
+ return new PropagatorBuilder(vals);
}
- public PropagatorBuilder<?> propagating(Iterable<? extends Sensor<?>> vals) {
- return new ConcretePropagatorBuilder(vals);
+ public PropagatorBuilder propagating(Iterable<? extends Sensor<?>> vals) {
+ return new PropagatorBuilder(vals);
}
- public PropagatorBuilder<?> propagating(Sensor<?>... vals) {
- return new ConcretePropagatorBuilder(vals);
+ public PropagatorBuilder propagating(Sensor<?>... vals) {
+ return new PropagatorBuilder(vals);
}
- public PropagatorBuilder<?> propagatingAll() {
- return new ConcretePropagatorBuilder(true, null);
+ public PropagatorBuilder propagatingAll() {
+ return new PropagatorBuilder(true, null);
}
- public PropagatorBuilder<?> propagatingAllBut(Sensor<?>... vals) {
- return new ConcretePropagatorBuilder(true, ImmutableSet.copyOf(vals));
+ public PropagatorBuilder propagatingAllBut(Sensor<?>... vals) {
+ return new PropagatorBuilder(true, ImmutableSet.copyOf(vals));
}
- public PropagatorBuilder<?> propagatingAllBut(Iterable<? extends Sensor<?>> vals) {
- return new ConcretePropagatorBuilder(true, vals);
+ public PropagatorBuilder propagatingAllBut(Iterable<? extends Sensor<?>> vals) {
+ return new PropagatorBuilder(true, vals);
}
- public <S> TransformerBuilder<S, Object, ?> transforming(AttributeSensor<S> val) {
- return new ConcreteTransformerBuilder<S, Object>(val);
- }
- public <S> CombinerBuilder<S, Object, ?> combining(AttributeSensor<? extends S>... vals) {
- return new ConcreteCombinerBuilder<S, Object>(vals);
- }
- public <S> CombinerBuilder<S, Object, ?> combining(Collection<AttributeSensor<? extends S>> vals) {
- return new ConcreteCombinerBuilder<S, Object>(vals);
- }
- public <S> AggregatorBuilder<S, Object, ?> aggregating(AttributeSensor<S> val) {
- return new ConcreteAggregatorBuilder<S,Object>(val);
+
+ /** builds an enricher which transforms a given sensor:
+ * <li> applying a (required) function ({@link TransformerBuilder#computing(Function)}, or {@link TransformerBuilder#computingAverage()}/{@link TransformerBuilder#computingSum()}, mandatory);
+ * <li> and publishing it on the entity where the enricher is attached;
+ * <li> optionally taking the sensor from a different source entity ({@link TransformerBuilder#from(Entity)});
+ * <li> and optionally publishing it as a different sensor ({@link TransformerBuilder#publishing(AttributeSensor)});
+ * <p> (You must supply at least one of the optional values, of course, otherwise the enricher may loop endlessly!) */
+ public <S> TransformerBuilder<S, Object> transforming(AttributeSensor<S> val) {
+ return new TransformerBuilder<S, Object>(val);
+ }
+ /** as {@link #transforming(AttributeSensor)} but accepting multiple sensors, with the function acting on the set of values */
+ public <S> CombinerBuilder<S, Object> combining(Collection<AttributeSensor<? extends S>> vals) {
+ return new CombinerBuilder<S, Object>(vals);
+ }
+ /** as {@link #combining(Collection)} */
+ public <S> CombinerBuilder<S, Object> combining(AttributeSensor<? extends S>... vals) {
+ return new CombinerBuilder<S, Object>(vals);
+ }
+ /** as {@link #combining(Collection)} but the collection of values comes from the given sensor on multiple entities */
+ public <S> AggregatorBuilder<S, Object> aggregating(AttributeSensor<S> val) {
+ return new AggregatorBuilder<S,Object>(val);
}
/** creates an {@link UpdatingMap} enricher:
* {@link UpdatingMapBuilder#from(AttributeSensor)} and {@link UpdatingMapBuilder#computing(Function)} are required
@@ -107,7 +117,7 @@ public class Enrichers {
}
- public abstract static class AggregatorBuilder<S, T, B extends AggregatorBuilder<S, T, B>> extends Builder<B> {
+ protected abstract static class AbstractAggregatorBuilder<S, T, B extends AbstractAggregatorBuilder<S, T, B>> extends Builder<B> {
protected final AttributeSensor<S> aggregating;
protected AttributeSensor<T> publishing;
protected Entity fromEntity;
@@ -121,15 +131,13 @@ public class Enrichers {
protected Object defaultValueForUnreportedSensors;
protected Object valueToReportIfNoSensors;
- public AggregatorBuilder(AttributeSensor<S> aggregating) {
+ public AbstractAggregatorBuilder(AttributeSensor<S> aggregating) {
this.aggregating = aggregating;
}
- // TODO change the signature of this to have correct type info as done for UpdatingMapBuilder.from(Sensor)
- // (including change *Builder to Abstract*Builder and Concrete*Builder to *Builder, for all other enricher types)
@SuppressWarnings({ "unchecked", "rawtypes" })
- public B publishing(AttributeSensor<? extends T> val) {
+ public <T2 extends T> AggregatorBuilder<S,T2> publishing(AttributeSensor<? extends T2> val) {
this.publishing = (AttributeSensor) checkNotNull(val);
- return self();
+ return (AggregatorBuilder) self();
}
public B from(Entity val) {
this.fromEntity = checkNotNull(val);
@@ -236,7 +244,7 @@ public class Enrichers {
}
}
- public abstract static class CombinerBuilder<S, T, B extends CombinerBuilder<S, T, B>> extends Builder<B> {
+ protected abstract static class AbstractCombinerBuilder<S, T, B extends AbstractCombinerBuilder<S, T, B>> extends Builder<B> {
protected final List<AttributeSensor<? extends S>> combining;
protected AttributeSensor<T> publishing;
protected Entity fromEntity;
@@ -248,17 +256,17 @@ public class Enrichers {
// For summing/averaging
protected Object defaultValueForUnreportedSensors;
- public CombinerBuilder(AttributeSensor<? extends S>... vals) {
+ public AbstractCombinerBuilder(AttributeSensor<? extends S>... vals) {
this(ImmutableList.copyOf(vals));
}
- public CombinerBuilder(Collection<AttributeSensor<? extends S>> vals) {
+ public AbstractCombinerBuilder(Collection<AttributeSensor<? extends S>> vals) {
checkArgument(checkNotNull(vals).size() > 0, "combining-sensors must be non-empty");
this.combining = ImmutableList.<AttributeSensor<? extends S>>copyOf(vals);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- public B publishing(AttributeSensor<? extends T> val) {
+ public <T2 extends T> CombinerBuilder<S,T2> publishing(AttributeSensor<? extends T2> val) {
this.publishing = (AttributeSensor) checkNotNull(val);
- return self();
+ return (CombinerBuilder) this;
}
public B from(Entity val) {
this.fromEntity = checkNotNull(val);
@@ -325,26 +333,20 @@ public class Enrichers {
}
}
- /** builds an enricher which transforms a given sensor:
- * <li> applying a function ({@link #computing(Function)}, or {@link #computingAverage()}/{@link #computingSum()}, mandatory);
- * <li> and publishing it on the entity where the enricher is attached;
- * <li> optionally taking the sensor from a different source entity ({@link #from(Entity)});
- * <li> and optionally publishing it as a different sensor ({@link #publishing(AttributeSensor)});
- * <p> (You should supply at least one of the optional values, of course, otherwise the enricher may loop endlessly!) */
- public abstract static class TransformerBuilder<S, T, B extends TransformerBuilder<S, T, B>> extends Builder<B> {
+ protected abstract static class AbstractTransformerBuilder<S, T, B extends AbstractTransformerBuilder<S, T, B>> extends Builder<B> {
protected final AttributeSensor<S> transforming;
protected AttributeSensor<T> publishing;
protected Entity fromEntity;
protected Function<? super S, ?> computing;
protected Function<? super SensorEvent<S>, ?> computingFromEvent;
- public TransformerBuilder(AttributeSensor<S> val) {
+ public AbstractTransformerBuilder(AttributeSensor<S> val) {
this.transforming = checkNotNull(val);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- public B publishing(AttributeSensor<? extends T> val) {
+ public <T2 extends T> TransformerBuilder<S,T2> publishing(AttributeSensor<? extends T2> val) {
this.publishing = (AttributeSensor) checkNotNull(val);
- return self();
+ return (TransformerBuilder) this;
}
public B from(Entity val) {
this.fromEntity = checkNotNull(val);
@@ -382,25 +384,25 @@ public class Enrichers {
}
}
- public abstract static class PropagatorBuilder<B extends PropagatorBuilder<B>> extends Builder<B> {
+ protected abstract static class AbstractPropagatorBuilder<B extends AbstractPropagatorBuilder<B>> extends Builder<B> {
protected final Map<? extends Sensor<?>, ? extends Sensor<?>> propagating;
protected final Boolean propagatingAll;
protected final Iterable<? extends Sensor<?>> propagatingAllBut;
protected Entity fromEntity;
- public PropagatorBuilder(Map<? extends Sensor<?>, ? extends Sensor<?>> vals) {
+ public AbstractPropagatorBuilder(Map<? extends Sensor<?>, ? extends Sensor<?>> vals) {
checkArgument(checkNotNull(vals).size() > 0, "propagating-sensors must be non-empty");
this.propagating = vals;
this.propagatingAll = null;
this.propagatingAllBut = null;
}
- public PropagatorBuilder(Iterable<? extends Sensor<?>> vals) {
+ public AbstractPropagatorBuilder(Iterable<? extends Sensor<?>> vals) {
this(newIdentityMap(ImmutableSet.copyOf(vals)));
}
- public PropagatorBuilder(Sensor<?>... vals) {
+ public AbstractPropagatorBuilder(Sensor<?>... vals) {
this(newIdentityMap(ImmutableSet.copyOf(vals)));
}
- public PropagatorBuilder(boolean propagatingAll, Iterable<? extends Sensor<?>> butVals) {
+ public AbstractPropagatorBuilder(boolean propagatingAll, Iterable<? extends Sensor<?>> butVals) {
// Ugly constructor! Taking boolean to differentiate it from others; could use a static builder
// but feels like overkill having a builder for a builder, being called by a builder!
checkArgument(propagatingAll, "Not propagating all; use PropagatingAll(vals)");
@@ -507,41 +509,41 @@ public class Enrichers {
}
}
- private static class ConcreteInitialBuilder extends InitialBuilder<ConcreteInitialBuilder> {
+ public static class InitialBuilder extends AbstractInitialBuilder<InitialBuilder> {
}
- private static class ConcreteAggregatorBuilder<S, T> extends AggregatorBuilder<S, T, ConcreteAggregatorBuilder<S, T>> {
- public ConcreteAggregatorBuilder(AttributeSensor<S> aggregating) {
+ public static class AggregatorBuilder<S, T> extends AbstractAggregatorBuilder<S, T, AggregatorBuilder<S, T>> {
+ public AggregatorBuilder(AttributeSensor<S> aggregating) {
super(aggregating);
}
}
- private static class ConcretePropagatorBuilder extends PropagatorBuilder<ConcretePropagatorBuilder> {
- public ConcretePropagatorBuilder(Map<? extends Sensor<?>, ? extends Sensor<?>> vals) {
+ public static class PropagatorBuilder extends AbstractPropagatorBuilder<PropagatorBuilder> {
+ public PropagatorBuilder(Map<? extends Sensor<?>, ? extends Sensor<?>> vals) {
super(vals);
}
- public ConcretePropagatorBuilder(Iterable<? extends Sensor<?>> vals) {
+ public PropagatorBuilder(Iterable<? extends Sensor<?>> vals) {
super(vals);
}
- public ConcretePropagatorBuilder(Sensor<?>... vals) {
+ public PropagatorBuilder(Sensor<?>... vals) {
super(vals);
}
- public ConcretePropagatorBuilder(boolean propagatingAll, Iterable<? extends Sensor<?>> butVals) {
+ public PropagatorBuilder(boolean propagatingAll, Iterable<? extends Sensor<?>> butVals) {
super(propagatingAll, butVals);
}
}
- private static class ConcreteCombinerBuilder<S, T> extends CombinerBuilder<S, T, ConcreteCombinerBuilder<S, T>> {
- public ConcreteCombinerBuilder(AttributeSensor<? extends S>... vals) {
+ public static class CombinerBuilder<S, T> extends AbstractCombinerBuilder<S, T, CombinerBuilder<S, T>> {
+ public CombinerBuilder(AttributeSensor<? extends S>... vals) {
super(vals);
}
- public ConcreteCombinerBuilder(Collection<AttributeSensor<? extends S>> vals) {
+ public CombinerBuilder(Collection<AttributeSensor<? extends S>> vals) {
super(vals);
}
}
- private static class ConcreteTransformerBuilder<S, T> extends TransformerBuilder<S, T, ConcreteTransformerBuilder<S, T>> {
- public ConcreteTransformerBuilder(AttributeSensor<S> val) {
+ public static class TransformerBuilder<S, T> extends AbstractTransformerBuilder<S, T, TransformerBuilder<S, T>> {
+ public TransformerBuilder(AttributeSensor<S> val) {
super(val);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3c714ed1/core/src/test/java/brooklyn/enricher/EnrichersTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/enricher/EnrichersTest.java b/core/src/test/java/brooklyn/enricher/EnrichersTest.java
index 8bfd2bb..ab3f199 100644
--- a/core/src/test/java/brooklyn/enricher/EnrichersTest.java
+++ b/core/src/test/java/brooklyn/enricher/EnrichersTest.java
@@ -28,12 +28,15 @@ import org.testng.annotations.Test;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.entity.basic.BasicGroup;
import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntitySubscriptionTest.RecordingSensorEventListener;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.event.AttributeSensor;
import brooklyn.event.SensorEvent;
import brooklyn.event.basic.Sensors;
+import brooklyn.test.Asserts;
import brooklyn.test.EntityTestUtils;
import brooklyn.test.entity.TestEntity;
+import brooklyn.util.collections.CollectionFunctionals;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.guava.Functionals;
@@ -41,6 +44,7 @@ import brooklyn.util.text.StringFunctions;
import com.google.common.base.Function;
import com.google.common.base.Functions;
+import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -107,7 +111,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
public void testCombiningRespectsUnchanged() {
entity.addEnricher(Enrichers.builder()
.combining(NUM1, NUM2)
- .publishing(NUM3)
+ .<Object>publishing(NUM3)
.computing(new Function<Iterable<Integer>, Object>() {
@Override public Object apply(Iterable<Integer> input) {
if (input != null && Iterables.contains(input, 123)) {
@@ -156,7 +160,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
entity.addEnricher(Enrichers.builder()
.transforming(NUM1)
.publishing(LONG1)
- .computing(Functions.constant(Integer.valueOf(1)))
+ .computing(Functions.constant(Long.valueOf(1)))
.build());
entity.setAttribute(NUM1, 123);
@@ -179,23 +183,60 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
}
@Test(groups="Integration") // because takes a second
- public void testTransformingRespectsUnchanged() {
+ public void testTransformingRespectsUnchangedButWillRepublish() {
+ RecordingSensorEventListener record = new RecordingSensorEventListener();
+ app.getManagementContext().getSubscriptionManager().subscribe(entity, STR2, record);
+
entity.addEnricher(Enrichers.builder()
.transforming(STR1)
- .publishing(STR2)
+ .<Object>publishing(STR2)
.computing(new Function<String, Object>() {
@Override public Object apply(String input) {
return ("ignoredval".equals(input)) ? Entities.UNCHANGED : input;
}})
.build());
+ Asserts.assertThat(record.events, CollectionFunctionals.sizeEquals(0));
entity.setAttribute(STR1, "myval");
- EntityTestUtils.assertAttributeEqualsEventually(entity, STR2, "myval");
+ Asserts.eventually(Suppliers.ofInstance(record.events), CollectionFunctionals.sizeEquals(1));
+ EntityTestUtils.assertAttributeEquals(entity, STR2, "myval");
entity.setAttribute(STR1, "ignoredval");
EntityTestUtils.assertAttributeEqualsContinually(entity, STR2, "myval");
+
+ entity.setAttribute(STR1, "myval2");
+ Asserts.eventually(Suppliers.ofInstance(record.events), CollectionFunctionals.sizeEquals(2));
+ EntityTestUtils.assertAttributeEquals(entity, STR2, "myval2");
+
+ entity.setAttribute(STR1, "myval2");
+ entity.setAttribute(STR1, "myval2");
+ entity.setAttribute(STR1, "myval3");
+ Asserts.eventually(Suppliers.ofInstance(record.events), CollectionFunctionals.sizeEquals(5));
}
+ // TODO if we had something like suppressDuplicates(true) :
+// public void testTransformingSuppressDuplicates() {
+// RecordingSensorEventListener record = new RecordingSensorEventListener();
+// app.getManagementContext().getSubscriptionManager().subscribe(entity, STR2, record);
+//
+// entity.addEnricher(Enrichers.builder()
+// .transforming(STR1)
+// .publishing(STR2)
+// .computing(Functions.<String>identity())
+// .suppressDuplicates(true)
+// .build());
+//
+// entity.setAttribute(STR1, "myval");
+// Asserts.eventually(Suppliers.ofInstance(record.events), CollectionFunctionals.sizeEquals(1));
+// EntityTestUtils.assertAttributeEquals(entity, STR2, "myval");
+//
+// entity.setAttribute(STR1, "myval2");
+// entity.setAttribute(STR1, "myval2");
+// entity.setAttribute(STR1, "myval3");
+// EntityTestUtils.assertAttributeEqualsContinually(entity, STR2, "myval3");
+// Asserts.assertThat(record.events, CollectionFunctionals.sizeEquals(3));
+// }
+
@Test
public void testPropagating() {
entity.addEnricher(Enrichers.builder()
@@ -321,7 +362,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
.aggregating(NUM1)
.publishing(LONG1)
.fromMembers()
- .computing(Functions.constant(Integer.valueOf(1)))
+ .computing(Functions.constant(Long.valueOf(1)))
.build());
entity.setAttribute(NUM1, 123);
@@ -333,7 +374,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
group.addMember(entity);
group.addEnricher(Enrichers.builder()
.aggregating(NUM1)
- .publishing(LONG1)
+ .<Object>publishing(LONG1)
.fromMembers()
.computing(new Function<Iterable<Integer>, Object>() {
@Override public Object apply(Iterable<Integer> input) {