/*******************************************************************\

              Copyright (C) 2003 Joseph Coffland

    This program is free software; you can redistribute it and/or
     modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
        of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
             GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                           02111-1307, USA.

            For information regarding this software email
                   jcofflan@users.sourceforge.net

\*******************************************************************/


#ifndef XMLPULLPARSER_H
#define XMLPULLPARSER_H

#include "XMLEventTypes.h"
#include "XMLSerializable.h"
#include "XMLAttrib.h"

#include <BasicUtils/BasicFileLocation.h>

#include <string>
#include <string>
#include <iostream>

/** 
 * An implementation of the XML pull parser API in C++.
 *
 * See http://www.xmlpull.org/ for more info about the pull parser API.
 */
class XMLPullParser : public virtual XMLEventTypes {
public:
  /** 
   * @return An instance of the default implementation.
   */
  static XMLPullParser *createInstance();

  /** 
   * Deserialize an XMLSerializable using this pull parser.
   * 
   * @param targetNamespace 
   * @param topElementName The name to expect for the top level element.
   * @param serializable 
   */
  virtual void deserialize(const std::string targetNamespace,
			   const std::string topElementName,
			   XMLSerializable &serializable) = 0;

  virtual BasicFileLocation getLocation() = 0;

  /// @return The current element depth.
  virtual int getDepth() = 0;

  /** 
   * @return The current line number or -1 if parsing has not been started.
   */
  virtual int getLineNumber() = 0;

  /** 
   * @return The current column number or -1 if parsing has not been started.
   */
  virtual int getColumnNumber() = 0;

  /** 
   * Throws a BasicExeption if the current event is not START_ELEMENT.
   *
   * @return The number of attributes at the current element.
   */
  virtual unsigned int getNumAttributes() = 0;
  
  /**
   * Throws a BasicExeption if the current event is not START_ELEMENT
   * or the index is out of range
   *
   * @return An array of the current attributes.
   */
  virtual const XMLAttrib &getAttribute(const unsigned int index) = 0;

  /** 
   * Throws a BasicExeption if the current event is not START_ELEMENT.
   * A BasicException will be throw if the attribute doesn't exist.
   * 
   * @param name The attribute name.
   * @param uri The attribute namespace.
   * 
   * @return A pointer to the attribute.
   */
  virtual const XMLAttrib &getAttribute(const std::string name,
					const std::string uri = "") = 0;


  /** 
   * Throws a BasicExeption if the current event is not START_ELEMENT.
   * 
   * @return The index of the attribute if found, -1 otherwise.
   */
  virtual int findAttribute(const std::string name,
			    const std::string uri = "") = 0;


  /** 
   * Throws a BasicException if the current event is not START_ELEMENT,
   * END_ELEMENT or PROCESSING_INSTRUCTION.
   * 
   * @return The name of the current element or processing instruction.
   */
  virtual std::string getName() = 0;

  /** 
   * Throws a BasicException if the current event is not START_ELEMENT or
   * END_ELEMENT.
   * 
   * @return The namespace of the current element.
   */
  virtual std::string getNamespace() = 0;

  /** 
   * Throws a BasicException if the current event is not START_ELEMENT or
   * END_ELEMENT.
   * 
   * @return The prefix of the current element.
   */
  virtual std::string getPrefix() = 0;

  /** 
   * Throws a BasicException if the current event is not TEXT or
   * PROCESSING_INSTRUCTION.
   * 
   * @return The character data of the current event.
   */
  virtual std::string getText() = 0;

  /** 
   * Throw a BasicException if the current event is not START_ELEMENT or
   * END_ELEMENT with name equal to the parameter name.
   */
  virtual void assertName(const std::string name) = 0;

  /** 
   * Throw a BasicException if the current namespace is not equal
   * to the parameter uri.
   */
  virtual void assertNamespace(const std::string uri) = 0;

  /** 
   * Throws a BasicException if the current event is not TEXT.
   *
   * @return True if the current element is a text element and is only 
   *         whitespace, false otherwise.
   */
  virtual bool isWhitespace() = 0;

  /** 
   * Throws a BasicException if the current event is not START_ELEMENT.
   *
   * @return True if the current element has no children, false otherwise.
   */
  virtual bool isEmptyElementTag() = 0;

  /** 
   * Calls next() until the current event is in globalMask - mask or the end
   * of the document is encountered.
   */
  virtual void skip(event_t mask) = 0;

  /** 
   * Parse events are processed until one with a type that is in the
   * event mask is found.  The event mask is group of one or more
   * event types or'ed together.
   *
   * Leaving the TEXT type out of the mask can be useful for skipping
   * over text nodes.
   * 
   * If the mask is < 0 the events in the mask are subtracted from the
   * global mask and the result is used.
   *
   * See XMLEventTypes.
   * 
   * @param mask Events not is this mask are skipped.
   * 
   * @return The type of the next parse event.
   */
  virtual event_t next(XMLEventTypes::event_t mask) = 0;

  /// @return The type of the next parse event.
  virtual event_t next() = 0;

  /// @return The type of the current parse event.
  virtual event_t getEventType() = 0;

  /** 
   * Set a parser feature.
   * 
   * @param name Feature name.
   * @param state Feature state.
   */
  virtual void setFeature(const std::string name, bool state) = 0;

  /** 
   * @param name Feature name.
   * 
   * @return The current state of the named feature.
   */
  virtual bool getFeature(const std::string name) = 0;

  /** 
   * @param name The property name.
   * 
   * @return The current value of the property.
   */
  virtual void *getProperty(const std::string name) = 0;

  /** 
   * @param name The property name.
   * @param value The new property value.
   */
  virtual void setProperty(const std::string name, void *value) = 0;

  /** 
   * @return True if the current event matches event.
   */
  virtual bool check(event_t event) = 0;

  /** 
   * If the current event does not match the parameter event
   * a BasicException will be thrown.
   * 
   * @param event The expected event type.
   * @param msg The error message if not matched.
   */
  virtual void assertEvent(event_t event, const std::string msg = "") = 0;

  /** 
   * Equivalent to calling assertEvent() then next().
   */
  virtual void match(event_t event, const std::string msg = "") = 0;


  /** 
   * Equivalent to calling assertEvent() then next(mask).
   */
  virtual void match(event_t event, event_t mask, std::string msg = "") = 0;

  /** 
   * Match a simple element..  A 'simple' element is one with
   * empty or text only content.
   * If the current event is not START_ELEMENT or the element has
   * non-TEXT children a BasicException will be thrown.
   * 
   * @return The text within the element.
   */
  virtual std::string matchSimple() = 0;

  /** 
   * Initialize the parser to read from an std::istream.
   * 
   * @param in The input stream.
   */
  virtual void initParse(std::istream &in) = 0;

  /** 
   * Initialized the parser with the supplied file.
   * A BasicException will be thrown if the file cannot be opened for input.
   * 
   * @param filename File to open.
   */
  virtual void initParse(const std::string filename) = 0;


  /** 
   * Reset the parser to its initial state.
   */
  virtual void resetParser() = 0;

  /** 
   * Parse a schema to be used in validating XML nodes with match the
   * namespace of this schema.
   * 
   * @param schema The schema as an input stream.
   */
  virtual void preparseSchema(std::istream &schema) = 0;
};

#endif
