/* *************************************************************************************** * 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.expression.core; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventPropertyGetter; import com.espertech.esper.client.EventType; import com.espertech.esper.core.start.EPStatementStartMethod; import com.espertech.esper.epl.core.DuplicatePropertyException; import com.espertech.esper.epl.core.PropertyNotFoundException; import com.espertech.esper.epl.variable.VariableMetaData; import com.espertech.esper.epl.variable.VariableReader; import com.espertech.esper.event.EventTypeSPI; import com.espertech.esper.metrics.instrumentation.InstrumentationHelper; import java.io.StringWriter; import java.util.Map; /** * Represents a variable in an expression tree. */ public class ExprVariableNodeImpl extends ExprNodeBase implements ExprEvaluator, ExprVariableNode { private static final long serialVersionUID = 0L; private final String variableName; private final String optSubPropName; private final boolean isConstant; private final Object valueIfConstant; private Class variableType; private boolean isPrimitive; private transient EventPropertyGetter eventTypeGetter; private transient Map<Integer, VariableReader> readersPerCp; private transient VariableReader readerNonCP; public ExprVariableNodeImpl(VariableMetaData variableMetaData, String optSubPropName) { if (variableMetaData == null) { throw new IllegalArgumentException("Variables metadata is null"); } this.variableName = variableMetaData.getVariableName(); this.optSubPropName = optSubPropName; this.isConstant = variableMetaData.isConstant(); this.valueIfConstant = isConstant ? variableMetaData.getVariableStateFactory().getInitialState() : null; } public boolean isConstantValue() { return isConstant; } public ExprEvaluator getExprEvaluator() { return this; } public String getVariableName() { return variableName; } public Object getConstantValue(ExprEvaluatorContext context) { if (isConstant) { return valueIfConstant; } return null; } public boolean isConstantResult() { return isConstant; } public ExprNode validate(ExprValidationContext validationContext) throws ExprValidationException { // determine if any types are property agnostic; If yes, resolve to variable boolean hasPropertyAgnosticType = false; EventType[] types = validationContext.getStreamTypeService().getEventTypes(); for (int i = 0; i < validationContext.getStreamTypeService().getEventTypes().length; i++) { if (types[i] instanceof EventTypeSPI) { hasPropertyAgnosticType |= ((EventTypeSPI) types[i]).getMetadata().isPropertyAgnostic(); } } if (!hasPropertyAgnosticType) { // the variable name should not overlap with a property name try { validationContext.getStreamTypeService().resolveByPropertyName(variableName, false); throw new ExprValidationException("The variable by name '" + variableName + "' is ambigous to a property of the same name"); } catch (DuplicatePropertyException e) { throw new ExprValidationException("The variable by name '" + variableName + "' is ambigous to a property of the same name"); } catch (PropertyNotFoundException e) { // expected } } VariableMetaData variableMetadata = validationContext.getVariableService().getVariableMetaData(variableName); if (variableMetadata == null) { throw new ExprValidationException("Failed to find variable by name '" + variableName + "'"); } isPrimitive = variableMetadata.getEventType() == null; variableType = variableMetadata.getType(); if (optSubPropName != null) { if (variableMetadata.getEventType() == null) { throw new ExprValidationException("Property '" + optSubPropName + "' is not valid for variable '" + variableName + "'"); } eventTypeGetter = variableMetadata.getEventType().getGetter(optSubPropName); if (eventTypeGetter == null) { throw new ExprValidationException("Property '" + optSubPropName + "' is not valid for variable '" + variableName + "'"); } variableType = variableMetadata.getEventType().getPropertyType(optSubPropName); } readersPerCp = validationContext.getVariableService().getReadersPerCP(variableName); if (variableMetadata.getContextPartitionName() == null) { readerNonCP = readersPerCp.get(EPStatementStartMethod.DEFAULT_AGENT_INSTANCE_ID); } return null; } public Class getConstantType() { return variableType; } public Class getType() { return variableType; } public String toString() { return "variableName=" + variableName; } public Object evaluate(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { VariableReader reader; if (readerNonCP != null) { reader = readerNonCP; } else { reader = readersPerCp.get(exprEvaluatorContext.getAgentInstanceId()); } if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().qExprVariable(this); } Object value = reader.getValue(); if (isPrimitive || value == null) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aExprVariable(value); } return value; } EventBean theEvent = (EventBean) value; if (optSubPropName == null) { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aExprVariable(theEvent.getUnderlying()); } return theEvent.getUnderlying(); } Object result = eventTypeGetter.get(theEvent); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.get().aExprVariable(result); } return result; } public void toPrecedenceFreeEPL(StringWriter writer) { writer.append(variableName); if (optSubPropName != null) { writer.append("."); writer.append(optSubPropName); } } public ExprPrecedenceEnum getPrecedence() { return ExprPrecedenceEnum.UNARY; } public boolean equalsNode(ExprNode node, boolean ignoreStreamPrefix) { if (!(node instanceof ExprVariableNodeImpl)) { return false; } ExprVariableNodeImpl that = (ExprVariableNodeImpl) node; if (optSubPropName != null ? !optSubPropName.equals(that.optSubPropName) : that.optSubPropName != null) { return false; } return that.variableName.equals(this.variableName); } public String getVariableNameWithSubProp() { if (optSubPropName == null) { return variableName; } return variableName + "." + optSubPropName; } }