package lawOfDemeter;

import org.aspectj.lang.*;

/**
 * The GloballyPreferredBin 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
 * join points that are globally considered to be suppliers of prefered objects
 * for later examination by the Checker aspect.
 *
 * @author Paul Freeman
 */

public aspect GlobalPreferredBin extends TargetBinStack {

  /**
   * What this supplier contains.
   */
  public String contains(){ return "global preferred objects"; }

  /**
   * 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.GlobalPreferred();

  /**
   * 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 GloballyPreferred
   * call.
   * Must occur after the join point has executed.
   */
  void gatherAfter(JoinPoint thisJoinPoint, Object returnVal){
    if(returnVal != null){
      add(returnVal, local + at(thisJoinPoint));
    }
  }
}
