// file: $isip/class/mmedia/XMLToken/XMLToken.h
// version: $Id: XMLToken.h 10636 2007-01-26 22:18:09Z tm334 $

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

// isip included files
//
#ifndef ISIP_VECTOR
#include <Vector.h>
#endif

#ifndef ISIP_PAIR
#include <Pair.h>
#endif

#ifndef ISIP_STRING
#include <String.h>
#endif

#ifndef ISIP_SOF
#include <Sof.h>
#endif

#ifndef ISIP_DEBUGLEVEL
#include <DebugLevel.h>
#endif

// XMLToken: a class to store a single XML tag and information pertaining
// to the tag
//
class XMLToken {
  
  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:
  
  // define the class name
  //
  static const String CLASS_NAME;

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

  // define token types
  //
  enum TYPE { NULL_TAG = 0, START_TAG, END_TAG, CDATA, START_AND_END_TAG,
	      UNHANDLED, DEF_TYPE = NULL_TAG };
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  // error codes
  //
  static const long ERR = 50900;
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:
  
  // A String to store the name of the tag. In the case of CData,
  // this name tag will store the character data itself.
  //
  String value_d;
  
  // The type of the tag: START_TAG, END_TAG, or CDATA
  //
  TYPE type_d;
  
  // a short int to store the depth of the token in the document
  // to which this token belongs
  //
  short int depth_d;
  
  // a Vector of Attribute, Value pairs
  //
  Vector< Pair<String, String> > attributes_d;
  
  // the debug level
  //
  DebugLevel debug_level_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:
  
  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  }
  
  // method: diagnose
  //
  static boolean diagnose(Integral::DEBUG level);
  
  // method: default constructor
  //
  XMLToken() {
    clear(Integral::RESET);
  }
  
  // method: debug
  //
  boolean debug(const unichar* msg) const;
  
  // method: assign
  //
  boolean assign(const XMLToken& token);
  
  // method: operator=
  //
  XMLToken& operator=(const XMLToken& token) {
    assign(token);
    return *this;    
  }
  
  // method: clear
  //
  boolean clear(Integral::CMODE ctype);
  
  // method: read
  //
  boolean read(Sof& sof, long tag, const String& cname = CLASS_NAME) {
    return Error::handle(name(), L"read", Error::NOT_IMPLEM, __FILE__,
			 __LINE__);
  }
  
  // method: write
  //
  boolean write(Sof& sof, long tag, const String& cname = CLASS_NAME) const {
    return Error::handle(name(), L"write", Error::NOT_IMPLEM, __FILE__,
			 __LINE__);
  }
  
  // method: eq
  //
  boolean eq(const XMLToken& xt) const;
  
  // method: operator==
  //
  boolean operator==(const XMLToken& xt) const {
    return eq(xt);
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods
  //
  //---------------------------------------------------------------------------
public: 
  
  //--------------------------------------------------------
  //
  // get/set methods
  //
  //--------------------------------------------------------
  
  // method: setDepth
  //
  boolean setDepth(short int depth);
  
  // method: getDepth
  //
  long getDepth() const {
    return depth_d;
  }
  
  // method: setValue
  //
  boolean setValue(String value) {
    return value_d.assign(value);
  }
  
  // method: getValue
  //
  String getValue() const{
    return value_d;
  }
  
  // method: setType
  //
  boolean setType(TYPE type) {
    type_d = type;
    return true;
  } 
  
  // method: getType
  //
  TYPE getType() const{
    return type_d;
  }
  
  // method: setDebug
  //
  boolean setDebug(Integral::DEBUG level) {
    debug_level_d = level;
    return true;
  }
  
  // method: getDebug
  //
  DebugLevel getDebug() const {
    return debug_level_d;
  }
  
  // method: setAttributes
  //
  boolean setAttributes(Vector<Pair<String, String> >& attribs) {
    return attributes_d.assign(attribs);
  }
  
  // method: setAttributes
  //
  boolean setAttributes(const byte** attrib_array);
  
  // method: getAttributes
  //
  Vector< Pair<String, String> > getAttributes() {
    return attributes_d;
  }
  
  //--------------------------------------------------------
  //
  // attribute manipulation methods
  //
  //--------------------------------------------------------
  
  // method: addAttribute
  //
  boolean addAttribute(String attrib_name, String attrib_value);
  
  // method: removeAttribute
  //
  boolean removeAttribute(String attrib_name);
  
  // method: setAttributeValue
  //
  boolean setAttributeValue(const String aname, const String avalue) {
    removeAttribute(aname);
    return addAttribute(aname, avalue);
  }
  
  // method: getAttributeValue
  //
  String getAttributeValue(const String arg_name) const;
  
  // method: getPointerToValue
  // 
  String* getPointerToValue() {
    return &value_d;
  }
  
  //--------------------------------------------------------
  //
  // initialization methods
  //
  //--------------------------------------------------------
  
  // method: init
  //
  boolean init(TYPE type,
	       String value,
	       Vector< Pair<String, String> > attrib_array,
	       long token_depth = 0,
	       Integral::CMODE ctype = Integral::RESET);
  
  // method: init
  //
  boolean init(TYPE type,
	       String value,
	       long token_depth = 0,
	       Integral::CMODE ctype = Integral::RESET);
  
  // method: init
  //
  boolean init(TYPE type,
	       String value,
	       const byte** attrib_array,
	       long token_depth = 0,
	       Integral::CMODE ctype = Integral::RESET);
  
  //--------------------------------------------------------
  //
  // comparison methods
  //
  //--------------------------------------------------------
  
  // method: isA
  //
  boolean isA(XMLToken::TYPE type);
  
  // method: isA
  //
  boolean isA(String value);
  
  // method: isA
  //
  boolean isA(String value, TYPE type);
  
  //--------------------------------------------------------
  //
  // miscellaneous methods
  //
  //--------------------------------------------------------
  
  // method: toXML
  //
  String toXML() const;
  
  // method: hasAttributes
  //
  boolean hasAttributes() {
    return (attributes_d.length() != 0);
  }
  
  //---------------------------------------------------------------------------
  //
  // protected methods
  //
  //---------------------------------------------------------------------------
protected:  
  
  // method: addQuotes
  //
  String addQuotes(String attrib) const;
  
  // method: concatAttributesAsXML
  //
  boolean concatAttributesAsXML(String& output) const;
  
};
#endif
