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 2015/08/20 00:54:19 UTC
[31/36] incubator-brooklyn git commit: Rename o.a.b.sensor.enricher
to o.a.b.core.enricher
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorPropagatingEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorPropagatingEnricher.java b/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorPropagatingEnricher.java
deleted file mode 100644
index 51d3d48..0000000
--- a/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorPropagatingEnricher.java
+++ /dev/null
@@ -1,180 +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.sensor.enricher;
-
-import java.util.Collection;
-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.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.api.sensor.SensorEventListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-
-/**
- * an enricher policy which just listens for the target sensor(s) on a child entity and passes it up.
- * now superseded by syntax such as:
- *
- * <pre>{@code Enrichers.builder().propagating(XXX).from(source).build()}</pre>
- *
- * @deprecated since 0.7.0; use {@link Enrichers#builder()}
- *
- * @see Propagator if need to sub-class
- */
-public class SensorPropagatingEnricher extends AbstractEnricher implements SensorEventListener<Object> {
-
- public static final Logger log = LoggerFactory.getLogger(SensorPropagatingEnricher.class);
-
- /** the entity to listen to */
- private final Entity source;
-
- /** the sensors to listen to */
- private final Set<Sensor<?>> sensors;
-
- /** the sensors to listen to */
- private final Map<Sensor<?>, Sensor<?>> sensorMappings;
-
- public static SensorPropagatingEnricher newInstanceListeningToAllSensors(Entity source) {
- return newInstanceListeningToAllSensorsBut(source);
- }
- public static SensorPropagatingEnricher newInstanceListeningToAllSensorsBut(Entity source, Sensor<?>... excludes) {
- Set<Sensor<?>> excluded = ImmutableSet.copyOf(excludes);
- Set<Sensor<?>> includes = Sets.newLinkedHashSet();
-
- for (Sensor<?> it : source.getEntityType().getSensors()) {
- if (!excluded.contains(it)) includes.add(it);
- }
- return new SensorPropagatingEnricher(source, includes);
- }
-
- public static SensorPropagatingEnricher newInstanceListeningTo(Entity source, Sensor<?>... includes) {
- return new SensorPropagatingEnricher(source, includes);
- }
-
- /**
- * listens to sensors from source, propagates them here renamed according to the map
- *
- * Instead, consider calling:
- * <pre>
- * {@code
- * addEnricher(Enrichers.builder()
- * .propagating(mapOfOldSensorNamesToNewSensorNames)
- * .from(source)
- * .build());
- * }
- * </pre>
- *
- * @deprecated since 0.7.0; use {@link Enrichers#builder()}
- */
- public static SensorPropagatingEnricher newInstanceRenaming(Entity source, Map<? extends Sensor<?>, ? extends Sensor<?>> sensors) {
- return new SensorPropagatingEnricher(source, sensors);
- }
-
- /**
- * @deprecated since 0.7.0; use {@link Enrichers#builder()}
- */
- public SensorPropagatingEnricher(Entity source, Sensor<?>... sensors) {
- this(source, ImmutableList.copyOf(sensors));
- }
-
- /**
- * Instead, consider calling:
- * <pre>
- * {@code
- * addEnricher(Enrichers.builder()
- * .propagating(sensors)
- * .from(source)
- * .build());
- * }
- * </pre>
- *
- * @deprecated since 0.7.0; use {@link Enrichers#builder()}
- */
- public SensorPropagatingEnricher(Entity source, Collection<Sensor<?>> sensors) {
- this.source = source;
- this.sensors = ImmutableSet.copyOf(sensors);
- this.sensorMappings = ImmutableMap.of();
- }
-
- public SensorPropagatingEnricher(Entity source, Map<? extends Sensor<?>, ? extends Sensor<?>> sensors) {
- this.source = source;
- this.sensors = ImmutableSet.copyOf(sensors.keySet());
- this.sensorMappings = ImmutableMap.copyOf(sensors);
- }
-
- public void setEntity(EntityLocal entity) {
- super.setEntity(entity);
- for (Sensor<?> s: sensors) {
- subscribe(source, s, this);
- }
- }
-
- @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)destinationSensor, event.getValue());
- } else {
- entity.emit((Sensor)destinationSensor, event.getValue());
- }
- }
-
- /** useful post-addition to emit current values */
- public void emitAllAttributes() {
- emitAllAttributes(false);
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- 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(destinationSensor, v);
- }
- }
- }
-
- /** convenience, to be called by the host */
- public SensorPropagatingEnricher addToEntityAndEmitAll(Entity host) {
- host.addEnricher(this);
- emitAllAttributes();
- return this;
- }
-
- private Sensor<?> getDestinationSensor(Sensor<?> sourceSensor) {
- return sensorMappings.containsKey(sourceSensor) ? sensorMappings.get(sourceSensor): sourceSensor;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorTransformingEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorTransformingEnricher.java b/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorTransformingEnricher.java
deleted file mode 100644
index 2ad1bdf..0000000
--- a/core/src/main/java/org/apache/brooklyn/sensor/enricher/SensorTransformingEnricher.java
+++ /dev/null
@@ -1,106 +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.sensor.enricher;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.util.groovy.GroovyJavaMethods;
-import org.apache.brooklyn.util.javalang.JavaClassNames;
-import org.apache.brooklyn.util.time.Duration;
-
-import groovy.lang.Closure;
-
-import com.google.common.base.Function;
-
-/**
- * @deprecated since 0.7.0; use {@link Enrichers.builder()}
- * @see Transformer if need to sub-class
- */
-public class SensorTransformingEnricher<T,U> extends AbstractTypeTransformingEnricher {
-
- private Function<? super T, ? extends U> transformation;
-
- public SensorTransformingEnricher(Entity producer, Sensor<T> source, Sensor<U> target, Function<? super T, ? extends U> transformation) {
- super(producer, source, target);
- this.transformation = transformation;
- this.uniqueTag = JavaClassNames.simpleClassName(getClass())+":"+source.getName()+"*->"+target.getName();;
- }
-
- public SensorTransformingEnricher(Entity producer, Sensor<T> source, Sensor<U> target, Closure transformation) {
- this(producer, source, target, GroovyJavaMethods.functionFromClosure(transformation));
- }
-
- public SensorTransformingEnricher(Sensor<T> source, Sensor<U> target, Function<T,U> transformation) {
- this(null, source, target, transformation);
- }
-
- public SensorTransformingEnricher(Sensor<T> source, Sensor<U> target, Closure transformation) {
- this(null, source, target, GroovyJavaMethods.functionFromClosure(transformation));
- }
-
- @Override
- public void onEvent(SensorEvent event) {
- if (accept((T)event.getValue())) {
- if (target instanceof AttributeSensor)
- entity.setAttribute((AttributeSensor)target, compute((T)event.getValue()));
- else
- entity.emit(target, compute((T)event.getValue()));
- }
- }
-
- protected boolean accept(T value) {
- return true;
- }
-
- protected U compute(T value) {
- return transformation.apply(value);
- }
-
- /**
- * creates an enricher which listens to a source (from the producer),
- * transforms it and publishes it under the target
- *
- * Instead, consider calling:
- * <pre>
- * {@code
- * addEnricher(Enrichers.builder()
- * .transforming(source)
- * .publishing(target)
- * .from(producer)
- * .computing(transformation)
- * .build());
- * }
- * </pre>
- *
- * @deprecated since 0.7.0; use {@link Enrichers.builder()}
- */
- public static <U,V> SensorTransformingEnricher<U,V> newInstanceTransforming(Entity producer, AttributeSensor<U> source,
- Function<U,V> transformation, AttributeSensor<V> target) {
- return new SensorTransformingEnricher<U,V>(producer, source, target, transformation);
- }
-
- /** as {@link #newInstanceTransforming(Entity, AttributeSensor, Function, AttributeSensor)}
- * using the same sensor as the source and the target */
- public static <T> SensorTransformingEnricher<T,T> newInstanceTransforming(Entity producer, AttributeSensor<T> sensor,
- Function<T,T> transformation) {
- return newInstanceTransforming(producer, sensor, transformation, sensor);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/main/java/org/apache/brooklyn/sensor/enricher/Transformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/enricher/Transformer.java b/core/src/main/java/org/apache/brooklyn/sensor/enricher/Transformer.java
deleted file mode 100644
index f77bd8c..0000000
--- a/core/src/main/java/org/apache/brooklyn/sensor/enricher/Transformer.java
+++ /dev/null
@@ -1,103 +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.sensor.enricher;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.util.collections.MutableSet;
-import org.apache.brooklyn.util.core.task.Tasks;
-import org.apache.brooklyn.util.core.task.ValueResolver;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
-import com.google.common.reflect.TypeToken;
-
-//@Catalog(name="Transformer", description="Transforms attributes of an entity; see Enrichers.builder().transforming(...)")
-@SuppressWarnings("serial")
-public class Transformer<T,U> extends AbstractTransformer<T,U> {
-
- @SuppressWarnings("unused")
- private static final Logger LOG = LoggerFactory.getLogger(Transformer.class);
-
- // exactly one of these should be supplied to set a value
- public static ConfigKey<?> TARGET_VALUE = ConfigKeys.newConfigKey(Object.class, "enricher.targetValue");
- public static ConfigKey<Function<?, ?>> TRANSFORMATION_FROM_VALUE = ConfigKeys.newConfigKey(new TypeToken<Function<?, ?>>() {}, "enricher.transformation");
- public static ConfigKey<Function<?, ?>> TRANSFORMATION_FROM_EVENT = ConfigKeys.newConfigKey(new TypeToken<Function<?, ?>>() {}, "enricher.transformation.fromevent");
-
- public Transformer() {
- }
-
- /** returns a function for transformation, for immediate use only (not for caching, as it may change) */
- @Override
- @SuppressWarnings("unchecked")
- protected Function<SensorEvent<T>, U> getTransformation() {
- MutableSet<Object> suppliers = MutableSet.of();
- suppliers.addIfNotNull(config().getRaw(TARGET_VALUE).orNull());
- suppliers.addIfNotNull(config().getRaw(TRANSFORMATION_FROM_EVENT).orNull());
- suppliers.addIfNotNull(config().getRaw(TRANSFORMATION_FROM_VALUE).orNull());
- checkArgument(suppliers.size()==1,
- "Must set exactly one of: %s, %s, %s", TARGET_VALUE.getName(), TRANSFORMATION_FROM_VALUE.getName(), TRANSFORMATION_FROM_EVENT.getName());
-
- Function<?, ?> fromEvent = config().get(TRANSFORMATION_FROM_EVENT);
- if (fromEvent != null) {
- return (Function<SensorEvent<T>, U>) fromEvent;
- }
-
- final Function<T, U> fromValueFn = (Function<T, U>) config().get(TRANSFORMATION_FROM_VALUE);
- if (fromValueFn != null) {
- // named class not necessary as result should not be serialized
- return new Function<SensorEvent<T>, U>() {
- @Override public U apply(SensorEvent<T> input) {
- return fromValueFn.apply(input.getValue());
- }
- @Override
- public String toString() {
- return ""+fromValueFn;
- }
- };
- }
-
- // from target value
- // named class not necessary as result should not be serialized
- final Object targetValueRaw = config().getRaw(TARGET_VALUE).orNull();
- return new Function<SensorEvent<T>, U>() {
- @Override public U apply(SensorEvent<T> input) {
- // evaluate immediately, or return null
- // PRETTY_QUICK/200ms seems a reasonable compromise for tasks which require BG evaluation
- // but which are non-blocking
- // TODO better would be to have a mode in which tasks are not permitted to block on
- // external events; they can submit tasks and block on them (or even better, have a callback architecture);
- // however that is a non-trivial refactoring
- return (U) Tasks.resolving(targetValueRaw).as(targetSensor.getType())
- .context(entity)
- .description("Computing sensor "+targetSensor+" from "+targetValueRaw)
- .timeout(ValueResolver.PRETTY_QUICK_WAIT)
- .getMaybe().orNull();
- }
- public String toString() {
- return ""+targetValueRaw;
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/main/java/org/apache/brooklyn/sensor/enricher/UpdatingMap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/enricher/UpdatingMap.java b/core/src/main/java/org/apache/brooklyn/sensor/enricher/UpdatingMap.java
deleted file mode 100644
index 6ae48a7..0000000
--- a/core/src/main/java/org/apache/brooklyn/sensor/enricher/UpdatingMap.java
+++ /dev/null
@@ -1,158 +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.sensor.enricher;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.api.sensor.SensorEventListener;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Maps;
-import com.google.common.reflect.TypeToken;
-
-/**
- * Enricher which updates an entry in a sensor map ({@link #TARGET_SENSOR})
- * based on the value of another sensor ({@link #SOURCE_SENSOR}.
- * <p>
- * The key used defaults to the name of the source sensor but can be specified with {@link #KEY_IN_TARGET_SENSOR}.
- * The value placed in the map is the result of applying the function in {@link #COMPUTING} to the sensor value,
- * with default behaviour being to remove an entry if <code>null</code> is returned
- * but this can be overriden by setting {@link #REMOVING_IF_RESULT_IS_NULL} false.
- * {@link Entities#REMOVE} and {@link Entities#UNCHANGED} are also respeced as return values for the computation
- * (ignoring generics).
- * Unlike most other enrichers, this defaults to {@link AbstractEnricher#SUPPRESS_DUPLICATES} being true
- *
- * @author alex
- *
- * @param <S> source sensor type
- * @param <TKey> key type in target sensor map
- * @param <TVal> value type in target sensor map
- */
-@SuppressWarnings("serial")
-public class UpdatingMap<S,TKey,TVal> extends AbstractEnricher implements SensorEventListener<S> {
-
- private static final Logger LOG = LoggerFactory.getLogger(UpdatingMap.class);
-
- @SetFromFlag("fromSensor")
- public static final ConfigKey<Sensor<?>> SOURCE_SENSOR = ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.sourceSensor");
- @SetFromFlag("targetSensor")
- public static final ConfigKey<Sensor<?>> TARGET_SENSOR = ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.targetSensor");
- @SetFromFlag("key")
- public static final ConfigKey<?> KEY_IN_TARGET_SENSOR = ConfigKeys.newConfigKey(Object.class, "enricher.updatingMap.keyInTargetSensor",
- "Key to update in the target sensor map, defaulting to the name of the source sensor");
- @SetFromFlag("computing")
- public static final ConfigKey<Function<?, ?>> COMPUTING = ConfigKeys.newConfigKey(new TypeToken<Function<?,?>>() {}, "enricher.updatingMap.computing");
- @SetFromFlag("removingIfResultIsNull")
- public static final ConfigKey<Boolean> REMOVING_IF_RESULT_IS_NULL = ConfigKeys.newBooleanConfigKey("enricher.updatingMap.removingIfResultIsNull",
- "Whether the key in the target map is removed if the result if the computation is null");
-
- protected AttributeSensor<S> sourceSensor;
- protected AttributeSensor<Map<TKey,TVal>> targetSensor;
- protected TKey key;
- protected Function<S,? extends TVal> computing;
- protected Boolean removingIfResultIsNull;
-
- public UpdatingMap() {
- this(Maps.newLinkedHashMap());
- }
-
- public UpdatingMap(Map<Object, Object> flags) {
- super(flags);
- // this always suppresses duplicates, but it updates the same map *in place* so the usual suppress duplicates logic should not be applied
- // TODO clean up so that we have synchronization guarantees and can inspect the item to see whether it has changed
- suppressDuplicates = false;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public void setEntity(EntityLocal entity) {
- super.setEntity(entity);
- this.sourceSensor = (AttributeSensor<S>) getRequiredConfig(SOURCE_SENSOR);
- this.targetSensor = (AttributeSensor<Map<TKey,TVal>>) getRequiredConfig(TARGET_SENSOR);
- this.key = (TKey) getConfig(KEY_IN_TARGET_SENSOR);
- this.computing = (Function) getRequiredConfig(COMPUTING);
- this.removingIfResultIsNull = getConfig(REMOVING_IF_RESULT_IS_NULL);
-
- subscribe(entity, sourceSensor, this);
- onUpdated();
- }
-
- @Override
- public void onEvent(SensorEvent<S> event) {
- onUpdated();
- }
-
- /**
- * Called whenever the values for the set of producers changes (e.g. on an event, or on a member added/removed).
- */
- @SuppressWarnings("unchecked")
- protected void onUpdated() {
- try {
- Object v = computing.apply(entity.getAttribute(sourceSensor));
- if (v == null && !Boolean.FALSE.equals(removingIfResultIsNull)) {
- v = Entities.REMOVE;
- }
- if (v == Entities.UNCHANGED) {
- // nothing
- } else {
- // TODO check synchronization
- TKey key = this.key;
- if (key==null) key = (TKey) sourceSensor.getName();
-
- Map<TKey, TVal> map = entity.getAttribute(targetSensor);
-
- boolean created = (map==null);
- if (created) map = MutableMap.of();
-
- boolean changed;
- if (v == Entities.REMOVE) {
- changed = map.containsKey(key);
- if (changed)
- map.remove(key);
- } else {
- TVal oldV = map.get(key);
- if (oldV==null)
- changed = (v!=null || !map.containsKey(key));
- else
- changed = !oldV.equals(v);
- if (changed)
- map.put(key, (TVal)v);
- }
- if (changed || created)
- emit(targetSensor, map);
- }
- } catch (Throwable t) {
- LOG.warn("Error calculating map update for enricher "+this, t);
- throw Exceptions.propagate(t);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlRollingTimeWindowMeanEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlRollingTimeWindowMeanEnricher.java b/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlRollingTimeWindowMeanEnricher.java
deleted file mode 100644
index dc65fa8..0000000
--- a/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlRollingTimeWindowMeanEnricher.java
+++ /dev/null
@@ -1,178 +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.sensor.enricher;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-
-import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.util.time.Duration;
-
-import com.google.common.base.Function;
-
-/**
- * Transforms {@link Sensor} data into a rolling average based on a time window.
- *
- * All values within the window are weighted or discarded based on the timestamps associated with
- * them (discards occur when a new value is added or an average is requested)
- * <p>
- * This will not extrapolate figures - it is assumed a value is valid and correct for the entire
- * time period between it and the previous value. Normally, the average attribute is only updated
- * when a new value arrives so it can give a fully informed average, but there is a danger of this
- * going stale.
- * <p>
- * When an average is requested, it is likely there will be a segment of the window for which there
- * isn't a value. Instead of extrapolating a value and providing different extrapolation techniques,
- * the average is reported with a confidence value which reflects the fraction of the time
- * window for which the values were valid.
- * <p>
- * Consumers of the average may ignore the confidence value and just use the last known average.
- * They could multiply the returned value by the confidence value to get a decay-type behavior as
- * the window empties. A third alternative is to, at a certain confidence threshold, report that
- * the average is no longer meaningful.
- * <p>
- * The default average when no data has been received is 0, with a confidence of 0
- */
-public class YamlRollingTimeWindowMeanEnricher<T extends Number> extends AbstractTransformer<T,Double> {
-
- public static ConfigKey<Duration> WINDOW_DURATION = ConfigKeys.newConfigKey(Duration.class, "enricher.window.duration",
- "Duration for which this window should store data, default one minute", Duration.ONE_MINUTE);
-
- public static ConfigKey<Double> CONFIDENCE_REQUIRED_TO_PUBLISH = ConfigKeys.newDoubleConfigKey("enricher.window.confidenceRequired",
- "Minimum confidence level (ie period covered) required to publish a rolling average", 0.8d);
-
- public static class ConfidenceQualifiedNumber {
- final Double value;
- final double confidence;
-
- public ConfidenceQualifiedNumber(Double value, double confidence) {
- this.value = value;
- this.confidence = confidence;
- }
-
- @Override
- public String toString() {
- return ""+value+" ("+(int)(confidence*100)+"%)";
- }
-
- }
-
- private final LinkedList<T> values = new LinkedList<T>();
- private final LinkedList<Long> timestamps = new LinkedList<Long>();
- volatile ConfidenceQualifiedNumber lastAverage = new ConfidenceQualifiedNumber(0d,0d);
-
- @Override
- protected Function<SensorEvent<T>, Double> getTransformation() {
- return new Function<SensorEvent<T>, Double>() {
- @Override
- public Double apply(SensorEvent<T> event) {
- long eventTime = event.getTimestamp();
- if (event.getValue()==null) {
- return null;
- }
- values.addLast(event.getValue());
- timestamps.addLast(eventTime);
- if (eventTime>0) {
- ConfidenceQualifiedNumber average = getAverage(eventTime, 0);
-
- if (average.confidence > getConfig(CONFIDENCE_REQUIRED_TO_PUBLISH)) {
- // without confidence, we might publish wildly varying estimates,
- // causing spurious resizes, so allow it to be configured, and
- // by default require a high value
-
- // TODO would be nice to include timestamp, etc
- return average.value;
- }
- }
- return null;
- }
- };
- }
-
- public ConfidenceQualifiedNumber getAverage(long fromTime, long graceAllowed) {
- if (timestamps.isEmpty()) {
- return lastAverage = new ConfidenceQualifiedNumber(lastAverage.value, 0.0d);
- }
-
- long firstTimestamp = -1;
- Iterator<Long> ti = timestamps.iterator();
- while (ti.hasNext()) {
- firstTimestamp = ti.next();
- if (firstTimestamp>0) break;
- }
- if (firstTimestamp<=0) {
- // no values with reasonable timestamps
- return lastAverage = new ConfidenceQualifiedNumber(values.get(values.size()-1).doubleValue(), 0.0d);
- }
-
- long lastTimestamp = timestamps.get(timestamps.size()-1);
-
- long now = fromTime;
- if (lastTimestamp > fromTime - graceAllowed) {
- // without this, if the computation takes place X seconds after the publish,
- // we treat X seconds as time for which we have no confidence in the data
- now = lastTimestamp;
- }
- pruneValues(now);
-
- Duration timePeriod = getConfig(WINDOW_DURATION);
- long windowStart = Math.max(now-timePeriod.toMilliseconds(), firstTimestamp);
- long windowEnd = Math.max(now-timePeriod.toMilliseconds(), lastTimestamp);
- Double confidence = ((double)(windowEnd - windowStart)) / timePeriod.toMilliseconds();
- if (confidence <= 0.0000001d) {
- // not enough timestamps in window
- double lastValue = values.get(values.size()-1).doubleValue();
- return lastAverage = new ConfidenceQualifiedNumber(lastValue, 0.0d);
- }
-
- long start = windowStart;
- long end;
- double weightedAverage = 0.0d;
-
- Iterator<T> valuesIter = values.iterator();
- Iterator<Long> timestampsIter = timestamps.iterator();
- while (valuesIter.hasNext()) {
- // Ignores null and out-of-date values (and also values that are received out-of-order, but that shouldn't happen!)
- Number val = valuesIter.next();
- Long timestamp = timestampsIter.next();
- if (val!=null && timestamp >= start) {
- end = timestamp;
- weightedAverage += ((end - start) / (confidence * timePeriod.toMilliseconds())) * val.doubleValue();
- start = timestamp;
- }
- }
-
- return lastAverage = new ConfidenceQualifiedNumber(weightedAverage, confidence);
- }
-
- /**
- * Discards out-of-date values, but keeps at least one value.
- */
- private void pruneValues(long now) {
- // keep one value from before the period, so that we can tell the window's start time
- Duration timePeriod = getConfig(WINDOW_DURATION);
- while(timestamps.size() > 1 && timestamps.get(1) < (now - timePeriod.toMilliseconds())) {
- timestamps.removeFirst();
- values.removeFirst();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlTimeWeightedDeltaEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlTimeWeightedDeltaEnricher.java b/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlTimeWeightedDeltaEnricher.java
deleted file mode 100644
index c49ac26..0000000
--- a/core/src/main/java/org/apache/brooklyn/sensor/enricher/YamlTimeWeightedDeltaEnricher.java
+++ /dev/null
@@ -1,83 +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.sensor.enricher;
-
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.sensor.enricher.AbstractTransformer;
-import org.apache.brooklyn.util.core.flags.TypeCoercions;
-import org.apache.brooklyn.util.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
-
-/**
- * Converts an absolute count sensor into a delta sensor (i.e. the diff between the current and previous value),
- * presented as a units/timeUnit based on the event timing.
- * <p>
- * For example, given a requests.count sensor, this can make a requests.per_sec sensor with {@link #DELTA_PERIOD} set to "1s" (the default).
- * <p>
- * Suitable for configuration from YAML.
- */
-public class YamlTimeWeightedDeltaEnricher<T extends Number> extends AbstractTransformer<T,Double> {
- private static final Logger LOG = LoggerFactory.getLogger(YamlTimeWeightedDeltaEnricher.class);
-
- transient Object lock = new Object();
- Number lastValue;
- long lastTime = -1;
-
- public static ConfigKey<Duration> DELTA_PERIOD = ConfigKeys.newConfigKey(Duration.class, "enricher.delta.period",
- "Duration that this delta should compute for, default per second", Duration.ONE_SECOND);
-
- @Override
- protected Function<SensorEvent<T>, Double> getTransformation() {
- return new Function<SensorEvent<T>, Double>() {
- @Override
- public Double apply(SensorEvent<T> event) {
- synchronized (lock) {
- Double current = TypeCoercions.coerce(event.getValue(), Double.class);
-
- if (current == null) return null;
-
- long eventTime = event.getTimestamp();
- long unitMillis = getConfig(DELTA_PERIOD).toMilliseconds();
- Double result = null;
-
- if (eventTime > 0 && eventTime > lastTime) {
- if (lastValue == null || lastTime < 0) {
- // cannot calculate time-based delta with a single value
- if (LOG.isTraceEnabled()) LOG.trace("{} received event but no last value so will not emit, null -> {} at {}", new Object[] {this, current, eventTime});
- } else {
- double duration = eventTime - lastTime;
- result = (current - lastValue.doubleValue()) / (duration / unitMillis);
- }
- }
-
- lastValue = current;
- lastTime = eventTime;
-
- return result;
- }
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/enricher/BasicEnricherTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/enricher/BasicEnricherTest.java b/core/src/test/java/org/apache/brooklyn/core/enricher/BasicEnricherTest.java
new file mode 100644
index 0000000..be87f1f
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/enricher/BasicEnricherTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.core.enricher;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.sensor.Enricher;
+import org.apache.brooklyn.api.sensor.EnricherSpec;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.BasicConfigKey;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
+import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestApplicationNoEnrichersImpl;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * Test that enricher can be created and accessed, by construction and by spec
+ */
+public class BasicEnricherTest extends BrooklynAppUnitTestSupport {
+
+ // TODO These tests are a copy of BasicPolicyTest, which is a code smell.
+ // However, the src/main/java code does not contain as much duplication.
+
+ protected void setUpApp() {
+ EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class, TestApplicationNoEnrichersImpl.class)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution());
+ app = ApplicationBuilder.newManagedApp(appSpec, mgmt);
+ }
+
+ public static class MyEnricher extends AbstractEnricher {
+ @SetFromFlag("intKey")
+ public static final BasicConfigKey<Integer> INT_KEY = new BasicConfigKey<Integer>(Integer.class, "bkey", "b key");
+
+ @SetFromFlag("strKey")
+ public static final ConfigKey<String> STR_KEY = new BasicConfigKey<String>(String.class, "akey", "a key");
+ public static final ConfigKey<Integer> INT_KEY_WITH_DEFAULT = new BasicConfigKey<Integer>(Integer.class, "ckey", "c key", 1);
+ public static final ConfigKey<String> STR_KEY_WITH_DEFAULT = new BasicConfigKey<String>(String.class, "strKey", "str key", "str key default");
+
+ MyEnricher(Map<?,?> flags) {
+ super(flags);
+ }
+
+ public MyEnricher() {
+ super();
+ }
+ }
+
+ @Test
+ public void testAddInstance() throws Exception {
+ MyEnricher enricher = new MyEnricher();
+ enricher.setDisplayName("Bob");
+ enricher.config().set(MyEnricher.STR_KEY, "aval");
+ enricher.config().set(MyEnricher.INT_KEY, 2);
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getDisplayName(), "Bob");
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY), "aval");
+ assertEquals(enricher.getConfig(MyEnricher.INT_KEY), (Integer)2);
+ }
+
+ @Test
+ public void testAddSpec() throws Exception {
+ MyEnricher enricher = app.addEnricher(EnricherSpec.create(MyEnricher.class)
+ .displayName("Bob")
+ .configure(MyEnricher.STR_KEY, "aval").configure(MyEnricher.INT_KEY, 2));
+
+ assertEquals(enricher.getDisplayName(), "Bob");
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY), "aval");
+ assertEquals(enricher.getConfig(MyEnricher.INT_KEY), (Integer)2);
+ }
+
+ @Test
+ public void testTagsFromSpec() throws Exception {
+ MyEnricher enricher = app.addEnricher(EnricherSpec.create(MyEnricher.class).tag(99).uniqueTag("x"));
+
+ assertEquals(enricher.tags().getTags(), MutableSet.of("x", 99));
+ assertEquals(enricher.getUniqueTag(), "x");
+ }
+
+ @Test
+ public void testSameUniqueTagEnricherNotAddedTwice() throws Exception {
+ app.addEnricher(EnricherSpec.create(MyEnricher.class).tag(99).uniqueTag("x"));
+ app.addEnricher(EnricherSpec.create(MyEnricher.class).tag(94).uniqueTag("x"));
+
+ assertEquals(app.getEnrichers().size(), 1);
+ // the more recent one should dominate
+ Enricher enricher = Iterables.getOnlyElement(app.getEnrichers());
+ Assert.assertTrue(enricher.tags().containsTag(94));
+ Assert.assertFalse(enricher.tags().containsTag(99));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/enricher/EnricherConfigTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/enricher/EnricherConfigTest.java b/core/src/test/java/org/apache/brooklyn/core/enricher/EnricherConfigTest.java
new file mode 100644
index 0000000..150a09b
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/enricher/EnricherConfigTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.core.enricher;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import org.apache.brooklyn.core.config.BasicConfigKey;
+import org.apache.brooklyn.core.enricher.BasicEnricherTest.MyEnricher;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.testng.annotations.Test;
+
+/**
+ * Test that configuration properties are usable and inherited correctly.
+ */
+public class EnricherConfigTest extends BrooklynAppUnitTestSupport {
+
+ // TODO These tests are a copy of PolicyConfigTest, which is a code smell.
+ // However, the src/main/java code does not contain as much duplication.
+
+ private BasicConfigKey<String> differentKey = new BasicConfigKey<String>(String.class, "differentkey", "diffval");
+
+ @Test
+ public void testConfigFlagsPassedInAtConstructionIsAvailable() throws Exception {
+ MyEnricher enricher = new MyEnricher(MutableMap.builder()
+ .put("strKey", "aval")
+ .put("intKey", 2)
+ .build());
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY), "aval");
+ assertEquals(enricher.getConfig(MyEnricher.INT_KEY), (Integer)2);
+ // this is set, because key name matches annotation on STR_KEY
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY_WITH_DEFAULT), "aval");
+ }
+
+ @Test
+ public void testUnknownConfigPassedInAtConstructionIsWarnedAndIgnored() throws Exception {
+ // TODO Also assert it's warned
+ MyEnricher enricher = new MyEnricher(MutableMap.builder()
+ .put(differentKey, "aval")
+ .build());
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(differentKey), null);
+ assertEquals(enricher.getEnricherType().getConfigKey(differentKey.getName()), null);
+ }
+
+ @Test
+ public void testConfigPassedInAtConstructionIsAvailable() throws Exception {
+ MyEnricher enricher = new MyEnricher(MutableMap.builder()
+ .put(MyEnricher.STR_KEY, "aval")
+ .put(MyEnricher.INT_KEY, 2)
+ .build());
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY), "aval");
+ assertEquals(enricher.getConfig(MyEnricher.INT_KEY), (Integer)2);
+ // this is not set (contrast with above)
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY_WITH_DEFAULT), MyEnricher.STR_KEY_WITH_DEFAULT.getDefaultValue());
+ }
+
+ @Test
+ public void testConfigSetToGroovyTruthFalseIsAvailable() throws Exception {
+ MyEnricher enricher = new MyEnricher(MutableMap.builder()
+ .put(MyEnricher.INT_KEY_WITH_DEFAULT, 0)
+ .build());
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(MyEnricher.INT_KEY_WITH_DEFAULT), (Integer)0);
+ }
+
+ @Test
+ public void testConfigSetToNullIsAvailable() throws Exception {
+ MyEnricher enricher = new MyEnricher(MutableMap.builder()
+ .put(MyEnricher.STR_KEY_WITH_DEFAULT, null)
+ .build());
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY_WITH_DEFAULT), null);
+ }
+
+ @Test
+ public void testConfigCanBeSetOnEnricher() throws Exception {
+ MyEnricher enricher = new MyEnricher();
+ enricher.config().set(MyEnricher.STR_KEY, "aval");
+ enricher.config().set(MyEnricher.INT_KEY, 2);
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY), "aval");
+ assertEquals(enricher.getConfig(MyEnricher.INT_KEY), (Integer)2);
+ }
+
+ @Test
+ public void testConfigSetterOverridesConstructorValue() throws Exception {
+ MyEnricher enricher = new MyEnricher(MutableMap.builder()
+ .put(MyEnricher.STR_KEY, "aval")
+ .build());
+ enricher.config().set(MyEnricher.STR_KEY, "diffval");
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY), "diffval");
+ }
+
+ @Test
+ public void testConfigCannotBeSetAfterApplicationIsStarted() throws Exception {
+ MyEnricher enricher = new MyEnricher(MutableMap.builder()
+ .put(MyEnricher.STR_KEY, "origval")
+ .build());
+ app.addEnricher(enricher);
+
+ try {
+ enricher.config().set(MyEnricher.STR_KEY,"newval");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // success
+ }
+
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY), "origval");
+ }
+
+ @Test
+ public void testConfigReturnsDefaultValueIfNotSet() throws Exception {
+ MyEnricher enricher = new MyEnricher();
+ app.addEnricher(enricher);
+
+ assertEquals(enricher.getConfig(MyEnricher.STR_KEY_WITH_DEFAULT), "str key default");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/entity/EntitySpecTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntitySpecTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntitySpecTest.java
index d53bc87..1fec2e8 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/EntitySpecTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntitySpecTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.sensor.EnricherSpec;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.BasicConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
import org.apache.brooklyn.core.location.SimulatedLocation;
import org.apache.brooklyn.core.policy.AbstractPolicy;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
@@ -37,7 +38,6 @@ import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.core.test.entity.TestEntityImpl;
import org.apache.brooklyn.core.test.entity.TestEntityNoEnrichersImpl;
import org.apache.brooklyn.entity.group.BasicGroup;
-import org.apache.brooklyn.sensor.enricher.AbstractEnricher;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import org.testng.annotations.BeforeMethod;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterTestFixture.java
index f751bcb..03a9c79 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterTestFixture.java
@@ -46,7 +46,7 @@ import org.apache.brooklyn.core.mgmt.rebind.RecordingRebindExceptionHandler;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.core.test.policy.TestPolicy;
-import org.apache.brooklyn.sensor.enricher.Enrichers;
+import org.apache.brooklyn.enricher.stock.Enrichers;
import org.testng.SkipException;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
index c4d295a..e79ba8a 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.api.sensor.Enricher;
import org.apache.brooklyn.api.sensor.EnricherSpec;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.EntityPredicates;
@@ -42,9 +43,8 @@ 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.core.test.entity.TestEntityImpl;
+import org.apache.brooklyn.enricher.stock.Enrichers;
import org.apache.brooklyn.entity.group.DynamicCluster;
-import org.apache.brooklyn.sensor.enricher.AbstractEnricher;
-import org.apache.brooklyn.sensor.enricher.Enrichers;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindFailuresTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindFailuresTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindFailuresTest.java
index 26ee74f..e78f062 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindFailuresTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindFailuresTest.java
@@ -42,6 +42,7 @@ import org.apache.brooklyn.api.sensor.EnricherSpec;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.config.ConfigMap;
import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
import org.apache.brooklyn.core.entity.EntityFunctions;
import org.apache.brooklyn.core.entity.EntityPredicates;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
@@ -49,7 +50,6 @@ import org.apache.brooklyn.core.mgmt.rebind.RebindEntityTest.MyEntity;
import org.apache.brooklyn.core.mgmt.rebind.RebindEntityTest.MyEntityImpl;
import org.apache.brooklyn.core.policy.AbstractPolicy;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.sensor.enricher.AbstractEnricher;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
index 28c9ba8..faff0c9 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.api.sensor.EnricherSpec;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.location.Locations;
import org.apache.brooklyn.core.mgmt.rebind.RebindEnricherTest.MyEnricher;
@@ -42,7 +43,6 @@ import org.apache.brooklyn.core.policy.AbstractPolicy;
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.sensor.enricher.AbstractEnricher;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java
index a9f9655..12a6bff 100644
--- a/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java
@@ -22,7 +22,7 @@ import static org.testng.Assert.assertEquals;
import org.apache.brooklyn.api.sensor.EnricherType;
import org.apache.brooklyn.core.config.BasicConfigKey;
-import org.apache.brooklyn.sensor.enricher.AbstractEnricher;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/core/test/policy/TestEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/policy/TestEnricher.java b/core/src/test/java/org/apache/brooklyn/core/test/policy/TestEnricher.java
index 2340c51..42b52d2 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/policy/TestEnricher.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/policy/TestEnricher.java
@@ -26,7 +26,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.BasicConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.sensor.enricher.AbstractEnricher;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f15e8a6/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.groovy b/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.groovy
new file mode 100644
index 0000000..481e233
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/enricher/stock/CustomAggregatingEnricherDeprecatedTest.groovy
@@ -0,0 +1,368 @@
+/*
+ * 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 static org.testng.Assert.assertEquals
+
+import org.apache.brooklyn.api.entity.EntitySpec
+import org.apache.brooklyn.api.sensor.AttributeSensor
+import org.apache.brooklyn.core.test.entity.TestApplication
+import org.apache.brooklyn.core.test.entity.TestEntity
+import org.apache.brooklyn.enricher.stock.CustomAggregatingEnricher;
+import org.apache.brooklyn.core.entity.Entities
+import org.apache.brooklyn.entity.group.BasicGroup
+import org.apache.brooklyn.core.location.SimulatedLocation
+import org.apache.brooklyn.core.sensor.BasicAttributeSensor
+import org.apache.brooklyn.test.TestUtils
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.testng.annotations.AfterMethod
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.Test
+
+import com.google.common.base.Function
+
+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
+
+ AttributeSensor<Integer> intSensor
+ AttributeSensor<Integer> target
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ producer = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ intSensor = new BasicAttributeSensor<Integer>(Integer.class, "int sensor")
+ target = new BasicAttributeSensor<Integer>(Long.class, "target sensor")
+
+ app.start([new SimulatedLocation()])
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() {
+ if (app!=null) Entities.destroyAll(app.getManagementContext());
+ }
+
+ @Test
+ public void testEnrichersWithNoProducers() {
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher([:], intSensor, target, 11, 40)
+ producer.addEnricher(cae)
+ assertEquals cae.getAggregate(), 40
+ }
+
+ @Test
+ public void testSummingEnricherWhenNoSensorValuesYet() {
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(
+ intSensor, target, producers:[producer], 11, 40)
+ producer.addEnricher(cae)
+ assertEquals cae.getAggregate(), 11
+ }
+
+ @Test
+ public void testSingleProducerSum() {
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(
+ intSensor, target, null, null, producers:[producer])
+ producer.addEnricher(cae)
+ assertEquals cae.getAggregate(), null
+ cae.onEvent(intSensor.newEvent(producer, 1))
+ assertEquals cae.getAggregate(), 1
+ }
+
+ @Test
+ public void testSummingEnricherWhenNoAndNullSensorValue() {
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(
+ intSensor, target, null, null, producers:[producer])
+ producer.addEnricher(cae)
+ assertEquals cae.getAggregate(), null
+ cae.onEvent(intSensor.newEvent(producer, null))
+ assertEquals cae.getAggregate(), null
+ }
+
+ @Test
+ public void testSummingEnricherWhenNoAndNullSensorValueExplicitValue() {
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(
+ intSensor, target, 3 /** if null */, 5 /** if none */, producers:[producer])
+ producer.addEnricher(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 = [
+ app.createAndManageChild(EntitySpec.create(TestEntity.class)),
+ app.createAndManageChild(EntitySpec.create(TestEntity.class)),
+ app.createAndManageChild(EntitySpec.create(TestEntity.class))
+ ]
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(
+ intSensor, target, null, null, producers:producers)
+
+ producer.addEnricher(cae)
+ assertEquals cae.getAggregate(), null
+ cae.onEvent(intSensor.newEvent(producers[2], 1))
+ assertEquals cae.getAggregate(), 1
+ cae.onEvent(intSensor.newEvent(producers[0], 3))
+ assertEquals cae.getAggregate(), 4
+ cae.onEvent(intSensor.newEvent(producers[1], 3))
+ assertEquals cae.getAggregate(), 7
+
+ }
+
+ @Test
+ public void testAveragingEnricherWhenNoAndNullSensorValues() {
+ List<TestEntity> producers = [
+ app.createAndManageChild(EntitySpec.create(TestEntity.class))
+ ]
+ CustomAggregatingEnricher<Double> cae = CustomAggregatingEnricher.<Double>newAveragingEnricher(
+ intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), null, null, producers:producers)
+ producer.addEnricher(cae)
+ assertEquals cae.getAggregate(), null
+ cae.onEvent(intSensor.newEvent(producers[0], null))
+ assertEquals cae.getAggregate(), null
+ }
+
+ @Test
+ public void testAveragingEnricherWhenNoAndNullSensorValuesExplicit() {
+ List<TestEntity> producers = [
+ app.createAndManageChild(EntitySpec.create(TestEntity.class))
+ ]
+ CustomAggregatingEnricher<Double> cae = CustomAggregatingEnricher.<Double>newAveragingEnricher(
+ intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), 3 /** if null */, 5 /** if none */,
+ producers:producers)
+ producer.addEnricher(cae)
+
+ assertEquals cae.getAggregate(), 3d
+ cae.onEvent(intSensor.newEvent(producers[0], null))
+ assertEquals cae.getAggregate(), 3d
+ cae.onEvent(intSensor.newEvent(producers[0], 4))
+ assertEquals cae.getAggregate(), 4d
+ }
+
+ @Test
+ public void testAveragingEnricherWhenNoSensors() {
+ List<TestEntity> producers = [
+ ]
+ CustomAggregatingEnricher<Double> cae = CustomAggregatingEnricher.<Double>newAveragingEnricher(
+ intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), 3 /** if null */, 5 /** if none */,
+ producers:producers)
+ producer.addEnricher(cae)
+
+ assertEquals cae.getAggregate(), 5d
+ }
+
+ @Test
+ public void testMultipleProducersAverage() {
+ List<TestEntity> producers = [
+ app.createAndManageChild(EntitySpec.create(TestEntity.class)),
+ app.createAndManageChild(EntitySpec.create(TestEntity.class)),
+ app.createAndManageChild(EntitySpec.create(TestEntity.class))
+ ]
+ CustomAggregatingEnricher<Double> cae = CustomAggregatingEnricher.<Double>newAveragingEnricher(
+ intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), null, null, producers:producers)
+
+ producer.addEnricher(cae)
+
+ assertEquals cae.getAggregate(), null
+ cae.onEvent(intSensor.newEvent(producers[0], 3))
+ assertEquals cae.getAggregate(), 3d
+
+ cae.onEvent(intSensor.newEvent(producers[1], 3))
+ assertEquals cae.getAggregate(), 3d
+
+ cae.onEvent(intSensor.newEvent(producers[2], 6))
+ assertEquals cae.getAggregate(), 4d
+
+ // change p2's value to 7.5, average increase of 0.5.
+ cae.onEvent(intSensor.newEvent(producers[2], 7.5))
+ assertEquals cae.getAggregate(), 4.5d
+ }
+
+ @Test
+ public void testMultipleProducersAverageDefaultingZero() {
+ List<TestEntity> producers = [
+ app.createAndManageChild(EntitySpec.create(TestEntity.class)),
+ app.createAndManageChild(EntitySpec.create(TestEntity.class)),
+ app.createAndManageChild(EntitySpec.create(TestEntity.class))
+ ]
+ CustomAggregatingEnricher<Double> cae = CustomAggregatingEnricher.<Double>newAveragingEnricher(
+ intSensor, new BasicAttributeSensor<Double>(Double.class, "target sensor"), 0, 0, producers:producers)
+
+ producer.addEnricher(cae)
+
+ assertEquals cae.getAggregate(), 0d
+ cae.onEvent(intSensor.newEvent(producers[0], 3))
+ assertEquals cae.getAggregate(), 1d
+
+ cae.onEvent(intSensor.newEvent(producers[1], 3))
+ assertEquals cae.getAggregate(), 2d
+
+ cae.onEvent(intSensor.newEvent(producers[2], 6))
+ assertEquals cae.getAggregate(), 4d
+
+ // change p2's value to 7.5, average increase of 0.5.
+ cae.onEvent(intSensor.newEvent(producers[2], 7.5))
+ 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> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(
+ intSensor, target, null, null, producers:[p1])
+
+ producer.addEnricher(cae)
+ 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> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(intSensor, target, 0, 0, allMembers:true)
+ group.addEnricher(cae)
+
+ assertEquals cae.getAggregate(), 0
+
+ group.addMember(p1)
+ p1.setAttribute(intSensor, 1)
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT_MS) {
+ assertEquals cae.getAggregate(), 1
+ }
+
+ group.addMember(p2)
+ p2.setAttribute(intSensor, 2)
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT_MS) {
+ assertEquals cae.getAggregate(), 3
+ }
+
+ group.removeMember(p2)
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT_MS) {
+ assertEquals cae.getAggregate(), 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.setAttribute(intSensor, 1)
+ Entities.manage(group);
+
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(intSensor, target, null, null, allMembers:true)
+ group.addEnricher(cae)
+
+ assertEquals cae.getAggregate(), 1
+
+ p2.setAttribute(intSensor, 2)
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT_MS) {
+ assertEquals cae.getAggregate(), 3
+ }
+
+ group.removeMember(p2)
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT_MS) {
+ assertEquals cae.getAggregate(), 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.setAttribute(intSensor, 1)
+ p2.setAttribute(intSensor, 2)
+ p3.setAttribute(intSensor, 4)
+
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newSummingEnricher(intSensor, target, null, null, allMembers:true, filter:{it == p1})
+ group.addEnricher(cae)
+
+ assertEquals cae.getAggregate(), 1
+
+ group.addMember(p3)
+ TestUtils.assertSucceedsContinually(timeout:SHORT_WAIT_MS) {
+ assertEquals cae.getAggregate(), 1
+ }
+ }
+
+ @Test
+ public void testCustomAggregatingFunction() {
+ TestEntity p1 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ Function<Collection<Integer>,Integer> aggregator = { Collection c ->
+ int result = 0; c.each { result += it*it }; return result;
+ } as Function
+
+ CustomAggregatingEnricher<Integer> cae = CustomAggregatingEnricher.<Integer>newEnricher(
+ intSensor, target, aggregator, 0, producers:[p1])
+
+ producer.addEnricher(cae)
+ assertEquals cae.getAggregate(), 0
+
+ // Event by producer
+ cae.onEvent(intSensor.newEvent(p1, 2))
+ assertEquals cae.getAggregate(), 4
+ }
+}