"""
    DOM Nodes
    === =====
"""
# $Id: Node.py,v 1.2 2002/05/01 22:41:43 adrian Exp $
#
# $Log: Node.py,v $
# Revision 1.2  2002/05/01 22:41:43  adrian
# *** empty log message ***
#
# Revision 1.1.1.1  2002/02/03 17:07:16  root
#
#
# Revision 1.3  2001/10/31 01:25:47  adrian
# Fixed several problems with creation and editing of XMLFiles
# Fixed pretty-printing of XML (Indentation)
#
# Revision 1.2  2001/10/21 15:10:16  adrian
# no message
#
#
__version__ = '$Revision: 1.2 $'[11:-2]

import string
import xmllib
import urlparse
import httplib
import XMLParser
try:
    from Globals import Persistent, PersistentMapping
except:
    class Persistent:
        pass
    def PersistentMapping(value):
        return value

class _base(
        Persistent,
    ):
    """ Base class for all Node type objects """
# Always call this from your __init__
    def __init__(self):
        """ Set up the basic attributes that all nodes share """
        self._parent = None
        self._cdata = ''

# Do not override this
    def addCDATA(self, data):
        """ Add CDATA to this node """
        self._cdata = self._cdata + data

    def getCDATA(self):
        """ """
        return self._cdata

# Do not override this
    def __cmp__(self, other):
        """ A little hack to allow __getattr__ below """
        if other:
            return cmp(self.__dict__, other.__dict__)
        else:
            return cmp(self.__dict__, other)

# Override this
    def __str__(self, prettyLevel=0):
        """ Output this node as XML """
        data = ''
        if hasattr(self, '_cdata') and self._cdata:
            data = data + "%s" % XMLParser.encode(str(self._cdata))
        return data

# Do not override this
    def dump(self, prettyLevel=0):
        """ Encode this node's XML for screen output """
        return XMLParser.encode(self.__str__(prettyLevel))

class _children(
        Persistent,
    ):
    """ Mixin with children support """
    def __init__(self):
        """ """
        self._children = []

    def addChild(self, child):
        """ Add a node to the children list """
        list = self._children
        list.append(child)
        self._children = list
        child._parent = self
        return child

    def delChild(self, item):
        """ """
        list = []
        for child in self._children:
            if child!=item:
                list.append(child)
        self._children = list

    def getChildrenByName(self, name=None):
        """ Return all children (Optionally matching 'name') """
        list = []
        for item in self._children:
            if hasattr(item, '_tag') and (name == None or item._tag == name):
                list.append(item)
        return list

    def getNextChildByName(self, name=None, start=None):
        """ Return next child (Optionally matching 'name') """
        found = start == None
        for item in self._children:
            if found and hasattr(item, '_tag') and (name == None or item._tag == name):
                return item
            if item == start:
                found = 1
        return None

    def getChildrenByType(self, t=None):
        """ """
        list = []
        for item in self._children:
            if t==None or type(item._children)==type(t):
                list.append(item)
        return list

    def getNextChildByType(self, t=None, start=None):
        """ """
        found = start == None
        for item in self._children:
            if found and (t == None or type(item._children) == type(t)):
                return item
            if item == start:
                found = 1
        return None

    def __str__(self, prettyLevel=0):
        """ Dump the children of this node """
        data = ""
        if self._children:
            data = data + "\n"
            for item in self._children:
                data = data + item.__str__(prettyLevel+1)
        return data

class _attrs(
        Persistent,
    ):
    """ Mixin class with attribute support """
    def __init__(self, attrs):
        """ """
        self._attrs = PersistentMapping(attrs)

    def getAttr(self, key, default=None):
        """ """
        if self._attrs.has_key(key):
            return self._attrs[key]
        else:
            return default

    def __getitem__(self, key, default=None):
        """ """
        return self.getAttr(key, default)

    def __setitem__(self, key, value):
        """ """
        self._attrs[key]=value

    def __delitem__(self, key):
        """ """
        if self._attrs.has_key(key):
            del self._attrs[key]

    def keys(self):
        """ """
        return self._attrs.keys()

    def has_key(self, key):
        """ """
        return self._attrs.has_key(key)

    def __str__(self, prettyLevel=0):
        """ Output the attributes of this node """
        data = ''
        for item in self._attrs.keys():
            data = data + ' %s="%s"' % (item, XMLParser.encode(str(self._attrs[item])), )
        return data

class Document(
        _base,
        _children,
    ):
    """ """
    def __init__(self):
        _base.__init__(self)
        _children.__init__(self)

    def __str__(self, prettyLevel=0):
        """ """
        data = _children.__str__(self, prettyLevel-1)
        return data

class Node(
        _base,
        _children,
        _attrs,
    ):
    """ """
    def __init__(self, tag, ns='', attrs=None):
        """ Create this node """
        _base.__init__(self)
        _children.__init__(self)
        _attrs.__init__(self, attrs)
        self._tag = tag
        self._ns = ns

    def getTag(self):
        """ Return this entities tag """
        return self._tag

    def __str__(self, prettyLevel=0):
        """ Output this node and its children """
        data = ''
        for count in range(0, prettyLevel):
            data = data + ' '
        data = data + "<%s" % self._tag
        data = data + _attrs.__str__(self, prettyLevel)
        inner = _base.__str__(self, prettyLevel) + _children.__str__(self, prettyLevel)
        if inner:
            data = data + ">"
            data = data + inner
            if inner[-1]=='\n':
                for count in range(0, prettyLevel):
                    data = data + ' '
            data = data + "</%s>\n" % self._tag
        else:
            data = data + " />\n"
        return data

class PINode(
        _base,
        _attrs,
    ):
    """ """
    def __init__(self, name, data=''):
        """ """
        _base.__init__(self)
        attrs = {}
        data = string.strip(data)
        items = string.split(data)
        for item in items:
            ti = string.split(item, '=', 1)
            if ti[1][0] == '"' and ti[1][-1] == '"':
                ti[1] = ti[1][1:-1]
            attrs[ti[0]] = ti[1]
        _attrs.__init__(self, attrs)
        self._tag = name

    def __str__(self, prettyLevel=0):
        """ """
        data = "<?%s" % self._tag
        data = data + _attrs.__str__(self, prettyLevel)
        data = data + "?>\n"
        return data

class XMLNode(
        PINode,
    ):
    """ """
    def __init__(self, encoding='', standalone=''):
        """ """
        PINode.__init__(self, 'xml', '')
        self._version = '1.0'
        if encoding:
            self['encoding'] = encoding
        if standalone:
            self['standalone'] = standalone

    def __str__(self, prettyLevel=0):
        """ """
        if self.has_key('version'):
            self._version = self['version']
            del self['version']
        data = '<?%s version="%s"' % (self._tag, self._version)
        data = data + _attrs.__str__(self, prettyLevel)
        data = data + "?>\n"
        return data

class DocType(
        _base,
        _attrs,
    ):
    """ """
    def __init__(self, tag, pubid='', syslit='', data=''):
        """ """
        _base.__init__(self)
        _attrs.__init__(self, {})
        self['tag'] = tag
        if pubid:
            self['pubid'] = pubid
        if syslit:
            self['syslit'] = syslit
        if data:
            self['data'] = data

    def __str__(self, prettyLevel=0):
        """ """
        data = "<!DOCTYPE %s" % self['tag']
        if self.has_key('pubid'):
            data = data + ' PUBLIC "%s"' % self['pubid']
        else:
            data = data + ' SYSTEM'
        if self.has_key('syslit'):
            data = data + ' "%s"' % self['syslit']
        if self.has_key('data'):
            data = data + ' [%s]' % self['data']
        data = data + ">\n"
        return data

class CommentNode(
        _base,
    ):
    """ """
    def __init__(self, data=''):
        """ """
        _base.__init__(self)
        self._cdata = data

    def __str__(self, prettyLevel=0):
        """ """
        data = '<!-- %s -->\n' % self._cdata
        return data
