package com.tinkerpop.pipes.sideeffect; import com.tinkerpop.pipes.AbstractPipe; import com.tinkerpop.pipes.PipeFunction; import com.tinkerpop.pipes.util.structures.Pair; import java.util.HashMap; import java.util.Map; /** * GroupCountFunctionPipe is analogous to GroupCountPipe save that it takes two optional functions. * The first function is a key function which determines the key to use for each incoming object. * The second function is a value function which determines the value to put into the Map for each key. * * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class GroupCountFunctionPipe<S, K> extends AbstractPipe<S, S> implements SideEffectPipe.GreedySideEffectPipe<S, Map<K, Number>> { private Map<K, Number> countMap; private final PipeFunction<Pair<S, Number>, Number> valueFunction; private final PipeFunction<S, K> keyFunction; public GroupCountFunctionPipe(final Map<K, Number> countMap, final PipeFunction<S, K> keyFunction, final PipeFunction<Pair<S, Number>, Number> valueFunction) { this.countMap = countMap; this.valueFunction = valueFunction; this.keyFunction = keyFunction; } public GroupCountFunctionPipe(final PipeFunction<S, K> keyFunction, final PipeFunction<Pair<S, Number>, Number> valueFunction) { this(new HashMap<K, Number>(), keyFunction, valueFunction); } protected S processNextStart() { final S s = this.starts.next(); final K key = this.getKey(s); this.countMap.put(key, this.getValue(s, key)); return s; } public Map<K, Number> getSideEffect() { return this.countMap; } public void reset() { try { this.countMap = this.countMap.getClass().getConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } super.reset(); } private K getKey(final S start) { if (null == keyFunction) { return (K) start; } else { return keyFunction.compute(start); } } //TODO: Fix java.lang.Number issue. private Number getValue(final S start, final K key) { Number number = this.countMap.get(key); if (null == number) { number = 0l; } if (null == valueFunction) { return 1l + number.longValue(); } else { return this.valueFunction.compute(new Pair<S, Number>(start, number)); } } }