/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CXmlDoc.h  -  description
                             -------------------
    begin                : Sun May 22 2003
    based on the code    : Mikko Lahteenmaki <Laza@Flashmail.com>
    copyright            : (C) 2003 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 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 Library
   General Public License for more details.

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

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef __CXMLDOC_H__
#define __CXMLDOC_H__

#include <sptk3/xml/CXmlNode.h>
#include <sptk3/xml/CXmlDocType.h>
#include <sptk3/CSharedStrings.h>
#include <sptk3/CBuffer.h>

#include <string>
#include <map>

namespace sptk {

   /// @addtogroup XML
   /// @{

   /// @brief XML document.
   ///
   /// Represents the entire XML document.
   /// It provides access to document root node, which includes all nodes in XML document tree.
	class CXmlDoc: public CSharedStrings, public CXmlElement {
		friend class CXmlParser;

		CXmlDocType    m_doctype;        ///< Document type
		static int     m_indent_spaces;  ///< Indent spaces

		static const std::string nodeNameString;
	protected:

      /// Creates new named node of type CXmlNode::DOM_ELEMENT.
      /// It can be added to document DOM tree.
      /// @param tagname const char *, name of the element
      /// @see CXmlNode
		CXmlNode *createElement(const char *tagname);

	public:

      /// Constructs an empty document, without doctype.
		CXmlDoc();

      /// Constructs an empty document, with doctype.
      /// @param name const char *, name of the document.
      /// @param public_id const char *, public id of the document, placed on DOCTYPE declaration
      /// @param system_id const char *, system id of the document, placed on DOCTYPE declaration
		CXmlDoc(const char *name, const char *public_id=0, const char *system_id=0);

      /// Destructor
		virtual ~CXmlDoc() { clear(); }

      /// @brief Returns node type
		virtual CXmlNodeType type() const { return DOM_DOCUMENT; }

      /// Destroys all nodes in document
		virtual void clear();

      /// @brief Returns the node name.
      ///
      /// The meaning of the value depends on the node type
		virtual const std::string& name() const { return nodeNameString; }

      /// @brief Sets the new name for the node
      /// @param name const std::string&, new node name
		virtual void name(const std::string& name) {}

      /// @brief Sets new name for node
      /// @param name const char *, new node name
		virtual void name(const char *name) {}

		/// Returns doctype of document.
		/// You can use it to add e.g. custom entities.
		/// <pre>
		/// mydoc->doctype().set_entity("myentity", "myreplacement");
		/// </pre>
		CXmlDocType &docType() { return m_doctype; }

      /// Returns doctype of document.
		/// You can use it to add e.g. custom entities.
		/// <pre>
		/// mydoc->doctype().set_entity("myentity", "myreplacement");
		/// </pre>
		const CXmlDocType &docType() const { return m_doctype; }

	   /// @brief Returns pointer to root element of document
		CXmlNode *rootNode();

	   /// @brief Returns indentation in save
		static int indentSpaces() { return m_indent_spaces; }

	   /// @brief Set indentation in save, defaults to 2
      ///
	   /// @param i as new indent spaces
		static void indentSpaces(int i) { m_indent_spaces = i; }

      /// Loads document from buffer.
      /// @param buffer const CBuffer&, source buffer
      /// @param htmlMode bool, true for HTML mode
		void load(const CBuffer &buffer,bool htmlMode=false);

      /// Saves document to buffer.
      /// @param buffer CBuffer&, a buffer to save document
      /// @param indent int, how many indent spaces at start
		void save(CBuffer &buffer, int indent=0) const;
	};	
   /// @}
}
#endif
