//
// C++ Interface: xmldata
//
// Description:
//
//
// Author: Benjamin Mesing,,, <bensmail@gmx.net>, (C) 2004
//
// Copyright: See COPYING file that comes with this distribution
//
//

#ifndef __XMLDATA_H_2004_01_22
#define __XMLDATA_H_2004_01_22

#include <string>

#include <qdom.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qtextstream.h>
#include <qfile.h>


namespace NXml
{


using namespace std;



/** @brief This class manages an QDomTree.
  *
  * @author Benjamin Mesing
  */
class XmlData 
{
protected:
	/** hier wird das geladene XML Document gehalten, QDomDocument Objecte sind auch
	  * auch nach dem Ladevorgang weiterhin mit der zugehörigen XMLDatei verknüpft (siehe
	  * DOM Documentation)
	  */
	QDomDocument _domDocument;
public:
	/** Default constructor. Make sure to call either startDocument() or loadFile() before trying
	  * to do anything with the class. */
	XmlData();
	/** @brief Create a document with the name "name" and a root tag with the same name. */
	XmlData(const QString& name);
	/** Creates a XmlData instance for an existing document. */
	XmlData(QDomDocument document);
	virtual ~XmlData();

	/** Sets node to be the next sibling which is not a comment. If node is not a comment it
	  * will not be changed.
	  * @returns if the given node was a comment. */
	static bool skipComments(QDomNode& node);
	/** Loads an XML file and fills the QDomTree with it.
	  * @returns true on success, false on fail (file could not be read or was syntactically incorrect */
	bool loadFile(const QString& filename);

	/** Starts a new DomTree. This will be a blank one, except for the root element
	  * which does also have the handed name. If the DomTree was filled before it will be emptied.
	  * @param name first element in the DomTree.  */
	QDomElement startDocument(const QString& name);
	/** @brief Returns a reference to the document used. */
	const QDomDocument document() const	{	return _domDocument; }
	/** Writes the content of the QDomTree to a file. */
	bool writeFile(const QString& filename) const;
	/** @brief Adds an element into the QDomTree.
	  *
	  * The element is filled with a text section containing the text from writeFrom.
	  * @param parent node under which to add the new element
	  * @param tagName name of the element (tagname)
	  * @returns the Element created
	  */
	QDomElement addElement(QDomElement parent, const QString& tagName);
	/** @brief Adds the given text to the element.
	  *
	  * @returns the QDomText node created. 
	  */
	QDomText addText(QDomElement element, QString text);
	/** @brief Adds the given QStringList as text nodes inside a number of nodes
	  * of the name tagName beneath element.
	  * 
	  * @param element the element where to add the new nodes
	  * @param tagName the name of the nodes to be created
	  * @param text the text to be added inside the created nodes
	  * 
	  * <b>Example:</b><br>
	  * Consider the structure:
	  * @verbatim
	  * <myElements>
	  * </myElements>
	  * @endverbatim
	  * inside <tt>XmlData data</tt> with a <tt>QElement myElements</tt> referring 
	  * to <tt>myElements</tt> in the XML structure. Now running 
	  * @code
	  * QStringList elements;
	  * elments.push_back("el1");
	  * elments.push_back("el2");
	  * data.addText(myElement, "element", elements);
	  * @endcode
	  * results in the structure:
	  * @verbatim
	  * <myElements>
	  *   <element>el1</element>
	  *   <element>el2</element>
	  * </myElements>
	  * @endverbatim
	  */
	void addText(QDomElement element, QString tagName, QStringList text);
	/** Adds the given text to the element.
	  *
	  * @returns the QDomText node created. 
	  */
	QDomText addText(QDomElement element, const string& text);
	/** Adds an Attribute to the given Element.
	  * @param node where to add the element.
	  * @param value for the attribute
	  * @param name of the attribute
	  * @returns the attribute that was created
	  */
	QDomAttr addAttribute(QDomElement node, const QString& value, const QString& name);
	/** This is an overloaded member function, provided for convenience.
	  * It behaves essentially like the above function.\n
	  * Adds a double attribute. */
	QDomAttr addAttribute(QDomElement node, const string& value, const QString& name);
	/** This is an overloaded member function, provided for convenience.
	  * It behaves essentially like the above function.\n
	  * Adds a double attribute. */
	QDomAttr addAttribute(QDomElement node, double value, const QString& name);
	/** This is an overloaded member function, provided for convenience.
	  * It behaves essentially like the above function. \n
	  * Adds an uint attribute. */
	QDomAttr addAttribute(QDomElement node, uint value, const QString& name);
	/** This is an overloaded member function, provided for convenience.
	  * It behaves essentially like the above function. \n
	  * Adds an int attribute. */
	QDomAttr addAttribute(QDomElement node, int value, const QString& name);
	/** This is an overloaded member function, provided for convenience.
	  * It behaves essentially like the above function. \n
	  * Adds a bool attribute. It will be represented as either 0 or 1.*/
	QDomAttr addAttribute(QDomElement node, bool value, const QString& name);
	/** @brief Imports a node from another document into this XML structure.
	  *
	  * Imports the node src from its document and inserts it as child of
	  * dst.
	  * @param src the node to be imported
	  * @param dst the node where to add <em>src</em>
	  * @param deep if the whole subtree beneath <em>src</em> should be imported
	  * @returns the new node created
	  */
	QDomElement importNode(QDomElement src, QDomElement dst, bool deep);
	/** @returns the root element (QDomDocument::documentElement() in QT) */
	QDomElement root()	{	return _domDocument.documentElement(); };
	/** Macht einen String XML Konform, das heißt ersetzt die nicht zulässigen Sonderzeichen
	  * durch ihre XML Notation (z.B. > wird zu \&gt);
	  */
	static void xmlifyString(QString& string);
	/** Added for your convenience.
	  * @see xmlifyString(), aber für Stringlist
	  */
	static void xmlifyStringList(QStringList& stringList);
};


/** @brief Find the first element which is sibling to the given node or the node itself.
  *
  * Starting with the given node this searches through
  * all sibling following siblings  for the first node which is an element
  * skipping comments and everything else which is not a element.
  * @returns the first element, or null if there is no element or if node is null
  */
QDomElement getFirstElement(QDomNode node);

/** @brief Find the next sibling of this node which is an element.
  *
  * This does the same as getFirstElement() but starts searching at
  * the next sibling instead of itself.
  * @returns the first element, 
  */
QDomElement getNextElement(QDomNode node);



/** @brief This loads an attribute from node into the loadInto value.
	*
	* This function fills loadInto with the value of the attribute "name" of the element
	* node. If the attrbute was not existent loadInto will be set to the default value.\n
	* If node is a comment the function will search for the next sibling which is not
	* a comment.\n
	* If the given node is not an element (or the one after the comment), false will be
	* returned.
	* @param element the node to be read. It should be either an element or a comment
	* @param loadInto the string that will be filled with the value.
	* @param name the name of the attribute.
	* @param def the default value, to be used if the loading failed
	* @pre node.toElement() != 0
	* @returns if the attribute was specified and loaded correctly 
	*/
bool getAttribute(QDomElement element, QString& loadInto, const QString& name, QString def="");
/** This is an overloaded member function, provided for convenience.
	* It behaves essentially like the above function. \n
	* Loads a string attribute. */
bool getAttribute(QDomElement element, string& loadInto, const QString& name, string def="");
/** This is an overloaded member function, provided for convenience.
	* It behaves essentially like the above function. \n
	* Loads a double attribute. */
bool getAttribute(QDomElement element, double& loadInto, const QString& name, double def=0);
/** This is an overloaded member function, provided for convenience.
	* It behaves essentially like the above function. \n
	* Loads a float attribute. */
bool getAttribute(QDomElement element, float& loadInto, const QString& name, float=0);
/** This is an overloaded member function, provided for convenience.
	* It behaves essentially like the above function. \n
	* Loads an uint attribute. */
bool getAttribute(QDomElement element, uint& loadInto, const QString& name, uint=0);
/** This is an overloaded member function, provided for convenience.
	* It behaves essentially like the above function. \n
	* Loads an int attribute. */
bool getAttribute(QDomElement element, int& loadInto, const QString& name, int=0);
/** This is an overloaded member function, provided for convenience.
	* It behaves essentially like the above function. \n
	* Loads an uchar attribute. It must be saved as 0 or 1. */
bool getAttribute(QDomElement element, uchar& loadInto, const QString& name, uchar=0);
/** This is an overloaded member function, provided for convenience.
	* It behaves essentially like the above function. \n
	* Loads an int attribute. */
bool getAttribute(QDomElement element, bool& loadInto, const QString& name, bool=false);

/** @brief This reads a number of text nodes inside the nodes beneath element.
  *
  * @param element the element beneath were the nodes are located
  * @returns a list of all the texts found
  * 
  * <b>Example:</b><br>
  * Consider the structure:
  * @verbatim
  * <myElements>
  *   <element>el1</element>
  *   <element>el2</element>
  * </myElements>
  * @endverbatim
  * with a <tt>QElement myElements</tt> referring 
  * to <tt>myElements</tt> in the XML structure. Now running 
  * @code
  * QStringList strings = getTextList(myElements);
  * @endcode
  * results in strings containing el1 and el2.
  * @note that all nodes beneath element must have a text node as first child
  * @see XmlData::addText(QDomElement, QString, QStringList)
  */
QStringList getTextList(QDomElement element);

}	// namespace NXml


#endif	// __XMLDATA_H_2004_01_22
