""" ifrist adapters

$Id: adapters.py,v 1.2 2007/02/09 13:47:31 tseaver Exp $
"""
import warnings

from StringIO import StringIO

from zope.interface import implements
from zope.interface import classImplements
from zope.interface import directlyProvides

from ifrit.interfaces import IElement
from ifrit.interfaces import IElementFactory
from ifrit.interfaces import IXMLSerialization

try:
    from lxml.etree import XML as _XML
    from lxml.etree import ElementBase
    from lxml.etree import ElementDefaultClassLookup
    from lxml.etree import XMLParser

    class _MarkableElement(ElementBase):
        implements(IElement)

    _lookup = ElementDefaultClassLookup(element=_MarkableElement)
    _parser = XMLParser()
    _parser.setElementClassLookup(_lookup)

    def XML(stringvalue):
        return _XML(stringvalue, _parser)

except ImportError:  # fall back to Python's elementtree
    warnings.warn('ifrit: No lxml, falling back pure-python elementtree')
    from elementtree.ElementTree import XML

class OFSFileAsXML(object):
    """ "Convert" OFS.Image.File-like object to XML.

    o Assume that the 'data' element is a string, unicode, or a pdata chunk,
      containing the actual XML to be returned.
    """
    implements(IXMLSerialization)

    def __init__(self, context):
        self.context = context

    def serialize(self, buffer):
        data = self.context.data
        if isinstance(data, str):
            buffer.write(data)
        elif isinstance(data, unicode):
            buffer.write(data.encode('utf8'))
        else:
            while data is not None:
                buffer.write(data.data)
                data = data.next

class ElementMaker(object):
    """ Adapter factories which use paths to find nodes.
    """
    implements(IElementFactory)

    def __init__(self, path=None, marker=IElement):
        self.path = path
        self.marker = marker

    def __call__(self, context):
        buffer = StringIO()

        adapter = IXMLSerialization(context)
        adapter.serialize(buffer)
        tree = XML(buffer.getvalue())

        if self.path is not None:
            node = tree.find(self.path)
        else:
            node = tree

        if node is not None:
            directlyProvides(node, self.marker)

        return node
