package eu.stratosphere.sopremo.expressions;
import eu.stratosphere.sopremo.EvaluationContext;
import eu.stratosphere.sopremo.function.Aggregation;
import eu.stratosphere.sopremo.type.IArrayNode;
import eu.stratosphere.sopremo.type.IJsonNode;
/**
* Returns an aggregate of the elements of a {@link IArrayNode}.
* The result is calculated with help of the specified {@link AggregationExpression}.
*/
public class AggregationExpression extends EvaluationExpression {
/**
*
*/
private static final long serialVersionUID = -1420818869290609780L;
private final Aggregation<IJsonNode, IJsonNode> function;
private CachingExpression<IJsonNode> preprocessing;
private transient IJsonNode aggregator;
/**
* Initializes an AggregationExpression with the given {@link AggregationFunction}.
*
* @param function
* the function which will should be used for aggregation
*/
public AggregationExpression(final Aggregation<?, ?> function) {
this(function, EvaluationExpression.VALUE);
}
/**
* Initializes an AggregationExpression with the given {@link AggregationFunction} and an additional preprocessing.
*
* @param function
* the function which will should be used for aggregation
* @param preprocessing
* an {@link EvaluationExpression} which evaluates each element of the input before they are used for
* aggregation.
*/
@SuppressWarnings("unchecked")
public AggregationExpression(final Aggregation<?, ?> function, final EvaluationExpression preprocessing) {
this.function = (Aggregation<IJsonNode, IJsonNode>) function.clone();
this.preprocessing = CachingExpression.ofSubclass(preprocessing, IJsonNode.class);
}
@Override
public IJsonNode evaluate(final IJsonNode nodes, final IJsonNode target, final EvaluationContext context) {
this.aggregator = this.function.initialize(this.aggregator);
for (final IJsonNode node : (IArrayNode) nodes)
this.aggregator =
this.function.aggregate(this.preprocessing.evaluate(node, context), this.aggregator, context);
return this.function.getFinalAggregate(this.aggregator, target);
}
/*
* (non-Javadoc)
* @see
* eu.stratosphere.sopremo.expressions.EvaluationExpression#transformRecursively(eu.stratosphere.sopremo.expressions
* .TransformFunction)
*/
@SuppressWarnings("unchecked")
@Override
public EvaluationExpression transformRecursively(final TransformFunction function) {
this.preprocessing = (CachingExpression<IJsonNode>) this.preprocessing.transformRecursively(function);
return function.call(this);
}
/**
* Returns the function.
*
* @return the function
*/
public Aggregation<IJsonNode, IJsonNode> getFunction() {
return this.function;
}
/**
* Returns the preprocessing.
*
* @return the preprocessing
*/
public EvaluationExpression getPreprocessing() {
return this.preprocessing.getInnerExpression();
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (this.function == null ? 0 : this.function.hashCode());
result = prime * result + (this.preprocessing == null ? 0 : this.preprocessing.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj))
return false;
final AggregationExpression other = (AggregationExpression) obj;
return this.function.equals(other.function) && this.preprocessing.equals(other.preprocessing);
}
@Override
public void toString(final StringBuilder builder) {
super.toString(builder);
builder.append('.');
this.function.toString(builder);
builder.append('(');
if (this.preprocessing != EvaluationExpression.VALUE)
this.preprocessing.toString(builder);
// builder.append(this.preprocessing);
builder.append(')');
}
}