/*
 *  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/XMLStreamer.hpp
 *  \brief  Definition of class XMLStreamer.
 *  \author Marc Parizeau
 *  \author Christian Gagne
 *  $Revision: 1.4 $
 *  $Date: 2004/07/01 23:59:00 $
 */

#ifndef Beagle_XMLStreamer_hpp
#define Beagle_XMLStreamer_hpp

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

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


namespace Beagle {

/*!
 *  \class XMLStreamer beagle/XMLStreamer.hpp "beagle/XMLStreamer.hpp"
 *  \brief Simple XML document streamer.
 *  \ingroup OOF
 *  \ingroup IO
 *  \note  This class is mostly based on class XML::Streamer of Marc Parizeau, with some
 *    minor modifications to comply with Open BEAGLE conventions.
 *
 *  This class is for streaming XML tags with automatic indentation.
 */
class XMLStreamer : public Object {

public:

  //! XMLStreamer allocator type.
  typedef AllocatorT< XMLStreamer, Object::Alloc >
          Alloc;
  //! XMLStreamer handle type.
  typedef PointerT< XMLStreamer, Object::Handle >
          Handle;
  //! XMLStreamer bag type.
  typedef ContainerT< XMLStreamer, Object::Bag >
          Bag;
  
  explicit XMLStreamer(std::ostream& inStream, unsigned int inWidth=2);
  virtual ~XMLStreamer() { }

  XMLStreamer& operator<<(int inValue);
  XMLStreamer& operator<<(double inValue);
  XMLStreamer& operator<<(const std::string& inValue);
  XMLStreamer& operator<<(const Object& inObject);
  
  void closeTag(bool inIndent=true);
  void insertAttribute(const std::string& inName, std::string inValue);
  void insertFloat(double inValue, const std::string& inName="", bool inIndent=true);
  void insertHeader(std::string inEncoding="ISO-8859-1");
  void insertInteger(long int inValue, const std::string& inName="", bool inIndent=true);
  void insertSpecialTag(const std::string& inTag, bool inIndent=true);
  void insertString(const std::string& inValue, const std::string& inName="", bool inIndent=true);
  void openTag(const std::string& inName, bool inIndent=true);

  /*!
   *  \return Output stream of streamer.
   */
  inline std::ostream& getStream()
  {
    return mStream;
  }
      
protected:
  std::ostream&           mStream;  //!< Output stream.
  std::stack<std::string> mTags;    //!< Stack of opened tags.
  unsigned int            mWidth;   //!< Width of indentation.
  bool                    mClosed;  //!< Indicates if start tag has been closed.
  bool                    mDirty;   //!< Indicates if output streamer has been used.
      
};

}

#endif // Beagle_XMLStreamer_hpp


