Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import java.util.List;
+
+import org.apache.commons.functor.UnaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractListBackedAggregator}
+ * which sums up all the numbers in the list.
+ */
+public final class DoubleSumAggregatorFunction implements UnaryFunction<List<Double>, Double> {
+ /**
+ * Does the actual adding and returns the result. Please note that caller is
+ * responsible for synchronizing access to the list.
+ *
+ * @param data
+ * List to traverse and sum
+ * @return arithmetic sum of all the data in the list or null if the list is
+ * empty.
+ */
+ public Double evaluate(List<Double> data) {
+ if (data == null  data.size() == 0) {
+ return null;
+ }
+ double sum = 0.0;
+ for (Double d : data) {
+ sum += d;
+ }
+ return sum;
+ }
+
+ @Override
+ public String toString() {
+ return DoubleSumAggregatorFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import org.apache.commons.functor.BinaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractNoStoreAggregator} which
+ * simply increments the first argument by 1 and returns it. The reason behind
+ * this class is to provide a simple counter implementation: users call
+ * {@link org.apache.commons.functor.aggregator.AbstractNoStoreAggregator#add(Object)}
+ * with some data (which will be ignored) and the class will simply count how
+ * many times this call was made. Such an implementation can be used for
+ * instance to keep track for instance of number of transactions going through a
+ * system, whereas every time a transaction was made we just increment a
+ * counter. This can be achieved still using a
+ * {@link org.apache.commons.functor.aggregator.AbstractNoStoreAggregator} and a
+ * {@link DoubleSumAggregatorBinaryFunction}like function (but using int) and always
+ * supplying the second parameter as 1 (one). However, using this might make the
+ * code clearer.
+ */
+public final class IntegerCountAggregatorBinaryFunction implements BinaryFunction<Integer, Integer, Integer> {
+ /**
+ * Increments <code>left</code> by one and returns it.
+ *
+ * @param left
+ * Value to be incremented by 1 and returned. If
+ * <code>null</code>, <code>null</code> is returned.
+ * @param right
+ * ignored
+ * @return <code>left + 1</code> if <code>left != null</code> otherwise it
+ * returns <code>null</code>.
+ */
+ public Integer evaluate(Integer left, Integer right) {
+ if (left == null) {
+ return null;
+ }
+ return left + 1;
+ }
+
+ @Override
+ public String toString() {
+ return IntegerCountAggregatorBinaryFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorBinaryFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorBinaryFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorBinaryFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorBinaryFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import org.apache.commons.functor.BinaryFunction;
+
+/**
+ * Aggregation function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractNoStoreAggregator} which
+ * finds the maximum of 2 ints.
+ */
+public class IntegerMaxAggregatorBinaryFunction implements BinaryFunction<Integer, Integer, Integer> {
+ /**
+ * Computes the maximum of the 2 given numbers and returns the result.
+ *
+ * @param left
+ * first number to compare. If <code>null</code>, then
+ * <code>right</code> will be returned.
+ * @param right
+ * second number to add. If <code>null</code>, then
+ * <code>left</code> will be returned.
+ * @return max of the 2 integers as described above
+ */
+ public Integer evaluate(Integer left, Integer right) {
+ if (left == null) {
+ return right;
+ }
+ if (right == null) {
+ return left;
+ }
+ if (left.intValue() < right.intValue()) {
+ return right;
+ }
+ return left;
+ }
+
+ @Override
+ public String toString() {
+ return IntegerMaxAggregatorBinaryFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorBinaryFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorBinaryFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorBinaryFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import java.util.List;
+
+import org.apache.commons.functor.UnaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractListBackedAggregator}
+ * which finds the maximum number in a list. It does this by traversing the list
+ * (once)  so the complexity of this will be <i>O(n)</i>.
+ */
+public class IntegerMaxAggregatorFunction implements UnaryFunction<List<Integer>, Integer> {
+ /**
+ * Does the actual traversal of the list and finds the maximum value then
+ * returns the result. Please note that caller is responsible for
+ * synchronizing access to the list.
+ *
+ * @param data
+ * List to traverse and find max
+ * @return max number in the list or null if the list is empty.
+ */
+ public Integer evaluate(List<Integer> data) {
+ if (data == null  data.size() == 0) {
+ return null;
+ }
+ Integer max = null;
+ for (Integer d : data) {
+ if (max == null) {
+ max = d;
+ } else {
+ if (max.intValue() < d.intValue()) {
+ max = d;
+ }
+ }
+ }
+ return max;
+ }
+
+ @Override
+ public String toString() {
+ return IntegerMaxAggregatorFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMaxAggregatorFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMeanValueAggregatorFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMeanValueAggregatorFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMeanValueAggregatorFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMeanValueAggregatorFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import java.util.List;
+
+import org.apache.commons.functor.UnaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractListBackedAggregator}
+ * which computes the arithmetic mean of all the numbers in the list.
+ */
+public final class IntegerMeanValueAggregatorFunction implements UnaryFunction<List<Integer>, Integer> {
+ /**
+ * Does the actual computation and returns the result. Please note that
+ * caller is responsible for synchronizing access to the list.
+ *
+ * @param data
+ * List to traverse and sum
+ * @return arithmetic mean (average) of all the data in the list or null if
+ * the list is empty.
+ */
+ public Integer evaluate(List<Integer> data) {
+ if (data == null  data.size() == 0) {
+ return null;
+ }
+ int mean = 0;
+ int n = data.size();
+ for (Integer d : data) {
+ mean += d.intValue();
+ }
+ mean /= n;
+
+ return mean;
+ }
+
+ @Override
+ public String toString() {
+ return IntegerMeanValueAggregatorFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMeanValueAggregatorFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMeanValueAggregatorFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMeanValueAggregatorFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMedianValueAggregatorFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMedianValueAggregatorFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMedianValueAggregatorFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMedianValueAggregatorFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.functor.UnaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractListBackedAggregator}
+ * which computes the <a href="http://en.wikipedia.org/wiki/Median">median</a>
+ * of all the numbers in the list.
+ */
+public final class IntegerMedianValueAggregatorFunction implements UnaryFunction<List<Integer>, Integer> {
+ /**
+ * Flag to indicate whether we are going to operate on a copy of the list
+ * given or not. In order to compute the median, we need to sort the list
+ * first (and then choose the item in the middle). This function offers 2
+ * ways of doing the sorting:
+ * <ul>
+ * <li>by sorting (modifying) the original list (<code>useCopy=false</code>)
+ * </li>
+ * <li>by operating on a copy of the original list and leaving the original
+ * untouched (<code>useCopy=true</code>)</li>
+ * </ul>
+ * NOTE: While using a copy ensures the original list is untouched, it does
+ * mean we are creating a temporary list for the purpose of this computation
+ * so it will have an impact on memory!
+ */
+ private boolean useCopy;
+
+ /**
+ * By default create a function which will operate on a copy of the original
+ * list ({@link #useCopy} = true).
+ *
+ * @see #useCopy
+ */
+ public IntegerMedianValueAggregatorFunction() {
+ this(true);
+ }
+
+ /**
+ * Constructor which allows the caller to specify whether to operate on the
+ * original list or a copy of it.
+ *
+ * @param useCopy
+ * Set to true to operate on a copy of the list or false to
+ * operate on the original list.
+ * @see #useCopy
+ */
+ public IntegerMedianValueAggregatorFunction(boolean useCopy) {
+ this.useCopy = useCopy;
+ }
+
+ /**
+ * Getter for {@link #useCopy}.
+ *
+ * @return Current value of {@link #useCopy}.
+ * @see #useCopy
+ */
+ public boolean isUseCopy() {
+ return useCopy;
+ }
+
+ /**
+ * Sorts the given list and chooses the median value. The sorting can be
+ * carried out against the original list or a copy of it, based on the value
+ * of {@link #useCopy}.
+ *
+ * @param data
+ * List to compute the median value for
+ * @return the median value of the given list or <code>null</code> if the
+ * list is <code>null</code> or empty.
+ */
+ public Integer evaluate(List<Integer> data) {
+ if (data == null  data.size() == 0) {
+ return null;
+ }
+ // if only one element in it, it is the mean
+ if (data.size() == 1) {
+ return data.get(0);
+ }
+ List<Integer> copy = data;
+ if (useCopy) {
+ copy = new ArrayList<Integer>(data);
+ }
+ Collections.sort(copy);
+ int n = copy.size();
+ int middle = n / 2;
+ if (n % 2 == 0) {
+ // need to compute the mean of middle and middle1 (zero based
+ // index!)
+ return (copy.get(middle) + copy.get(middle  1)) / 2;
+ }
+
+ // we're already positioned on the element in the middle so just return
+ // it
+ return copy.get(middle);
+ }
+
+ @Override
+ public String toString() {
+ return IntegerMedianValueAggregatorFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMedianValueAggregatorFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMedianValueAggregatorFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerMedianValueAggregatorFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerPercentileAggregatorFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerPercentileAggregatorFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerPercentileAggregatorFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerPercentileAggregatorFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.functor.UnaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractListBackedAggregator}
+ * which retrieves the <a
+ * href="http://en.wikipedia.org/wiki/Percentile">percentile</a> value for a
+ * given percentile. The percentile rank/index for a value P can be obtained
+ * using formula: <code>n = round((P / 100) * N + 0.5)</code> where N is the
+ * number of items in a list.
+ */
+public class IntegerPercentileAggregatorFunction implements UnaryFunction<List<Integer>, Integer> {
+ /** A percentile goes from 0 to 100% and that's it. */
+ private static final double MAX_PERCENTAGE = 100.0;
+ /**
+ * Percentile value to calculate. 0 < percentile <= 100
+ */
+ private double percentile;
+
+ /**
+ * Flag to indicate whether we are going to operate on a copy of the list
+ * given or not. In order to compute the percentile, we need to sort the
+ * list first (and then choose the item based on the formula given above).
+ * This function offers 2 ways of doing the sorting:
+ * <ul>
+ * <li>by sorting (modifying) the original list (<code>useCopy=false</code>)
+ * </li>
+ * <li>by operating on a copy of the original list and leaving the original
+ * untouched (<code>useCopy=true</code>)</li>
+ * </ul>
+ * NOTE: While using a copy ensures the original list is untouched, it does
+ * mean we are creating a temporary list for the purpose of this computation
+ * so it will have an impact on memory!
+ */
+ private boolean useCopy;
+
+ /**
+ * Similar to {@link #IntegerPercentileAggregatorFunction(double, boolean)
+ * IntPercentilAggregatorFunction(percentile,true)}.
+ *
+ * @param percentile
+ * Percentile this function will return the value for
+ */
+ public IntegerPercentileAggregatorFunction(double percentile) {
+ this(percentile, true);
+ }
+
+ /**
+ * Initializes the function with the given percentile and decides whether
+ * the function will modify the original list or not.
+ *
+ * @param percentile
+ * Percentile this function will return the value for
+ * @param useCopy
+ * If set to true, the original list will not be modified and
+ * will contain the data in sorted order, if false, this instance
+ * will operate on a copy of the list
+ */
+ public IntegerPercentileAggregatorFunction(double percentile, boolean useCopy) {
+ if (percentile < 0.0  percentile > MAX_PERCENTAGE) {
+ throw new IllegalArgumentException("Invalid value for percentile: " + percentile);
+ }
+ this.percentile = percentile;
+ this.useCopy = useCopy;
+ }
+
+ /**
+ * Used internally to compute the rank of the item in the list for the
+ * requested percentile. This is invoked internally from
+ * {@link #evaluate(List)}.
+ *
+ * @param data
+ * List containing data. This cannot be <code>null</code> (throws
+ * <code>NullPointerException</code>) or empty (throws
+ * <code>ArrayIndexOutOfBoundsException</code>).
+ * @return Index of the item for the requested percentile
+ * @see #getPercentile()
+ */
+ final int computeRank(List<Integer> data) {
+ int maxRank = data.size()  1;
+ int rank = (int) Math.floor((percentile * maxRank) / MAX_PERCENTAGE);
+ return rank;
+ }
+
+ /**
+ * Traverses the list and computes the percentile. In doing so, it sorts the
+ * list first  and might or might not use the original list or a copy
+ * depending on {@link #isUseCopy()}.
+ *
+ * @param data
+ * List to compute the percentile for
+ * @return percentile of the given list or null if list is <code>null</code>
+ * or empty (zero size).
+ */
+ public Integer evaluate(List<Integer> data) {
+ if (data == null  data.size() == 0) {
+ return null;
+ }
+ List<Integer> copy = data;
+ if (useCopy) {
+ copy = new ArrayList<Integer>(data);
+ }
+ Collections.sort(copy);
+ int rank = computeRank(data);
+ return copy.get(rank);
+ }
+
+ /**
+ * Getter for {@link #percentile}.
+ *
+ * @return Retrieves the percentile this instance will return
+ */
+ public double getPercentile() {
+ return percentile;
+ }
+
+ /**
+ * Does this instance modify the passed in list or not?
+ *
+ * @return If true, this instance will sort the list passed in and then use
+ * it to compute the percentile; if false, it will operate on a copy
+ * of the list
+ * @see IntegerPercentileAggregatorFunction#IntegerPercentileAggregatorFunction(double,
+ * boolean)
+ */
+ public boolean isUseCopy() {
+ return useCopy;
+ }
+
+ @Override
+ public String toString() {
+ return IntegerPercentileAggregatorFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerPercentileAggregatorFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerPercentileAggregatorFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerPercentileAggregatorFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorBinaryFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorBinaryFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorBinaryFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorBinaryFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import org.apache.commons.functor.BinaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractNoStoreAggregator} which
+ * sums up the 2 given numbers (hence the "Binary" in the name!). Counterpart of
+ * {@link IntegerSumAggregatorFunction}.
+ */
+public final class IntegerSumAggregatorBinaryFunction implements BinaryFunction<Integer, Integer, Integer> {
+ /**
+ * Adds the 2 numbers together and returns the result.
+ *
+ * @param left
+ * first number to add. If <code>null</code>, then
+ * <code>right</code> will be returned.
+ * @param right
+ * second number to add. If <code>null</code>, then
+ * <code>left</code> will be returned.
+ * @return sum of the 2 int's as described above
+ */
+ public Integer evaluate(Integer left, Integer right) {
+ if (left == null) {
+ return right;
+ }
+ if (right == null) {
+ return left;
+ }
+ return left + right;
+ }
+
+ @Override
+ public String toString() {
+ return IntegerSumAggregatorBinaryFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorBinaryFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorBinaryFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorBinaryFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorFunction.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorFunction.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorFunction.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorFunction.java Thu May 31 14:56:47 2012
@@ 0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.aggregator.functions;
+
+import java.util.List;
+
+import org.apache.commons.functor.UnaryFunction;
+
+/**
+ * Aggregator function to be used with subclasses of
+ * {@link org.apache.commons.functor.aggregator.AbstractListBackedAggregator}
+ * which sums up all the numbers in the list.
+ */
+public final class IntegerSumAggregatorFunction implements UnaryFunction<List<Integer>, Integer> {
+ /**
+ * Does the actual adding and returns the result. Please note that caller is
+ * responsible for synchronizing access to the list.
+ *
+ * @param data
+ * List to traverse and sum
+ * @return arithmetic sum of all the data in the list or null if the list is
+ * empty.
+ */
+ public Integer evaluate(List<Integer> data) {
+ if (data == null  data.size() == 0) {
+ return null;
+ }
+ int sum = 0;
+ for (Integer d : data) {
+ sum += d;
+ }
+ return sum;
+ }
+
+ @Override
+ public String toString() {
+ return IntegerSumAggregatorFunction.class.getName();
+ }
+}
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorFunction.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorFunction.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/IntegerSumAggregatorFunction.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/packageinfo.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/packageinfo.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/packageinfo.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/packageinfo.java Thu May 31 14:56:47 2012
@@ 0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>
+ * This package contains <code>UnaryFunction</code>'s used by aggregators
+ * defined in <code>org.apache.commons.functor.aggregator</code>.
+ * </p>
+ * <p>
+ * These will normally be passed as parameters in constructors to classes
+ * such as {@link org.apache.commons.functor.aggregator.AbstractListBackedAggregator}
+ * to allow for customization of aggregation services.
+ * </p>
+ */
+package org.apache.commons.functor.aggregator.functions;
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/packageinfo.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/packageinfo.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/functions/packageinfo.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/packageinfo.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/packageinfo.java?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/packageinfo.java (added)
+++ commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/packageinfo.java Thu May 31 14:56:47 2012
@@ 0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>
+ * This package contains the interfaces and utilities needed to implement
+ * an aggregation service.
+ * </p>
+ * <p>
+ * Aggregation refers to being able to add data to a data "sink" which
+ * "aggregates" them automatically (e.g. sum them up or average, median etc).
+ * </p>
+ * <p>
+ * An example of an aggregation service is being able to average a series
+ * of <code>int</code> values (perhaps generated from a monitoring component)
+ * and be able to constantly report on the average (or mean) value of
+ * this series. There is no specification about the maximum amount of data that
+ * can be aggregated  some subclasses might impose such restrictions,
+ * if that is the case then that will be specified in their JavaDoc's.
+ * </p>
+ */
+package org.apache.commons.functor.aggregator;
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/packageinfo.java

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/packageinfo.java

svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/functor/trunk/src/main/java/org/apache/commons/functor/aggregator/packageinfo.java

svn:mimetype = text/plain
Added: commons/proper/functor/trunk/src/site/xdoc/aggregate.xml
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/site/xdoc/aggregate.xml?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/site/xdoc/aggregate.xml (added)
+++ commons/proper/functor/trunk/src/site/xdoc/aggregate.xml Thu May 31 14:56:47 2012
@@ 0,0 +1,283 @@
+<?xml version="1.0"?>
+<!
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+>
+<document>
+ <properties>
+ <title>Aggregator</title>
+ <author email="me@liviutudor.com">Aggregator</author>
+ </properties>
+ <body>
+
+ <section name="Overview">
+ <p>
+ The <a href="apidocs/org/apache/commons/functor/aggregate/packagesummary.html">aggregator package</a>
+ provides a component which can be "fed" data from various sources and apply various
+ computations to this data to "aggregate" it. The design allows for a pluggable
+ implementation to be used for the purpose of aggregation and also provides flexibility
+ with regards to storing the data being fed to this component.
+ <br/>
+ There are 2 implementations as far as storage is concerned : <i>nostore</i> and
+ <code>ArrayList</code>backed store. The former should be used when the aggregation
+ formula is simple enough to be applied onthefly without having to traverse a series
+ of data  e.g. summarizing / adding the data (TODO need more explanation).
+ </p>
+ </section>
+
+ <section name="Storage">
+ <p>The <code>ArrayList</code>backed store implementation stores the whole data series in a
+ growing <code>ArrayList</code> such that when data is aggregated one can traverse the
+ series and apply complex formulas (find the <a href="http://en.wikipedia.org/wiki/Median"
+ target="_blank">median</a> of a set of numeric values for instance).
+ </p>
+
+ <p>While the <i>store</i> implementation stores the data in a list, the <i>nostore</i> one
+ stores just a single object  every time data is fed into the <code>Aggregator</code>,
+ the data stored in this object and the data
+ <a href="apidocs/org/apache/commons/functor/aggregate/Aggregator.html#add(T)">passed in</a>
+ are "aggregated" there and then using the supplied formula and the result of this operation
+ is stored back in the object this implementation uses to store data.
+ <br/>
+ This has the implication that unlike the listbacked storage implementation (where the
+ result of aggregating the data is not known until <a href="apidocs/org/apache/commons/functor/aggregate/Aggregator.html#evaluate()">evaluate()</a>
+ is called) with the <i>nostore</i> implementation the result is known (and saved back) at
+ any moment. This arguably makes this class "faster", however this comes at the cost of a
+ slower <a href="apidocs/org/apache/commons/functor/aggregate/Aggregator.html#add(T)">add()</a>
+ operation, as the aggregation formula is applied. Also, let's remind ourselves that not all
+ formulas can be implemented using the <i>nostore</i> implementation (see above).
+ </p>
+ </section>
+
+ <section name="Flushing Data">
+ <p>
+ The data an aggregator handles can be "reset" at any point  in the case of the
+ <i>store</i> implementation this means emptying the <code>ArrayList</code>; in the case
+ of <i>nostore</i> this means setting the "start value" to a "neutral" value  for
+ instance 0 for implementations which involve additions (<code>Y + 0 = Y</code>), 1 for
+ multiplication (<code>Y * 1 = Y</code>) etc. This operation ultimately resets the
+ aggregator to the initial state it was in when created in the first place. This feature
+ allows for a caller to schedule regular resets to free up resources etc.
+ </p>
+ </section>
+
+ <section name="Timers">
+ <p>
+ Retrieving the data and regular intervals then flush/reset the aggregator was an
+ envisaged scenario for the aggregator  so the base class
+ <a href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ offers support to start a timer internally to do that. The class offers a <i>listener</i>
+ mechanism where classes can register to receive <a href="apidocs/org/apache/commons/functor/aggregate/TimedAggregatorListener">timer notifications</a> (if timer support was configured) and after all listeners have been
+ notified the aggregator is <a href="apidocs/org/apache/commons/functor/aggregate/Aggregator.html#reset()">reset</a>.
+ The result of
+ <a href="apidocs/org/apache/commons/functor/aggregate/Aggregator.html#evaluate()">evaluate()</a>
+ (the result of aggregating data) is passed in to the listeners. This allows for an object
+ to simply register itself as a timer listener to the aggregator and only react to the
+ timer notifications (e.g. write the result to a file for offline analysis etc) while the
+ aggregator itself manages all the internals.
+ </p>
+
+ <p>
+ There are 2 ways the
+ <a href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ can be configured with timer support:
+ </p>
+ <ul>
+ <li><b>Using a perinstance timer</b> : by default, when using the
+ <a href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html#AbstractTimedAggregator(long)">1
+ parameter constructor</a> with a value > 0, the aggregator will create a
+ <code>Timer</code> object internally and schedule the regular task of resetting the
+ aggregator under this <code>Timer</code>. While this helps preventing memory leaks
+ (both <code>Aggregator</code> and <code>Timer</code> will be recycled together) it
+ does increase the threading level in the system with each aggregator object created.
+ If your system creates a lot of <code>AbstractTimedAggregator</code> instances with
+ timer support, you might want to consider using the shared timer (see below).</li>
+ <li><b>Using a shared timer</b> : the <a
+ href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ class creates a <a
+ href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html#MAIN_TIMER">static
+ timer instance</a> which can be shared amongst all instances of this class, if using
+ <a
+ href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html#AbstractTimedAggregator(long, boolean)">the
+ constructor with 2 params</a>. When doing so, each such instance will schedule its
+ regular reset task against this timer. While this reduces the memory footprint and
+ threading on the system, it can lead to memory leaks if this is not handled correctly.
+ Therefore please make sure you invoke <a
+ href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html#stop()">stop()</a>
+ on such aggregators when finished working with them.</li>
+ </ul>
+ <p>
+ It is recommended you always invoke <a
+ href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html#stop()">stop()</a>
+ at the end of the lifecycle of an aggregator  regardless of timer support (shared /
+ per instance) or not  in particular calling <code>stop()</code> on an aggregator with
+ no timer support has no effect, however doing so ensures code uniformity and cleanliness.
+ </p>
+ </section>
+
+ <section name="Examples">
+ <p>An example of usage for this component (though not necessarily the only one) could be in
+ a highly transactional system where, for instance, the average transaction time can be an
+ indication of the system health. While a fullyfledged monitoring system can say monitor
+ the system load, file system etc., you might also want your monitoring system to keep an
+ eye on the average transaction time. One way to do so is have an <a
+ href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ which is capturing each transaction execution time and every say 5 seconds it computes
+ the arithmetic mean (average) and writes that to a log file (which then your monitoring
+ system can tail). To do so you would use a piece of code like this:
+ </p>
+
+ <source>
+public class AggregatorTesting implements TimedAggregatorListener<Double> {
+ Aggregator<Double> agg;
+
+ public AggregatorTesting() {
+ AbstractTimedAggregator<Double> aggregator = new ArrayListBackedAggregator<Double>(new DoubleMeanValueAggregatorFunction(),
+ 5000L);
+ aggregator.addTimerListener(this);
+ this.agg = aggregator;
+ }
+
+ @Override
+ public void onTimer(AbstractTimedAggregator<Double> aggregator) {
+ double aggregated = aggregator.evaluate();
+ /* log the value etc. */
+ }
+
+ private void add(double d) {
+ agg.add(d);
+ }
+
+ public static void main(String[] args) {
+ AggregatorTesting t = new AggregatorTesting();
+ /* add data */
+ t.add( 1.0 );
+ t.add( 2.0 );
+ /* .. */
+ }
+}
+ </source>
+
+ <p>Now let's assume that you occasionally see the odd spike in transaction times  which,
+ for the purpose of this example, we'll assume is normal. As such you are not concerned with
+ these spikes, so you want a formula to exclude them. Chances are an arithmetic median
+ would be more appropriate in this case; in which case the code above can suffer just a
+ small change:
+ </p>
+
+ <source>
+ ...
+ AbstractTimedAggregator<Double> aggregator = new ArrayListBackedAggregator<Double>(new DoubleMedianValueAggregatorFunction(),
+ 5000L);
+ ...
+ </source>
+
+ <p>Or maybe you want to be more precise and ensure that lets say 95% of your transactions
+ take less than a certain execution time, so you replace the median formula with a
+ percentile one:
+ </p>
+
+ <source>
+ ...
+ AbstractTimedAggregator<Double> aggregator = new ArrayListBackedAggregator<Double>(new DoublePercentileAggregatorFunction(95),
+ 5000L);
+ ...
+ </source>
+
+ <p>Or maybe your health indicator is the number of transactions going through the system
+ every 5 seconds. In this case you can use a <i>nostore</i> aggregator with a sum formula
+ like this:
+ </p>
+
+ <source>
+public class AggregatorTesting implements TimedAggregatorListener<Double> {
+ Aggregator<Double> agg;
+
+ public AggregatorTesting() {
+ AbstractTimedAggregator<Double> aggregator = new AbstractNoStoreAggregator<Double>(
+ new DoubleSumAggregatorFunction2(), 5000L) {
+ @Override
+ protected Double initialValue() {
+ return 0.0;
+ }
+ };
+ aggregator.addTimerListener(this);
+ this.agg = aggregator;
+ }
+
+ @Override
+ public void onTimer(AbstractTimedAggregator<Double> aggregator) {
+ double aggregated = aggregator.evaluate();
+ /* log the value etc. */
+ }
+
+ private void add(double d) {
+ agg.add(d);
+ }
+
+ public static void main(String[] args) {
+ AggregatorTesting t = new AggregatorTesting();
+ /* add data */
+ t.add(1.0);
+ t.add(2.0);
+ /* .. */
+ }
+}
+ </source>
+
+ <p>(Bear in mind that there is also a <a href="apidocs/org/apache/commons/functor/aggregate/functions/IntCountAggregatorFunction2.html">IntCountAggregatorFunction2</a> too!)
+ </p>
+
+ <p>This has the advantage of a lower memory footprint as well (see above). If your healthcheck
+ indicator is based on the maximum transaction time over a 5 seconds interval, then you simply
+ replace the <a href="apidocs/org/apache/commons/functor/aggregate/AbstractNoStoreAggregator.html#getAggregationFunction()">aggregation function</a> with a max value implementation:
+ </p>
+
+ <source>
+ ...
+ AbstractTimedAggregator<Double> aggregator = new AbstractNoStoreAggregator<Double>(
+ new DoubleMaxAggregatorFunction2(), 5000L) {
+ ...
+ </source>
+
+ <p>Or you can simply roll out your own code  if using the <i>nostore</i> implementation,
+ all you need to do is implement a
+ <a href="apidocs/org/apache/commons/functor/BinaryFunction.html">BinaryFunction</a> and pass
+ it to the <a href="apidocs/org/apache/commons/functor/aggregate/AbstractNoStoreAggregator.html#AbstractNoStoreAggregator(org.apache.commons.functor.BinaryFunction)">Aggregator constructor</a>. This function will receive the alreadystored
+ aggregated value as the first parameter, and data just passed in (via <a
+ href="apidocs/org/apache/commons/functor/aggregate/Aggregator.html#add(T)">add()</a>) as the
+ second parameter; the result of this function will be stored back in the aggregator.
+ <br/>
+ For the listbased aggregators, use an instance of <a href="apidocs/org/apache/commons/functor/aggregate/AbstractListBackedAggregator.html">AbstractListBackedAggregator</a> and pass in an instance of <a href="apidocs/org/apache/commons/functor/UnaryFunction.html">UnaryFunction</a>
+ which accepts a <code>List</code> and returns a single object.
+ <br/>
+ Have a look at the
+ <a href="apidocs/org/apache/commons/functor/aggregate/functions/packagesummary.html">org.apache.commons.functor.aggregate.functions package</a> which includes a set of functions to achieve
+ various of these tasks already.
+ </p>
+
+ <p><b>Note on class naming</b> : You will notice in the <a href="apidocs/org/apache/commons/functor/aggregate/functions/packagesummary.html">org.apache.commons.functor.aggregate.functions package</a> there are functions with similar names  e.g.
+ <a href="apidocs/org/apache/commons/functor/aggregate/functions/DoubleSumAggregatorFunction.html">DoubleSumAggregatorFunction</a> and <a href="apidocs/org/apache/commons/functor/aggregate/functions/DoubleSumAggregatorFunction2.html">DoubleSumAggregatorFunction2</a>. The naming convention is that if the function takes 2
+ parameters (i.e. it is an instance of <a href="apidocs/org/apache/commons/functor/BinaryFunction.html">BinaryFunction</a> then the
+ name of the class in this package will end in <code>2</code>, otherwise, if it is an instance
+ of <a href="apidocs/org/apache/commons/functor/UnaryFunction.html">UnaryFunction</a> then the
+ name will not end in a <code>2</code>.<br/>
+ The reason behind it is that instances of <code>BinaryFunction</code> can be used with
+ <a href="apidocs/org/apache/commons/functor/aggregate/AbstractNoStoreAggregator.html">AbstractNoStoreAggregator</a> whereas the instances of <code>UnaryFunction</code> can be used
+ with <a href="apidocs/org/apache/commons/functor/aggregate/AbstractTimedAggregator.html">AbstractTimedAggregator</a>.
+ </p>
+ </section>
+ </body>
+</document>
Propchange: commons/proper/functor/trunk/src/site/xdoc/aggregate.xml

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/site/xdoc/aggregate.xml

svn:keywords = Date Revision Author HeadURL Id
Propchange: commons/proper/functor/trunk/src/site/xdoc/aggregate.xml

svn:mimetype = text/xml
Added: commons/proper/functor/trunk/src/site/xdoc/aggregator.xml
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/site/xdoc/aggregator.xml?rev=1344757&view=auto
==============================================================================
 commons/proper/functor/trunk/src/site/xdoc/aggregator.xml (added)
+++ commons/proper/functor/trunk/src/site/xdoc/aggregator.xml Thu May 31 14:56:47 2012
@@ 0,0 +1,311 @@
+<?xml version="1.0"?>
+<!
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+>
+<document>
+ <properties>
+ <title>Aggregator</title>
+ <author email="me@liviutudor.com">Aggregator</author>
+ </properties>
+ <body>
+
+ <section name="Overview">
+ <p>
+ The <a href="apidocs/org/apache/commons/functor/aggregator/packagesummary.html">aggregator package</a>
+ provides a component which can be "fed" data from various sources and apply various
+ computations to this data to "aggregate" it. The design allows for a pluggable
+ implementation to be used for the purpose of aggregation and also provides flexibility
+ with regards to storing the data being fed to this component.
+ <br/>
+ There are 2 implementations as far as storage is concerned : <i>nostore</i> and
+ <code>List</code>backed store. The former should be used when the aggregation
+ formula is simple enough to be applied onthefly without having to traverse a series
+ of data  e.g. summarizing / adding the data  while the latter can perform more advanced processing  e.g.
+ statistical calculations: median, average, percentile etc.
+ </p>
+ </section>
+
+ <section name="Storage">
+ <p>The <code>List</code>backed store implementation stores the whole data series in a
+ growing <code>List</code> such that when data is aggregated one can traverse the
+ series and apply complex formulas (find the <a href="http://en.wikipedia.org/wiki/Median"
+ target="_blank">median</a> of a set of numeric values for instance).
+ <br/>
+ The framework allows for any <code>List</code>based implementation to be plugged in, by
+ implementing <a href="apidocs/org/apache/commons/functor/aggregator/AbstractListBackedAggregator.html#createList()">createList()</a>,
+ however, there is also an <code>ArrayList</code>based implementation provided in
+ <a href="apidocs/org/apache/commons/functor/aggregator/ArrayListBackedAggregator.html">ArrayListBackedAggregator</a>
+ which can be used outofthebox.
+ </p>
+
+ <p>While the <i>store</i> implementation stores the data in a list, the <i>nostore</i> one
+ stores just a single object  every time data is fed into the <code>Aggregator</code>,
+ the data stored in this object and the data
+ <a href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html#add(T)">passed in</a>
+ are "aggregated" there and then using the supplied
+ <a href="apidocs/org/apache/commons/functor/BinaryFunction.html">formula</a> and the result of this operation
+ is stored back in the object this implementation uses to store data.
+ <br/>
+ This has the implication that unlike the listbacked storage implementation (where the
+ result of aggregating the data is not known until <a href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html#evaluate()">evaluate()</a>
+ is called), with the <i>nostore</i> implementation the result is known (and saved back) at
+ any moment. This arguably makes this class "faster", however this comes at the cost of a
+ slower <a href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html#add(T)">add()</a>
+ operation, as the aggregation formula is applied. Also, let's remind ourselves that not all
+ formulas can be implemented using the <i>nostore</i> implementation (see above).
+ </p>
+ </section>
+
+ <section name="Flushing Data">
+ <p>
+ The data an aggregator handles can be "reset" at any point  in the case of the
+ <i>store</i> implementation this means emptying the <code>List</code>; in the case
+ of <i>nostore</i> this means setting the "start value" to a "neutral" value  for
+ instance 0 for implementations which involve additions (<code>Y + 0 = Y</code>), 1 for
+ multiplication (<code>Y * 1 = Y</code>) etc. This operation ultimately resets the
+ aggregator to the initial state it was in when created in the first place. This feature
+ allows for a caller to schedule regular resets to free up resources etc.
+ </p>
+ </section>
+
+ <section name="Timers">
+ <p>
+ Retrieving the data and regular intervals then flush/reset the aggregator was an
+ envisaged scenario for the aggregator  so the base class
+ <a href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ offers support to start a timer internally to do that. The class offers a <i>listener</i>
+ mechanism where classes can register to receive <a href="apidocs/org/apache/commons/functor/aggregator/TimedAggregatorListener.html">timer notifications</a> (if timer support was configured) and after all listeners have been
+ notified the aggregator is <a href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html#reset()">reset</a>.
+ The result of
+ <a href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html#evaluate()">evaluate()</a>
+ (the result of aggregating data) is passed in to the listeners. This allows for an object
+ to simply register itself as a timer listener to the aggregator and only react to the
+ timer notifications (e.g. write the result to a file for offline analysis etc) while the
+ aggregator itself manages all the internals.
+ </p>
+
+ <p>
+ When the data is being flushed/reset, a
+ <a href="apidocs/org/apache/commons/functor/aggregator/TimedAggregatorListener.html">TimedAggregatorListener</a>
+ can be registered to receive a notification. The notification is sent <b>after</b> the data is reset.
+ Prior to resetting the data, <a href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html#evaluate()">evaluate()</a>
+ is called, and the result of the evaluation is sent to the listener.<br/>
+ This allows for data aggregated periodically to be processed (e.g. logged, written into a database etc) without
+ worrying about what happens in between.
+ </p>
+
+ <p>
+ There are 2 ways the
+ <a href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ can be configured with timer support:
+ </p>
+ <ul>
+ <li><b>Using a perinstance timer</b> : by default, when using the
+ <a href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html#AbstractTimedAggregator(long)">1
+ parameter constructor</a> with a value > 0, the aggregator will create a
+ <code>Timer</code> object internally and schedule the regular task of resetting the
+ aggregator under this <code>Timer</code>. While this helps preventing memory leaks
+ (both <code>Aggregator</code> and <code>Timer</code> will be recycled together) it
+ does increase the threading level in the system with each aggregator object created.
+ If your system creates a lot of <code>AbstractTimedAggregator</code> instances with
+ timer support, you might want to consider using the shared timer (see below).</li>
+ <li><b>Using a shared timer</b> : the <a
+ href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ class creates a <a
+ href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html#MAIN_TIMER">static
+ timer instance</a> which can be shared amongst all instances of this class, if using
+ <a
+ href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html#AbstractTimedAggregator(long, boolean)">the
+ constructor with 2 params</a>. When doing so, each such instance will schedule its
+ regular reset task against this timer. While this reduces the memory footprint and
+ threading on the system, it can lead to memory leaks if this is not handled correctly.
+ Therefore please make sure you invoke <a
+ href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html#stop()">stop()</a>
+ on such aggregators when finished working with them.</li>
+ </ul>
+ <p>
+ It is recommended you always invoke <a
+ href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html#stop()">stop()</a>
+ at the end of the lifecycle of an aggregator  regardless of timer support (shared /
+ per instance) or not  in particular calling <code>stop()</code> on an aggregator with
+ no timer support has no effect, however doing so ensures code uniformity and cleanliness.
+ </p>
+ </section>
+
+ <section name="Examples">
+ <p>An example of usage for this component (though not necessarily the only one) could be in
+ a highly transactional system where, for instance, the average transaction time can be an
+ indication of the system health. While a fullyfledged monitoring system can say monitor
+ the system load, file system etc., you might also want your monitoring system to keep an
+ eye on the average transaction time. One way to do so is have an <a
+ href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html">AbstractTimedAggregator</a>
+ which is capturing each transaction execution time and every say 5 seconds it computes
+ the arithmetic mean (average) and writes that to a log file (which then your monitoring
+ system can tail). To do so you would use a piece of code like this:
+ </p>
+
+ <source>
+public class AggregatorTesting implements TimedAggregatorListener<Double> {
+ Aggregator<Double> agg;
+
+ public AggregatorTesting() {
+ AbstractTimedAggregator<Double> aggregator = new ArrayListBackedAggregator<Double>(new DoubleMeanValueAggregatorFunction(),
+ 5000L);
+ aggregator.addTimerListener(this);
+ this.agg = aggregator;
+ }
+
+ @Override
+ public void onTimer(AbstractTimedAggregator<Double> aggregator) {
+ double aggregated = aggregator.evaluate();
+ /* log the value etc. */
+ }
+
+ private void add(double d) {
+ agg.add(d);
+ }
+
+ public static void main(String[] args) {
+ AggregatorTesting t = new AggregatorTesting();
+ /* add data */
+ t.add( 1.0 );
+ t.add( 2.0 );
+ /* .. */
+ }
+}
+ </source>
+
+ <p>Now let's assume that you occasionally see the odd spike in transaction times  which,
+ for the purpose of this example, we'll assume is normal. As such you are not concerned with
+ these spikes, so you want a formula to exclude them. Chances are an arithmetic median
+ would be more appropriate in this case; in which case the code above can suffer just a
+ small change:
+ </p>
+
+ <source>
+ ...
+ AbstractTimedAggregator<Double> aggregator = new ArrayListBackedAggregator<Double>(new DoubleMedianValueAggregatorFunction(),
+ 5000L);
+ ...
+ </source>
+
+ <p>Or maybe you want to be more precise and ensure that lets say 95% of your transactions
+ take less than a certain execution time, so you replace the median formula with a
+ percentile one:
+ </p>
+
+ <source>
+ ...
+ AbstractTimedAggregator<Double> aggregator = new ArrayListBackedAggregator<Double>(new DoublePercentileAggregatorFunction(95),
+ 5000L);
+ ...
+ </source>
+
+ <p>Or maybe your health indicator is the number of transactions going through the system
+ every 5 seconds. In this case you can use a <i>nostore</i> aggregator with a sum formula
+ like this:
+ </p>
+
+ <source>
+public class AggregatorTesting implements TimedAggregatorListener<Double> {
+ Aggregator<Double> agg;
+
+ public AggregatorTesting() {
+ AbstractTimedAggregator<Double> aggregator = new AbstractNoStoreAggregator<Double>(
+ new DoubleSumAggregatorBinaryFunction(), 5000L) {
+ @Override
+ protected Double initialValue() {
+ return 0.0;
+ }
+ };
+ aggregator.addTimerListener(this);
+ this.agg = aggregator;
+ }
+
+ @Override
+ public void onTimer(AbstractTimedAggregator<Double> aggregator) {
+ double aggregated = aggregator.evaluate();
+ /* log the value etc. */
+ }
+
+ private void add(double d) {
+ agg.add(d);
+ }
+
+ public static void main(String[] args) {
+ AggregatorTesting t = new AggregatorTesting();
+ /* add data */
+ t.add(1.0);
+ t.add(2.0);
+ /* .. */
+ }
+}
+ </source>
+
+ <p>(Bear in mind that there is also a
+ <a href="apidocs/org/apache/commons/functor/aggregator/functions/IntegerCountAggregatorBinaryFunction.html">IntegerCountAggregatorBinaryFunction</a> too!)
+ </p>
+
+ <p>This has the advantage of a lower memory footprint as well (see above). If your healthcheck
+ indicator is based on the maximum transaction time over a 5 seconds interval, then you simply
+ replace the <a href="apidocs/org/apache/commons/functor/aggregator/AbstractNoStoreAggregator.html#getAggregationFunction()">aggregation
+ function</a> with a max value implementation:
+ </p>
+
+ <source>
+ ...
+ AbstractTimedAggregator<Double> aggregator = new AbstractNoStoreAggregator<Double>(
+ new DoubleMaxAggregatorBinaryFunction(), 5000L) {
+ ...
+ </source>
+
+ <p>Or you can simply roll out your own code  if using the <i>nostore</i> implementation,
+ all you need to do is implement a
+ <a href="apidocs/org/apache/commons/functor/BinaryFunction.html">BinaryFunction</a> and pass
+ it to the <a href="apidocs/org/apache/commons/functor/aggregator/AbstractNoStoreAggregator.html#AbstractNoStoreAggregator(org.apache.commons.functor.BinaryFunction)">Aggregator
+ constructor</a>. This function will receive the alreadystored
+ aggregated value as the first parameter, and data just passed in (via <a
+ href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html#add(T)">add()</a>) as the
+ second parameter; the result of this function will be stored back in the aggregator.
+ <br/>
+ For the listbased aggregators, use an instance of
+ <a href="apidocs/org/apache/commons/functor/aggregator/AbstractListBackedAggregator.html">AbstractListBackedAggregator</a>
+ and pass in an instance of <a href="apidocs/org/apache/commons/functor/UnaryFunction.html">UnaryFunction</a>
+ which accepts a <code>List</code> and returns a single object.
+ <br/>
+ Have a look at the
+ <a href="apidocs/org/apache/commons/functor/aggregator/functions/packagesummary.html">org.apache.commons.functor.aggregator.functions
+ package</a> which includes a set of functions to achieve various of these tasks already.
+ </p>
+
+ <p><b>Note on class naming</b> : You will notice in the
+ <a href="apidocs/org/apache/commons/functor/aggregator/functions/packagesummary.html">org.apache.commons.functor.aggregator.functions
+ package</a> there are functions with similar names  e.g.
+ <a href="apidocs/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorFunction.html">DoubleSumAggregatorFunction</a>
+ and <a href="apidocs/org/apache/commons/functor/aggregator/functions/DoubleSumAggregatorBinaryFunction.html">DoubleSumAggregatorBinaryFunction</a>.
+ The naming convention is that if the function takes 2
+ parameters (i.e. it is an instance of <a href="apidocs/org/apache/commons/functor/BinaryFunction.html">BinaryFunction</a> then the
+ name of the class in this package will contain <code>BinaryFunction</code>, otherwise, if it is an instance
+ of <a href="apidocs/org/apache/commons/functor/UnaryFunction.html">UnaryFunction</a> then the
+ name will only contain <code>Function</code>.<br/>
+ The reason behind it is that instances of <code>BinaryFunction</code> can be used with
+ <a href="apidocs/org/apache/commons/functor/aggregator/AbstractNoStoreAggregator.html">AbstractNoStoreAggregator</a>
+ whereas the instances of <code>UnaryFunction</code> can be used
+ with <a href="apidocs/org/apache/commons/functor/aggregator/AbstractTimedAggregator.html">AbstractTimedAggregator</a>.
+ </p>
+ </section>
+ </body>
+</document>
Propchange: commons/proper/functor/trunk/src/site/xdoc/aggregator.xml

svn:eolstyle = native
Propchange: commons/proper/functor/trunk/src/site/xdoc/aggregator.xml

svn:keywords = Date Revision Author HeadURL Id
Propchange: commons/proper/functor/trunk/src/site/xdoc/aggregator.xml

svn:mimetype = text/xml
Modified: commons/proper/functor/trunk/src/site/xdoc/examples.xml
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/site/xdoc/examples.xml?rev=1344757&r1=1344756&r2=1344757&view=diff
==============================================================================
 commons/proper/functor/trunk/src/site/xdoc/examples.xml (original)
+++ commons/proper/functor/trunk/src/site/xdoc/examples.xml Thu May 31 14:56:47 2012
@@ 20,6 +20,7 @@
<title>Examples</title>
<author email="dev@commons.apache.org">Apache Commons Development Team</author>
<author email="rwaldhoff@apache.org">Rodney Waldhoff</author>
+ <author email="me@liviutudor.com">Liviu Tudor</author>
</properties>
<body>
@@ 115,7 +116,27 @@
The <a href="http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/test/java/org/apache/commons/functor/example/lines/">lines</a>
package demonstrates a functional approach to IO using Generators and the Algorithms class.
</p>
 </subsection>
+ </subsection>
+
+ <subsection name="Aggregators">
+ <p>
+ There are some code snippets / examples for the <code>org.apache.commons.functor.aggregator</code> package
+ available on <a href="aggregator.html">this page</a>. Also, to exemplify the usage of the <code>Aggregator</code>
+ classes, there are code examples in the test section.
+ <br/>
+ First such set of example involves the usage of the <i>nostore</i> <code>Aggregator</code>. Code can be found in
+ <a href="http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/test/java/org/apache/commons/functor/example/aggregator/nostore/">org.apache.commons.functor.example.aggregator.nostore</a>.
+ This shows how can you use an aggregator which doesn't store the data series and processes them on the fly.
+ Also, there are examples provided which show how can you implement your own aggregation function
+ to be used with this <code>Aggregator</code> type.
+ <br/>
+ For using an <code>Aggregator</code> which stores the data series in a list, examples are in
+ <a href="http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/test/java/org/apache/commons/functor/example/aggregator/list/">org.apache.commons.functor.example.aggregator.list</a>.
+ This shows how can you use the <code>ArrayList</code>backed aggregator or provide your own <code>List</code>based implementation.
+ Also, there are examples provided which show how can you implement your own aggregation function
+ to be used with this <code>Aggregator</code> type.
+ </p>
+ </subsection>
<subsection name="Reuse Through Composition">
<p>
