// 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 __ACModel_h__
#define __ACModel_h__
#include "Elements.h"
#include "ACModelFile.h"
#include <map>

// While 'ProjectModel' is merely a container for the model data, ACModel
// adds semantics. For example, filenames are automatically turned into canonical
// form and stored relatively to the respective project path.

class ACModel : public ProjectModel {

  std::string model_filename(const std::string &filename, ACM_ProjectPath *&projectpath);

  ACM_TUnit *_tunit_file;
  // map needed to check if a file is already known
  // multiple filenames can be mapped to the same model object (paths can be relative, absolute, whatever)
  typedef std::map<std::string, ACM_File*> FileMap;
  typedef FileMap::value_type FileMapPair;
  FileMap file_map_;
  FileMap canonical_map_;

public:

  ACModel();

  // reset the model to a state as if it were just created
  void clear();

  // clear the model and load new contents from a file
  bool load(ACModelFile &model_file);

  // save the model into a file
  bool save(ACModelFile &model_file);

  // merge the elements of another model into this one
  void merge(ProjectModel &that);

  // register the translation unit and initialize the root scope Parameters:
  //   model_filename: relative path in one of the project directories or absolute
  //   len:            Number of lines in the tranlation unit file
  //   modi_time:      UNIX timestamp of last modification time
  ACM_TUnit *setup_tunit(std::string &model_filename, int len, int modi_time);

  // a header file shall be found or registered if it is still unknown
  ACM_File *register_file(const std::string &filename, int len, int modi_time, bool is_header, bool is_crosscutting = false);

  // get the translation unit as a model object
  ACM_TUnit *tunit_file () const { return _tunit_file; }

  // create a class in the join point model (phase 1)
  ACM_Class *register_class1 (ACM_Name *scope, std::string name, bool in_project = true);

  // create an aspect in the join point model (phase 1)
  ACM_Aspect *register_aspect1 (ACM_Name *scope, std::string name,
      bool in_project = true);

  // create a named pointcut in the join point model (phase 1)
  ACM_Pointcut *register_pointcut1 (ACM_Name *parent, const std::string &name,
      bool is_virtual, const std::string& expr);
  bool overrides_virtual_pointcut (ACM_Name *parent, const string &name); // helper function

  // create an attribute in the join point model (phase 1)
  ACM_Attribute *register_attrdecl1(ACM_Namespace *parent, const std::string &name);

  // find an attribute declaration
  ACM_Attribute *find_attrdecl (const std::vector<std::string> &qual_name);

  // create a Namespace in the join point model (phase 1)
  ACM_Namespace *register_namespace1 (ACM_Name *scope, std::string name,
      bool in_project = true);

  // create a class slice in the join point model (phase 1)
  ACM_ClassSlice *register_class_slice (ACM_Name *scope, string name, bool is_struct);

};

#endif // __ACModel_h__
