brooklyn.enricher.CustomAggregatingEnricher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of brooklyn-core Show documentation
Show all versions of brooklyn-core Show documentation
Entity implementation classes, events, and other core elements
package brooklyn.enricher;
import groovy.lang.Closure;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.enricher.basic.AbstractAggregatingEnricher;
import brooklyn.event.AttributeSensor;
import brooklyn.event.SensorEventListener;
import brooklyn.util.GroovyJavaMethods;
import brooklyn.util.flags.TypeCoercions;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
/**
* 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
*/
public class CustomAggregatingEnricher extends AbstractAggregatingEnricher implements SensorEventListener {
private static final Logger LOG = LoggerFactory.getLogger(CustomAggregatingEnricher.class);
protected final Function, 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 or Closure, indicating which entities to include
*
* @param flags
* @param source
* @param target
* @param aggregator Aggregates a collection of values, to return a single value for the target sensor
* @param defaultValue Default value to populate the collection given to aggregator, defaults to null
*/
public CustomAggregatingEnricher(Map flags, AttributeSensor extends S> source, AttributeSensor target,
Function, T> aggregator, S defaultValue) {
super(flags, source, target, defaultValue);
this.aggregator = aggregator;
}
public CustomAggregatingEnricher(Map flags, AttributeSensor extends S> source, AttributeSensor target,
Function, T> aggregator) {
this(flags, source, target, aggregator, null);
}
public CustomAggregatingEnricher(AttributeSensor extends S> source, AttributeSensor target,
Function, T> aggregator, S defaultValue) {
this(Collections.emptyMap(), source, target, aggregator, defaultValue);
}
public CustomAggregatingEnricher(AttributeSensor extends S> source, AttributeSensor target,
Function, T> aggregator) {
this(Collections.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 defaultValue
*
* @see #CustomAggregatingEnricher(Map, AttributeSensor, AttributeSensor, Function, Object)
*/
@SuppressWarnings("unchecked")
public CustomAggregatingEnricher(Map flags, AttributeSensor extends S> source, AttributeSensor target,
Closure> aggregator, S defaultValue) {
this(flags, source, target, GroovyJavaMethods., T>functionFromClosure((Closure)aggregator), defaultValue);
}
public CustomAggregatingEnricher(Map flags, AttributeSensor extends S> source, AttributeSensor target, Closure> aggregator) {
this(flags, source, target, aggregator, null);
}
public CustomAggregatingEnricher(AttributeSensor source, AttributeSensor target, Closure> aggregator, S defaultValue) {
this(Collections.emptyMap(), source, target, aggregator, defaultValue);
}
public CustomAggregatingEnricher(AttributeSensor source, AttributeSensor target, Closure> aggregator) {
this(Collections.emptyMap(), source, target, aggregator, null);
}
@Override
public void onUpdated() {
try {
entity.setAttribute(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 (T) aggregator.apply(values.values());
}
}
// FIXME Clean up explosion of overloading, caused by groovy-equivalent default vals...
public static CustomAggregatingEnricher newEnricher(
Map flags, AttributeSensor source, AttributeSensor target, Closure> aggregator, S defaultVal) {
return new CustomAggregatingEnricher(flags, source, target, aggregator, defaultVal);
}
public static CustomAggregatingEnricher newEnricher(
Map flags, AttributeSensor source, AttributeSensor target, Closure> aggregator) {
return newEnricher(flags, source, target, aggregator, null);
}
public static CustomAggregatingEnricher newEnricher(
AttributeSensor source, AttributeSensor target, Closure> aggregator, S defaultVal) {
return newEnricher(Collections.emptyMap(), source, target, aggregator, defaultVal);
}
public static CustomAggregatingEnricher newEnricher(
AttributeSensor source, AttributeSensor target, Closure> aggregator) {
return newEnricher(Collections.emptyMap(), source, target, aggregator, null);
}
// FIXME Clean up explosion of overloading, caused by groovy-equivalent default vals...
public static CustomAggregatingEnricher newEnricher(
Map flags, AttributeSensor source, AttributeSensor target, Function, T> aggregator, S defaultVal) {
return new CustomAggregatingEnricher(flags, source, target, aggregator, defaultVal);
}
public static CustomAggregatingEnricher newEnricher(
Map flags, AttributeSensor source, AttributeSensor target, Function, T> aggregator) {
return newEnricher(flags, source, target, aggregator, null);
}
public static CustomAggregatingEnricher newEnricher(
AttributeSensor source, AttributeSensor target, Function, T> aggregator, S defaultVal) {
return newEnricher(Collections.emptyMap(), source, target, aggregator, defaultVal);
}
public static CustomAggregatingEnricher newEnricher(
AttributeSensor source, AttributeSensor target, Function, T> aggregator) {
return newEnricher(Collections.emptyMap(), source, target, aggregator, null);
}
public static CustomAggregatingEnricher newSummingEnricher(
Map flags, AttributeSensor source, final AttributeSensor target) {
Function, T> aggregator = new Function, T>() {
@Override public T apply(Collection vals) {
Object result = (vals == null || vals.isEmpty()) ? 0 : sum(vals);
return TypeCoercions.castPrimitive(result, (Class)target.getType());
}
};
return new CustomAggregatingEnricher(flags, source, target, aggregator);
}
public static CustomAggregatingEnricher newSummingEnricher(
AttributeSensor source, AttributeSensor target) {
return newSummingEnricher(Collections.emptyMap(), source, target);
}
// TODO semantics of ZERO default seem very odd for an average (okay for summing)
/** creates an enricher which averages over all children/members,
* counting ZERO for sensors which have not yet published anything;
* to have those sensors excluded, pass null as an additional argument (defaultValue)
*/
// this function can't strictly return like the others because
// we have to supply a 0 of instance of N
public static CustomAggregatingEnricher newAveragingEnricher(
Map flags, AttributeSensor extends Number> source, AttributeSensor target) {
return newAveragingEnricher(flags, source, target, 0);
}
/** defaultValue of null means that the sensor is excluded */
public static CustomAggregatingEnricher newAveragingEnricher(
Map flags, AttributeSensor extends N> source, AttributeSensor target,
N defaultValue) {
Function, Double> aggregator = new Function, Double>() {
@Override public Double apply(Collection vals) {
int count = count(vals);
return (count==0) ? 0d : ((Double) sum(vals) / count);
}
};
return new CustomAggregatingEnricher(flags, source, target, aggregator, defaultValue);
}
/** averages the given source sensor over all children/members, storing in target */
public static CustomAggregatingEnricher newAveragingEnricher(
AttributeSensor source, AttributeSensor target) {
return newAveragingEnricher(Collections.emptyMap(), source, target);
}
private static double sum(Iterable vals) {
double result = 0d;
if (vals!=null) for (Number val : vals) if (val!=null) result += val.doubleValue();
return result;
}
private static int count(Iterable extends Object> vals) {
int result = 0;
if (vals!=null) for (Object val : vals) if (val!=null) result++;
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy