// This file is part of the AspectC++ compiler 'ac++'.
// Copyright (C) 1999-2003  The 'ac++' developers (see aspectc.org)
//                                                                
// This program is free software;  you can redistribute it and/or 
// modify it under the terms of the GNU General Public License as 
// published by the Free Software Foundation; either version 2 of 
// the License, or (at your option) any later version.            
//                                                                
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
// GNU General Public License for more details.                   
//                                                                
// You should have received a copy of the GNU General Public      
// License along with this program; if not, write to the Free     
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
// MA  02111-1307  USA                                            

#ifndef __JoinPointPlan_h__
#define __JoinPointPlan_h__

#include "JPAdvice.h"
#include "AdviceInfo.h"
#include "IntroductionInfo.h"
#include "OrderPlanner.h"
#include "CFlow.h"

#include "Puma/Array.h"
using namespace Puma;

namespace Puma {
  class ErrorSink;
  class CUnit;
  class ManipCommander;
  class ACAspectInfo;
} // namespace Puma

class Condition;
class LineDirectiveMgr;

// abstract base of all join point plans
// (referenced by JoinPointLoc)

class JoinPointPlan : public OrderPlanner<ACAspectInfo> {

 public:
  virtual ~JoinPointPlan () {}

  // check the final plan for this join point -> false on error
  virtual bool check (ErrorSink &err) { return true; }
};

// base class of all plans for code join points
class JPP_Code : public JoinPointPlan {
  JPAdvice _jpa;
  Array<AdviceInfo*> _unsorted;
  Array<const Condition*> _conds;
  CFlowList _triggers;
  
 public:

  // get the join point advice tree structure
  JPAdvice *jp_advice () { return &_jpa; }

  // consider an advice in the plan for this code join point
  bool consider (AdviceInfo *ai, const Condition &cond);
  
  // consider a necessary cflow trigger at this join point
  bool consider (const CFlow &cflow) {
    _triggers.push_back (cflow);
    return true;
  }
  
  // return the list of cflows that must be entered/left here
  const CFlowList &cflows () const { return _triggers; }
  
  void issue (int index);

  bool check (ErrorSink &err);
};

class JPP_Class : public JoinPointPlan {
  Array<IntroductionInfo*> _base;
  Array<IntroductionInfo*> _other;
  Array<IntroductionInfo*> _unsorted;

 public:
  // consider an introduction in the plan for this class join point
  bool consider (IntroductionInfo *ii);
  void issue (IntroductionInfo *ii);

  bool check(ErrorSink &err);

  int baseIntros () const { return _base.length (); }
  IntroductionInfo *baseIntro (int i) const { return _base.lookup (i); }
  string gen_baseclass_list () const;
  int otherIntros () const { return _other.length (); }
  IntroductionInfo *otherIntro (int i) const { return _other.lookup (i); }
  Unit *gen_intro (ErrorStream &err, CStructure *target,
    LineDirectiveMgr &lmgr) const;
  void instantiate_intro (ErrorStream &err, Unit *unit, CT_Intro *intro,
    const Unit &pattern, Unit &target_name, Location &loc) const;
  
};

#endif // __JoinPointPlan_h__
