Source:
<code>private Aggregator[] getAggregators (byte[] data) throws IOException { DataInputStream input = null; try { input = new DataInputStream(new ByteArrayInputStream(data)); int keyLength = WritableUtils.readVInt(input); byte[] keyBytes = new byte[keyLength]; input.readFully(keyBytes, 0, keyLength); ImmutableBytesPtr key = new ImmutableBytesPtr(keyBytes, 0, keyLength); int valueLength = WritableUtils.readVInt(input); byte[] valueBytes = new byte[valueLength]; input.readFully(valueBytes, 0, valueLength); KeyValue keyValue = KeyValueUtil.newKeyValue( key.get(),key.getOffset(), key.getLength(), QueryConstants.SINGLE_COLUMN_FAMILY, QueryConstants.SINGLE_COLUMN, QueryConstants.AGG_TIMESTAMP, valueBytes, 0, valueBytes.length); SingleKeyValueTuple skv = new SingleKeyValueTuple(keyValue); clientAggregators.reset( aggregators ); clientAggregators.aggregate( aggregators, skv ); <START> Aggregator[] sAggs = serverAggregators.newAggregators(); <END> for(int i = 0; i < sAggs.length; i++) { sAggs[i].init( aggregators[i] ); } return sAggs; } finally { Closeables.closeQuietly(input); } }</code><technical_language>I of this more strongly typed is add a SingleAggregateFunction.newServerAggregator(Tuple tuple, ImmutableBytesWritable ptr). ptr a pointer bytes of serialized for aggregator. derived class implement this in a type-safe way, this is class client aggregator server aggregator class. client aggregator instantiated initialized aggregator.aggregate(tuple, ptr) method. newServerAggregator method instantiate correct server aggregator, passing in client aggregator (a new constructor added server aggregator). server aggregator access member variables of client aggregator assign server aggregator initialize (to save deserializing reserializing again, is simple for COUNT, complicated for STDDEV)</technical_language>

Target:
private Aggregator[] getAggregators(byte[] data) throws IOException { DataInputStream input = null; try { input = new DataInputStream(new ByteArrayInputStream(data)); int keyLength = WritableUtils.readVInt(input); byte[] keyBytes = new byte[keyLength]; input.readFully(keyBytes, 0, keyLength); ImmutableBytesPtr ptr = new ImmutableBytesPtr(keyBytes, 0, keyLength); int valueLength = WritableUtils.readVInt(input); byte[] valueBytes = new byte[valueLength]; input.readFully(valueBytes, 0, valueLength); KeyValue keyValue = KeyValueUtil.newKeyValue(ptr.get(), ptr.getOffset(), ptr.getLength(), QueryConstants.SINGLE_COLUMN_FAMILY, QueryConstants.SINGLE_COLUMN, QueryConstants.AGG_TIMESTAMP, valueBytes, 0, valueBytes.length); Tuple result = new SingleKeyValueTuple(keyValue); TupleUtil.getAggregateValue(result, ptr); KeyValueSchema schema = aggregators.getValueSchema(); ValueBitSet tempValueSet = ValueBitSet.newInstance(schema); tempValueSet.clear(); tempValueSet.or(ptr); int i = 0, maxOffset = ptr.getOffset() + ptr.getLength(); SingleAggregateFunction[] funcArray = aggregators.getFunctions(); Aggregator[] sAggs = new Aggregator[funcArray.length]; Boolean hasValue; schema.iterator(ptr); while ((hasValue = schema.next(ptr, i, maxOffset, tempValueSet)) != null) { SingleAggregateFunction func = funcArray[i]; sAggs[i++] = hasValue ? func.newServerAggregator(conf, ptr) : func.newServerAggregator(conf); } return sAggs; } finally { Closeables.closeQuietly(input); } }