########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/Xslt/XPathDocumentDefinition.py,v 1.7 2005/04/06 23:05:46 jkloth Exp $
"""
XSLT extension elements and functions supporting the 4SS XPathDocumentDefinition API

Copyright 2004 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

import cStringIO

from Ft.Rdf import OBJECT_TYPE_LITERAL, OBJECT_TYPE_RESOURCE
from Ft.Server import FTSERVER_NAMESPACE
from Ft.Server.Common import DocumentDefinitionSerialization
from Ft.Xml import Domlette
from Ft.Xml.XPath import Conversions
from Ft.Xml.Xslt import XsltElement
from Ft.Xml.Xslt import ContentInfo, AttributeInfo
from Ft.Xml.Xslt import OutputParameters

from Ns import SCORE_NS
import FtssXsltBase


def GetNsMap(context, path=None):
    path = Conversions.StringValue(path)
    base = FtssXsltBase.FetchBaseObject(context.processor, path)
    doc = Domlette.implementation.createDocument(FTSERVER_NAMESPACE,'ftss:NsMap',None)
    DocumentDefinitionSerialization._SerializeNsMap(doc,base.getNsMap())
    return [doc]


def GetRdfMaps(context, path=None):
    path = Conversions.StringValue(path)
    base = FtssXsltBase.FetchBaseObject(context.processor, path)
    proc = context.processor
    proc.pushResult()
    for (s,p,o,t) in base.getRdfMaps():
        proc.writers[-1].startElement('RdfMapping')
        proc.writers[-1].startElement('Subject')
        proc.writers[-1].text(s)
        proc.writers[-1].endElement('Subject')
        proc.writers[-1].startElement('Predicate')
        proc.writers[-1].text(p)
        proc.writers[-1].endElement('Predicate')
        proc.writers[-1].startElement('Object')
        if t == OBJECT_TYPE_RESOURCE:
            proc.writers[-1].attribute('type',"RESOURCE")
        elif t == OBJECT_TYPE_LITERAL:
            proc.writers[-1].attribute('type',"LITERAL")
        proc.writers[-1].text(o)
        proc.writers[-1].endElement('Object')
        proc.writers[-1].endElement('RdfMapping')

    frag = proc.popResult()
    context.rtfs.append(frag)
    stmt_nodeset = frag.childNodes
    return stmt_nodeset


class RemoveNsMapElement(XsltElement):
    """
    Change the namespace mapping of this doc def.
    """

    content = ContentInfo.Empty

    legalAttrs = {
        'path' : AttributeInfo.UriReferenceAvt(
            description='The path of the document definition'),
        'prefix' : AttributeInfo.PrefixesAvt(
            required=1, description=('A whitespace-separated list of namespace'
                                     ' prefixes to remove.')),
        }

    def instantiate(self, context, processor):
        context.setProcessState(self)
        path = self._path.evaluate(context)
        prefixes = self._prefix.evaluate(context)
        base = FtssXsltBase.FetchBaseObject(processor, path)
        nsMap = base.getNsMap()
        for p in prefixes:
            if nsMap.has_key(p):
                del nsMap[p]

        base.setNsMap(nsMap);
        return


class AddNsMapElement(XsltElement):
    """
    Change the namespace mapping of this doc def.
    """

    content = ContentInfo.Empty

    legalAttrs = {
        'path' : AttributeInfo.UriReferenceAvt(
            description='The path of the document definition'),
        'prefix' : AttributeInfo.PrefixAvt(
            required=1, description='The prefix to add.'),
        'uri' : AttributeInfo.UriReferenceAvt(
            required=1, description='The uri to add.'),
        }

    def instantiate(self, context, processor):
        context.setProcessState(self)
        path = self._path.evaluate(context)
        prefix = self._prefix.evaluate(context)
        uri = self._uri.evaluate(context)
        base = FtssXsltBase.FetchBaseObject(processor, path)
        nsMap = base.getNsMap()
        nsMap[prefix] = uri
        base.setNsMap(nsMap);
        return


class AddRdfMapElement(XsltElement):
    """
    Change the rdf mapping of this doc def.
    """

    content = ContentInfo.Empty

    legalAttrs = {
        'path' : AttributeInfo.UriReferenceAvt(
            description='The path of the document definition'),
        'subject' : AttributeInfo.StringAvt(
            required=1, description='The subject to add.'),
        'predicate' : AttributeInfo.StringAvt(
            required=1, description='The predicate to add.'),
        'object' : AttributeInfo.StringAvt(
            required=1, description='The object to add.'),
        'object-is-resource' : AttributeInfo.YesNoAvt(
            required=1, description='Is the object a resource?'),
        }

    def instantiate(self, context, processor):
        context.setProcessState(self)

        path = self._path.evaluate(context)
        subject = self._subject.evaluate(context)
        predicate = self._predicate.evaluate(context)
        object = self._object.evaluate(context)
        ot = self._object_is_resource.evaluate(context)
        if ot:
            ot = OBJECT_TYPE_RESOURCE
        else:
            ot = OBJECT_TYPE_LITERAL
        base = FtssXsltBase.FetchBaseObject(processor, path)
        nm = (subject,predicate,object,ot)
        rMap = base.getRdfMaps()
        rMap.append(nm)
        base.setRdfMaps(rMap)
        return


class RemoveRdfMapElement(XsltElement):
    """
    Change the rdf mapping of this doc def.
    """

    content = ContentInfo.Empty

    legalAttrs = {
        'path' : AttributeInfo.UriReferenceAvt(
            description='The path of the document definition'),
        'subject' : AttributeInfo.StringAvt(
            required=1, description='The subject to add.'),
        'predicate' : AttributeInfo.StringAvt(
            required=1, description='The predicate to add.'),
        'object' : AttributeInfo.StringAvt(
            required=1, description='The object to add.'),
        }

    def instantiate(self, context, processor):
        context.setProcessState(self)

        path = self._path.evaluate(context)
        subject = self._subject.evaluate(context)
        predicate = self._predicate.evaluate(context)
        object = self._object.evaluate(context)
        base = FtssXsltBase.FetchBaseObject(processor, path)
        rMap = base.getRdfMaps()
        nMap = []
        for s,p,o,t in rMap:
            print s,subject,p,predicate,o,object
            if (s != subject or p != predicate or o != object):
                nMap.append((s,p,o,t))

        base.setRdfMaps(nMap)
        return


ExtFunctions = {
    (SCORE_NS, 'get-ns-map'): GetNsMap,
    (SCORE_NS, 'get-rdf-maps'): GetRdfMaps,
}

ExtElements = {
    (SCORE_NS, 'remove-ns-map'): RemoveNsMapElement,
    (SCORE_NS, 'add-ns-map'): AddNsMapElement,
    (SCORE_NS, 'add-rdf-map'): AddRdfMapElement,
    (SCORE_NS, 'remove-rdf-map'): RemoveRdfMapElement,
}
