package se.l4.vibe.probes;
/**
* Methods for scaling probe values. Useful for example when wanting to measure
* data in kilobytes instead of bytes.
*
* @author Andreas Holstenson
*
*/
public class Scale
{
private Scale()
{
}
/**
* Scale a number to a number of significant decimals.
*
* @param probe
* @param decimals
* @return
*/
public static SampledProbe<Double> scale(
SampledProbe<? extends Number> probe,
int decimals)
{
return new ScaledSampledProbe(probe, decimals);
}
/**
* Scale a number to a number of significant decimals.
*
* @param probe
* @param decimals
* @return
*/
public static Probe<Double> scale(
Probe<? extends Number> probe,
int decimals)
{
return new ScaledProbe(probe, decimals);
}
/**
* Create a new sampled probe that will use another probe.
*
* @param probe
* @param divisor
* @return
*/
public static SampledProbe<Double> divide(
SampledProbe<? extends Number> probe,
int divisor)
{
return new DoubleSampledProbe(probe, 1.0 / divisor);
}
/**
* Create a new sampled probe that will use another probe.
*
* @param probe
* @param divisor
* @return
*/
public static SampledProbe<Long> divideAsLong(
SampledProbe<? extends Number> probe,
int divisor)
{
return new LongSampledProbe(probe, 1.0 / divisor);
}
/**
* Create a new sampled probe that will use another probe.
*
* @param probe
* @param divisor
* @return
*/
public static SampledProbe<Double> multiply(
SampledProbe<? extends Number> probe,
int multiplier)
{
return new DoubleSampledProbe(probe, multiplier);
}
/**
* Create a new sampled probe that will use another probe.
*
* @param probe
* @param divisor
* @return
*/
public static SampledProbe<Long> multiplyAsLong(
SampledProbe<? extends Number> probe,
int multiplier)
{
return new LongSampledProbe(probe, 1.0 / multiplier);
}
/**
* Create a new probe that will divide the value of another probe.
*
* @param probe
* @param divisor
* @return
*/
public static Probe<Double> divide(
Probe<? extends Number> probe,
int divisor)
{
return new DoubleProbe(probe, 1.0 / divisor);
}
/**
* Create a new probe that will divide the value of another probe.
*
* @param probe
* @param divisor
* @return
*/
public static Probe<Long> divideAsLong(
Probe<? extends Number> probe,
int divisor)
{
return new LongProbe(probe, 1.0 / divisor);
}
/**
* Create a new probe that will multiply the value of another probe.
*
* @param probe
* @param divisor
* @return
*/
public static Probe<Double> multiply(
Probe<? extends Number> probe,
int multiplier)
{
return new DoubleProbe(probe, multiplier);
}
/**
* Create a new that will multiply the value of another probe.
*
* @param probe
* @param divisor
* @return
*/
public static Probe<Long> multiplyAsLong(
Probe<? extends Number> probe,
int multiplier)
{
return new LongProbe(probe, 1.0 / multiplier);
}
private static class ScaledSampledProbe
implements SampledProbe<Double>
{
private final SampledProbe<? extends Number> probe;
private final int scale;
public ScaledSampledProbe(SampledProbe<? extends Number> probe, int scale)
{
this.probe = probe;
this.scale = scale * 10;
}
private double scale(Number in)
{
return (Math.round(in.doubleValue() * scale)) / (double) scale;
}
@Override
public Double peek()
{
return scale(probe.peek());
}
@Override
public Double read()
{
return scale(probe.read());
}
@Override
public Double sample()
{
return scale(probe.sample());
}
}
private static class ScaledProbe
implements Probe<Double>
{
private final Probe<? extends Number> probe;
private final int scale;
public ScaledProbe(Probe<? extends Number> probe, int scale)
{
this.probe = probe;
this.scale = scale * 10;
}
private double scale(Number in)
{
return (Math.round(in.doubleValue() * scale)) / (double) scale;
}
@Override
public Double read()
{
return scale(probe.read());
}
}
private static class DoubleSampledProbe
implements SampledProbe<Double>
{
private final SampledProbe<? extends Number> probe;
private final double scale;
public DoubleSampledProbe(SampledProbe<? extends Number> probe, double scale)
{
this.probe = probe;
this.scale = scale;
}
@Override
public Double peek()
{
return probe.peek().doubleValue() * scale;
}
@Override
public Double read()
{
return probe.read().doubleValue() * scale;
}
@Override
public Double sample()
{
return probe.sample().doubleValue() * scale;
}
}
private static class LongSampledProbe
implements SampledProbe<Long>
{
private final SampledProbe<? extends Number> probe;
private final double scale;
public LongSampledProbe(SampledProbe<? extends Number> probe, double scale)
{
this.probe = probe;
this.scale = scale;
}
@Override
public Long peek()
{
return (long) (probe.peek().doubleValue() * scale);
}
@Override
public Long read()
{
return (long) (probe.read().doubleValue() * scale);
}
@Override
public Long sample()
{
return (long) (probe.sample().doubleValue() * scale);
}
}
private static class DoubleProbe
implements Probe<Double>
{
private final Probe<? extends Number> probe;
private final double scale;
public DoubleProbe(Probe<? extends Number> probe, double scale)
{
this.probe = probe;
this.scale = scale;
}
@Override
public Double read()
{
return probe.read().doubleValue() * scale;
}
}
private static class LongProbe
implements Probe<Long>
{
private final Probe<? extends Number> probe;
private final double scale;
public LongProbe(Probe<? extends Number> probe, double scale)
{
this.probe = probe;
this.scale = scale;
}
@Override
public Long read()
{
return (long) (probe.read().doubleValue() * scale);
}
}
}