001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.functor.aggregator; 018 019import org.apache.commons.functor.BinaryFunction; 020 021/** 022 * An implementation of an aggregator which doesn't store the data series but 023 * instead it processes the data on the fly, as it arrives in 024 * {@link #add(Object)} and stores the result after each addition. It processes 025 * the data by using a {@link BinaryFunction} which takes the result of the 026 * previous {@link #add(Object)} and the data passed in and returns a new result 027 * which gets stored (for using again in the next call to {@link #add(Object)}. 028 * The call to {@link #evaluate()} simply returns this stored value at any 029 * point. This has a lower memory footprint compared to 030 * {@link AbstractListBackedAggregator} however it only allows for simpler 031 * processing on the data received. 032 * 033 * @param <T> 034 * Type of object stored. 035 */ 036public abstract class AbstractNoStoreAggregator<T> extends AbstractTimedAggregator<T> { 037 /** 038 * Function used to aggregate the data on the fly in {@link #add(Object)}. 039 * 040 * @see #add(Object) 041 * @see #AbstractNoStoreAggregator(BinaryFunction) 042 */ 043 private BinaryFunction<T, T, T> aggregationFunction; 044 045 /** 046 * Stores the result of the last {@link #add(Object)} operation. 047 * 048 * @see #add(Object) 049 */ 050 private T result; 051 052 /** 053 * Similar to {@link #AbstractNoStoreAggregator(BinaryFunction, long) 054 * AbstractNoStoreAggregator(aggregationFunction,0L)}. 055 * 056 * @param aggregationFunction 057 * Aggregation function to use in {@link #add(Object)}. Throws 058 * <code>NullPointerException</code> if this is <code>null</code> 059 * @see #add(Object) 060 * @see #aggregationFunction 061 */ 062 public AbstractNoStoreAggregator(BinaryFunction<T, T, T> aggregationFunction) { 063 this(aggregationFunction, 0L); 064 } 065 066 /** 067 * Similar to 068 * {@link #AbstractNoStoreAggregator(BinaryFunction, long,boolean) 069 * AbstractNoStoreAggregator(aggregationFunction,0L,false)}. 070 * 071 * @param aggregationFunction 072 * Aggregation function to use in {@link #add(Object)}. Throws 073 * <code>NullPointerException</code> if this is <code>null</code> 074 * @param interval 075 * interval in miliseconds to reset this aggregator 076 * @see #add(Object) 077 * @see #aggregationFunction 078 */ 079 public AbstractNoStoreAggregator(BinaryFunction<T, T, T> aggregationFunction, long interval) { 080 this(aggregationFunction, interval, false); 081 } 082 083 /** 084 * Constructs an aggregator which will use the given function, reset itself 085 * at the given interval and will use a shared timer on own private timer. 086 * Simply prepares an aggregator which will use the given aggregation 087 * function each time {@link #add(Object)} is called. Also it initializes 088 * {@link #result} with the value returned by {@link #initialValue()}, thus 089 * allowing subclasses to have a custom way of specifying the start value. 090 * 091 * @param aggregationFunction 092 * Aggregation function to use in {@link #add(Object)}. Throws 093 * <code>NullPointerException</code> if this is <code>null</code> 094 * @param interval 095 * interval in miliseconds to reset this aggregator 096 * @param useSharedTimer 097 * if set to true, it will use a shared timer, as per 098 * {@link AbstractTimedAggregator#AbstractTimedAggregator(long, boolean)} 099 * ; otherwise if it's false it will use its own timer instance 100 * @see AbstractTimedAggregator#AbstractTimedAggregator(long, boolean) 101 */ 102 public AbstractNoStoreAggregator(BinaryFunction<T, T, T> aggregationFunction, long interval, 103 boolean useSharedTimer) { 104 super(interval, useSharedTimer); 105 this.aggregationFunction = aggregationFunction; 106 result = initialValue(); 107 } 108 109 /** 110 * Receives data to be aggregated/processed on the fly. This implementation 111 * simply calls {@link #aggregationFunction} and stores the result. 112 * 113 * @param data 114 * Data to aggregate 115 */ 116 @Override 117 protected final void doAdd(T data) { 118 result = aggregationFunction.evaluate(result, data); 119 } 120 121 /** 122 * Returns the value already computed and stored in {@link #result}. 123 * 124 * @return Current (aggregated) value stored in {@link #result} 125 * @see Aggregator#evaluate() 126 */ 127 @Override 128 protected final T doEvaluate() { 129 return result; 130 } 131 132 /** 133 * Resets the {@link #result} member to the {@link #initialValue()}. 134 * 135 * @see #initialValue() 136 */ 137 @Override 138 protected final void doReset() { 139 result = initialValue(); 140 } 141 142 /** 143 * Allows subclasses to define the "initial" value. This value will be 144 * stored in {@link #result} when an instance of this class is created or 145 * when {@link #reset()} is called. 146 * 147 * @return Initial value to be used in {@link #result}. 148 */ 149 protected abstract T initialValue(); 150 151 /** 152 * Getter for {@link #aggregationFunction}. 153 * 154 * @return Current value of the member. 155 */ 156 final BinaryFunction<T, T, T> getAggregationFunction() { 157 return aggregationFunction; 158 } 159 160 /** 161 * Getter for {@link #result}. Provided for test purposes only. 162 * 163 * @return Current value of the aggregated data. 164 */ 165 final T getResult() { 166 return result; 167 } 168 169 /** 170 * Setter for {@link #result}. Provided for test purposes only. 171 * 172 * @param result 173 * New value to store in {@link #result} 174 */ 175 final void setResult(T result) { 176 this.result = result; 177 } 178 179 /** 180 * This aggregator doesn't store any data, so the data series size is always 181 * 0 (zero). 182 * 183 * @return 0 184 */ 185 @Override 186 protected int retrieveDataSize() { 187 return 0; 188 } 189 190 @Override 191 public String toString() { 192 return AbstractNoStoreAggregator.class.getName(); 193 } 194}