#ifndef __ListAdviceContainer_h_
#define __ListAdviceContainer_h_

#include "ac.h"
#include "DynamicJoinPoint.h"

#include "ListAdviceContainerAroundJoinPoint.h"
#include "AdviceList.h"


// base class for Code shared around ListAdviceContainer instances
struct ListAdviceContainerBase {
  static bool unregisterAdvice(void *ptr, AdviceListElement *first);
  static bool runAdvice(void *djp, AdviceListElement *elem);
};

//! can register multiple advice on the same JoinPoint
/**
 * Attention! if this advice container is used, Context instrumentation
 * MUST be used even when not using any, iff it is possible that advice
 * with context is run on the same JP!
 */
template<int JPID, int REPOID>
  class ListAdviceContainer : public ListAdviceContainerBase {

public:
  //typedef ContextJoinPointInfo JoinPointInfo;
  typedef DynamicJoinPoint DJP;
  typedef ListAdviceContainerAroundJoinPoint ADJP;

  // in these advicelists we hold information about the list heads statically
  typedef AdviceLists<JPID, REPOID> AdviceList;

  static DJP make_djp() {
    return DJP();
  }

  static ADJP make_adjp(AC::Action& action) {
    return ADJP(action, AdviceList::around);
  }

  static bool registerAroundAdvice(void *ptr) {
    // insert at front
    AdviceList::around = new AroundAdviceListElement(true, ptr, AdviceList::around);
    return true;
  }
  
  static bool registerAfterAdvice(void *ptr, bool hasContext) {
    AdviceList::after = new AdviceListElement(hasContext, ptr, AdviceList::after);
    return true;
  }

  static bool registerBeforeAdvice(void *ptr, bool hasContext) {
    AdviceList::before = new AdviceListElement(hasContext, ptr, AdviceList::before);
    return true;
  }

  static bool runBeforeAdvice(void *djp) {
    return runAdvice(djp, AdviceList::before); 
  }

  static bool runAfterAdvice(void *djp)  {
    return runAdvice(djp, AdviceList::after);  
  }

  static bool runAroundAdvice(void *djp) { 
    return runAdvice(djp, AdviceList::around);
  }

  static bool unregisterAroundAdvice(void *ptr) {
    return unregisterAdvice(ptr, AdviceList::around);
  }
  static  bool unregisterBeforeAdvice(void *ptr) {
    return unregisterAdvice(ptr, AdviceList::before);
  }
  static void unregisterAfterAdvice(void *ptr) {
    return unregisterAfterAdvice(ptr, AdviceList::after);
  }  
};


#endif

// Local Variables: 
// mode:c++
// End:
