Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D8DD4200CD7 for ; Mon, 17 Jul 2017 11:06:09 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id D5B801649A4; Mon, 17 Jul 2017 09:06:09 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 0A5DC1649A5 for ; Mon, 17 Jul 2017 11:06:08 +0200 (CEST) Received: (qmail 3189 invoked by uid 500); 17 Jul 2017 09:06:08 -0000 Mailing-List: contact commits-help@brooklyn.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@brooklyn.apache.org Delivered-To: mailing list commits@brooklyn.apache.org Received: (qmail 3170 invoked by uid 99); 17 Jul 2017 09:06:08 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 17 Jul 2017 09:06:08 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 69BE9E9809; Mon, 17 Jul 2017 09:06:07 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: drigodwin@apache.org To: commits@brooklyn.apache.org Date: Mon, 17 Jul 2017 09:06:08 -0000 Message-Id: <978d759c2a524c5ea14cd2bf1179bdb8@git.apache.org> In-Reply-To: <7480a9cec22340b29882493ef2e10d3b@git.apache.org> References: <7480a9cec22340b29882493ef2e10d3b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: =?utf-8?q?=5B2/3=5D_brooklyn-server_git_commit=3A_Adds_Aggregator_?= =?utf-8?b?Zm9yIOKAmGZpcnN04oCZIChhbmQgYWRkcyB5YW1sIHRlc3RzKQ==?= archived-at: Mon, 17 Jul 2017 09:06:10 -0000 Adds Aggregator for ‘first’ (and adds yaml tests) Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/d99e932b Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/d99e932b Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/d99e932b Branch: refs/heads/master Commit: d99e932b57eab13136d0488ed798038b04d8a27e Parents: ec01ecb Author: Aled Sage Authored: Fri Jul 14 15:24:48 2017 +0100 Committer: Aled Sage Committed: Fri Jul 14 15:24:48 2017 +0100 ---------------------------------------------------------------------- .../camp/brooklyn/AggregatorYamlTest.java | 199 +++++++++++++++++++ .../brooklyn/enricher/stock/Aggregator.java | 11 +- 2 files changed, 209 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d99e932b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AggregatorYamlTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AggregatorYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AggregatorYamlTest.java new file mode 100644 index 0000000..b5dadf8 --- /dev/null +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AggregatorYamlTest.java @@ -0,0 +1,199 @@ +/* + * 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.camp.brooklyn; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.sensor.AttributeSensor; +import org.apache.brooklyn.core.entity.EntityAsserts; +import org.apache.brooklyn.core.sensor.Sensors; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.enricher.stock.Aggregator; +import org.apache.brooklyn.entity.stock.BasicApplication; +import org.apache.brooklyn.util.collections.MutableList; +import org.apache.brooklyn.util.time.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +@Test +public class AggregatorYamlTest extends AbstractYamlTest { + private static final Logger log = LoggerFactory.getLogger(AggregatorYamlTest.class); + + AttributeSensor myVal = Sensors.newSensor(Object.class, "myVal"); + AttributeSensor myResult = Sensors.newSensor(Object.class, "myResult"); + + @Test + public void testSum() throws Exception { + Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.children:", + " - type: " + TestEntity.class.getName(), + " - type: " + TestEntity.class.getName(), + " brooklyn.enrichers:", + " - type: " + Aggregator.class.getName(), + " brooklyn.config:", + " "+Aggregator.SOURCE_SENSOR.getName()+": myVal", + " "+Aggregator.TARGET_SENSOR.getName()+": myResult", + " "+Aggregator.TRANSFORMATION_UNTYPED.getName()+": sum"); + Entity child1 = Iterables.get(app.getChildren(), 0); + Entity child2 = Iterables.get(app.getChildren(), 1); + + child1.sensors().set(myVal, 1d); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, 1d); + + child2.sensors().set(myVal, 2d); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, 3d); + + child1.sensors().set(myVal, 3d); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, 5d); + + child2.sensors().set(myVal, null); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, 3d); + } + + @Test + public void testAverage() throws Exception { + Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.children:", + " - type: " + TestEntity.class.getName(), + " - type: " + TestEntity.class.getName(), + " brooklyn.enrichers:", + " - type: " + Aggregator.class.getName(), + " brooklyn.config:", + " "+Aggregator.SOURCE_SENSOR.getName()+": myVal", + " "+Aggregator.TARGET_SENSOR.getName()+": myResult", + " "+Aggregator.TRANSFORMATION_UNTYPED.getName()+": average"); + Entity child1 = Iterables.get(app.getChildren(), 0); + Entity child2 = Iterables.get(app.getChildren(), 1); + + child1.sensors().set(myVal, 1d); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, 1d); + + child2.sensors().set(myVal, 3d); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, 2d); + + child1.sensors().set(myVal, null); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, 3d); + } + + @Test + public void testList() throws Exception { + Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.children:", + " - type: " + TestEntity.class.getName(), + " - type: " + TestEntity.class.getName(), + " brooklyn.enrichers:", + " - type: " + Aggregator.class.getName(), + " brooklyn.config:", + " "+Aggregator.SOURCE_SENSOR.getName()+": myVal", + " "+Aggregator.TARGET_SENSOR.getName()+": myResult", + " "+Aggregator.TRANSFORMATION_UNTYPED.getName()+": list"); + Entity child1 = Iterables.get(app.getChildren(), 0); + Entity child2 = Iterables.get(app.getChildren(), 1); + + child1.sensors().set(myVal, "val1"); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, MutableList.of("val1", null)); + + child2.sensors().set(myVal, "val2"); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, ImmutableList.of("val1", "val2")); + + child1.sensors().set(myVal, "val1b"); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, ImmutableList.of("val1b", "val2")); + + child1.sensors().set(myVal, null); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, MutableList.of(null, "val2")); + } + + @Test + public void testFirst() throws Exception { + Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.children:", + " - type: " + TestEntity.class.getName(), + " - type: " + TestEntity.class.getName(), + " brooklyn.enrichers:", + " - type: " + Aggregator.class.getName(), + " brooklyn.config:", + " "+Aggregator.SOURCE_SENSOR.getName()+": myVal", + " "+Aggregator.TARGET_SENSOR.getName()+": myResult", + " "+Aggregator.TRANSFORMATION_UNTYPED.getName()+": first", + " "+Aggregator.VALUE_FILTER.getName()+": notNull"); + Entity child1 = Iterables.get(app.getChildren(), 0); + Entity child2 = Iterables.get(app.getChildren(), 1); + + child1.sensors().set(myVal, "val1"); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, "val1"); + + child2.sensors().set(myVal, "val2"); + EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout", Duration.millis(50)), app, myResult, "val1"); + + child1.sensors().set(myVal, null); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, "val2"); + + child2.sensors().set(myVal, null); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, null); + + child1.sensors().set(myVal, "val3"); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, "val3"); + } + + @Test + public void testQuorum() throws Exception { + Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.children:", + " - type: " + TestEntity.class.getName(), + " - type: " + TestEntity.class.getName(), + " brooklyn.enrichers:", + " - type: " + Aggregator.class.getName(), + " brooklyn.config:", + " "+Aggregator.SOURCE_SENSOR.getName()+": myVal", + " "+Aggregator.TARGET_SENSOR.getName()+": myResult", + " "+Aggregator.TRANSFORMATION_UNTYPED.getName()+": isQuorate", + " "+Aggregator.QUORUM_CHECK_TYPE.getName()+": all", + " "+Aggregator.QUORUM_TOTAL_SIZE.getName()+": 2"); + Entity child1 = Iterables.get(app.getChildren(), 0); + Entity child2 = Iterables.get(app.getChildren(), 1); + + child1.sensors().set(myVal, true); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, false); + + child2.sensors().set(myVal, true); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, true); + + child2.sensors().set(myVal, null); + EntityAsserts.assertAttributeEqualsEventually(app, myResult, false); + } + + @Override + protected Logger getLogger() { + return log; + } +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d99e932b/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java index f94c652..1ba4e6d 100644 --- a/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java +++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java @@ -62,7 +62,8 @@ public class Aggregator extends AbstractAggregator implements SensorEv "Specifies a transformation, as a function from a collection to the value, or as a string " + "matching a pre-defined named transformation, such as 'average' (for numbers), " + "'sum' (for numbers), 'isQuorate' (to compute a quorum), " + - "or 'list' (the default, putting any collection of items into a list)"); + "'list' (the default, putting any collection of items into a list), " + + "or 'first' (the first value, or null if empty)"); public static final ConfigKey, ?>> TRANSFORMATION = ConfigKeys.newConfigKey(new TypeToken, ?>>() {}, "enricher.transformation"); @@ -120,6 +121,7 @@ public class Aggregator extends AbstractAggregator implements SensorEv if ("isQuorate".equalsIgnoreCase(t1)) return new Enrichers.ComputingIsQuorate(targetSensor.getTypeToken(), QuorumChecks.of(config().get(QUORUM_CHECK_TYPE)), config().get(QUORUM_TOTAL_SIZE)); if ("list".equalsIgnoreCase(t1)) return new ComputingList(); + if ("first".equalsIgnoreCase(t1)) return new FirstOrNull(); return null; } @@ -131,6 +133,13 @@ public class Aggregator extends AbstractAggregator implements SensorEv } } + private static class FirstOrNull implements Function, TT> { + @Override + public TT apply(Collection input) { + return (input==null) ? null : Iterables.getFirst(input, null); + } + } + @Override protected void setEntityBeforeSubscribingProducerChildrenEvents() { BrooklynLogging.log(LOG, BrooklynLogging.levelDebugOrTraceIfReadOnly(producer),