package se.l4.vibe.probes; import se.l4.vibe.probes.Sampler.Entry; /** * Probes for detecting changes to the sampled values of a * {@link Sampler time series}. * * @author Andreas Holstenson * */ public class Change { private Change() { } /** * Create a probe that will return the numeric change for the given series. * * @param series * @return */ public static <T extends Number> Probe<Number> forSampler(Sampler<T> series) { return new ChangeProbe<T, T>(series, ValueReaders.<T>same()); } /** * Create a probe that will return the numeric change for the given series. * * @param series * @return */ public static <I, T extends Number> Probe<Number> forSampler(Sampler<I> series, ValueReader<I, T> reader) { return new ChangeProbe<I, T>(series, reader); } /** * Create a probe that will return the change as a fraction for the given * series. * * @param series * @return */ public static <T extends Number> Probe<Double> asFraction(Sampler<T> series) { return new ChangeAsFractionProbe<T, T>(series, ValueReaders.<T>same()); } /** * Create a probe that will return the change as a fraction for the given * series. * * @param series * @return */ public static <I, T extends Number> Probe<Double> asFraction(Sampler<I> series, ValueReader<I, T> reader) { return new ChangeAsFractionProbe<I, T>(series, reader); } private static class ChangeProbe<I, O extends Number> implements Probe<Number> { private double lastValue; private double value; public ChangeProbe(Sampler<I> series, final ValueReader<I, O> reader) { lastValue = Double.NaN; series.addListener(new SampleListener<I>() { @Override public void sampleAcquired(SampledProbe<I> probe, Entry<I> entry) { double current = reader.read(entry.getValue()).doubleValue(); value = current - lastValue; lastValue = current; } }); } @Override public Number read() { return value; } } private static class ChangeAsFractionProbe<I, O extends Number> implements Probe<Double> { private double lastValue; private double value; public ChangeAsFractionProbe(Sampler<I> series, final ValueReader<I, O> reader) { lastValue = Double.NaN; series.addListener(new SampleListener<I>() { @Override public void sampleAcquired(SampledProbe<I> probe, Entry<I> entry) { double current = reader.read(entry.getValue()).doubleValue(); value = current == lastValue ? 0 : (current - lastValue) / lastValue; lastValue = current; } }); } @Override public Double read() { return value; } } }