package lawOfDemeter;

import org.aspectj.lang.*;

/**
 * The ReturnValueBin 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 stores the objects returned to by:
 *  local methods, i.e. methods that are declared in the object currently executing,
 *  static methods, i.e. global methods
 *  all methods if the current method is a static method
 * for later examination by the Checker aspect.
 *
 * @author Paul Freeman
 */

public aspect ReturnValueBin extends TargetBinStack {

  /**
   * What this supplier contains.
   */
  public String contains(){ return "objects returned from local methods"; }

  /**
   * Returns the object associated with the supplied argument thisObj.
   *
   * @param thisObj
   * @return Returns the correct supplier for the supplied Object thisObject
   * if there is one, else returns null.
   */
  public Supplier getSupplier(Object thisObj) {
    return this.aspectOf();
  }

  /**
   * This is the pointcut used by the before and after advice to stack the
   * target bins.
   */
  pointcut EventToStack(): Any.Execution();

  /**
   * This is the pointcut used by the around advice to gather the objects.
   */
  pointcut EventToGather(): Any.MethodCall() || Any.Get();

  /**
   * There is nothing to gather before the EventToGather join point executes.
   */
  void gatherBefore(JoinPoint thisJoinPoint){
    // do nothing
  }

  /**
   * The method that gathers the returned objects of the current method call iff the
   * method call is a local method.
   * Must occur after the method has executed.
   */
  void gatherAfter(JoinPoint thisJoinPoint, Object returnVal){
    if(thisJoinPoint.getThis() == thisJoinPoint.getTarget()){
      add(returnVal, local + JPUtil.at(thisJoinPoint));
    }
  }

}
