#if     !defined(ATM_ERROR_H)

using namespace std;

namespace atm {
  
#include <string>
#include <stdarg.h>
  
  /** Definition of the sequence of error levels sorted by ascending severity.
   */
  enum ErrorLevel { NOERROR=0, WARNING, MINOR, SERIOUS, FATAL };
  
  /** The Error class represents a list of exceptions that may happen when errors occur.
      To every error is associated a severity level. There is at any time an acceptable level
      of severity. If an error occurs at that level or a more severe level, an exception is thrown.
      The critical level of severity below which errors are tolerated can be modified. 
  */
  class Error
    {
    public:
      Error();
      Error(ErrorLevel errlev);
      /** Declare the occurence of an error
       *  @pre the default level of tolerence for an acceptable error is used or a different critical
       *  level has been set.
       *  @param errlev the level of severity for the error being declared
       *  @param message Error message
       *  @post the declaration may have or may have not thrown an exception depending on the current
       *  tolerence about the severity level.
       */  
      Error(ErrorLevel errlev, string message);
      
      /** Declare the occurence of an error
       *  @pre the default level of tolerence for an acceptable error is used or a different critical
       *  level has been set.
       *  @param errlev the level of severity for the error being declared
       *  @param fmt Error message format as in a standard C printf
       *  @param ... Variable arguments as in printf
       *  @post the declaration may have or may have not thrown an exception depending on the current
       *  tolerence about the severity level. 
       */  
      Error(ErrorLevel errlev, char* fmt, ... );
      /** Destructor */
      ~Error();
      
      void   notify(ErrorLevel errlev, string message);
      void   notify(string message);
      
      /** Setter to modify the critical current level of severity below which errors are tolerated.
       *  @param criticalErrlev critical limit: when errlev >= criticalErrlev an exception will be thrown
       *  @post  New declarations of errors will be thrown or not according to this new critical limit  
       */
      static void       setAcceptableLevel(ErrorLevel criticalErrlev);
      
      /** Accessor to the current limit below wich error are not thrown 
       */
      static ErrorLevel getAcceptableLevel();
      
      /** Accessor to the current limit in the form of a string 
       */
      static string     getAcceptableLevelToString();
      
      /** Accessor to the severity level of the error which has just been declared
       */
      static ErrorLevel getLevel();
      
      /** Accessor to the severity level, in the form of a string, of the error which has just been declared
       */
      static string     getLevelToString();
      
      /** Accessor to the error message for the error which has just been declared
       */
      static string     getErrorMessage();
      
      /** Clear the stack of all the error messages which passed up to the last declaration which has 
       * finaly triggered the exception 
       */
      static void       clearMessage();
      
      /** Clear the stack of all the error levels which passed up to the last declaration which has
       * finaly triggered the exception 
       */
      static void       clearErrLev();
      
    private:
      static ErrorLevel         acceptableErrorLevel;          //!< Current acceptable level of severity
      static string             errorMessage_;                 //!< Error message
      static ErrorLevel         errlev_;                       //!< Error level
      
      string                    errorLog;                      //!< Error log (TBD)
      void                      printMessage( string message); //!< Print utility
    };
  /** \page testError Example showing how to use the class Error
      
  \dontinclude testError.cpp
  
  The codes using the Error class must include its header file.
  \skip include
  \until using
  
  To illustrate how to use this class we take here an example defining a class Array with a constraint
  about a maximum index.
  \skip const
  \until testbed
  
  In the test program we begin by showing the default critical limit for acceptable errors:
  \skip main()
  \until default
  
  An array is declared and it is populated by integers for indices from 0 to 100. The opperator []
  generate an Error throwing it if the index exceeds the maximum allowed limit, we insert the loop in a try
  section. When the index j exceeds the upper limit in the indexing, an Error is thrown unless
  this type type of errors is acceptable.
  \skip Array
  \until Error
  
  The out-of-range indexing in the [] operator methods having been declared to be SERIOUS, when j
  exceeds the maximum size allowed, its severity, SERIOUS (see the method []) is just at the critical
  when the error become unacceptable. Hence an Error exception is thrown. 
  \skip getLevel
  \until input!
  
  The execution proceeds; the following test attests that this error was considered as acceptable:
  \skip if(Error
  \until proceed
  
  We now repeat this scenario triggering with the same error but before that we  test with a tolerence
  which is more constraining: any error will be thrown only when it severity reach the FATAL limit:
  \from setAcceptableLevel
  \until cout
  
  The scenario is now repeated:
  \skip Test:
  \until return
  
  The Error is not catched because with this new contextthe error which is still SERIOUS is considered
  as acceptable.
  
  */
  
}

#define ATM_ERROR_H
#endif
