/***************************************************************************
 *   Copyright (C) 2001 by Bernd Gehrmann                                  *
 *   bernd@kdevelop.org                                                    *
 *   jakob@simon-gaarde.dk                                                 *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef _DOMUTIL_H_
#define _DOMUTIL_H_

#include <tqdom.h>
#include <tqpair.h>
#include <tqstringlist.h>
#include <tqvaluelist.h>
#include <tqmap.h>

/**
@file domutil.h
Utility functions to operate on %DOM.
*/

struct DomAttribute
{
  TQString name;
  TQString value;
};

struct DomPathElement
{
  TQString tagName;
  TQValueList<DomAttribute> attribute;
  int matchNumber;  // for use when more than one element matches the path
};

typedef TQValueList<DomPathElement> DomPath;

/**
 * Utility class for conveniently accessing data in a %DOM tree.
 */
class DomUtil
{
public:
    typedef TQPair<TQString, TQString> Pair;
    typedef TQValueList<Pair> PairList;
    /**
     * Remove all child elements from a given element.
     */
    static void makeEmpty( TQDomElement& );
    /**
     * Reads a string entry.
     */
    static TQString readEntry(const TQDomDocument &doc, const TQString &path, const TQString &defaultEntry = TQString());
    /**
     * Reads a number entry.
     */
    static int readIntEntry(const TQDomDocument &doc, const TQString &path, int defaultEntry = 0);
    /**
     * Reads a boolean entry. The strings "true" and "TRUE" are interpreted
     * as true, all other as false.
     */
    static bool readBoolEntry(const TQDomDocument &doc, const TQString &path, bool defaultEntry = false);
    /**
     * Reads a list entry. See writeListEntry().
     */
    static TQStringList readListEntry(const TQDomDocument &doc, const TQString &path, const TQString &tag);
    /**
     * Reads a list of string pairs. See writePairListEntry().
     */
    static PairList readPairListEntry(const TQDomDocument &doc, const TQString &path, const TQString &tag,
                                      const TQString &firstAttr, const TQString &secondAttr);
    /**
     * Reads a string to string map. See writeMapEntry()
     */
    static TQMap<TQString, TQString> readMapEntry(const TQDomDocument &doc, const TQString &path);
    /**
     * Retrieves an element by path, return null if any item along
     * the path does not exist.
     */
    static TQDomElement elementByPath( const TQDomDocument& doc, const TQString& path );
    /**
     * Retrieves an element by path, creating the necessary nodes.
     */
    static TQDomElement createElementByPath( TQDomDocument& doc, const TQString& path );
    /**
     * Retrieves a child element, creating it if it does not exist.
     * The return value is guaranteed to be non isNull()
     */
    static TQDomElement namedChildElement( TQDomElement& el, const TQString& name );
    /**
      Writes a string entry. For example,
      \verbatim
        <code>
          writeEntry(doc, "/general/special", "foo");
        </code>
      \endverbatim creates the %DOM fragment: \verbatim
        <code>
          <general><special>foo</special></general>
        </code>
      \endverbatim
     */
    static void writeEntry(TQDomDocument &doc, const TQString &path, const TQString &value);
    /**
     * Writes a number entry.
     */
    static void writeIntEntry(TQDomDocument &doc, const TQString &path, int value);
    /**
     * Writes a boolean entry. Booleans are stored as "true", "false" resp.
     */
    static void writeBoolEntry(TQDomDocument &doc, const TQString &path, bool value);
    /**
      Writes a string list element. The list elements are separated by tag. For example,
      \verbatim
        <code>
          TQStringList l; l << "one" << "two";
          writeListEntry(doc, "/general/special", "el", l);
        </code>
      \endverbatim creates the %DOM fragment: \verbatim
        <code>
          <general><special><el>one</el><el>two</el></special></general>
        </code>
      \endverbatim
     */
    static void writeListEntry(TQDomDocument &doc, const TQString &path, const TQString &tag,
                               const TQStringList &value);
    /**
      Writes a list of string pairs. The list elements are stored in the attributes
      firstAttr and secondAttr of elements named tag. For example,
      \verbatim
        <code>
          DomUtil::PairList l;
          l << DomUtil::StringPair("one", "1");
          l << DomUtil::StringPair("two", "2");
          writePairListEntry(doc, "/general/special", "el", "first", "second", l);
        </code>
      \endverbatim creates the %DOM fragment: \verbatim
        <code>
          <general><special>
            <el first="one" second="1"/>
            <el first="two" second="2"/>
          </special></general>
        </code>
      \endverbatim
     */
    static void writePairListEntry(TQDomDocument &doc, const TQString &path, const TQString &tag,
                                   const TQString &firstAttr, const TQString &secondAttr,
                                   const PairList &value);
    /**
     * Writes a string to string map. This map is stored in a way, that it can be read with
     * readMapEntry() and readEntry()
     */
    static void writeMapEntry(TQDomDocument &doc, const TQString& path, const TQMap<TQString,TQString> &map);

    /**
     * Resolves an extended path
     * Extended path format:
     * pathpart: tag[|attr1=value[;attr2=value;..][|matchNumber]]
     * where matchNumber is zero-based
     * path: pathpart[/pathpart/..]
     */
    static DomPath resolvPathStringExt(const TQString pathstring);

    /**
      Retrieve an element specified with extended path
      examples:

       - 1: "widget|class=TQDialog/property|name=geometry"
         or "widget|class=TQDialog/property||1"
       - 2: "widget/property|name=caption/string"
         or "widget/property||2/string"
       .
      \verbatim
        <widget class="TQDialog">
          <property name="name">
              <cstring>KdevFormName</cstring>
          </property>
          <property name="geometry">       <-- 1. reaches this node
              <rect>
                  <x>0</x>
                  <y>0</y>
                  <width>600</width>
                  <height>480</height>
              </rect>
          </property>
          <property name="caption">
              <string>KdevFormCaption</string>     <-- 2. reaches this node
          </property>
        </widget>
      \endverbatim
     */
    static TQDomElement elementByPathExt(TQDomDocument &doc, const TQString &pathstring);

    /**
    * Open file - filename - and set setContents of doc
    */
    static bool openDOMFile(TQDomDocument &doc, TQString filename);

    /**
    * Store contents of doc in file - filename. Existing file will be truncated!
    */
    static bool saveDOMFile(TQDomDocument &doc, TQString filename);

    /**
    * Remove all child text nodes of parent described in pathExt
    */
    static bool removeTextNodes(TQDomDocument doc,TQString pathExt);

    /**
    * Add child text node to parent described in pathExt
    */
    static bool appendText(TQDomDocument doc, TQString pathExt, TQString text);

    /**
    * Replace all chilt text nodes of parent described in pathExt with one new.
    */
    static bool replaceText(TQDomDocument doc, TQString pathExt, TQString text);

private:
    static TQString readEntryAux(const TQDomDocument &doc, const TQString &path);
};

#endif
