// file: $isip/class/pr/LanguageModel/LanguageModel.h
//

// make sure definitions are only made once
//
#ifndef ISIP_LANGUAGE_MODEL
#define ISIP_LANGUAGE_MODEL

#ifndef ISIP_LANGUAGE_MODEL_BASE
#include <LanguageModelBase.h>
#endif

#ifndef ISIP_LANGUAGE_MODEL_UNDEFINED
#include <LanguageModelUndefined.h>
#endif

// forward class definitions
//
class LanguageModelIHD;
class LanguageModelJSGF;
//class LanguageModelXML;

// forward class definitions
//

// LanguageModelBase: defines the minimal interface contract for all
// language model classes
//
class LanguageModel : public LanguageModelBase {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name
  //
  static const String CLASS_NAME;

  //--------------------------------------------------------------
  //
  // other important constants
  //
  //--------------------------------------------------------------

  // define the currently available language model formats
  //
  enum ALGORITHM { UNKNOWN = 0, IHD, JSGF, XML,
		   BNF, ABNF, DEF_ALGO = UNKNOWN };

  // define the implementation map
  //
  enum IMPLEMENTATION { HD, DEF_IMPL = HD };

  // define static NameMap objects
  //
  static const NameMap ALGO_MAP;
  static const NameMap IMPL_MAP;
    
  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  
  
  static const String PARAM_ALGO;
  static const String PARAM_IMPL;  
  static const String DEF_PARAM;
  static const long DEF_TAG;

  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------

  // define the default value(s) of the class data
  //
  static LanguageModelUndefined NO_LANGUAGE_MODEL;
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  static const long ERR = 100102;
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // a virtual pointer to a language model
  //
  LanguageModelBase* virtual_lm_d;

  // debug level
  //
  // inherited from LanguageModelBase

  // memory manager
  //
  static MemoryManager mgr_d;

  // format
  //
  ALGORITHM format_d;

  // implementation
  //
  IMPLEMENTATION implementation_d;

  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  }

  // method: diagnose
  //
  static boolean diagnose(Integral::DEBUG debug_level);
  
  // debug methods
  //
  boolean debug(const unichar* msg) const {
    return virtual_lm_d->debug(msg);
  }
 
  // method: setDebug
  //
  boolean setDebug(Integral::DEBUG debug_level) {
    
    return (LanguageModelBase::setDebug(debug_level) &&
	    virtual_lm_d->setDebug(debug_level));
  }
  
  // destructor/constructor(s)
  //

  // method: destructor
  //
  ~LanguageModel() {
    if (virtual_lm_d != (LanguageModel*)&NO_LANGUAGE_MODEL) {
      delete virtual_lm_d;
    }
  }

  // method: default constructor
  //
  LanguageModel() {
    implementation_d = DEF_IMPL;
    format_d = DEF_ALGO;
    virtual_lm_d = (LanguageModelBase*)&NO_LANGUAGE_MODEL;
  }

  // method: copy constructor
  //
  LanguageModel(const LanguageModel& arg) {
    virtual_lm_d = (LanguageModelBase*)&NO_LANGUAGE_MODEL;
    assign(arg);
  }

  // assign methods
  //
  boolean assign(const LanguageModel& arg) {
    return assign(*arg.virtual_lm_d);
  }

  // i/o methods
  //
  // method: sofSize
  //
  long sofSize() const {
    return (ALGO_MAP.elementSofSize() + IMPL_MAP.elementSofSize() +
	    virtual_lm_d->sofSize());
  }

  // method: read
  //
  boolean read(Sof& sof, long tag = DEF_TAG, const String& cname = CLASS_NAME);

  // method: write
  //
  boolean write(Sof& sof, long tag = DEF_TAG, const String& cname = CLASS_NAME) const;


  // method: readData
  //
  boolean readData(Sof& sof, const String& pname = DEF_PARAM,
		   long size = SofParser::FULL_OBJECT,
		   boolean param = true, boolean nested = false);

  // method: writeData
  //
  boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

  // other memory managements methods
  //
  boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE);
  
  // equality methods
  //
  boolean eq(const LanguageModel& arg) const {
    return virtual_lm_d->eq(*arg.virtual_lm_d);
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods required by interface contract
  // defined in LanguageModelBase.h
  //
  //---------------------------------------------------------------------------
  
  //--------------------------------------------------------
  //
  // other methods
  //
  //--------------------------------------------------------  

  // method: className
  //
  const String& className() const {
    return virtual_lm_d->className();
  }

  // method: getRuleModel
  //
  RuleModel getRuleModel() {
    return virtual_lm_d->getRuleModel();
  }

  // method: setRuleModel
  //
  boolean setRuleModel(const RuleModel& hg) {
    return virtual_lm_d->setRuleModel(hg);
  }

  // method: get
  //
  //HierarchicalDigraph& getHDigraph() {
  //  return (HierarchicalDigraph&)0;
  // }
  
  // method: set
  //
  //boolean setHDigraph(const HierarchicalDigraph& hg) {
  //  return false;
  //}
  
  // method: convert
  //
  boolean convert(ALGORITHM format);
  
  // method: assign (for LanguageModelBase pointer)
  //
  boolean assign(const LanguageModelBase& arg) {
    return virtual_lm_d->assign(arg);
  }

  // method: eq (for LanguageModelBase pointer)
  //
  boolean eq(const LanguageModelBase& arg) const {
    return virtual_lm_d->eq(arg);
  }
  
  // method: setFormat
  //
  boolean setFormat(ALGORITHM format);

  // method: getFormat
  //
  ALGORITHM getFormat() {
    return format_d;
  }

  // method: minimizeGraph
  //
  boolean minimizeGraph();
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:  
  
};

// end of include file
// 
#endif
