########################################################################
#
# File Name:   XPointer.py
#
# Docs:        http://docs.4suite.org/XPointer/XPointer.py.html
#
"""
A Parsed Token that represents a list of XPointers
WWW: http://4suite.org/XPointer        e-mail: support@4suite.org

Copyright (c) 2000-2001 Fourthought Inc, USA.   All Rights Reserved.
See  http://4suite.org/COPYRIGHT  for license and copyright information
"""

from xml.dom import Node
from Ft.Xml.XPath import Util
from Ft.Xml.XPointer import XPtrException

class BareName:
    def __init__(self, name):
        self.name = name

    def select(self, context):
        doc = context.node.rootNode
        if hasattr(doc, 'getElementById'):
            element = doc.getElementById(self.name)
        else:
            # May raise ValueError
            element = Util.GetElementById(doc, self.name)

        if not element:
            raise XPtrException(XPtrException.SUB_RESOURCE_ERROR)
        return element

    def pprint(self, indent=''):
        print indent + str(self)

    def __str__(self):
        return '<BareName at %x: %s>' % (id(self), self.name)

    def __repr__(self):
        return self.name


class ChildSequence:
    def __init__(self, sequence):
        if type(sequence[0]) != type(1):
            self.bareName = sequence[0]
            self.sequence = sequence[1:]
        else:
            self.bareName = None
            self.sequence = sequence

    def select(self, context):
        if self.bareName:
            node = self.bareName.select(context)
        else:
            node = context.node.rootNode
        for index in self.sequence:
            elements = filter(lambda child:
                              child.nodeType == Node.ELEMENT_NODE,
                              node.childNodes)
            try:
                node = elements[index-1]
            except IndexError:
                raise XPtrException(XPtrException.SUB_RESOURCE_ERROR)
        return node

    def pprint(self, indent=''):
        print indent + str(self)

    def __str__(self):
        return '<ChildSequence at %x: %s>' % (id(self), repr(self))

    def __repr__(self):
        result = self.bareName and repr(self.bareName) or ''
        for index in self.sequence:
            result = result + '/%d' % index
        return result


class FullXPtr:
    def __init__(self, parts):
        self.parts = parts

    def select(self, context):
        for part in self.parts:
            node_set = part.evaluate(context)
            if len(node_set) == 1:
                return node_set[0]
            elif node_set:
                # The scheme found more than 1 node
                raise XPtrException(XPtrException.SUB_RESOURCE_ERROR)
            # Nothing found, try the next one
        # No schemes found an node
        raise XPtrException(XPtrException.SUB_RESOURCE_ERROR)

    def pprint(self, indent=''):
        print indent + str(self)
        for part in self.parts:
            part.pprint(indent + '  ')

    def __str__(self):
        return '<FullXPtr at %x: %s>' % (id(self), repr(self))

    def __repr__(self):
        return ' '.join(map(lambda p: repr(p), self.parts))
