/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.epl.agg.service;
import com.espertech.esper.client.annotation.Hint;
import com.espertech.esper.client.annotation.HintEnum;
import com.espertech.esper.core.context.util.AgentInstanceContext;
import com.espertech.esper.epl.agg.access.AggregationAccessorSlotPair;
import com.espertech.esper.epl.core.EngineImportService;
import com.espertech.esper.epl.expression.core.ExprEvaluator;
import com.espertech.esper.epl.expression.core.ExprValidationException;
import com.espertech.esper.epl.variable.VariableMetaData;
import com.espertech.esper.epl.variable.VariableReader;
import com.espertech.esper.epl.variable.VariableService;
import com.espertech.esper.epl.variable.VariableServiceUtil;
import com.espertech.esper.type.DoubleValue;
import com.espertech.esper.util.JavaClassHelper;
/**
* Implementation for handling aggregation with grouping by group-keys.
*/
public class AggSvcGroupByReclaimAgedFactory extends AggregationServiceFactoryBase {
protected final AggregationAccessorSlotPair[] accessors;
protected final AggregationStateFactory[] accessAggregations;
protected final boolean isJoin;
protected final AggSvcGroupByReclaimAgedEvalFuncFactory evaluationFunctionMaxAge;
protected final AggSvcGroupByReclaimAgedEvalFuncFactory evaluationFunctionFrequency;
/**
* Ctor.
*
* @param evaluators - evaluate the sub-expression within the aggregate function (ie. sum(4*myNum))
* @param prototypes - collect the aggregation state that evaluators evaluate to, act as prototypes for new aggregations
* aggregation states for each group
* @param reclaimGroupAged hint to reclaim
* @param reclaimGroupFrequency hint to reclaim
* @param variableService variables
* @param accessors accessor definitions
* @param accessAggregations access aggs
* @param isJoin true for join, false for single-stream
* @param optionalContextName context name
* @throws com.espertech.esper.epl.expression.core.ExprValidationException when validation fails
*/
public AggSvcGroupByReclaimAgedFactory(ExprEvaluator[] evaluators,
AggregationMethodFactory[] prototypes,
Hint reclaimGroupAged,
Hint reclaimGroupFrequency,
final VariableService variableService,
AggregationAccessorSlotPair[] accessors,
AggregationStateFactory[] accessAggregations,
boolean isJoin,
String optionalContextName)
throws ExprValidationException {
super(evaluators, prototypes);
this.accessors = accessors;
this.accessAggregations = accessAggregations;
this.isJoin = isJoin;
String hintValueMaxAge = HintEnum.RECLAIM_GROUP_AGED.getHintAssignedValue(reclaimGroupAged);
if (hintValueMaxAge == null) {
throw new ExprValidationException("Required hint value for hint '" + HintEnum.RECLAIM_GROUP_AGED + "' has not been provided");
}
evaluationFunctionMaxAge = getEvaluationFunction(variableService, hintValueMaxAge, optionalContextName);
String hintValueFrequency = HintEnum.RECLAIM_GROUP_FREQ.getHintAssignedValue(reclaimGroupAged);
if ((reclaimGroupFrequency == null) || (hintValueFrequency == null)) {
evaluationFunctionFrequency = evaluationFunctionMaxAge;
} else {
evaluationFunctionFrequency = getEvaluationFunction(variableService, hintValueFrequency, optionalContextName);
}
}
public AggregationService makeService(AgentInstanceContext agentInstanceContext, EngineImportService engineImportService, boolean isSubquery, Integer subqueryNumber) {
AggSvcGroupByReclaimAgedEvalFunc max = evaluationFunctionMaxAge.make(agentInstanceContext);
AggSvcGroupByReclaimAgedEvalFunc freq = evaluationFunctionFrequency.make(agentInstanceContext);
return new AggSvcGroupByReclaimAgedImpl(evaluators, aggregators, accessors, accessAggregations, isJoin, max, freq, agentInstanceContext.getStatementContext().getTimeAbacus());
}
private AggSvcGroupByReclaimAgedEvalFuncFactory getEvaluationFunction(final VariableService variableService, String hintValue, String optionalContextName)
throws ExprValidationException {
final VariableMetaData variableMetaData = variableService.getVariableMetaData(hintValue);
if (variableMetaData != null) {
if (!JavaClassHelper.isNumeric(variableMetaData.getType())) {
throw new ExprValidationException("Variable type of variable '" + variableMetaData.getVariableName() + "' is not numeric");
}
String message = VariableServiceUtil.checkVariableContextName(optionalContextName, variableMetaData);
if (message != null) {
throw new ExprValidationException(message);
}
return new AggSvcGroupByReclaimAgedEvalFuncFactory() {
public AggSvcGroupByReclaimAgedEvalFunc make(AgentInstanceContext agentInstanceContext) {
VariableReader reader = variableService.getReader(variableMetaData.getVariableName(), agentInstanceContext.getAgentInstanceId());
return new AggSvcGroupByReclaimAgedEvalFuncVariable(reader);
}
};
} else {
final Double valueDouble;
try {
valueDouble = DoubleValue.parseString(hintValue);
} catch (RuntimeException ex) {
throw new ExprValidationException("Failed to parse hint parameter value '" + hintValue + "' as a double-typed seconds value or variable name");
}
if (valueDouble <= 0) {
throw new ExprValidationException("Hint parameter value '" + hintValue + "' is an invalid value, expecting a double-typed seconds value or variable name");
}
return new AggSvcGroupByReclaimAgedEvalFuncFactory() {
public AggSvcGroupByReclaimAgedEvalFunc make(AgentInstanceContext agentInstanceContext) {
return new AggSvcGroupByReclaimAgedEvalFuncConstant(valueDouble);
}
};
}
}
}