/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* 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.view.ext;
import com.espertech.esper.client.EventType;
import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext;
import com.espertech.esper.core.service.ExprEvaluatorContextStatement;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.epl.expression.*;
import com.espertech.esper.view.*;
import com.espertech.esper.view.window.RandomAccessByIndexGetter;
import java.util.List;
/**
* Factory for rank window views.
*/
public class RankWindowViewFactory implements DataWindowViewFactory, DataWindowViewWithPrevious
{
private final static String NAME = "Rank view";
private List<ExprNode> viewParameters;
/**
* The unique-by expressions.
*/
protected ExprNode[] uniqueCriteriaExpressions;
/**
* The sort-by expressions.
*/
protected ExprNode[] sortCriteriaExpressions;
/**
* The flags defining the ascending or descending sort order.
*/
protected boolean[] isDescendingValues;
/**
* The sort window size.
*/
protected int sortWindowSize;
private EventType eventType;
public void setViewParameters(ViewFactoryContext viewFactoryContext, List<ExprNode> viewParams) throws ViewParameterException
{
this.viewParameters = viewParams;
}
public void attach(EventType parentEventType, StatementContext statementContext, ViewFactory optionalParentFactory, List<ViewFactory> parentViewFactories) throws ViewParameterException
{
eventType = parentEventType;
String message = NAME + " requires a list of expressions providing unique keys, a numeric size parameter and a list of expressions providing sort keys";
if (viewParameters.size() < 3)
{
throw new ViewParameterException(message);
}
// validate
ExprNode[] validated = ViewFactorySupport.validate(NAME, parentEventType, statementContext, viewParameters, true);
// find size-parameter index
int indexNumericSize = -1;
for (int i = 0; i < validated.length; i++) {
if (validated[i] instanceof ExprConstantNode) {
indexNumericSize = i;
break;
}
}
if (indexNumericSize == -1) {
throw new ViewParameterException("Failed to find constant value for the numeric size parameter");
}
if (indexNumericSize == 0) {
throw new ViewParameterException("Failed to find unique value expressions that are expected to occur before the numeric size parameter");
}
if (indexNumericSize == validated.length - 1) {
throw new ViewParameterException("Failed to find sort key expressions after the numeric size parameter");
}
// validate non-constant for unique-keys and sort-keys
for (int i = 0; i < indexNumericSize; i++)
{
ViewFactorySupport.assertReturnsNonConstant(NAME, validated[i], i);
}
for (int i = indexNumericSize+1; i < validated.length; i++)
{
ViewFactorySupport.assertReturnsNonConstant(NAME, validated[i], i);
}
// get sort size
ExprEvaluatorContextStatement exprEvaluatorContext = new ExprEvaluatorContextStatement(statementContext);
Object sortSize = ViewFactorySupport.evaluateAssertNoProperties(NAME, validated[indexNumericSize], indexNumericSize, exprEvaluatorContext);
if ((sortSize == null) || (!(sortSize instanceof Number)))
{
throw new ViewParameterException(message);
}
sortWindowSize = ((Number) sortSize).intValue();
// compile unique expressions
uniqueCriteriaExpressions = new ExprNode[indexNumericSize];
System.arraycopy(validated, 0, uniqueCriteriaExpressions, 0, indexNumericSize);
// compile sort expressions
sortCriteriaExpressions = new ExprNode[validated.length - indexNumericSize - 1];
isDescendingValues = new boolean[sortCriteriaExpressions.length];
int count = 0;
for (int i = indexNumericSize + 1; i < validated.length; i++)
{
if (validated[i] instanceof ExprOrderedExpr)
{
isDescendingValues[count] = ((ExprOrderedExpr) validated[i]).isDescending();
sortCriteriaExpressions[count] = validated[i].getChildNodes().get(0);
}
else
{
sortCriteriaExpressions[count] = validated[i];
}
count++;
}
}
public View makeView(AgentInstanceViewFactoryChainContext agentInstanceViewFactoryContext)
{
IStreamSortRankRandomAccess rankedRandomAccess = ViewServiceHelper.getOptPreviousExprSortedRankedAccess(agentInstanceViewFactoryContext);
boolean useCollatorSort = false;
if (agentInstanceViewFactoryContext.getAgentInstanceContext().getStatementContext().getConfigSnapshot() != null)
{
useCollatorSort = agentInstanceViewFactoryContext.getAgentInstanceContext().getStatementContext().getConfigSnapshot().getEngineDefaults().getLanguage().isSortUsingCollator();
}
ExprEvaluator[] uniqueEvals = ExprNodeUtility.getEvaluators(uniqueCriteriaExpressions);
ExprEvaluator[] sortEvals = ExprNodeUtility.getEvaluators(sortCriteriaExpressions);
return new RankWindowView(this, uniqueCriteriaExpressions, uniqueEvals, sortCriteriaExpressions, sortEvals, isDescendingValues, sortWindowSize, rankedRandomAccess, useCollatorSort, agentInstanceViewFactoryContext);
}
public Object makePreviousGetter() {
return new RandomAccessByIndexGetter();
}
public EventType getEventType()
{
return eventType;
}
public boolean canReuse(View view)
{
if (!(view instanceof SortWindowView))
{
return false;
}
SortWindowView other = (SortWindowView) view;
if ((other.getSortWindowSize() != sortWindowSize) ||
(!compare(other.getIsDescendingValues(), isDescendingValues)) ||
(!ExprNodeUtility.deepEquals(other.getSortCriteriaExpressions(), sortCriteriaExpressions)) )
{
return false;
}
return other.isEmpty();
}
private boolean compare(boolean[] one, boolean[] two)
{
if (one.length != two.length)
{
return false;
}
for (int i = 0; i < one.length; i++)
{
if (one[i] != two[i])
{
return false;
}
}
return true;
}
}