/* (c) 2014 LinkedIn Corp. All rights reserved.
*
* Licensed 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/LICENSE-2.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.
*/
package com.linkedin.cubert.operator.cube;
import com.linkedin.cubert.memory.LongArrayList;
/**
* Builtin default implementation of a {@link DupleCubeAggregator} that aggregates input
* columns using inner and outer {@link ValueAggregator}.
* <p>
* Implementation notes: this object creates an extra copy of long[] array (in addition to
* the one created by the superclass {@link DefaultCubeAggregator}) for aggregating values
* for inner dimension.
*
* @see DefaultCubeAggregator
* @author Maneesh Varshney
*
*/
public final class DefaultDupleCubeAggregator extends DefaultCubeAggregator implements
DupleCubeAggregator
{
// ValueAggregator for aggregating across inner dimension
private final ValueAggregator innerAgg;
// array for storing aggregated values across inner dimension
private final LongArrayList innerValueTable;
public DefaultDupleCubeAggregator(ValueAggregator outerAgg, ValueAggregator innerAgg)
{
super(outerAgg);
this.innerAgg = innerAgg;
innerValueTable = new LongArrayList();
innerValueTable.setDefaultValue(innerAgg.initialValue());
}
@Override
public void allocate(int size)
{
super.allocate(size);
// allocate and initialize the inner aggregation table
innerValueTable.ensureCapacity(size);
}
@Override
public void clear()
{
super.clear();
innerValueTable.reset();
}
@Override
public void innerAggregate(int index)
{
if (currentValue == null)
return;
innerValueTable.ensureCapacity(index);
final long previousValue = innerValueTable.getLong(index);
innerValueTable.updateLong(index, innerAgg.aggregate(previousValue, currentValue));
}
@Override
public void aggregate(int index)
{
// obtain the inner aggregate value
Object innerVal = innerAgg.output(innerValueTable.getLong(index));
// reset it to initial value again
innerValueTable.updateLong(index, innerAgg.initialValue());
if (innerVal == null)
return;
// aggregate the "outer" aggregation table
valueTable.updateLong(index, aggregator.aggregate(valueTable.getLong(index), innerVal));
}
}