package rocks.inspectit.shared.cs.indexing.aggregation.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import rocks.inspectit.shared.all.communication.DefaultData;
import rocks.inspectit.shared.all.communication.IAggregatedData;
import rocks.inspectit.shared.cs.indexing.aggregation.IAggregator;
/**
* This class encapsulates the aggregation process. When ever aggregation is needed, it this class
* should be used with combination of available {@link IAggregator}s.
*
* @author Ivan Senic
*
* @param <E>
* Type to be aggregated.
*/
public class AggregationPerformer<E extends DefaultData> {
/**
* Map for caching.
*/
private Map<Object, IAggregatedData<E>> aggregationMap;
/**
* {@link IAggregator} used.
*/
private IAggregator<E> aggregator;
/**
* Default constructor.
*
* @param aggregator
* {@link IAggregator} to use. Must not be <code>null</code>.
*/
public AggregationPerformer(IAggregator<E> aggregator) {
if (null == aggregator) {
throw new IllegalArgumentException("Aggregator can not be null.");
}
this.aggregator = aggregator;
this.aggregationMap = new HashMap<>();
}
/**
* Process one element.
*
* @param element
* Element to process.
*/
public void processElement(E element) {
Object key = aggregator.getAggregationKey(element);
IAggregatedData<E> aggregatedObject = aggregationMap.get(key);
if (null != aggregatedObject) {
aggregator.aggregate(aggregatedObject, element);
} else {
aggregatedObject = aggregator.getClone(element);
aggregationMap.put(key, aggregatedObject);
aggregator.aggregate(aggregatedObject, element);
}
}
/**
* Process the collection of elements.
*
* @param collection
* Collection that should be aggregated.
*/
public void processCollection(Collection<E> collection) {
for (E element : collection) {
processElement(element);
}
}
/**
* Process the list of elements starting from the fromIndex (inclusive) to toIndex (exclusive).
*
* @param list
* List of elements.
* @param fromIndex
* Starting index.
* @param toIndex
* Ending index.
*/
public void processList(List<E> list, int fromIndex, int toIndex) {
int size = list.size();
if ((fromIndex < 0) || (fromIndex >= size)) {
throw new IllegalArgumentException("Starting index " + fromIndex + " is not valid for given list of size " + size);
}
if ((toIndex < fromIndex) || (toIndex > size)) {
throw new IllegalArgumentException("Ending index " + toIndex + " is not valid for given list of size " + size + " and starting index " + fromIndex);
}
for (int i = fromIndex; i < toIndex; i++) {
E element = list.get(i);
processElement(element);
}
}
/**
* Returns aggregation results.
*
* @return Returns aggregation results.
*/
public List<E> getResultList() {
List<E> returnList = new ArrayList<>();
for (IAggregatedData<E> aggregatedData : aggregationMap.values()) {
returnList.add(aggregatedData.getData());
}
return returnList;
}
/**
* Resets the current results of the aggregations so that the new clean aggregation can start.
*/
public void reset() {
aggregationMap.clear();
}
}