/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2012, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.apmrouter.monitor.aggregate; import java.lang.reflect.Array; import java.util.*; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.TimeUnit; /** * <p>Title: AggregateFunction</p> * <p>Description: Defines aggregate functions for aggregating the values of multiple attributes into one return value</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.monitor.aggregate.AggregateFunction</code></p> */ public enum AggregateFunction implements IAggregator { /** Calculates the sum of the returned values */ SUM(new SumAggregator(false)), /** Calculates the sum of the returned values (strict) */ STRSUM(new SumAggregator(true)), /** Returns the number of items in the result set */ COUNT(new CountAggregator(false)), /** Returns the number of items in the result set (strict) */ STRCOUNT(new CountAggregator(true)), /** Returns the average of the returned values */ AVG(new AverageAggregator(false)), /** Returns the average of the returned values (strict) */ STRAVG(new AverageAggregator(true)), /** Returns the minimum value */ MIN(new MinAggregator(false)), /** Returns the minimum value (strict)*/ STRMIN(new MinAggregator(true)), /** Returns the maximum value */ MAX(new MaxAggregator(false)), /** Returns the maximum value (strict)*/ STRMAX(new MaxAggregator(true)), /** Returns the number of distinct items based on {@link Object#equals(Object)} */ DISTINCT(new DistinctAggregator()), /** Returns a json group with each unique item and a count of the occurences */ GROUP(new GroupAggregator()), /** Returns a JSON composite of Min, Max, Average and Count */ MMAC(new MinMaxAvgCntAggregator(false)), /** Returns a JSON composite of Min, Max, Average and Count (strict) */ STRMMAC(new MinMaxAvgCntAggregator(true)), /** Returns the average delta of the sequence of passed items */ DELTA_ALL(new Delta(false)), /** Returns the delta of the most recent 2 of the passed items */ DELTA_LAST(new Delta(true)), /** Returns the average rate per second from the sequence of passed items */ PS_RATE_ALL(new Rate(false, TimeUnit.SECONDS)), /** Returns the rate per second from the most recent 2 of the passed items */ PS_RATE_LAST(new Rate(false, TimeUnit.SECONDS)), /** Returns the average rate per milli-second from the sequence of passed items */ PMS_RATE_ALL(new Rate(false, TimeUnit.MILLISECONDS)), /** Returns the rate per milli-second from the most recent 2 of the passed items */ PMS_RATE_LAST(new Rate(false, TimeUnit.MILLISECONDS)); /** * Creates a new AggregateFunction * @param aggr The entry's aggregator */ private AggregateFunction(IAggregator aggr) { this.aggr = aggr; } /** The enum entry's aggregator implementation */ private final IAggregator aggr; /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Object aggregate(List<Object> items) { return aggr.aggregate(items); } /** * Returns the AggregateFunction for the passed name. Applies trim and toUpper to the name first. * @param name The name of the function * @return the named AggregateFunction */ public static AggregateFunction forName(CharSequence name) { if(name==null) throw new IllegalArgumentException("The passed AggregateFunction name was null", new Throwable()); try { return AggregateFunction.valueOf(name.toString().trim().toUpperCase()); } catch (Exception e) { throw new IllegalArgumentException("The passed AggregateFunction name [" + name + "] is not a valid function name", new Throwable()); } } /** * Retrieves an AggregateFunction by name, returning null for no match * @param name The name of the function to apply * @return the named AggregateFunction or null if one was not found */ public static AggregateFunction getAggregateFunction(CharSequence name) { try { return forName(name); } catch (Exception e) { return null; } } /** * Computes and returns the aggregate for the named aggregator and list of input items * @param name The name of the aggregator function * @param items The list of items to aggregate * @return the aggregate value */ public static Object aggregate(CharSequence name, List<Object> items) { return AggregateFunction.forName(name).aggr.aggregate(items); } /** * Computes and returns the aggregate for the named aggregator and object of nput items. * The object is introspected to determine if it is:<ul> * <li>Null</li> * <li>{@link java.util.Map}</li> * <li>{@link java.util.Collection}</li> * <li>An array</li> * </ul>. * If it is none of the above, a runtime exception is thrown. * If it is a map or an array, it is converted to a list for aggregate computation. * @param name The name of the aggregator function * @param item The object of items to aggregate * @return the aggregate value * TODO: Do we need to support multi dimmensional arrays ? */ @SuppressWarnings("unchecked") public static Object aggregate(CharSequence name, Object item) { final List<Object> items; final AggregateFunction function = AggregateFunction.forName(name); if(item==null) { items = Collections.EMPTY_LIST; } else if(item instanceof Map) { Map<Object, Object> map = (Map<Object, Object>)item; items = new ArrayList<Object>(map.keySet()); } else if(item instanceof Collection) { items = new ArrayList<Object>((Collection<Object>)item); } else if(item.getClass().isArray()) { int length = Array.getLength(item); items = new ArrayList<Object>(length); for(int i = 0; i < length; i++) { items.add(i, Array.get(item, i)); } } else { throw new IllegalArgumentException("Aggregate object of type [" + item.getClass().getName() + "] was not a Map, Collection or Array", new Throwable()); } return function.aggregate(items); } /** * <p>Title: NumericAggregator</p> * <p>Description: Aggregates a numeric computation of all the values that are assumed to be numbers or implement {@link INumberProvider}</p> * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.SumAggregator</code></p> */ public static abstract class NumericAggregator implements IAggregator { /** If true, throws an error if any item is null or not a number */ protected final boolean strict; /** * Creates a new SumAggregator * @param strict If true, throws an error if any item is null or not a number. Otherwise ignores the non number items */ public NumericAggregator(boolean strict) { this.strict = strict; } /** * Sifts through the passed items, looking for exceptions and if non-strict, returns a list of compliant items. * @param items The list of items to sift * @return a list of valid items and instances of {@link INumberProvider}s wrapped as Numbers. */ protected List<Number> sift(List<Object> items) { if(items==null) { if(strict) throw new RuntimeException("List of items was null and aggregator was strict", new Throwable()); } @SuppressWarnings("null") List<Number> numbers = new ArrayList<Number>(items.size()); for(Object o: items) { if(o==null) { if(strict) throw new RuntimeException("List of items had a null and aggregator was strict", new Throwable()); continue; } if(o instanceof Number) { numbers.add((Number)o); continue; } if(o instanceof INumberProvider) { numbers.add(NumberWrapper.getNumber((INumberProvider)o)); continue; } if(strict) throw new RuntimeException("List of items had a non-number item [" + o.getClass().getName() + "] and aggregator was strict", new Throwable()); } return numbers; } /** * Sums an array * @param items The items to sum * @return the total sum */ protected long sum(long[] items) { if(items==null || items.length<1) return 0L; long total = 0; for(long t: items) { total += t; } return total; } /** * Sums an array * @param items The items to sum * @return the total sum */ protected double sum(double[] items) { if(items==null || items.length<1) return 0D; double total = 0; for(double t: items) { total += t; } return total; } } /** * <p>Title: Delta</p> * <p>Description: Computes deltas of the passed numbers</p> * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.Delta</code></p> */ public static class Delta extends NumericAggregator { /** If true, returns the delta of the last two items, otherwise returns the average delta of all entries */ protected final boolean last; /** * Creates a new Delta * @param last If true, returns the delta of the last two items, otherwise returns the average delta of all entries */ public Delta(boolean last) { super(true); this.last = last; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Object aggregate(List<Object> items) { List<Number> numbers = sift(items); if(numbers.size()<2) return 0; if(last) { return numbers.get(0).doubleValue() - numbers.get(1).doubleValue(); } double[] deltas = new double[numbers.size()-1]; for(int i = 0; i < numbers.size()-1; i++) { deltas[i] = numbers.get(i+1).doubleValue() - numbers.get(i).doubleValue(); } return STRAVG.aggregate(deltas); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { if(items.length<2) return 0; if(last) { return items[0] - items[1]; } long[] deltas = new long[items.length-1]; for(int i = 0; i < items.length-1; i++) { deltas[i] = items[i+1] - items[i]; } return STRAVG.aggregate(deltas); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { if(items.length<2) return 0; if(last) { return items[0] - items[1]; } double[] deltas = new double[items.length-1]; for(int i = 0; i < items.length-1; i++) { deltas[i] = items[i+1] - items[i]; } return STRAVG.aggregate(deltas); } } /** * <p>Title: Rate</p> * <p>Description: Computes rate of the passed numbers</p> * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.Rate</code></p> */ public static class Rate extends Delta { /** The time unit for which to report rates */ protected final TimeUnit rateUnit; /** * Creates a new Rate * @param last If true, returns the delta of the last two items, otherwise returns the average delta of all entries * @param rateUnit The time unit for which to report rates */ public Rate(boolean last, TimeUnit rateUnit) { super(last); this.rateUnit = rateUnit; } /** * Calculates a rate from the passed numbers. The time window is passed as the first entry in the list * and is assumed to be in the same unit as this Rate instance and the values are assumed to be ticks per second. * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.AggregateFunction.Delta#aggregate(java.util.List) */ @Override public Object aggregate(List<Object> items) { List<Number> numbers = sift(items); if(numbers.size()<3) return 0; double window = rateUnit.convert(numbers.remove(0).longValue(), TimeUnit.SECONDS); double delta = ((Number)super.aggregate(new ArrayList<Object>(numbers))).doubleValue(); return delta/window; } /** * Calculates a rate from the passed double array. The time window is passed as the first array entry * and is assumed to be in the same unit as this Rate instance and the values are assumed to be ticks per second. * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.AggregateFunction.Delta#aggregate(double[]) */ @Override public double aggregate(double[] items) { if(items.length<3) return 0; double[] anumbers = new double[items.length-1]; System.arraycopy(items, 1, anumbers, 0, items.length-1); double window = TimeUnit.SECONDS.convert((long)items[0], rateUnit); double delta = super.aggregate(anumbers); if(delta<=0 || window<=0) return 0D; return delta/window; } /** * Calculates a rate from the passed long array. The time window is passed as the first array entry * and is assumed to be in the same unit as this Rate instance and the values are assumed to be ticks per second. * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.AggregateFunction.Delta#aggregate(long[]) */ @Override public long aggregate(long[] items) { if(items.length<3) return 0; long[] anumbers = new long[items.length-1]; System.arraycopy(items, 1, anumbers, 0, items.length-1); double window = rateUnit.convert(items[0], TimeUnit.SECONDS); double delta = super.aggregate(anumbers); if(delta<=0 || window<=0) return 0L; return (long)(delta/window); } } /** * <p>Title: SumAggregator</p> * <p>Description: Aggregates the numeric sum of all the values</p> * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.SumAggregator</code></p> */ public static class SumAggregator extends NumericAggregator { /** * Creates a new SumAggregator * @param strict If true, throws an error if any item is null or not a number. Otherwise ignores the non number items */ public SumAggregator(boolean strict) { super(strict); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Double aggregate(List<Object> items) { double d = 0D; for(Number n: sift(items)) { d += n.doubleValue(); } return d; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { return sum(items); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { return sum(items); } } /** * <p>Title: AverageAggregator</p> * <p>Description: Aggregates the mathematical average of all the values</p> * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.AverageAggregator</code></p> */ public static class AverageAggregator extends NumericAggregator { /** * Creates a new AverageAggregator * @param strict If true, throws an error if any item is null or not a number. Otherwise ignores the non number items */ public AverageAggregator(boolean strict) { super(strict); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Double aggregate(List<Object> items) { double total = 0D; double count = 0D; for(Number n: sift(items)) { count++; total += n.doubleValue(); } if(total==0 || count==0) return 0D; return total/count; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { if(items==null) return 0; double total = sum(items); double length = items.length; if(total==0 || length==0) return 0; double avg = total/length; return (long)avg; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { if(items==null) return 0; double total = sum(items); double length = items.length; if(total==0 || length==0) return 0; double avg = total/length; return avg; } } /** * <p>Title: MinAggregator</p> * <p>Description: Computes the lowest numeric value of all the values. If non-strict, returns -1D for an empty list</p> * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.MinAggregator</code></p> */ public static class MinAggregator extends NumericAggregator { /** * Creates a new MinAggregator * @param strict If true, throws an error if any item is null or not a number. Otherwise ignores the non number items */ public MinAggregator(boolean strict) { super(strict); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Double aggregate(List<Object> items) { List<Number> numbers = sift(items); if(numbers.isEmpty()) { if(strict) throw new RuntimeException("List of items for MIN was empty and aggregator was strict", new Throwable()); return -1D; } double min = Double.MAX_VALUE; for(Number n: sift(items)) { if(n.doubleValue() < min) min = n.doubleValue(); } return min; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { if(items==null) return 0; Arrays.sort(items); return items[0]; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { if(items==null) return 0; Arrays.sort(items); return items[0]; } } /** * <p>Title: MaxAggregator</p> * <p>Description: Computes the highest numeric value of all the values. If non-strict, returns -1D for an empty list</p> * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.MaxAggregator</code></p> */ public static class MaxAggregator extends NumericAggregator { /** * Creates a new MaxAggregator * @param strict If true, throws an error if any item is null or not a number. Otherwise ignores the non number items */ public MaxAggregator(boolean strict) { super(strict); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Double aggregate(List<Object> items) { List<Number> numbers = sift(items); if(numbers.isEmpty()) { if(strict) throw new RuntimeException("List of items for MAX was empty and aggregator was strict", new Throwable()); return -1D; } double max = Double.MIN_VALUE; for(Number n: sift(items)) { if(n.doubleValue() > max) max = n.doubleValue(); } return max; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { if(items==null) return 0; Arrays.sort(items); return items[items.length-1]; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { if(items==null) return 0; Arrays.sort(items); return items[items.length-1]; } } /** * <p>Title: CountAggregator</p> * <p>Description: Aggregates the items to a simple count of the number of items. If strict, throws an exception if any item is null, otherwise ignores null items.</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.CountAggregator</code></p> */ public static class CountAggregator implements IAggregator { /** The strict indicator */ private final boolean strict; /** * Creates a new CountAggregator * @param strict If true, implements strict count rules */ public CountAggregator(boolean strict) { this.strict = strict; } /** * Counts the number if items * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Object aggregate(List<Object> items) { if(items==null) { if(strict) { throw new RuntimeException("List of items for Count was null and aggregator was strict", new Throwable()); } return 0; } if(strict) { for(Object o: items) { if(o==null) throw new RuntimeException("List of items for Count contained a null and aggregator was strict", new Throwable()); } } return items.size(); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { return items==null ? 0 : items.length; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { return items==null ? 0 : items.length; } } /** * <p>Title: DistinctAggregator</p> * <p>Description: Aggregates the items to a simple count of the number of distinct items where equality is determined by {@link Object#equals(Object)}. </p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.jzab.agent.commands.impl.aggregate.AggregateFunction.DistinctAggregator</code></p> */ public static class DistinctAggregator implements IAggregator { /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Object aggregate(List<Object> items) { if(items==null || items.isEmpty()) return 0; Set<Object> set = new CopyOnWriteArraySet<Object>(items); return set.size(); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { if(items==null || items.length<1) return 0; Set<Long> set = new HashSet<Long>(items.length); for(int i = 0; i < items.length; i++) { set.add(items[i]); } return set.size(); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { if(items==null || items.length<1) return 0; Set<Double> set = new HashSet<Double>(items.length); for(int i = 0; i < items.length; i++) { set.add(items[i]); } return set.size(); } } /** * <p>Title: GroupAggregator</p> * <p>Description: Aggregates the items to a map with each unique item and a count of the occurences where equality is determined by and items * are represented using {@link Object#toString()}. Null items are ignored.</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.monitor.aggregate.AggregateFunction.GroupAggregator</code></p> */ public static class GroupAggregator implements IAggregator { /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Object aggregate(List<Object> items) { if(items==null || items.isEmpty()) return Collections.emptyMap(); Map<String, Long> map = new HashMap<String, Long>(); for(Object o: items) { if(o==null) continue; String key = o.toString(); Long l = map.get(key); if(l==null) { l = 0L; } l = l++; map.put(key, l); } return map; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { throw new UnsupportedOperationException("The direct aggregate(long[]) cannot return a JSONObject. Please use AggregateFunction.aggreaget(Object)", new Throwable()); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { throw new UnsupportedOperationException("The direct aggregate(double[]) cannot return a JSONObject. Please use AggregateFunction.aggreaget(Object)", new Throwable()); } } /** * <p>Title: MinMaxAvgCntAggregator</p> * <p>Description: Aggregates the passed numberic items to a map representing the min, max, average and count. If non-strict, returns -1D values for a null list and for null items</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.monitor.aggregate.AggregateFunction.MinMaxAvgCntAggregator</code></p> */ public static class MinMaxAvgCntAggregator extends NumericAggregator { /** The MinMaxAvgCnt key for the min value */ public static final String KEY_MIN = "min"; /** The MinMaxAvgCnt key for the max value */ public static final String KEY_MAX = "max"; /** The MinMaxAvgCnt key for the avg value */ public static final String KEY_AVG = "avg"; /** The MinMaxAvgCnt key for the value count */ public static final String KEY_CNT = "cnt"; /** The base response for a non-strict MinMaxAvgCnt with null items */ private static final Map<String, Double> BASE_RESP; static { Map<String, Double> map = new HashMap<String, Double>(4); map.put(KEY_MIN, -1D); map.put(KEY_MAX, -1D); map.put(KEY_AVG, -1D); map.put(KEY_CNT, 0D); BASE_RESP = Collections.unmodifiableMap(map); } /** * Creates a new MaxAggregator * @param strict If true, throws an error if any item is null or not a number. Otherwise ignores the non number items */ public MinMaxAvgCntAggregator(boolean strict) { super(strict); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(java.util.List) */ @Override public Map<String, Double> aggregate(List<Object> items) { List<Number> numbers = sift(items); if(numbers.isEmpty()) { if(strict) throw new RuntimeException("List of items for MinMaxAvgCnt was empty and aggregator was strict", new Throwable()); return BASE_RESP; } double max = Double.MIN_VALUE; double min = Double.MAX_VALUE; double total = 0D; double count = 0D; for(Number n: sift(items)) { Double d = n.doubleValue(); if(d > max) max = d; if(d < min) min = d; total += d; count++; } double avg = (total==0D || count==0D) ? 0D : (total/count); Map<String, Double> map = new HashMap<String, Double>(4); map.put(KEY_MIN, min); map.put(KEY_MAX, max); map.put(KEY_AVG, avg); map.put(KEY_CNT, count); return map; } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { throw new UnsupportedOperationException("The direct aggregate(long[]) cannot return a JSONObject. Please use AggregateFunction.aggreaget(Object)", new Throwable()); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { throw new UnsupportedOperationException("The direct aggregate(double[]) cannot return a JSONObject. Please use AggregateFunction.aggreaget(Object)", new Throwable()); } } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(long[]) */ @Override public long aggregate(long[] items) { return aggr.aggregate(items); } /** * {@inheritDoc} * @see org.helios.apmrouter.monitor.aggregate.IAggregator#aggregate(double[]) */ @Override public double aggregate(double[] items) { return aggr.aggregate(items); } }