/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package org.codehaus.aspectwerkz.expression;
import org.codehaus.aspectwerkz.reflect.ClassInfo;
import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
import org.codehaus.aspectwerkz.reflect.FieldInfo;
import org.codehaus.aspectwerkz.reflect.MethodInfo;
import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
import org.codehaus.aspectwerkz.reflect.StaticInitializationInfo;
import gnu.trove.TIntIntHashMap;
import gnu.trove.TObjectIntHashMap;
/**
* The expression context for AST evaluation.
*
* @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a>
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class ExpressionContext {
public static final int INFO_NOT_AVAILABLE = -1;
public static final int METHOD_INFO = 0;
public static final int CONSTRUCTOR_INFO = 1;
public static final int FIELD_INFO = 2;
public static final int CLASS_INFO = 3;
private static final int STATIC_INFO = 4;
private final int m_reflectionInfoType;
private final PointcutType m_pointcutType;
private final ReflectionInfo m_matchingReflectionInfo;
private final ReflectionInfo m_withinReflectionInfo;
private boolean m_inCflowSubAST = false;
private boolean m_cflowEvaluation = false;
private boolean m_hasBeenVisitingCflow = false;
private int m_currentTargetArgsIndex = 0;
/**
* Expression to advised target (method / ctor) argument index map.
* It depends on the matching context and the pointcut signature, as well as args(..)
*/
public gnu.trove.TObjectIntHashMap m_exprIndexToTargetIndex = new TObjectIntHashMap();
/**
* The variable name corresponding to the this(..) designator,
* or null if nothing is bound (this(<type>) or no this(..))
*/
public String m_thisBoundedName = null;
/**
* The variable name corresponding to the target(..) designator,
* or null if nothing is bound (target(<type>) or no target(..))
*/
public String m_targetBoundedName = null;
/**
* Set to true when we encounter a poincut using target(..) and when match cannot be done without a
* runtime check with instance of.
*/
public boolean m_targetWithRuntimeCheck = false;
/**
* Creates a new expression context.
*
* @param pointcutType
* @param reflectionInfo - can be null f.e. with early evaluation of CALL pointcut
* @param withinReflectionInfo
*/
public ExpressionContext(final PointcutType pointcutType,
final ReflectionInfo reflectionInfo,
final ReflectionInfo withinReflectionInfo) {
if (pointcutType == null) {
throw new IllegalArgumentException("pointcut type can not be null");
}
m_pointcutType = pointcutType;
m_matchingReflectionInfo = reflectionInfo;
if (withinReflectionInfo != null) {
m_withinReflectionInfo = withinReflectionInfo;
} else {
if (PointcutType.EXECUTION.equals(pointcutType)
|| PointcutType.STATIC_INITIALIZATION.equals(pointcutType)
|| PointcutType.WITHIN.equals(pointcutType)) {
m_withinReflectionInfo = m_matchingReflectionInfo;
} else {
m_withinReflectionInfo = null;
}
}
if (reflectionInfo instanceof MethodInfo) {
m_reflectionInfoType = METHOD_INFO;
} else if (reflectionInfo instanceof ConstructorInfo) {
m_reflectionInfoType = CONSTRUCTOR_INFO;
} else if (reflectionInfo instanceof FieldInfo) {
m_reflectionInfoType = FIELD_INFO;
} else if (reflectionInfo instanceof ClassInfo) {
m_reflectionInfoType = CLASS_INFO;
} else if (reflectionInfo instanceof StaticInitializationInfo) {
m_reflectionInfoType = STATIC_INFO;
} else {
m_reflectionInfoType = INFO_NOT_AVAILABLE;// used for early eval on CALL
}
}
public ReflectionInfo getReflectionInfo() {
return m_matchingReflectionInfo;
}
public ReflectionInfo getWithinReflectionInfo() {
return m_withinReflectionInfo;
}
public boolean hasExecutionPointcut() {
return m_pointcutType.equals(PointcutType.EXECUTION);
}
public boolean hasCallPointcut() {
return m_pointcutType.equals(PointcutType.CALL);
}
public boolean hasSetPointcut() {
return m_pointcutType.equals(PointcutType.SET);
}
public boolean hasGetPointcut() {
return m_pointcutType.equals(PointcutType.GET);
}
public boolean hasHandlerPointcut() {
return m_pointcutType.equals(PointcutType.HANDLER);
}
public boolean hasStaticInitializationPointcut() {
return m_pointcutType.equals(PointcutType.STATIC_INITIALIZATION);
}
public boolean hasWithinPointcut() {
return m_pointcutType.equals(PointcutType.WITHIN);
}
//
// public boolean hasHasMethodPointcut() {
// return m_pointcutType.equals(PointcutType.HAS_METHOD);
// }
//
// public boolean hasHasFieldPointcut() {
// return m_pointcutType.equals(PointcutType.HAS_FIELD);
// }
public boolean hasWithinReflectionInfo() {
return m_withinReflectionInfo != null;
}
public boolean hasMethodInfo() {
return m_reflectionInfoType == METHOD_INFO;
}
public boolean hasConstructorInfo() {
return m_reflectionInfoType == CONSTRUCTOR_INFO;
}
public boolean hasFieldInfo() {
return m_reflectionInfoType == FIELD_INFO;
}
public boolean hasClassInfo() {
return m_reflectionInfoType == CLASS_INFO;
}
public boolean hasReflectionInfo() {
return m_reflectionInfoType != INFO_NOT_AVAILABLE;
}
public void setInCflowSubAST(final boolean inCflowAST) {
m_inCflowSubAST = inCflowAST;
}
public boolean inCflowSubAST() {
return m_inCflowSubAST;
}
public void setHasBeenVisitingCflow(final boolean hasBeenVisitingCflow) {
m_hasBeenVisitingCflow = hasBeenVisitingCflow;
}
public boolean hasBeenVisitingCflow() {
return m_hasBeenVisitingCflow;
}
public boolean getCflowEvaluation() {
return m_cflowEvaluation;
}
public void setCflowEvaluation(boolean cflowEvaluation) {
m_cflowEvaluation = cflowEvaluation;
}
public int getCurrentTargetArgsIndex() {
return m_currentTargetArgsIndex;
}
public void setCurrentTargetArgsIndex(int argsIndex) {
this.m_currentTargetArgsIndex = argsIndex;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ExpressionContext)) {
return false;
}
final ExpressionContext expressionContext = (ExpressionContext) o;
if (m_reflectionInfoType != expressionContext.m_reflectionInfoType) {
return false;
}
if (!m_matchingReflectionInfo.equals(expressionContext.m_matchingReflectionInfo)) {
return false;
}
if (!m_pointcutType.equals(expressionContext.m_pointcutType)) {
return false;
}
if ((m_withinReflectionInfo != null) ?
(!m_withinReflectionInfo
.equals(expressionContext.m_withinReflectionInfo)) :
(expressionContext.m_withinReflectionInfo != null)) {
return false;
}
return true;
}
public int hashCode() {
int result;
result = m_pointcutType.hashCode();
result = (29 * result) + m_matchingReflectionInfo.hashCode();
result = (29 * result) + ((m_withinReflectionInfo != null) ? m_withinReflectionInfo.hashCode() : 0);
result = (29 * result) + m_reflectionInfoType;
return result;
}
public PointcutType getPointcutType() {
return m_pointcutType;
}
public void resetRuntimeState() {
m_targetBoundedName = null;
m_thisBoundedName = null;
m_exprIndexToTargetIndex = new TObjectIntHashMap();
m_targetWithRuntimeCheck = false;
}
}