/* -*- c++ -*- */
#include "xerces_parser.h"

#ifndef USE_XERCESC

#include <cassert>

aka2::xerces_parser::xerces_parser() {
  assert(!"Not configured to use Xerces-C++");
}

#else

#include "xerces_handler.h"
#include "../classes/scoped_ptr.h"
#include "../classes/global_attributes.h"
#include "../classes/document.h"
#include "istream_inputsource.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/StdInInputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>

namespace aka2 {

xerces_parser::xerces_parser() {}

document xerces_parser::parse_stdin(){
  xercesc::StdInInputSource is;
  return parse_internal(is, "(stdin)");
}

document xerces_parser::parse(const char *buff){
  char *membuf_id = "(document on memory)";
  xercesc::MemBufInputSource membuf_is(reinterpret_cast<const XMLByte*>(buff),
                                       strlen(buff),
                                       membuf_id,
                                       false);
  return parse_internal(membuf_is, "(membuf)");
}

document xerces_parser::parse(const std::string& document){
  char *membuf_id = "(document on memory)";
  xercesc::MemBufInputSource membuf_is(reinterpret_cast<const XMLByte*>(document.c_str()),
                                       document.length(),
                                       membuf_id,
                                       false);
  return parse_internal(membuf_is, "(std::string)");
}

document xerces_parser::parse(std::istream &istm){
  IStreamInputSource istmsrc(istm);
  return parse_internal(istmsrc, "(std::istream)");
}

document xerces_parser::parse_file(const std::string& filename) {
  XMLCh * xch_filename = xercesc::XMLString::transcode(filename.c_str());
  xercesc::LocalFileInputSource file_is(xch_filename);
  xercesc::XMLString::release(&xch_filename);
  return parse_internal(file_is, filename);
}

document xerces_parser::parse_internal(xercesc::InputSource &is, const std::string &source_name) {
  bool do_namespaces         = true;
  bool do_namespace_prefixes = false;
  bool do_schema             = false;
  bool do_full_checking      = false;

  xercesc::SAX2XMLReader::ValSchemes valschemes = xercesc::SAX2XMLReader::Val_Auto;

  scoped_ptr<xerces_handler> handler(new xerces_handler);

  handler->set_source_name(source_name);

  scoped_ptr<xercesc::SAX2XMLReader> parser(xercesc::XMLReaderFactory::createXMLReader());

  parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpaces,        do_namespaces);
  parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpacePrefixes, do_namespace_prefixes);

  parser->setFeature(xercesc::XMLUni::fgXercesSchema,              do_schema);
  parser->setFeature(xercesc::XMLUni::fgXercesSchemaFullChecking,  do_full_checking);

  if (valschemes == xercesc::SAX2XMLReader::Val_Auto)  {
      parser->setFeature(xercesc::XMLUni::fgSAX2CoreValidation, true);
      parser->setFeature(xercesc::XMLUni::fgXercesDynamic,      true);
  }
  if (valschemes == xercesc::SAX2XMLReader::Val_Never)  {
      parser->setFeature(xercesc::XMLUni::fgSAX2CoreValidation, false);
  }
  if (valschemes == xercesc::SAX2XMLReader::Val_Always)  {
      parser->setFeature(xercesc::XMLUni::fgSAX2CoreValidation, true);
      parser->setFeature(xercesc::XMLUni::fgXercesDynamic,      false);
  }

  parser->setContentHandler(handler.get());
  parser->setErrorHandler(handler.get());

  parser->parse(is);

  return handler->get_document();
}

} // namespace aka2

#endif /* ifndef USE_XERCESC */
