// file: $isip/class/mmedia/XMLParser/xp_06.cc
// version: $Id: xp_06.cc 10284 2005-10-27 20:52:14Z wholland $

#if defined(HAVE_EXPAT)

#include "XMLParser.h"

// method: addToken
//
// arguments:
//   XMLToken token: an XML token to be added to the expansion
//
// return: a boolean indicating status
//
// concats a token to the token vector, and checks for
// start_and_end_tags.
// 
boolean XMLParser::addToken(XMLToken token_a) {
  
  // add the new tag to the expansion, if it is not a CDATA
  // tag immediately following another CDATA tag
  //
  // if length() = 5, index of last element is 4
  //
  // do not allow the vector to access anything out of bounds
  //    
  if(token_vector_d.length() >=1) {
    
    // if the previous tag was a start tag, and this tag is an end tag,
    // with no other data in between, combine the two tags as follows:
    // <tag></tag> => <tag/>
    //
    if (token_vector_d(token_vector_d.length()-1).getType() ==
	XMLToken::START_TAG && token_a.getType() ==
	XMLToken::END_TAG) {
      
      token_vector_d(token_vector_d.length()-1)
	.setType(XMLToken::START_AND_END_TAG);
      
      // indicate success
      //
      return true;
    }
  }
  
  // note that execution does not reach this point in the case of
  // sequential CDATA tags. Therefore, no CDATA tags after the first
  // in any sequence will increase the lengh of the vector. They will
  // be combined into a single CDATA tag.
  //
  return token_vector_d.concat(token_a);
}

// method: parseXML
//
// arguments:
//   String document: (input) an xml format document
//
// return: a boolean indicating status
//
boolean XMLParser::parseXML(String document_a) {
  
  // clear the parser, and initialize it for reuse
  //
  token_vector_d.clear(Integral::RESET);
  this->Create();
  
  // remove all leading and trailing white space from the string,
  // since an end line before a <?xml?> statement will break the
  // expat parse
  //
  document_a.trim();
  
  // parse the entire document at once. inform expat that
  // this is the final parse (true)
  // so that it will check for well formedness. The -1 here
  // forces Parse to dynamically check for the size of the
  // string passed to it, (as opposed to parsing a positive
  // fixed number of bytes)
  //
  if(!this->Parse((char*)(byte*)document_a, -1, true)) {
    document_a.debug(L"document_a->");
    return Error::handle(name(),
			 L"Parse Failed. Check document for well formednes",
			 Error::TEST,
			 __FILE__, __LINE__);
  }
  
  if(debug_level_d > Integral::DETAILED) {
    Console::put(L"The parsed document:");
    Console::increaseIndention();
    Console::put(toXML());
    Console::decreaseIndention();
  }
  
  // filter out non-handled tokens, if a list of
  // valid values has been specified.
  //
  if(valid_values_d.length() > 0) {
    removeUnhandledTokens();
  }
  
  // ensure that the depths are correct before exiting
  //
  setTokenDepths();
  
  if(debug_level_d > Integral::DETAILED) {
    Console::put(L"The document after removal of unwanted tags:");
    Console::increaseIndention();
    Console::put(toXML());
    Console::decreaseIndention();
  }
  
  // exit gracefully
  //
  return true;
}

#endif
