"""
This class produces an XML file representing the contents of a folder in
the Zope tree. This can either be in RSS format or plain XML.

You can select to sort on one of a handful of Zope standard properties, and
based on this sort order, RSS will only list the first 15 objects found.

RSS Entities:
rss version="0.91"
    channel
        title             =   folder.title_or_id
        description       =   self.title
        link              =   self.channellink
        item
            title         =   item.getId (or item.title)
            description   =   item.title (or item.description)
            link          =   item.absolute_url

Plain XML Entities:
folder
    id            =   folder.title_or_id
    title         =   self.title
    url           =   folder.absolute_url
    link          =   self.channellink
    meta_type     =   folder.meta_type
    icon          =   (absolute_url of icon)
    object
        id        =   object.getId
        title     =   object.title
        url       =   object.absolute_url
        meta_type =   object.meta_type
        icon      =   (absolute_url of icon)
"""
# $Id: XMLFolderIndex.py,v 1.1.1.1 2002/02/03 17:07:16 root Exp $
#
# $Log: XMLFolderIndex.py,v $
# Revision 1.1.1.1  2002/02/03 17:07:16  root
#
#
# Revision 1.6  2001/11/14 17:08:49  adrian
# Corrected Auto Update bug where changing properties failed to
# cause a data-reload.
# Changed XMLODBCClient to return brains instead of XML
# (DOM(self) returns the DOM for clients if required)
#
# Revision 1.5  2001/10/31 01:25:46  adrian
# Fixed several problems with creation and editing of XMLFiles
# Fixed pretty-printing of XML (Indentation)
#
# Revision 1.4  2001/10/29 09:20:48  adrian
# Cleaned up a number of "Ambiguous name..." warnings
#
# Revision 1.3  2001/10/24 15:34:12  adrian
# Completed factoring out common code into 3 base classes
# (XMLClientBase, XMLServerBase, and XMLReloadBase)
#
# Completed XMLProxy.
#
# Revision 1.2  2001/10/21 15:10:15  adrian
# no message
#
#
__version__ = '$Revision: 1.1.1.1 $'[11:-2]

import Globals
import AccessControl.Role
import OFS.SimpleItem
import OFS.PropertyManager
import Persistence
import Acquisition
import XML
import OFS.History
import DateTime
import urllib
import XMLDocument
import XMLKitBase

manage_addXMLFolderIndexForm = Globals.HTMLFile('www/addXMLFolderIndex', globals())
def manage_addXMLFolderIndex(self, id='', title='', rss='', submit=None, REQUEST=None):
    """ """
    if not id:
        id = 'index_xml'
    if not title:
        title = 'XML Index of %s' % self.title_and_id()
    obj = XMLFolderIndex(str(id), str(title), rss=='1' and 1 or 0)
    self._setObject(obj.getId(), obj)
    if REQUEST is not None:
        try: u=self.DestinationURL()
        except: u=REQUEST['URL1']
        if submit==" Add and Edit ": u="%s/%s" % (u, urllib.quote(obj.getId()))
        REQUEST.RESPONSE.redirect(u+'/manage_workspace')
    return ''

class XMLFolderIndex(
        XMLKitBase.XMLReloadBase,
        XMLKitBase.XMLServerBase,
        OFS.PropertyManager.PropertyManager,
        OFS.SimpleItem.SimpleItem,
        Persistence.Persistent,
        Acquisition.Implicit,
        AccessControl.Role.RoleManager,
        OFS.History.Historical,
    ):
    """ Create an XML listing of the contents of a folder """
    id = "XMLFolderIndex"
    title = "XML Folder Index"
    meta_type = "XML Folder Index"
    manage_main = OFS.PropertyManager.PropertyManager.manage_propertiesForm
    manage_main.setName('manage_main')
    index_html = None

    # Masquerade as function:
    class func_code: pass
    func_code=func_code()
    func_code.co_varnames='self','REQUEST','RESPONSE'
    func_code.co_argcount=3

    manage_options = (
        OFS.PropertyManager.PropertyManager.manage_options +
        XMLKitBase.XMLServerBase.manage_options +
        XMLKitBase.XMLReloadBase.manage_options +
        OFS.History.Historical.manage_options +
        OFS.SimpleItem.SimpleItem.manage_options
    )
    _properties=(
        (
            {'id':  'title',        'type': 'string',   'mode': 'w'},
            {'id':  'rss',          'type': 'boolean',  'mode': 'w'},
            {'id':  'itemlimit',    'type': 'int',      'mode': 'w'},
            {'id':  'channellink',  'type': 'string',   'mode': 'w'},
            {'id':  'excludeIds',   'type': 'lines',    'mode': 'w'},
            {'id':  'sort',         'type': 'selection','mode': 'w',
             'select_variable': 'sortKeys'},
        ) +
        XMLKitBase.XMLServerBase._properties +
        XMLKitBase.XMLReloadBase._properties
    )
    sortKeys = (
        '',
        'bobobase_modification_time',
        'getId',
        'title_and_id',
        'meta_type',
    )
    sort = ''
    channellink = ''
    itemlimit = 0
    excludeIds = []

    def __init__(self, id, title, rss):
        """ """
        self.id = id
        self.title = title
        self.rss = rss
        self._internal_initEmpty()

    def _internal_initEmpty(self):
        """ Clear the DOM """
        self.DOM = XML.Node.Document()

    def _internal_reload(self):
        """ Reload the XML data """
        self._internal_initEmpty()
        self.DOM.addChild(XML.Node.XMLNode())
        self.DOM.addChild(XML.Node.CommentNode("XML Data Cached: %s" % DateTime.DateTime().rfc822()))
        if self.itemlimit:
            self.DOM.addChild(XML.Node.CommentNode("Item Limit: %d" % self.itemlimit))
        if self.reloadtimer:
            self.DOM.addChild(XML.Node.CommentNode("Age Limit: %d minutes" % self.reloadtimer))
        if self.sort:
            self.DOM.addChild(XML.Node.CommentNode("Sort Key: %s" % self.sort))
        folder = self.aq_parent
        id = folder.getId()
        title = folder.title_or_id()
        url = folder.absolute_url()
        link = self.channellink
        if link:
            try:
                linkItem = self.unrestrictedTraverse(link)
                link = linkItem.absolute_url()
            except:
                pass
        icon = folder.icon
        if callable(icon): icon = icon()
        REQUEST = self.REQUEST
        icon = "%s/%s" % (REQUEST['BASE1'], icon)
        meta_type = folder.meta_type
        if callable(meta_type): meta_type = meta_type()
        if self.rss:
            rss = self.DOM.addChild(XML.Node.Node('rss'))
            rss['version'] = '0.91'
            fld = rss.addChild(XML.Node.Node('channel'))
            fld.addChild(XML.Node.Node('title')).addCDATA(title)
            fld.addChild(XML.Node.Node('description')).addCDATA(self.title)
            fld.addChild(XML.Node.Node('link')).addCDATA(link)
        else:
            fld = self.DOM.addChild(XML.Node.Node('folder'))
            fld.addChild(XML.Node.Node('id')).addCDATA(id)
            fld.addChild(XML.Node.Node('title')).addCDATA(title)
            fld.addChild(XML.Node.Node('description')).addCDATA(self.title)
            fld.addChild(XML.Node.Node('url')).addCDATA(url)
            fld.addChild(XML.Node.Node('link')).addCDATA(link)
            fld.addChild(XML.Node.Node('meta_type')).addCDATA(meta_type)
            fld.addChild(XML.Node.Node('icon')).addCDATA(icon)
        cnt = 0
        list = folder.objectValues()
        if self.sort:
            list.sort(self._sort)
        for item in list:
            meta_type = item.meta_type
            if not hasattr(self, 'excludeIds'):
                self.excludeIds = []
            if callable(meta_type): meta_type = meta_type()
            if not (meta_type in (XMLFolderIndex.meta_type,
                    XMLDocument.XMLDocument.meta_type,
                    XMLDocument.RSSDocument.meta_type)
                    ) and item.getId() not in self.excludeIds:
                cnt = cnt + 1
                if self.itemlimit and (cnt > self.itemlimit):
                    break
                id = item.getId()
                title = item.title
                if callable(title): title = title()
                url = item.absolute_url()
                if hasattr(item, 'link'):
                    url = getattr(item, 'link')
                    if url[0] == '/':
                        linkItem = self.unrestrictedTraverse(url)
                        url = linkItem.absolute_url()
                if hasattr(item, 'description'):
                    description = getattr(item, 'description')
                    if callable(description): description = description()
                else:
                    description = None
                icon = item.icon
                if callable(icon): icon = icon()
                icon = "%s/%s" % (REQUEST['BASE1'], icon)
                if self.rss:
                    itm = fld.addChild(XML.Node.Node('item'))
                    if description:
                        itm.addChild(XML.Node.Node('title')).addCDATA(title)
                        itm.addChild(XML.Node.Node('description')).addCDATA(description)
                    else:
                        itm.addChild(XML.Node.Node('title')).addCDATA(id)
                        itm.addChild(XML.Node.Node('description')).addCDATA(title)
                    itm.addChild(XML.Node.Node('link')).addCDATA(url)
                else:
                    itm = fld.addChild(XML.Node.Node('object'))
                    itm.addChild(XML.Node.Node('id')).addCDATA(id)
                    itm.addChild(XML.Node.Node('title')).addCDATA(title)
                    if description:
                        itm.addChild(XML.Node.Node('description')).addCDATA(description)
                    itm.addChild(XML.Node.Node('url')).addCDATA(url)
                    itm.addChild(XML.Node.Node('meta_type')).addCDATA(meta_type)
                    itm.addChild(XML.Node.Node('icon')).addCDATA(icon)

    def _internal_getDOMref(self):
        """ Return a reference to the DOM """
        return self.DOM

    def _internal_setDOMref(self, newDOM):
        """ replace the DOM with a new one """
        self.DOM = newDOM

    def _sort(self, item1, item2):
        """ """
        k1 = getattr(item1, self.sort)
        if callable(k1): k1 = k1()
        k2 = getattr(item2, self.sort)
        if callable(k2): k2 = k2()
        if self.sort == 'bobobase_modification_time':
            return cmp(k2, k1)
        else:
            return cmp(k1, k2)

Globals.default__class_init__(XMLFolderIndex)
