/*
 *  Open BEAGLE
 *  Copyright (C) 2001-2004 by Christian Gagne and Marc Parizeau
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  Contact:
 *  Laboratoire de Vision et Systemes Numeriques
 *  Departement de genie electrique et de genie informatique
 *  Universite Laval, Quebec, Canada, G1K 7P4
 *  http://vision.gel.ulaval.ca
 *
 */

/*!
 *  \file   beagle/XMLParser.hpp
 *  \brief  Definition of class XMLParser.
 *  \author Marc Parizeau
 *  \author Christian Gagne
 *  $Revision: 1.5 $
 *  $Date: 2004/04/25 23:12:21 $
 */

/*!
 *  \defgroup IO XML Input/Output
 *  \ingroup OOF
 *  \brief XML Input Parser and Output Streamers, part of the Object Oriented Foundations.
 *
 *  Reading and writing files containing evolutionary data, such the population, the parameters, the
 *  results of the evolution, is an important aspect of an EC framework. The C++ already provides an
 *  interesting streaming mechanism to read and write objects into a file, the memory or the standard
 *  input/output. Although, there is also a very interesting technology that is more and more used as
 *  a file format, the eXtensible Markup Language (XML). Mixing these two concepts
 *  together lead us to an important mechanism of this framework: the Open BEAGLE input XML parser and 
 *  output object streamer.
 *
 *  The XML format was first intended to be an improved generic replacement to HTML,
 *  but it appears to be so generic, and so well accepted by the industry, that it's now a central
 *  technology for domains such data modeling (as in the modern word processor), lightweight
 *  distributed computing (SOAP and XML-RPC), databases interactions and web integration in general.
 *  Although the XML is a human understandable format, it is also a flexible and powerful file format,
 *  ideal for a to be used in conjunction of a framework such Open BEAGLE. A XML document can also be
 *  interpreted to screen by most recent versions of web browser such \e Mozilla and \e Microsoft
 *  \e Internet \e Explorer.
 *
 *  The new Open BEAGLE XML input / output classes (since version 1.2) consists into a DOM-like
 *  XML parser and a XML streamer. The XML parser read file by constructing a tree with the XML
 *  files it reads, using object of the class Beagle::XMLNode to build the tree. The XML parser uses a
 *  standard C++ input stream as input devices. The XML output streamer is a simple API class that
 *  can generate XML output into a standard C++ output stream.
 *
 *  For every Open BEAGLE objects that can read and written, the methods Beagle::Object::read and
 *  Beagle::Object::write must be over-defined consequently. For the Beagle::Object::read, this is 
 *  done by a exploring the tree build by the XML parser. For the Beagle::Object::write method,
 *  the object must be serialized using the XML streamer API.
 *
 *  To illustrate this, the following example presents the listing of the method Beagle::Object::read
 *  and Beagle::Object::write of the hypothetical class \c DataValue.
 *  \code
 *  class DataValue : public Beagle::Object {
 *  private:
 *    std::string mName;
 *    double mValue;
 *  public:
 *    virtual void read(Beagle::XMLNode::Handle& inNode) {
 *      if(inNode->getTagName() != "Data")
 *        throw Beagle_IOExceptionNodeM(*inNode, "tag <Data> expected");
 *      mName = inNode()->getTagAttribute("name");
 *      if(inNode->getFirstChild() == NULL)
 *        throw Beagle_IOExceptionNodeM(*inNode, "no value for tag <Data> found");
 *      mValue = uint2str(inNode->getFirstChild()->getValue());
 *    }
 *    virtual void write(Beagle::XMLStreamer& ioStreamer) const {
 *      ioStreamer.openTag("Data");
 *      if(mName != "") ioStreamer.insertAttribute("name", mName);
 *      ioStreamer.insertFloat(mValue);
 *      ioStreamer.closeTag();
 *    }
 *  };
 *  \endcode
 *  The XML output produced of an instance of a \c DataValue object that have as name
 *  \c mydata and as value 1.5 would be the following.
 *  \verbatim <Data name="mydata"> 1.5 </Data> \endverbatim
 *
 */
 
#ifndef Beagle_XMLParser_hpp
#define Beagle_XMLParser_hpp

#include <map>

#include "beagle/config.hpp"
#include "beagle/macros.hpp"
#include "beagle/Object.hpp"
#include "beagle/Tokenizer.hpp"
#include "beagle/AllocatorT.hpp"
#include "beagle/ContainerT.hpp"
#include "beagle/PointerT.hpp"
#include "beagle/Tokenizer.hpp"
#include "beagle/XMLNode.hpp"
#include "beagle/XMLStreamer.hpp"


namespace Beagle {  

/*!
 *  \class XMLParser beagle/XMLParser.hpp "beagle/XMLParser.hpp"
 *  \brief Simple XML document parser.
 *  \ingroup OOF
 *  \ingroup IO
 *  \note  This class is mostly based on class XML::Parser of Marc Parizeau, with some
 *    minor modifications to comply with Open BEAGLE conventions.
 *
 *  This class is for parsing simple XML documents. It respects most of the XML syntax, except for the
 *  following items:
 *  \li It does not deal with character encodings;
 *  \li It does not support DTD;
 *  \li Tag attributes must be enclosed by double quotes.
 *
 *  In other words, it can read most data coded in XML, but cannot validate its syntax, nor translate
 *  its character encodings (this translation must be done by the application).
 *
 */
class XMLParser : public Object {
   
public:

  //! XMLParser allocator type.
  typedef AllocatorT<XMLParser,Object::Alloc>
          Alloc;
  //! XMLParser handle type.
  typedef PointerT<XMLParser,Object::Handle>
          Handle;
  //! XMLParser bag type.
  typedef ContainerT<XMLParser,Object::Bag>
          Bag;
          
           XMLParser() { }
  virtual ~XMLParser() { }

  XMLNode::Handle getRootTagNode() const;
  void            parse(const std::string& inFileName);
  void            parse(std::istream& inStream, const std::string& inName="");

  /*!
   *  \return Parse tree root node.
   */
  XMLNode::Handle getRootNode() const
  {
    return mRoot;
  }
  
protected:
   XMLNode::Handle mRoot;     //!< Root node of parse tree.

};

}


#endif // Beagle_XMLParser_hpp

