// 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 __Plan_h__
#define __Plan_h_

#include <string>
using namespace std;

#include "JoinPointLoc.h"
#include "JoinPointPlan.h"
#include "Condition.h"
#include "Puma/Array.h"
using namespace Puma;

class AdviceCode;
class AdviceInfo;
class IntroductionInfo;
class OrderInfo;
class AspectInfo;
class JoinPointLoc;
class CFlow;

namespace Puma {
  class ACAspectInfo;
  class ACIntroductionInfo;
  class CT_AdviceDecl;
  class ErrorSink;
} // namespace Puma


class Plan {

  ErrorSink &_err;
  Array<AdviceCode*> _advice_codes;
  Array<AdviceInfo*> _advice_infos;
  Array<OrderInfo*> _order_infos;
  Array<AspectInfo*> _aspect_infos;
  Array<IntroductionInfo*> _introduction_infos;
  Array<JoinPointLoc*> _exec_jpls;
  Array<JoinPointLoc*> _call_jpls;
  Array<JoinPointLoc*> _cons_jpls;
  Array<JoinPointLoc*> _dest_jpls;
  Array<JoinPointLoc*> _class_jpls;
  TypeCheckSet _type_checks_false;
  TypeCheckSet _type_checks_true;
    
public:
  
  Plan (ErrorSink &e) : _err (e) {}
  ~Plan ();

  // manage advice and aspect ressources
  AspectInfo *addAspect (ACAspectInfo *ai);
  AspectInfo *getAspect (ACAspectInfo *ai) const;
  AdviceCode *addAdviceCode (CT_AdviceDecl *ad);
  AdviceInfo *addAdvice (AspectInfo *ai, CT_AdviceDecl *ad);
  IntroductionInfo *addIntroduction (AspectInfo *ai, ACIntroductionInfo *acii);
  OrderInfo *addOrder (AspectInfo *ai, CT_AdviceDecl *ad);
  
  // consider a join point and advice/intro in the plan
  void consider (JoinPointLoc *jpl, const Condition &cond, AdviceInfo *ai);
  void consider (JoinPointLoc *jpl, IntroductionInfo *ii);
  void consider (JoinPointLoc *jpl, ACAspectInfo&, ACAspectInfo&);
  void consider (JoinPointLoc *jpl, const CFlow& cflow);

  // check the final plan -> messages to the error sink
  void check ();

  // read the lists of managed ressources
  int intros () const { return _introduction_infos.length (); }
  IntroductionInfo *intro (int i) const {
    return _introduction_infos.lookup (i);
  }

  // read the accumulated plans
  int exec_jp_plans () const { return _exec_jpls.length (); }
  JPL_Method &exec_jp_loc (int i) const {
    return *(JPL_Method*)_exec_jpls.lookup (i);
  }
  JPP_Code &exec_jp_plan (int i) const {
    return *(JPP_Code*)exec_jp_loc (i).plan ();
  }

  int call_jp_plans () const { return _call_jpls.length (); }
  JPL_MethodCall &call_jp_loc (int i) const {
    return *(JPL_MethodCall*)_call_jpls.lookup (i);
  }
  JPP_Code &call_jp_plan (int i) const {
    return *(JPP_Code*)call_jp_loc (i).plan ();
  }

  int cons_jp_plans () const { return _cons_jpls.length (); }
  JPL_Construction &cons_jp_loc (int i) const {
    return *(JPL_Construction*)_cons_jpls.lookup (i);
  }
  JPP_Code &cons_jp_plan (int i) const {
    return *(JPP_Code*)cons_jp_loc (i).plan ();
  }

  int dest_jp_plans () const { return _dest_jpls.length (); }
  JPL_Destruction &dest_jp_loc (int i) const {
    return *(JPL_Destruction*)_dest_jpls.lookup (i);
  }
  JPP_Code &dest_jp_plan (int i) const {
    return *(JPP_Code*)dest_jp_loc (i).plan ();
  }

  int class_jp_plans () const { return _class_jpls.length (); }
  JPL_Class &class_jp_loc (int i) const {
    return *(JPL_Class*)_class_jpls.lookup (i);
  }
  JPP_Class &class_jp_plan (int i) const {
    return *(JPP_Class*)class_jp_loc (i).plan ();
  }
  
  const TypeCheckSet &type_checks_false () const {
    return _type_checks_false;
  }

  const TypeCheckSet &type_checks_true () const {
    return _type_checks_true;
  }
};

#endif // __Plan_h__


