/* -*- c++ -*- */
#include "namespaces.h"
#include <cassert>

namespace aka2 {

const id_type unregistered_token = -1;
const id_type empty_token = 0;

void namespace_map::initialize() {
  if (urimap_.size() != 0)
    return;

  urimap_.insert(urimap_type::value_type(empty_token, ""));
  idmap_.insert(idmap_type::value_type("", empty_token));
}

void namespace_map::uninitialize() {
  urimap_.clear();
  idmap_.clear();
}

const id_type namespace_map::register_namespace_uri(const std::string &uri) {
  idmap_type::const_iterator it = idmap_.find(uri);
  if (it != idmap_.end())
    return it->second;

  std::pair<idmap_type::iterator, bool> res_idmap =
    idmap_.insert(idmap_type::value_type(uri, current_id_));
  assert(res_idmap.second);

  std::pair<urimap_type::iterator, bool> res_tokenmap =
    urimap_.insert(urimap_type::value_type(current_id_, uri));
  assert(res_tokenmap.second);

  ++current_id_;
  return res_idmap.first->second;
}


const id_type namespace_map::get_namespace_id(const std::string &uri) const {
  idmap_type::const_iterator it = idmap_.find(uri);
  assert(it != idmap_.end());
  return it->second;
}

const std::string &namespace_map::get_namespace_uri(const id_type id) const {
  urimap_type::const_iterator it = urimap_.find(id);
  if (it == urimap_.end())
    throw invalid_argument();
  return it->second;
}


void prefix_map::assign_prefix(const std::string &prefix, const id_type id) {
  prefixmap_type::const_iterator itprefix = prefixmap_.find(id);
  idmap_type::const_iterator itid = idmap_.find(prefix);

  if ((itprefix != prefixmap_.end()) && (itid != idmap_.end())) {
    if (itprefix->second != prefix)
      throw invalid_argument();
    if (itid->second != id)
      throw invalid_argument();
  }
  else if ((itprefix != prefixmap_.end()) || (itid != idmap_.end()))
    throw invalid_argument();

  prefixmap_.insert(prefixmap_type::value_type(id, prefix));
  idmap_.insert(idmap_type::value_type(prefix, id));
}

const id_type prefix_map::get_prefix_id(const std::string &prefix) const {
  idmap_type::const_iterator it = idmap_.find(prefix);
  if (it == idmap_.end())
    return unregistered_token;
  else
    return it->second;
}

void prefix_map::initialize() {
  prefixmap_.clear();
  idmap_.clear();
}

void prefix_map::uninitialize() {
  prefixmap_.clear();
  idmap_.clear();
}

void prefix_map::clear_prefix(const std::string &prefix) {
  idmap_type::iterator itid = idmap_.find(prefix);
  if (itid == idmap_.end())
    throw invalid_argument();

  id_type id = itid->second;
  prefixmap_type::iterator itprefix = prefixmap_.find(id);

  if (itprefix == prefixmap_.end())
    throw invalid_argument();

  prefixmap_.erase(itprefix);
  idmap_.erase(itid);
}

const std::string &prefix_map::get_prefix(const id_type id) const {
  prefixmap_type::const_iterator it = prefixmap_.find(id);
  if (it == prefixmap_.end())
    throw invalid_argument();
  return it->second;
}

} // namespace aka2
