# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/
# Copyright (c) 2010, Eucalyptus Systems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import xml.sax
import utils

class XmlHandler(xml.sax.ContentHandler):

    def __init__(self, root_node, connection):
        self.connection = connection
        self.nodes = [('root', root_node)]
        self.current_text = ''

    def startElement(self, name, attrs):
        self.current_text = ''
        t = self.nodes[-1][1].startElement(name, attrs, self.connection)
        if t != None:
            if isinstance(t, tuple):
                self.nodes.append(t)
            else:
                self.nodes.append((name, t))

    def endElement(self, name):
        self.nodes[-1][1].endElement(name, self.current_text, self.connection)
        if self.nodes[-1][0] == name:
            self.nodes.pop()
        self.current_text = ''

    def characters(self, content):
        self.current_text += content

    def parse(self, s):
        xml.sax.parseString(s, self)
        
class Element(dict):

    def __init__(self, connection=None, element_name=None,
                 stack=None, parent=None, list_marker=('Set',),
                 item_marker=('member', 'item'),
                 pythonize_name=False):
        dict.__init__(self)
        self.connection = connection
        self.element_name = element_name
        self.list_marker = utils.mklist(list_marker)
        self.item_marker = utils.mklist(item_marker)
        if stack is None:
            self.stack = []
        else:
            self.stack = stack
        self.pythonize_name = pythonize_name
        self.parent = parent

    def __getattr__(self, key):
        if key in self:
            return self[key]
        for k in self:
            e = self[k]
            if isinstance(e, Element):
                try:
                    return getattr(e, key)
                except AttributeError:
                    pass
        raise AttributeError

    def get_name(self, name):
        if self.pythonize_name:
            name = utils.pythonize_name(name)
        return name

    def startElement(self, name, attrs, connection):
        self.stack.append(name)
        for lm in self.list_marker:
            if name.endswith(lm):
                l = ListElement(self.connection, name, self.list_marker,
                                self.item_marker, self.pythonize_name)
                self[self.get_name(name)] = l
                return l
        if len(self.stack) > 0:
            element_name = self.stack[-1]
            e = Element(self.connection, element_name, self.stack, self,
                        self.list_marker, self.item_marker,
                        self.pythonize_name)
            self[self.get_name(element_name)] = e
            return (element_name, e)
        else:
            return None

    def endElement(self, name, value, connection):
        if len(self.stack) > 0:
            self.stack.pop()
        value = value.strip()
        if value:
            if isinstance(self.parent, Element):
                self.parent[self.get_name(name)] = value
            elif isinstance(self.parent, ListElement):
                self.parent.append(value)

class ListElement(list):

    def __init__(self, connection=None, element_name=None,
                 list_marker=['Set'], item_marker=('member', 'item'),
                 pythonize_name=False):
        list.__init__(self)
        self.connection = connection
        self.element_name = element_name
        self.list_marker = list_marker
        self.item_marker = item_marker
        self.pythonize_name = pythonize_name

    def get_name(self, name):
        if self.pythonize_name:
            name = utils.pythonize_name(name)
        return name

    def startElement(self, name, attrs, connection):
        for lm in self.list_marker:
            if name.endswith(lm):
                l = ListElement(self.connection, name,
                                self.list_marker, self.item_marker,
                                self.pythonize_name)
                setattr(self, self.get_name(name), l)
                return l
        if name in self.item_marker:
            e = Element(self.connection, name, parent=self,
                        list_marker=self.list_marker,
                        item_marker=self.item_marker,
                        pythonize_name=self.pythonize_name)
            self.append(e)
            return e
        else:
            return None

    def endElement(self, name, value, connection):
        if name == self.element_name:
            if len(self) > 0:
                empty = []
                for e in self:
                    if isinstance(e, Element):
                        if len(e) == 0:
                            empty.append(e)
                for e in empty:
                    self.remove(e)
        else:
            setattr(self, self.get_name(name), value)
