package se.l4.vibe.probes;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
/**
* Range operations for {@link Sampler time series}.
*
* @author Andreas Holstenson
*
*/
public class Range
{
private Range()
{
}
/**
* Return a probe that will always return the minimum value ever measured
* in the given series.
*
* @param series
* @return
*/
public static <T extends Number> Probe<Double> min(Sampler<T> series)
{
return new SeriesMinMax<T>(series, ValueReaders.<T>same(), true);
}
/**
* Return a probe that will always return the minimum value ever measured
* in the given series.
*
* @param series
* @return
*/
public static <T, N extends Number> Probe<Double> min(Sampler<T> series, ValueReader<T, N> reader)
{
return new SeriesMinMax<T>(series, reader, true);
}
/**
* Return a probe that will always return the maximum value ever measured
* in the given series.
*
* @param series
* @return
*/
public static <T, N extends Number> Probe<Double> max(Sampler<T> series, ValueReader<T, N> reader)
{
return new SeriesMinMax<T>(series, reader, false);
}
/**
* Return a probe that will return the minimum value measured over a
* certain period.
*
* @param series
* @return
*/
public static <T extends Number> Probe<Double> minimum(
Sampler<T> series,
long duration,
TimeUnit unit)
{
return SamplerProbes.forSampler(series, duration, unit, new MinOperation<T, T>(ValueReaders.<T>same()));
}
/**
* Return a probe that will return the minimum value measured over a
* certain period.
*
* @param series
* @return
*/
public static <T, N extends Number> Probe<Double> minimum(
Sampler<T> series,
ValueReader<T, N> reader,
long duration,
TimeUnit unit)
{
return SamplerProbes.forSampler(series, duration, unit, new MinOperation<T, N>(reader));
}
/**
* Return a probe that will return the maximum value measured over a
* certain period.
*
* @param series
* @return
*/
public static <T extends Number> Probe<Double> maximum(
Sampler<T> series,
long duration,
TimeUnit unit)
{
return SamplerProbes.forSampler(series, duration, unit, new MaxOperation<T, T>(ValueReaders.<T>same()));
}
/**
* Return a probe that will return the maximum value measured over a
* certain period.
*
* @param series
* @return
*/
public static <T, N extends Number> Probe<Double> maximum(
Sampler<T> series,
ValueReader<T, N> reader,
long duration,
TimeUnit unit)
{
return SamplerProbes.forSampler(series, duration, unit, new MaxOperation<T, N>(reader));
}
/**
* Create a new operation that will calculate the minimum of any time
* series.
*
* @return
*/
public static <T extends Number> SampleOperation<T, Double> newMinimumOperation()
{
return new MinOperation<T, T>(ValueReaders.<T>same());
}
/**
* Create a new operation that will calculate the minimum of any time
* series.
*
* @return
*/
public static <T, N extends Number> SampleOperation<T, Double> newMinimumOperation(ValueReader<T, N> reader)
{
return new MinOperation<T, N>(reader);
}
/**
* Create a new operation that will calculate the minimum of any time
* series.
*
* @return
*/
public static <T extends Number> SampleOperation<T, Double> newMaximumOperation()
{
return new MaxOperation<T, T>(ValueReaders.<T>same());
}
/**
* Create a new operation that will calculate the minimum of any time
* series.
*
* @return
*/
public static <T, N extends Number> SampleOperation<T, Double> newMaximumOperation(ValueReader<T, N> reader)
{
return new MaxOperation<T, N>(reader);
}
private static class MinOperation<I, O extends Number>
implements SampleOperation<I, Double>
{
private final ValueReader<I, O> reader;
private double value;
public MinOperation(ValueReader<I, O> reader)
{
this.reader = reader;
}
@Override
public void add(I value, Collection<Sampler.Entry<I>> entries)
{
double min = Double.MAX_VALUE;
for(Sampler.Entry<I> entry : entries)
{
min = Math.min(min, reader.read(entry.getValue()).doubleValue());
}
this.value = min;
}
@Override
public void remove(I value, Collection<Sampler.Entry<I>> entries)
{
// Do nothing
}
@Override
public Double get()
{
return value;
}
}
private static class MaxOperation<I, T extends Number>
implements SampleOperation<I, Double>
{
private final ValueReader<I, T> reader;
private double value;
public MaxOperation(ValueReader<I, T> reader)
{
this.reader = reader;
}
@Override
public void add(I value, Collection<Sampler.Entry<I>> entries)
{
double max = Double.MIN_VALUE;
for(Sampler.Entry<I> entry : entries)
{
max = Math.max(max, reader.read(entry.getValue()).doubleValue());
}
this.value = max;
}
@Override
public void remove(I value, Collection<Sampler.Entry<I>> entries)
{
// Do nothing
}
@Override
public Double get()
{
return value;
}
}
private static class SeriesMinMax<T>
implements Probe<Double>
{
private double value;
public SeriesMinMax(Sampler<T> series, final ValueReader<T, ? extends Number> reader, final boolean min)
{
value = min ? Double.MAX_VALUE : Double.MIN_NORMAL;
series.addListener(new SampleListener<T>()
{
@Override
public void sampleAcquired(SampledProbe<T> probe, Sampler.Entry<T> entry)
{
double newValue = reader.read(entry.getValue()).doubleValue();
if(min)
{
value = Math.min(newValue, value);
}
else
{
value = Math.max(newValue, value);
}
}
});
}
@Override
public Double read()
{
return value;
}
}
}