Return-Path: X-Original-To: apmail-brooklyn-commits-archive@minotaur.apache.org Delivered-To: apmail-brooklyn-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 78E4911250 for ; Fri, 29 Aug 2014 23:01:25 +0000 (UTC) Received: (qmail 1367 invoked by uid 500); 29 Aug 2014 23:01:25 -0000 Delivered-To: apmail-brooklyn-commits-archive@brooklyn.apache.org Received: (qmail 1331 invoked by uid 500); 29 Aug 2014 23:01:25 -0000 Mailing-List: contact commits-help@brooklyn.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@brooklyn.incubator.apache.org Delivered-To: mailing list commits@brooklyn.incubator.apache.org Received: (qmail 1313 invoked by uid 99); 29 Aug 2014 23:01:25 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 29 Aug 2014 23:01:25 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,T_RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Fri, 29 Aug 2014 23:01:21 +0000 Received: (qmail 1001 invoked by uid 99); 29 Aug 2014 23:01:01 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 29 Aug 2014 23:01:01 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 537C29A9915; Fri, 29 Aug 2014 23:01:01 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: heneveld@apache.org To: commits@brooklyn.incubator.apache.org Date: Fri, 29 Aug 2014 23:01:05 -0000 Message-Id: In-Reply-To: <7aaa3b57f6a64993992dafadae84be67@git.apache.org> References: <7aaa3b57f6a64993992dafadae84be67@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [05/26] git commit: refactor Enrichers.builder() types to give correct generics for published sensor X-Virus-Checked: Checked by ClamAV on apache.org 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 Authored: Wed Aug 6 22:09:15 2014 -0400 Committer: Alex Heneveld 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> { @@ -67,36 +67,46 @@ public class Enrichers { } } - public abstract static class InitialBuilder> extends Builder { - public PropagatorBuilder propagating(Map, ? extends Sensor> vals) { - return new ConcretePropagatorBuilder(vals); + protected abstract static class AbstractInitialBuilder> extends Builder { + public PropagatorBuilder propagating(Map, ? extends Sensor> vals) { + return new PropagatorBuilder(vals); } - public PropagatorBuilder propagating(Iterable> vals) { - return new ConcretePropagatorBuilder(vals); + public PropagatorBuilder propagating(Iterable> 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> vals) { - return new ConcretePropagatorBuilder(true, vals); + public PropagatorBuilder propagatingAllBut(Iterable> vals) { + return new PropagatorBuilder(true, vals); } - public TransformerBuilder transforming(AttributeSensor val) { - return new ConcreteTransformerBuilder(val); - } - public CombinerBuilder combining(AttributeSensor... vals) { - return new ConcreteCombinerBuilder(vals); - } - public CombinerBuilder combining(Collection> vals) { - return new ConcreteCombinerBuilder(vals); - } - public AggregatorBuilder aggregating(AttributeSensor val) { - return new ConcreteAggregatorBuilder(val); + + /** builds an enricher which transforms a given sensor: + *
  • applying a (required) function ({@link TransformerBuilder#computing(Function)}, or {@link TransformerBuilder#computingAverage()}/{@link TransformerBuilder#computingSum()}, mandatory); + *
  • and publishing it on the entity where the enricher is attached; + *
  • optionally taking the sensor from a different source entity ({@link TransformerBuilder#from(Entity)}); + *
  • and optionally publishing it as a different sensor ({@link TransformerBuilder#publishing(AttributeSensor)}); + *

    (You must supply at least one of the optional values, of course, otherwise the enricher may loop endlessly!) */ + public TransformerBuilder transforming(AttributeSensor val) { + return new TransformerBuilder(val); + } + /** as {@link #transforming(AttributeSensor)} but accepting multiple sensors, with the function acting on the set of values */ + public CombinerBuilder combining(Collection> vals) { + return new CombinerBuilder(vals); + } + /** as {@link #combining(Collection)} */ + public CombinerBuilder combining(AttributeSensor... vals) { + return new CombinerBuilder(vals); + } + /** as {@link #combining(Collection)} but the collection of values comes from the given sensor on multiple entities */ + public AggregatorBuilder aggregating(AttributeSensor val) { + return new AggregatorBuilder(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> extends Builder { + protected abstract static class AbstractAggregatorBuilder> extends Builder { protected final AttributeSensor aggregating; protected AttributeSensor publishing; protected Entity fromEntity; @@ -121,15 +131,13 @@ public class Enrichers { protected Object defaultValueForUnreportedSensors; protected Object valueToReportIfNoSensors; - public AggregatorBuilder(AttributeSensor aggregating) { + public AbstractAggregatorBuilder(AttributeSensor 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 val) { + public AggregatorBuilder publishing(AttributeSensor 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> extends Builder { + protected abstract static class AbstractCombinerBuilder> extends Builder { protected final List> combining; protected AttributeSensor publishing; protected Entity fromEntity; @@ -248,17 +256,17 @@ public class Enrichers { // For summing/averaging protected Object defaultValueForUnreportedSensors; - public CombinerBuilder(AttributeSensor... vals) { + public AbstractCombinerBuilder(AttributeSensor... vals) { this(ImmutableList.copyOf(vals)); } - public CombinerBuilder(Collection> vals) { + public AbstractCombinerBuilder(Collection> vals) { checkArgument(checkNotNull(vals).size() > 0, "combining-sensors must be non-empty"); this.combining = ImmutableList.>copyOf(vals); } @SuppressWarnings({ "unchecked", "rawtypes" }) - public B publishing(AttributeSensor val) { + public CombinerBuilder publishing(AttributeSensor 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: - *

  • applying a function ({@link #computing(Function)}, or {@link #computingAverage()}/{@link #computingSum()}, mandatory); - *
  • and publishing it on the entity where the enricher is attached; - *
  • optionally taking the sensor from a different source entity ({@link #from(Entity)}); - *
  • and optionally publishing it as a different sensor ({@link #publishing(AttributeSensor)}); - *

    (You should supply at least one of the optional values, of course, otherwise the enricher may loop endlessly!) */ - public abstract static class TransformerBuilder> extends Builder { + protected abstract static class AbstractTransformerBuilder> extends Builder { protected final AttributeSensor transforming; protected AttributeSensor publishing; protected Entity fromEntity; protected Function computing; protected Function, ?> computingFromEvent; - public TransformerBuilder(AttributeSensor val) { + public AbstractTransformerBuilder(AttributeSensor val) { this.transforming = checkNotNull(val); } @SuppressWarnings({ "unchecked", "rawtypes" }) - public B publishing(AttributeSensor val) { + public TransformerBuilder publishing(AttributeSensor 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> extends Builder { + protected abstract static class AbstractPropagatorBuilder> extends Builder { protected final Map, ? extends Sensor> propagating; protected final Boolean propagatingAll; protected final Iterable> propagatingAllBut; protected Entity fromEntity; - public PropagatorBuilder(Map, ? extends Sensor> vals) { + public AbstractPropagatorBuilder(Map, ? 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> vals) { + public AbstractPropagatorBuilder(Iterable> vals) { this(newIdentityMap(ImmutableSet.copyOf(vals))); } - public PropagatorBuilder(Sensor... vals) { + public AbstractPropagatorBuilder(Sensor... vals) { this(newIdentityMap(ImmutableSet.copyOf(vals))); } - public PropagatorBuilder(boolean propagatingAll, Iterable> butVals) { + public AbstractPropagatorBuilder(boolean propagatingAll, Iterable> 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 { + public static class InitialBuilder extends AbstractInitialBuilder { } - private static class ConcreteAggregatorBuilder extends AggregatorBuilder> { - public ConcreteAggregatorBuilder(AttributeSensor aggregating) { + public static class AggregatorBuilder extends AbstractAggregatorBuilder> { + public AggregatorBuilder(AttributeSensor aggregating) { super(aggregating); } } - private static class ConcretePropagatorBuilder extends PropagatorBuilder { - public ConcretePropagatorBuilder(Map, ? extends Sensor> vals) { + public static class PropagatorBuilder extends AbstractPropagatorBuilder { + public PropagatorBuilder(Map, ? extends Sensor> vals) { super(vals); } - public ConcretePropagatorBuilder(Iterable> vals) { + public PropagatorBuilder(Iterable> vals) { super(vals); } - public ConcretePropagatorBuilder(Sensor... vals) { + public PropagatorBuilder(Sensor... vals) { super(vals); } - public ConcretePropagatorBuilder(boolean propagatingAll, Iterable> butVals) { + public PropagatorBuilder(boolean propagatingAll, Iterable> butVals) { super(propagatingAll, butVals); } } - private static class ConcreteCombinerBuilder extends CombinerBuilder> { - public ConcreteCombinerBuilder(AttributeSensor... vals) { + public static class CombinerBuilder extends AbstractCombinerBuilder> { + public CombinerBuilder(AttributeSensor... vals) { super(vals); } - public ConcreteCombinerBuilder(Collection> vals) { + public CombinerBuilder(Collection> vals) { super(vals); } } - private static class ConcreteTransformerBuilder extends TransformerBuilder> { - public ConcreteTransformerBuilder(AttributeSensor val) { + public static class TransformerBuilder extends AbstractTransformerBuilder> { + public TransformerBuilder(AttributeSensor 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) + .publishing(NUM3) .computing(new Function, Object>() { @Override public Object apply(Iterable 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) + .publishing(STR2) .computing(new Function() { @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.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) + .publishing(LONG1) .fromMembers() .computing(new Function, Object>() { @Override public Object apply(Iterable input) {