Delete CustomAggregatingEnricher Was deprecated in 0.7.0; did not have a constructor usable when deserialising from persisted state, so that backwards compatibility is not a worry!
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/26eeb7e0 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/26eeb7e0 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/26eeb7e0 Branch: refs/heads/master Commit: 26eeb7e0f2696006a4c111b20eba5959d5537e38 Parents: 263304b Author: Aled Sage <[email protected]> Authored: Sun Jun 11 12:44:25 2017 +0100 Committer: Aled Sage <[email protected]> Committed: Sun Jun 11 14:57:39 2017 +0100 ---------------------------------------------------------------------- .../stock/AbstractAggregatingEnricher.java | 175 -------- .../stock/CustomAggregatingEnricher.java | 352 ---------------- ...CustomAggregatingEnricherDeprecatedTest.java | 405 ------------------- 3 files changed, 932 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/26eeb7e0/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregatingEnricher.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregatingEnricher.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregatingEnricher.java deleted file mode 100644 index 9dd3d30..0000000 --- a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregatingEnricher.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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 java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.entity.Group; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.api.sensor.SensorEvent; -import org.apache.brooklyn.api.sensor.SensorEventListener; -import org.apache.brooklyn.core.enricher.AbstractEnricher; -import org.apache.brooklyn.core.entity.trait.Changeable; -import org.apache.brooklyn.util.groovy.GroovyJavaMethods; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.ImmutableMap; - - -/** - * AggregatingEnrichers implicitly subscribes to the same sensor<S> on all entities inside an - * {@link Group} and should emit an aggregate<T> on the target sensor - * - * @deprecated since 0.7.0; use {@link Enrichers.builder()} - * @see Aggregator if need to sub-class - */ -@Deprecated -public abstract class AbstractAggregatingEnricher<S,T> extends AbstractEnricher implements SensorEventListener<S> { - - private static final Logger LOG = LoggerFactory.getLogger(AbstractAggregatingEnricher.class); - - AttributeSensor<? extends S> source; - protected AttributeSensor<T> target; - protected S defaultValue; - - Set<Entity> producers; - List<Entity> hardCodedProducers; - boolean allMembers; - Predicate<Entity> filter; - - /** - * Users of values should either on it synchronize when iterating over its entries or use - * copyOfValues to obtain an immutable copy of the map. - */ - // We use a synchronizedMap over a ConcurrentHashMap for entities that store null values. - protected final Map<Entity, S> values = Collections.synchronizedMap(new LinkedHashMap<Entity, S>()); - - public AbstractAggregatingEnricher(Map<String,?> flags, AttributeSensor<? extends S> source, AttributeSensor<T> target) { - this(flags, source, target, null); - } - - @SuppressWarnings("unchecked") - public AbstractAggregatingEnricher(Map<String,?> flags, AttributeSensor<? extends S> source, AttributeSensor<T> target, S defaultValue) { - super(flags); - this.source = source; - this.target = target; - this.defaultValue = defaultValue; - hardCodedProducers = (List<Entity>) (flags.containsKey("producers") ? flags.get("producers") : Collections.emptyList()); - allMembers = (Boolean) (flags.containsKey("allMembers") ? flags.get("allMembers") : false); - filter = flags.containsKey("filter") ? GroovyJavaMethods.<Entity>castToPredicate(flags.get("filter")) : Predicates.<Entity>alwaysTrue(); - } - - public void addProducer(Entity producer) { - if (LOG.isDebugEnabled()) LOG.debug("{} linked ({}, {}) to {}", new Object[] {this, producer, source, target}); - subscriptions().subscribe(producer, source, this); - synchronized (values) { - S vo = values.get(producer); - if (vo==null) { - S initialVal = producer.getAttribute(source); - values.put(producer, initialVal != null ? initialVal : defaultValue); - //we might skip in onEvent in the short window while !values.containsKey(producer) - //but that's okay because the put which would have been done there is done here now - } else { - //vo will be null unless some weird race with addProducer+removeProducer is occuring - //(and that's something we can tolerate i think) - if (LOG.isDebugEnabled()) LOG.debug("{} already had value ({}) for producer ({}); but that producer has just been added", new Object[] {this, vo, producer}); - } - } - onUpdated(); - } - - // TODO If producer removed but then get (queued) event from it after this method returns, - public S removeProducer(Entity producer) { - if (LOG.isDebugEnabled()) LOG.debug("{} unlinked ({}, {}) from {}", new Object[] {this, producer, source, target}); - subscriptions().unsubscribe(producer); - S removed = values.remove(producer); - onUpdated(); - return removed; - } - - @Override - public void onEvent(SensorEvent<S> event) { - Entity e = event.getSource(); - synchronized (values) { - if (values.containsKey(e)) { - values.put(e, event.getValue()); - } else { - if (LOG.isDebugEnabled()) LOG.debug("{} received event for unknown producer ({}); presumably that producer has recently been removed", this, e); - } - } - onUpdated(); - } - - /** - * Called whenever the values for the set of producers changes (e.g. on an event, or on a member added/removed). - * Defaults to no-op - */ - // TODO should this be abstract? - protected void onUpdated() { - // no-op - } - - @Override - public void setEntity(EntityLocal entity) { - super.setEntity(entity); - - for (Entity producer : hardCodedProducers) { - if (filter.apply(producer)) { - addProducer(producer); - } - } - - if (allMembers) { - subscriptions().subscribe(entity, Changeable.MEMBER_ADDED, new SensorEventListener<Entity>() { - @Override public void onEvent(SensorEvent<Entity> it) { - if (filter.apply(it.getValue())) addProducer(it.getValue()); - } - }); - subscriptions().subscribe(entity, Changeable.MEMBER_REMOVED, new SensorEventListener<Entity>() { - @Override public void onEvent(SensorEvent<Entity> it) { - removeProducer(it.getValue()); - } - }); - - if (entity instanceof Group) { - for (Entity member : ((Group)entity).getMembers()) { - if (filter.apply(member)) { - addProducer(member); - } - } - } - } - } - - protected Map<Entity, S> copyOfValues() { - synchronized (values) { - return ImmutableMap.copyOf(values); - } - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/26eeb7e0/core/src/main/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricher.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricher.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricher.java deleted file mode 100644 index 2d797da..0000000 --- a/core/src/main/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricher.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * 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 groovy.lang.Closure; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.api.sensor.SensorEventListener; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.groovy.GroovyJavaMethods; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Function; -import com.google.common.base.Throwables; -import com.google.common.reflect.TypeToken; - -/** - * Subscribes to events from producers with a sensor of type T, aggregates them with the - * provided closure and emits the result on the target sensor V. - * @param <T> - * - * @deprecated since 0.7.0; use {@link Enrichers#builder()} - */ -@Deprecated -public class CustomAggregatingEnricher<S,T> extends AbstractAggregatingEnricher<S,T> implements SensorEventListener<S> { - - private static final Logger LOG = LoggerFactory.getLogger(CustomAggregatingEnricher.class); - - protected final Function<Collection<S>, T> aggregator; - - /** - * The valid keys for the flags are: - * - producers: a collection of entities to be aggregated - * - allMembers: indicates that should track members of the entity that the aggregator is associated with, - * to aggregate across all those members. - * - filter: a Predicate indicating which entities to include (support for {@link groovy.lang.Closure} is deprecated) - * - * @param flags - * @param source - * @param target - * @param aggregator Aggregates a collection of values, to return a single value for the target sensor - * @param defaultIniitalValueForUnreportedSensors Default value to populate the collection given to aggregator, - * where sensors are null or not present initially, defaults to null (note however that subsequent null reports will put an explicit null) - */ - public CustomAggregatingEnricher(Map<String,?> flags, AttributeSensor<? extends S> source, AttributeSensor<T> target, - Function<Collection<S>, T> aggregator, S defaultIniitalValueForUnreportedSensors) { - super(flags, source, target, defaultIniitalValueForUnreportedSensors); - this.aggregator = aggregator; - } - - public CustomAggregatingEnricher(Map<String,?> flags, AttributeSensor<? extends S> source, AttributeSensor<T> target, - Function<Collection<S>, T> aggregator) { - this(flags, source, target, aggregator, null); - } - - public CustomAggregatingEnricher(AttributeSensor<? extends S> source, AttributeSensor<T> target, - Function<Collection<S>, T> aggregator, S defaultValue) { - this(Collections.<String,Object>emptyMap(), source, target, aggregator, defaultValue); - } - - public CustomAggregatingEnricher(AttributeSensor<? extends S> source, AttributeSensor<T> target, - Function<Collection<S>, T> aggregator) { - this(Collections.<String,Object>emptyMap(), source, target, aggregator, null); - } - - /** - * @param flags - * @param source - * @param target - * @param aggregator Should take a collection of values and return a single, aggregate value - * @param defaultValueForUnreportedSensors - * - * @see #CustomAggregatingEnricher(Map, AttributeSensor, AttributeSensor, Function, Object) - * - * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted. - */ - @Deprecated - @SuppressWarnings("unchecked") - public CustomAggregatingEnricher(Map<String,?> flags, AttributeSensor<? extends S> source, AttributeSensor<T> target, - Closure<?> aggregator, S defaultValueForUnreportedSensors) { - this(flags, source, target, GroovyJavaMethods.<Collection<S>, T>functionFromClosure((Closure<T>)aggregator), defaultValueForUnreportedSensors); - } - - /** - * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted. - */ - @Deprecated - public CustomAggregatingEnricher(Map<String,?> flags, AttributeSensor<? extends S> source, AttributeSensor<T> target, Closure<?> aggregator) { - this(flags, source, target, aggregator, null); - } - - /** - * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted. - */ - @Deprecated - public CustomAggregatingEnricher(AttributeSensor<S> source, AttributeSensor<T> target, Closure<?> aggregator, S defaultValueForUnreportedSensors) { - this(Collections.<String,Object>emptyMap(), source, target, aggregator, defaultValueForUnreportedSensors); - } - - /** - * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted. - */ - @Deprecated - public CustomAggregatingEnricher(AttributeSensor<S> source, AttributeSensor<T> target, Closure<?> aggregator) { - this(Collections.<String,Object>emptyMap(), source, target, aggregator, null); - } - - @Override - public void onUpdated() { - try { - entity.sensors().set(target, getAggregate()); - } catch (Throwable t) { - LOG.warn("Error calculating and setting aggregate for enricher "+this, t); - throw Throwables.propagate(t); - } - } - - public T getAggregate() { - synchronized (values) { - return aggregator.apply(values.values()); - } - } - - /** - * Instead, consider calling: - * <pre> - * {@code - * Enrichers.Builder builder = Enrichers.builder() - * .aggregating(source) - * .publishing(target) - * .computing(GroovyJavaMethods.<Collection<S>, T>functionFromClosure((Closure<T>)aggregator)) - * .defaultValueForUnreportedSensors(defaultValueForUnreportedSensors); - * - * if (Boolean.TRUE.equals(allMembers)) builder.fromMembers(); - * if (filter != null) builder.entityFilter(filter); - * if (hardCodedProducers != null) builder.fromHardcodedProducers(hardCodedProducers); - * - * addEnricher(builder.build()); - * } - * </pre> - * - * @deprecated since 0.7.0; use {@link Enrichers#builder()} - */ - @Deprecated - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - Map<String,?> flags, AttributeSensor<S> source, AttributeSensor<T> target, Closure<?> aggregator, S defaultVal) { - return new CustomAggregatingEnricher<S,T>(flags, source, target, aggregator, defaultVal); - } - /** - * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted. - */ - @Deprecated - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - Map<String,?> flags, AttributeSensor<S> source, AttributeSensor<T> target, Closure<?> aggregator) { - return newEnricher(flags, source, target, aggregator, null); - } - /** - * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted. - */ - @Deprecated - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - AttributeSensor<S> source, AttributeSensor<T> target, Closure<?> aggregator, S defaultVal) { - return newEnricher(Collections.<String,Object>emptyMap(), source, target, aggregator, defaultVal); - } - /** - * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted. - */ - @Deprecated - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - AttributeSensor<S> source, AttributeSensor<T> target, Closure<?> aggregator) { - return newEnricher(Collections.<String,Object>emptyMap(), source, target, aggregator, null); - } - - /** - * Instead, consider calling: - * <pre> - * {@code - * Enrichers.Builder builder = Enrichers.builder() - * .aggregating(source) - * .publishing(target) - * .computing(aggregator) - * .defaultValueForUnreportedSensors(defaultVal); - * - * if (Boolean.TRUE.equals(allMembers)) builder.fromMembers(); - * if (filter != null) builder.entityFilter(filter); - * if (hardCodedProducers != null) builder.fromHardcodedProducers(hardCodedProducers); - * - * addEnricher(builder.build()); - * } - * </pre> - * - * @deprecated since 0.7.0; use {@link Enrichers#builder()} - */ - @Deprecated - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - Map<String,?> flags, AttributeSensor<S> source, AttributeSensor<T> target, Function<Collection<S>, T> aggregator, S defaultVal) { - return new CustomAggregatingEnricher<S,T>(flags, source, target, aggregator, defaultVal); - } - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - Map<String,?> flags, AttributeSensor<S> source, AttributeSensor<T> target, Function<Collection<S>, T> aggregator) { - return newEnricher(flags, source, target, aggregator, null); - } - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - AttributeSensor<S> source, AttributeSensor<T> target, Function<Collection<S>, T> aggregator, S defaultVal) { - return newEnricher(Collections.<String,Object>emptyMap(), source, target, aggregator, defaultVal); - } - public static <S,T> CustomAggregatingEnricher<S,T> newEnricher( - AttributeSensor<S> source, AttributeSensor<T> target, Function<Collection<S>, T> aggregator) { - return newEnricher(Collections.<String,Object>emptyMap(), source, target, aggregator, null); - } - - /** - * creates an enricher which sums over all children/members, - * defaulting to excluding sensors which have not published anything (or published null), and null if there are no sensors; - * this behaviour can be customised, both default value for sensors, and what to report if no sensors - * - * Instead, consider calling: - * <pre> - * {@code - * Enrichers.Builder builder = Enrichers.builder() - * .aggregating(source) - * .publishing(target) - * .computingSum() - * .defaultValueForUnreportedSensors(defaultValueForUnreportedSensors) - * .valueToReportIfNoSensors(valueToReportIfNoSensors); - * - * if (Boolean.TRUE.equals(allMembers)) builder.fromMembers(); - * if (filter != null) builder.entityFilter(filter); - * if (hardCodedProducers != null) builder.fromHardcodedProducers(hardCodedProducers); - * - * addEnricher(builder.build()); - * } - * </pre> - * - * @deprecated since 0.7.0; use {@link Enrichers#builder()} - */ - @Deprecated - public static <N extends Number, T extends Number> CustomAggregatingEnricher<N,T> newSummingEnricher( - Map<String,?> flags, AttributeSensor<N> source, final AttributeSensor<T> target, - final N defaultValueForUnreportedSensors, final T valueToReportIfNoSensors) { - - Function<Collection<N>, T> aggregator = new Function<Collection<N>, T>() { - @Override public T apply(Collection<N> vals) { - return sum(vals, defaultValueForUnreportedSensors, valueToReportIfNoSensors, target.getTypeToken()); - } - }; - return new CustomAggregatingEnricher<N,T>(flags, source, target, aggregator, defaultValueForUnreportedSensors); - } - - /** @see {@link #newSummingEnricher(Map, AttributeSensor, AttributeSensor, Number, Number)} */ - public static <N extends Number> CustomAggregatingEnricher<N,N> newSummingEnricher( - AttributeSensor<N> source, AttributeSensor<N> target) { - return newSummingEnricher(Collections.<String,Object>emptyMap(), source, target, null, null); - } - - /** creates an enricher which averages over all children/members, - * defaulting to excluding sensors which have not published anything (or published null), and null if there are no sensors; - * this behaviour can be customised, both default value for sensors, and what to report if no sensors - * - * Instead, consider calling: - * <pre> - * {@code - * Enrichers.Builder builder = Enrichers.builder() - * .aggregating(source) - * .publishing(target) - * .computingAverage() - * .defaultValueForUnreportedSensors(defaultValueForUnreportedSensors) - * .valueToReportIfNoSensors(valueToReportIfNoSensors); - * - * if (Boolean.TRUE.equals(allMembers)) builder.fromMembers(); - * if (filter != null) builder.entityFilter(filter); - * if (hardCodedProducers != null) builder.fromHardcodedProducers(hardCodedProducers); - * - * addEnricher(builder.build()); - * } - * </pre> - * - * @deprecated since 0.7.0; use {@link Enrichers#builder()} - */ - @Deprecated - public static <N extends Number> CustomAggregatingEnricher<N,Double> newAveragingEnricher( - Map<String,?> flags, AttributeSensor<? extends N> source, final AttributeSensor<Double> target, - final N defaultValueForUnreportedSensors, final Double valueToReportIfNoSensors) { - Function<Collection<N>, Double> aggregator = new Function<Collection<N>, Double>() { - @Override public Double apply(Collection<N> vals) { - int count = count(vals, defaultValueForUnreportedSensors!=null); - return (count==0) ? valueToReportIfNoSensors : - (Double) ((sum(vals, defaultValueForUnreportedSensors, 0, TypeToken.of(Double.class)) / count)); - } - }; - return new CustomAggregatingEnricher<N,Double>(flags, source, target, aggregator, defaultValueForUnreportedSensors); - } - - /** @see #newAveragingEnricher(Map, AttributeSensor, AttributeSensor, Number, Double) */ - public static <N extends Number> CustomAggregatingEnricher<N,Double> newAveragingEnricher( - AttributeSensor<N> source, AttributeSensor<Double> target) { - return newAveragingEnricher(Collections.<String,Object>emptyMap(), source, target, null, null); - } - - @SuppressWarnings("unchecked") - private static <N extends Number> N cast(Number n, TypeToken<? extends N> numberType) { - return (N) TypeCoercions.castPrimitive(n, numberType.getRawType()); - } - - private static <N extends Number> N sum(Iterable<? extends Number> vals, Number valueIfNull, Number valueIfNone, TypeToken<N> type) { - double result = 0d; - int count = 0; - if (vals!=null) { - for (Number val : vals) { - if (val!=null) { - result += val.doubleValue(); - count++; - } else if (valueIfNull!=null) { - result += valueIfNull.doubleValue(); - count++; - } - } - } - if (count==0) return cast(valueIfNone, type); - return cast(result, type); - } - - private static int count(Iterable<? extends Object> vals, boolean includeNullValues) { - int result = 0; - if (vals!=null) - for (Object val : vals) - if (val!=null || includeNullValues) result++; - return result; - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/26eeb7e0/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.java b/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.java deleted file mode 100644 index c7792af..0000000 --- a/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * 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 java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.core.entity.Entities; -import org.apache.brooklyn.core.location.SimulatedLocation; -import org.apache.brooklyn.core.sensor.BasicAttributeSensor; -import org.apache.brooklyn.core.sensor.Sensors; -import org.apache.brooklyn.core.test.entity.TestApplication; -import org.apache.brooklyn.core.test.entity.TestEntity; -import org.apache.brooklyn.entity.group.BasicGroup; -import org.apache.brooklyn.test.Asserts; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import com.google.common.base.Function; -import com.google.common.base.Predicates; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -@SuppressWarnings("deprecation") -public class CustomAggregatingEnricherDeprecatedTest { - - public static final Logger log = LoggerFactory.getLogger(CustomAggregatingEnricherDeprecatedTest.class); - - private static final long TIMEOUT_MS = 10*1000; - private static final long SHORT_WAIT_MS = 250; - - TestApplication app; - TestEntity producer; - Map<String, ?> producersFlags; - - AttributeSensor<Integer> intSensor = Sensors.newIntegerSensor("int sensor"); - AttributeSensor<Double> doubleSensor = Sensors.newDoubleSensor("double sensor"); - AttributeSensor<Integer> target = Sensors.newIntegerSensor("target sensor"); - - @BeforeMethod(alwaysRun=true) - public void setUp() { - app = TestApplication.Factory.newManagedInstanceForTests(); - producer = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - producersFlags = ImmutableMap.of("producers", ImmutableList.of(producer)); - - app.start(ImmutableList.of(new SimulatedLocation())); - } - - @AfterMethod(alwaysRun=true) - public void tearDown() { - if (app!=null) Entities.destroyAll(app.getManagementContext()); - } - - @Test - public void testEnrichersWithNoProducers() { - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher(ImmutableMap.<String,Object>of(), intSensor, target, 11, 40); - producer.enrichers().add(cae); - assertEquals(cae.getAggregate(), 40); - } - - @Test - public void testSummingEnricherWhenNoSensorValuesYet() { - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - producersFlags, intSensor, target, 11, 40); - producer.enrichers().add(cae); - assertEquals(cae.getAggregate(), 11); - } - - @Test - public void testSingleProducerSum() { - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - producersFlags, intSensor, target, null, null); - producer.enrichers().add(cae); - Assert.assertEquals(cae.getAggregate(), null); - cae.onEvent(intSensor.newEvent(producer, 1)); - assertEquals(cae.getAggregate(), 1); - } - - @Test - public void testSummingEnricherWhenNoAndNullSensorValue() { - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - producersFlags, intSensor, target, null, null); - producer.enrichers().add(cae); - Assert.assertEquals(cae.getAggregate(), null); - cae.onEvent(intSensor.newEvent(producer, null)); - Assert.assertEquals(cae.getAggregate(), null); - } - - @Test - public void testSummingEnricherWhenNoAndNullSensorValueExplicitValue() { - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - producersFlags, intSensor, target, 3 /** if null */, 5 /** if none */); - producer.enrichers().add(cae); - assertEquals(cae.getAggregate(), 3); - cae.onEvent(intSensor.newEvent(producer, null)); - assertEquals(cae.getAggregate(), 3); - cae.onEvent(intSensor.newEvent(producer, 1)); - assertEquals(cae.getAggregate(), 1); - cae.onEvent(intSensor.newEvent(producer, 7)); - assertEquals(cae.getAggregate(), 7); - } - - @Test - public void testMultipleProducersSum() { - List<TestEntity> producers = ImmutableList.of( - app.createAndManageChild(EntitySpec.create(TestEntity.class)), - app.createAndManageChild(EntitySpec.create(TestEntity.class)), - app.createAndManageChild(EntitySpec.create(TestEntity.class)) - ); - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - ImmutableMap.of("producers", producers), intSensor, target, null, null); - - producer.enrichers().add(cae); - Assert.assertEquals(cae.getAggregate(), null); - cae.onEvent(intSensor.newEvent(producers.get(2), 1)); - assertEquals(cae.getAggregate(), 1); - cae.onEvent(intSensor.newEvent(producers.get(0), 3)); - assertEquals(cae.getAggregate(), 4); - cae.onEvent(intSensor.newEvent(producers.get(1), 3)); - assertEquals(cae.getAggregate(), 7); - - } - - @Test - public void testAveragingEnricherWhenNoAndNullSensorValues() { - List<TestEntity> producers = ImmutableList.of( - app.createAndManageChild(EntitySpec.create(TestEntity.class)) - ); - CustomAggregatingEnricher<Integer, Double> cae = CustomAggregatingEnricher.<Integer>newAveragingEnricher( - ImmutableMap.of("producers", producers), intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), null, null); - producer.enrichers().add(cae); - Assert.assertEquals(cae.getAggregate(), null); - cae.onEvent(intSensor.newEvent(producers.get(0), null)); - Assert.assertEquals(cae.getAggregate(), null); - } - - @Test - public void testAveragingEnricherWhenNoAndNullSensorValuesExplicit() { - List<TestEntity> producers = ImmutableList.of( - app.createAndManageChild(EntitySpec.create(TestEntity.class)) - ); - CustomAggregatingEnricher<Integer, Double> cae = CustomAggregatingEnricher.<Integer>newAveragingEnricher( - ImmutableMap.of("producers", producers), intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), 3 /** if null */, 5d /** if none */); - producer.enrichers().add(cae); - - assertEquals(cae.getAggregate(), 3d); - cae.onEvent(intSensor.newEvent(producers.get(0), null)); - assertEquals(cae.getAggregate(), 3d); - cae.onEvent(intSensor.newEvent(producers.get(0), 4)); - assertEquals(cae.getAggregate(), 4d); - } - - @Test - public void testAveragingEnricherWhenNoSensors() { - List<TestEntity> producers = ImmutableList.of( - ); - CustomAggregatingEnricher<Integer, Double> cae = CustomAggregatingEnricher.<Integer>newAveragingEnricher( - ImmutableMap.of("producers", producers), intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), 3 /** if null */, 5d /** if none */); - producer.enrichers().add(cae); - - assertEquals(cae.getAggregate(), 5d); - } - - @Test - public void testMultipleProducersAverage() { - List<TestEntity> producers = ImmutableList.of( - app.createAndManageChild(EntitySpec.create(TestEntity.class)), - app.createAndManageChild(EntitySpec.create(TestEntity.class)), - app.createAndManageChild(EntitySpec.create(TestEntity.class)) - ); - CustomAggregatingEnricher<Double, Double> cae = CustomAggregatingEnricher.<Double>newAveragingEnricher( - ImmutableMap.of("producers", producers), - doubleSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), null, null); - - producer.enrichers().add(cae); - - Assert.assertEquals(cae.getAggregate(), null); - cae.onEvent(doubleSensor.newEvent(producers.get(0), 3d)); - assertEquals(cae.getAggregate(), 3d); - - cae.onEvent(doubleSensor.newEvent(producers.get(1), 3d)); - assertEquals(cae.getAggregate(), 3d); - - cae.onEvent(doubleSensor.newEvent(producers.get(2), 6d)); - assertEquals(cae.getAggregate(), 4d); - - // change p2's value to 7.5, average increase of 0.5. - cae.onEvent(doubleSensor.newEvent(producers.get(2), 7.5d)); - assertEquals(cae.getAggregate(), 4.5d); - } - - @Test - public void testMultipleProducersAverageDefaultingZero() { - List<TestEntity> producers = ImmutableList.of( - app.createAndManageChild(EntitySpec.create(TestEntity.class)), - app.createAndManageChild(EntitySpec.create(TestEntity.class)), - app.createAndManageChild(EntitySpec.create(TestEntity.class)) - ); - CustomAggregatingEnricher<Double, Double> cae = CustomAggregatingEnricher.<Double>newAveragingEnricher( - ImmutableMap.of("producers", producers), - doubleSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), 0d, 0d); - - producer.enrichers().add(cae); - - assertEquals(cae.getAggregate(), 0d); - cae.onEvent(doubleSensor.newEvent(producers.get(0), 3d)); - assertEquals(cae.getAggregate(), 1d); - - cae.onEvent(doubleSensor.newEvent(producers.get(1), 3d)); - assertEquals(cae.getAggregate(), 2d); - - cae.onEvent(doubleSensor.newEvent(producers.get(2), 6d)); - assertEquals(cae.getAggregate(), 4d); - - // change p2's value to 7.5, average increase of 0.5. - cae.onEvent(doubleSensor.newEvent(producers.get(2), 7.5d)); - assertEquals(cae.getAggregate(), 4.5d); - } - - @Test - public void testAddingAndRemovingProducers() { - TestEntity p1 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - TestEntity p2 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - ImmutableMap.of("producers", ImmutableList.of(p1)), - intSensor, target, null, null); - - producer.enrichers().add(cae); - Assert.assertEquals(cae.getAggregate(), null); - - // Event by initial producer - cae.onEvent(intSensor.newEvent(p1, 1)); - assertEquals(cae.getAggregate(), 1); - - // Add producer and fire event - cae.addProducer(p2); - cae.onEvent(intSensor.newEvent(p2, 4)); - assertEquals(cae.getAggregate(), 5); - - cae.removeProducer(p2); - assertEquals(cae.getAggregate(), 1); - } - - @Test - public void testAggregatesNewMembersOfGroup() { - try { - BasicGroup group = app.createAndManageChild(EntitySpec.create(BasicGroup.class)); - TestEntity p1 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - TestEntity p2 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - log.debug("created $group and the entities it will contain $p1 $p2"); - - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - ImmutableMap.of("allMembers", true), - intSensor, target, 0, 0); - group.enrichers().add(cae); - - assertEquals(cae.getAggregate(), 0); - - group.addMember(p1); - p1.sensors().set(intSensor, 1); - aggregateIsEventually(cae, 1); - - group.addMember(p2); - p2.sensors().set(intSensor, 2); - aggregateIsEventually(cae, 3); - - group.removeMember(p2); - aggregateIsEventually(cae, 1); - } catch (Exception e) { - log.error("testAggregatesNewMembersOfGroup failed (now cleaning up): "+e); - throw e; - } - } - - @Test(groups = "Integration") - public void testAggregatesGroupMembersFiftyTimes() { - for (int i=0; i<50; i++) { - log.debug("testAggregatesNewMembersOfGroup $i"); - testAggregatesNewMembersOfGroup(); - } - } - - @Test - public void testAggregatesExistingMembersOfGroup() { - BasicGroup group = app.addChild(EntitySpec.create(BasicGroup.class)); - TestEntity p1 = app.getManagementContext().getEntityManager().createEntity(EntitySpec.create(TestEntity.class).parent(group)); - TestEntity p2 = app.getManagementContext().getEntityManager().createEntity(EntitySpec.create(TestEntity.class).parent(group)); - group.addMember(p1); - group.addMember(p2); - p1.sensors().set(intSensor, 1); - Entities.manage(group); - - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - ImmutableMap.of("allMembers", true), - intSensor, target, null, null); - group.enrichers().add(cae); - - assertEquals(cae.getAggregate(), 1); - - p2.sensors().set(intSensor, 2); - aggregateIsEventually(cae, 3); - - group.removeMember(p2); - aggregateIsEventually(cae, 1); - } - - @Test - public void testAppliesFilterWhenAggregatingMembersOfGroup() { - BasicGroup group = app.createAndManageChild(EntitySpec.create(BasicGroup.class)); - TestEntity p1 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - TestEntity p2 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - TestEntity p3 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - group.addMember(p1); - group.addMember(p2); - p1.sensors().set(intSensor, 1); - p2.sensors().set(intSensor, 2); - p3.sensors().set(intSensor, 4); - - final CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newSummingEnricher( - ImmutableMap.of("allMembers", true, "filter", Predicates.equalTo(p1)), - intSensor, target, null, null); - group.enrichers().add(cae); - - assertEquals(cae.getAggregate(), 1); - - group.addMember(p3); - Asserts.succeedsContinually(ImmutableMap.of("timeout", SHORT_WAIT_MS), new Runnable() { - @Override - public void run() { - assertEquals(cae.getAggregate(), 1); - } - }); - } - - @Test - public void testCustomAggregatingFunction() { - TestEntity p1 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - Function<Collection<Integer>,Integer> aggregator = new Function<Collection<Integer>, Integer>() { - @Override - public Integer apply(Collection<Integer> c) { - int result = 0; - for (Integer it : c) { - result += it*it; - } - return result; - } - }; - - CustomAggregatingEnricher<Integer, Integer> cae = CustomAggregatingEnricher.<Integer, Integer>newEnricher( - ImmutableMap.of("producers", ImmutableList.of(p1)), - intSensor, target, aggregator, 0); - - producer.enrichers().add(cae); - assertEquals(cae.getAggregate(), 0); - - // Event by producer - cae.onEvent(intSensor.newEvent(p1, 2)); - assertEquals(cae.getAggregate(), 4); - } - - - private void assertEquals(Integer i1, int i2) { - Assert.assertEquals(i1, (Integer)i2); - } - private void assertEquals(Double i1, double i2) { - Assert.assertEquals(i1, i2); - } - - private void aggregateIsEventually(final CustomAggregatingEnricher<Integer, Integer> cae, final int avg) { - ImmutableMap<String, Long> timeout = ImmutableMap.of("timeout", TIMEOUT_MS); - - Asserts.succeedsEventually(timeout, new Runnable() { - @Override - public void run() { - assertEquals(cae.getAggregate(), avg); - } - }); - } - -}
