/* Date: 3/22/05 * File: TargetBinStack.java * Modified by: * Joseph Krauze * Chetan Loke * * Description: The around() advice on the EventToGather() pointcut * was replaced by a before and after since in AspectJ * 1.1.1, an around advice cannot be invoked on an object * that is getting initialized. */ package lawOfDemeter; import org.aspectj.lang.*; import java.util.*; /** * The BinStack aspect is part of a Law of Demeter Checker - a set of * classes and aspects that verify a given program does not violate * the Law of Demeter. This aspect addresses the concern of storing a stack of * bins that contain the targets being examined * * @author Paul Freeman */ abstract aspect TargetBinStack extends Supplier { /** * This is the pointcut used by the before and after advice to stack the * target bins. */ abstract pointcut EventToStack(); /** * This is the pointcut used by the around advice to gather the objects. */ abstract pointcut EventToGather(); /** * The method that fires to the implementing aspect before the EventToGather * proceeds, signalling gathering within the implementing aspect to take place. */ abstract void gatherBefore(JoinPoint thisJoinPoint); /** * The method that fires to the implementing aspect before the EventToGather * proceeds, signalling gathering within the implementing aspect to take place. */ abstract void gatherAfter(JoinPoint thisJoinPoint, Object returnValue); /** * Advice that assists in maintaining the stack of targets. * Adds a new target bin to the top of the stack. */ Stack targetStack = new Stack(); before(): // keep track of arguments EventToStack(){ // before a method executes, we store the current stack of targets targetStack.push(targets); // and initialize a new stack of targets targets = new IdentityHashMap(); } /** * Fires the gather method to the implementing aspect. The advice must occur * here in the implementing class so that it can be ordered correctly with the * gathering advice. If the gathering advice was implemented in the subclass, * it would fire before the super classes advice. The dominates keyword will not * override this. */ /** * NOTE: "Dominates" has been replaced by "precedes" **/ /*Object around(): EventToGather(){ gatherBefore(thisJoinPoint); Object returnValue = proceed(); gatherAfter(thisJoinPoint, returnValue); return returnValue; }*/ before() : EventToGather() { gatherBefore(thisJoinPoint); } after() returning (Object ret) : EventToGather() { gatherAfter(thisJoinPoint, ret); } /** * Advice that assists in maintaining the stack of targets. * Removes the target bin from the top of the stack. */ after(): EventToStack(){ // after the method executes, we restore the previous stack of targets targets = (IdentityHashMap)targetStack.pop(); } /** * Prints the objects in the top bin. * Overrides the method inherited from supplier. * Used for debugging. */ public void printTargets(){ System.out.println("== TOP "+contains()+" for "+thisObject+" =="); printHashMap(targets); System.out.println("======================"); } /** * Prints each bin in the stack. * Used for debugging. */ public void printAllTargets(){ System.out.println("== ALL "+contains()+" for "+thisObject+" =="); // targetStack contains one empty bin by default so don't print element at 0 for(int i = 0; i < targetStack.size(); i++){ System.out.println("-- bin " + (targetStack.size() - 1 - i) + " --"); if(i == 0){printHashMap(targets);} else{printHashMap((IdentityHashMap)targetStack.elementAt(i));} System.out.println("-------------------"); } // for(int i = targetStack.size() - 1; i >= 0; i--){ // System.out.println("-- bin " + i + " --"); // if(i == 0){printHashMap(targets);} // else{printHashMap((IdentityHashMap)targetStack.elementAt(i - 1));} // System.out.println("-------------------"); // } } }