/* -*- c++ -*- */
#ifndef AKAXISO_QNAME_H__
#define AKAXISO_QNAME_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) { 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);
  }

} // namespace aka2

#endif /* AKAXISO_QNAME_H__ */
