Logo Search packages:      
Sourcecode: afnix version File versions

XmlNode.cpp

// ---------------------------------------------------------------------------
// - XmlNode.cpp                                                             -
// - afnix:xml module - xml base node class implementation                   -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  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.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "XmlNode.hpp"
#include "Integer.hpp"
#include "Boolean.hpp"
#include "Runnable.hpp"
#include "XmlSystem.hpp"
#include "XmlReader.hpp"
#include "QuarkZone.hpp"
#include "Exception.hpp"

namespace afnix {

  // -------------------------------------------------------------------------
  // - class section                                                         -
  // -------------------------------------------------------------------------

  // create an empty node

00034   XmlNode::XmlNode (void) {
    d_eflg = false;
    p_pnod = nilp;
  }

  // create a node with an empty flag

00041   XmlNode::XmlNode (const bool eflg) {
    d_eflg = eflg;
    p_pnod = nilp;
  }

  // destroy this node

00048   XmlNode::~XmlNode (void) {
    Object::dref (p_pnod);
  }

  // return the document class name

00054   String XmlNode::repr (void) const {
    return "XmlNode";
  }

  // make this document shared

00060   void XmlNode::mksho (void) {
    if (p_shared != nilp) return;
    Object::mksho ();
    d_chld.mksho  ();
  }

  // get the empty flag

00068   bool XmlNode::geteflg (void) const {
    rdlock ();
    bool result = d_eflg;
    unlock ();
    return result;
  }

  // set the source line number
  
00077   void XmlNode::setlnum (const long lnum) {
    wrlock ();
    d_lnum = lnum;
    unlock ();
  }

  // get the source line number

00085   long XmlNode::getlnum (void) const {
    rdlock ();
    long result= d_lnum;
    unlock ();
    return result;
  }

  // set the node source name
  
00094   void XmlNode::setsnam (const String& snam) {
    wrlock ();
    d_snam = snam;
    unlock ();
  }

  // get the node source name

00102   String XmlNode::getsnam (void) const {
    rdlock ();
    String result= d_snam;
    unlock ();
    return result;
  }

  // check if a node name is valid

00111   bool XmlNode::isname (const String& name) const {
    rdlock ();
    bool result = false;
    unlock ();
    return result;
  }

  // get the parent node

00120   XmlNode* XmlNode::getparent (void) const {
    rdlock ();
    XmlNode* result = p_pnod;
    unlock ();
    return result;
  }

  // set the parent node

00129   void XmlNode::setparent (XmlNode* node) {
    wrlock ();
    Object::iref (node);
    Object::dref (p_pnod);
    p_pnod = node;
    unlock ();
  }

  // return true if there is no children

00139   bool XmlNode::nilchild (void) const {
    rdlock ();
    try {
      bool result = d_chld.empty ();
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return the number of children nodes

00153   long XmlNode::lenchild (void) const {
    rdlock ();
    try {
      long result = d_chld.length ();
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // append a child node to this node

00167   void XmlNode::addchild (XmlNode* node) {
    // check for nil first
    if (node == nilp) return;
    // lock, mark parent and append
    wrlock ();
    try {
      if (d_eflg == true) {
      throw Exception ("xml-error", "trying to add node in empty node");
      }
      // set the parent node
      node->setparent (this);
      // append the node
      d_chld.append (node);
      unlock ();
    } catch (...) {
      unlock();
      throw;
    }
  }

  // get a child node by index

00189   XmlNode* XmlNode::getchild (const long index) const {
    rdlock ();
    try {
      XmlNode* node = dynamic_cast <XmlNode*> (d_chld.get (index));
      unlock ();
      return node;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // get a child node by name if possible

00203   XmlNode* XmlNode::getchild (const String& name) const {
    rdlock ();
    try {
      long clen = lenchild ();
      for (long i = 0; i < clen; i++) {
      XmlNode* node = getchild (i);
      if (node == nilp) continue;
      if (node->isname (name) == true) {
        unlock ();
        return node;
      }
      }
      unlock ();
      return nilp;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // find a node by name or throw an exception

00225   XmlNode* XmlNode::lookchild (const String& name) const {
    rdlock ();
    try {
      XmlNode* result = getchild (name);
      if (result == nilp) {
      throw Exception ("lookup-error", "cannot find child node", name);
      }
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // parse a string and add the result as child nodes

00242   void XmlNode::parse (const String& s) {
    wrlock ();
    try {
      // create a default reader
      XmlReader xmlr;
      // parse the string
      xmlr.parse (s);
      // get the result root node
      XmlRoot* root = xmlr.getroot ();
      // get the child length and copy the nodes
      long nlen = (root == nilp) ? 0 : root->lenchild ();
      for (long i = 0; i < nlen; i++) addchild (root->getchild (i));
      // done
      unlock ();
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // -------------------------------------------------------------------------
  // - object section                                                        -
  // -------------------------------------------------------------------------

  // the quark zone
  static const long QUARK_ZONE_LENGTH = 14;
  static QuarkZone  zone (QUARK_ZONE_LENGTH);

  // the object supported quarks
  static const long QUARK_WRITE     = zone.intern ("write");
  static const long QUARK_NAMEP     = zone.intern ("name-p");
  static const long QUARK_PARSE     = zone.intern ("parse");
  static const long QUARK_GETPARENT = zone.intern ("get-parent");
  static const long QUARK_SETPARENT = zone.intern ("set-parent");
  static const long QUARK_ADDCHILD  = zone.intern ("add-child");
  static const long QUARK_GETCHILD  = zone.intern ("get-child");
  static const long QUARK_NILCHILDP = zone.intern ("nil-child-p");
  static const long QUARK_LOOKCHILD = zone.intern ("lookup-child");
  static const long QUARK_CHILDLEN  = zone.intern ("child-length");
  static const long QUARK_GETLNUM   = zone.intern ("get-source-line");
  static const long QUARK_SETLNUM   = zone.intern ("set-source-line");
  static const long QUARK_GETSNAM   = zone.intern ("get-source-name");
  static const long QUARK_SETSNAM   = zone.intern ("set-source-name");

  // return true if the given quark is defined

00288   bool XmlNode::isquark (const long quark, const bool hflg) const {
    rdlock ();
    if (zone.exists (quark) == true) {
      unlock ();
      return true;
    }
    bool result = hflg ? Object::isquark (quark, hflg) : false;
    unlock ();
    return result;
  }

  // apply this object with a set of arguments and a quark

00301   Object* XmlNode::apply (Runnable* robj, Nameset* nset, const long quark,
                    Vector* argv) {
    // get the number of arguments
    long argc = (argv == nilp) ? 0 : argv->length ();

    // check for 0 argument
    if (argc == 0) {
      if (quark == QUARK_CHILDLEN)  return new Integer (lenchild ());
      if (quark == QUARK_GETLNUM)   return new Integer (getlnum  ());
      if (quark == QUARK_GETSNAM)   return new String  (getsnam  ());
      if (quark == QUARK_NILCHILDP) return new Boolean (nilchild ());
      if (quark == QUARK_GETPARENT) {
      rdlock ();
      Object* result = getparent ();
      robj->post (result);
      unlock ();
      return result;
      }
      if (quark == QUARK_WRITE) {
      Output* os = (robj == nilp) ? nilp : robj->getos ();
      if (os == nilp) return nilp;
      write (*os);
      return nilp;
      }
    }
    // check for 1 argument
    if (argc == 1) {
      if (quark == QUARK_NAMEP) {
      String name= argv->getstring (0);
      return new Boolean (isname (name));
      }
      if (quark == QUARK_PARSE) {
      String s = argv->getstring (0);
      parse (s);
      return nilp;
      }
      if (quark == QUARK_SETPARENT) {
      // get the node object
      Object*   obj = argv->get (0);
      XmlNode* node = dynamic_cast <XmlNode*> (obj);
      if ((obj != nilp) && (node == nilp)) {
        throw Exception ("type-error", "invalid object with set-parent",
                     Object::repr (obj));
      }
      // set the node
      setparent (node);
      return nilp;
      }
      if (quark == QUARK_ADDCHILD) {
      // get the node object
      Object*   obj = argv->get (0);
      XmlNode* node = dynamic_cast <XmlNode*> (obj);
      if ((obj != nilp) && (node == nilp)) {
        throw Exception ("type-error", "invalid object with add-child",
                     Object::repr (obj));
      }
      // set the node
      addchild (node);
      return nilp;
      }
      if (quark == QUARK_WRITE) {
      Object* obj = argv->get (0);
      // check for an output stream
      Output* os = dynamic_cast <Output*> (obj);
      if (os != nilp) {
        write (*os);
        return nilp;
      }
      // check for a buffer
      Buffer* buf = dynamic_cast <Buffer*> (obj);
      if (buf != nilp) {
        write (*buf);
        return nilp;
      }
      throw Exception ("type-error", "invalid object with write",
                   Object::repr (obj));
      }
      if (quark == QUARK_GETCHILD) {
      Object* obj = argv->get (0);
      // check for an integer
      Integer* iobj = dynamic_cast <Integer*> (obj);
      if (iobj != nilp) {
        long index = iobj->tointeger ();
        rdlock ();
        try {
          XmlNode* result = getchild (index);
          robj->post (result);
          unlock ();
          return result;
        } catch (...) {
          unlock ();
          throw;
        }
      }
      // check for a string
      String* sobj = dynamic_cast <String*> (obj);
      if (sobj != nilp) {
        rdlock ();
        try {
          XmlNode* result = getchild (*sobj);
          robj->post (result);
          unlock ();
          return result;
        } catch (...) {
          unlock ();
          throw;
        }
      }
      throw Exception ("type-error", "invalid object with get-child",
                   Object::repr (obj));
      }
      if (quark == QUARK_LOOKCHILD) {
      String name = argv->getstring (0);
      rdlock ();
      try {
        XmlNode* result = lookchild (name);
        robj->post (result);
        unlock ();
        return result;
      } catch (...) {
        unlock ();
        throw;
      }
      }
      if (quark == QUARK_SETLNUM) {
      long lnum = argv->getint (0);
      setlnum (lnum);
      return nilp;
      }
      if (quark == QUARK_SETSNAM) {
      String snam = argv->getstring (0);
      setsnam (snam);
      return nilp;
      }
    }
    // call the object method
    return Object::apply (robj, nset, quark, argv);
  }
}

Generated by  Doxygen 1.6.0   Back to index