/* -*- c++ -*- */
#ifndef AKAXISO_NAME_H__
#define AKAXISO_NAME_H__

#include <akaxiso/classes/types.h>
#include <akaxiso/classes/global_attributes.h>

namespace aka2 {

  class qname {
  public:
    friend struct qname_less;
    qname() : uri_id_(empty_token){}
    qname(const std::string &rawname, 
	  const global_attributes& gattrs = system_global_attributes()) { set(rawname); }

    void set(const std::string &uri, const std::string &name);
    void set(const id_type uri_id, const std::string &name);
    void set(const std::string &rawname, 
	     const global_attributes& gattrs = system_global_attributes());
    
    const std::string &qualified() const {
      return qualified(system_global_attributes());
    }
    const std::string &qualified(const global_attributes &gattrs) const;
    const std::string &local() const;

    const id_type get_uri_id() const { return uri_id_; }
    bool operator==(const qname &rhs) const {  
      return (uri_id_ == rhs.uri_id_) && (name_ == rhs.name_); 
    }
    bool operator!=(const qname &rhs) const {  
      return (uri_id_ != rhs.uri_id_) || (name_ != rhs.name_); 
    }

    bool empty() const;

  private:
    bool is_qualified() const { 
      return uri_id_ != empty_token; 
    }
    id_type uri_id_;
    std::string name_;
    mutable std::string cache_;
  };

  struct qname_less  : std::binary_function<const qname, const qname, bool>{

    bool operator()(const qname &lhs, const qname &rhs) const {
      if (lhs.uri_id_ < rhs.uri_id_)
	return true;
      else if (lhs.uri_id_ == rhs.uri_id_)
	return (lhs.name_ < rhs.name_);
      return false;
    }

  };

}


inline std::ostream & operator<<(std::ostream &ostm, const aka2::qname &name) {
  ostm << name.qualified();
  return ostm;
}

inline bool operator<(const aka2::qname &lhs, const aka2::qname &rhs) {
  return aka2::qname_less()(lhs, rhs);
}

#endif
