org.aspectj.weaver.patterns.PointcutEvaluationExpenseComparator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjweaver Show documentation
Show all versions of aspectjweaver Show documentation
The AspectJ weaver introduces advices to java classes
/* *******************************************************************
* Copyright (c) 2004 IBM Corporation.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* ******************************************************************/
package org.aspectj.weaver.patterns;
import java.util.Comparator;
import org.aspectj.weaver.Shadow;
public class PointcutEvaluationExpenseComparator implements Comparator {
private static final int MATCHES_NOTHING = -1;
private static final int WITHIN = 1;
private static final int ATWITHIN = 2;
private static final int STATICINIT = 3;
private static final int ADVICEEXECUTION = 4;
private static final int HANDLER = 5;
private static final int GET_OR_SET = 6;
private static final int WITHINCODE = 7;
private static final int ATWITHINCODE = 8;
private static final int EXE_INIT_PREINIT = 9;
private static final int CALL_WITH_DECLARING_TYPE = 10;
private static final int THIS_OR_TARGET = 11;
private static final int CALL_WITHOUT_DECLARING_TYPE = 12;
private static final int ANNOTATION = 13;
private static final int AT_THIS_OR_TARGET = 14;
private static final int ARGS = 15;
private static final int AT_ARGS = 16;
private static final int CFLOW = 17;
private static final int IF = 18;
private static final int OTHER = 20;
/**
* Compare 2 pointcuts based on an estimate of how expensive they may be to evaluate.
*
* within
*
* {@literal @}within staticinitialization [make sure this has a fast match method] adviceexecution handler get, set withincode
* {@literal @}withincode execution, initialization, preinitialization call
* {@literal @}annotation this, target
* {@literal @}this, {@literal @}target args
* {@literal @}args cflow, cflowbelow if
*/
public int compare(Pointcut p1, Pointcut p2) {
// important property for a well-defined comparator
if (p1.equals(p2)) {
return 0;
}
int result = getScore(p1) - getScore(p2);
if (result == 0) {
// they have the same evaluation expense, but are not 'equal'
// sort by hashCode
int p1code = p1.hashCode();
int p2code = p2.hashCode();
if (p1code == p2code) {
return 0;
} else if (p1code < p2code) {
return -1;
} else {
return +1;
}
}
return result;
}
// a higher score means a more expensive evaluation
private int getScore(Pointcut p) {
if (p.couldMatchKinds() == Shadow.NO_SHADOW_KINDS_BITS) {
return MATCHES_NOTHING;
}
if (p instanceof WithinPointcut) {
return WITHIN;
}
if (p instanceof WithinAnnotationPointcut) {
return ATWITHIN;
}
if (p instanceof KindedPointcut) {
KindedPointcut kp = (KindedPointcut) p;
Shadow.Kind kind = kp.getKind();
if (kind == Shadow.AdviceExecution) {
return ADVICEEXECUTION;
} else if ((kind == Shadow.ConstructorCall) || (kind == Shadow.MethodCall)) {
TypePattern declaringTypePattern = kp.getSignature().getDeclaringType();
if (declaringTypePattern instanceof AnyTypePattern) {
return CALL_WITHOUT_DECLARING_TYPE;
} else {
return CALL_WITH_DECLARING_TYPE;
}
} else if ((kind == Shadow.ConstructorExecution) || (kind == Shadow.MethodExecution) || (kind == Shadow.Initialization)
|| (kind == Shadow.PreInitialization)) {
return EXE_INIT_PREINIT;
} else if (kind == Shadow.ExceptionHandler) {
return HANDLER;
} else if ((kind == Shadow.FieldGet) || (kind == Shadow.FieldSet)) {
return GET_OR_SET;
} else if (kind == Shadow.StaticInitialization) {
return STATICINIT;
} else {
return OTHER;
}
}
if (p instanceof AnnotationPointcut) {
return ANNOTATION;
}
if (p instanceof ArgsPointcut) {
return ARGS;
}
if (p instanceof ArgsAnnotationPointcut) {
return AT_ARGS;
}
if (p instanceof CflowPointcut || p instanceof ConcreteCflowPointcut) {
return CFLOW;
}
if (p instanceof HandlerPointcut) {
return HANDLER;
}
if (p instanceof IfPointcut) {
return IF;
}
if (p instanceof ThisOrTargetPointcut) {
return THIS_OR_TARGET;
}
if (p instanceof ThisOrTargetAnnotationPointcut) {
return AT_THIS_OR_TARGET;
}
if (p instanceof WithincodePointcut) {
return WITHINCODE;
}
if (p instanceof WithinCodeAnnotationPointcut) {
return ATWITHINCODE;
}
if (p instanceof NotPointcut) {
return getScore(((NotPointcut) p).getNegatedPointcut());
}
if (p instanceof AndPointcut) {
int leftScore = getScore(((AndPointcut) p).getLeft());
int rightScore = getScore(((AndPointcut) p).getRight());
if (leftScore < rightScore) {
return leftScore;
} else {
return rightScore;
}
}
if (p instanceof OrPointcut) {
int leftScore = getScore(((OrPointcut) p).getLeft());
int rightScore = getScore(((OrPointcut) p).getRight());
if (leftScore > rightScore) {
return leftScore;
} else {
return rightScore;
}
}
return OTHER;
}
}