#ifdef USE_XERCESC


#include "xerces_handler.h"

#include "../classes/document.h"

#include "../parser/sequence_handler.h"
#include "../parser/choice_handler.h"
#include "../parser/simplecontent_handler.h"

#include "../classes/membertype.h"
#include "xerces_locator.h"

#include <xercesc/sax2/Attributes.hpp>
#include <sstream>
#include <malloc.h>

using namespace aka2;

namespace {

  std::string conv_code(const XMLCh *ch, int length = -1) {
    if (length == -1)
      length = xercesc::XMLString::stringLen(ch);
    std::string::value_type *chars;
    while (true) {
      length *= 2;
      chars = reinterpret_cast<std::string::value_type*>
        (alloca(sizeof(std::string::value_type) * (length + 1)));
      bool b = xercesc::XMLString::transcode(ch, chars, length);
      if (b)
    	break;
    }
    return std::string(chars, strlen(chars));
  }

  void convert_to_attributes(const xercesc::Attributes &xattrs, attribute_values &attrs) {
    for (size_t i = 0; i < xattrs.getLength(); ++i) {
      std::string uri_name = conv_code(xattrs.getURI(i));
      std::string localname = conv_code(xattrs.getLocalName(i));
      std::string value = conv_code(xattrs.getValue(i));

      qname name;
      name.set(uri_name, localname);
      attrs.insert(attribute_values::value_type(name, value));
    }
  }

}


void xerces_handler::startElement(const XMLCh* const uri, const   XMLCh* const    localname, const   XMLCh* const qname , const xercesc::Attributes& xattrs) {

  std::string tagname = conv_code(localname);
  std::string uriname = conv_code(uri);
  attribute_values attrs;
  convert_to_attributes(xattrs, attrs);
  aka2::qname name;
  name.set(uriname, tagname);

  handler_.startElement(name, attrs);

}

void xerces_handler::endElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname){
  std::string tagname = conv_code(localname);
  std::string uriname = conv_code(uri);

  aka2::qname name;
  name.set(uriname, tagname);
  handler_.endElement(name);
}

void xerces_handler::characters(const   XMLCh* const    chars, 
				  const unsigned int    length){
  std::string charsbuf = conv_code(chars, length);
  handler_.characters(charsbuf.c_str(), charsbuf.size());
}


void xerces_handler::setDocumentLocator(const xercesc::Locator* const locator) {
  xerces_locator *xloc = new xerces_locator(locator);
  handler_.set_locator(xloc);
}

document xerces_handler::get_document() {
  return handler_.get_document();
}


void xerces_handler::startPrefixMapping(const XMLCh* const  prefix, const XMLCh* const  uri) {
  std::string prefix_converted = conv_code(prefix);
  std::string uri_converted = conv_code(uri);
  handler_.start_prefix_mapping(prefix_converted, uri_converted);

}

void xerces_handler::endPrefixMapping(const XMLCh* const  prefix) {
  std::string prefix_converted = conv_code(prefix);
  handler_.end_prefix_mapping(prefix_converted);
}

void xerces_handler::error(const xercesc::SAXParseException& e) {
}

void xerces_handler::fatalError(const xercesc::SAXParseException& e) {
  std::ostringstream error;
  error << handler_.get_context().get_source_name() 
	<< ':' << e.getLineNumber() << ':' << e.getColumnNumber()
	<< ' ' << xerces_string(e.getMessage()).str();
  throw parse_error(error.rdbuf()->str(), __FILE__, __LINE__);
}

void xerces_handler::warning(const xercesc::SAXParseException& e) {
}



#endif // USE_XERCESC
