#!/usr/bin/python

#
# Copyright (C) 2005 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

from xml.dom.minidom import Node, parse, parseString
import sys
from common import *

"""Class representing an XML file dump from GConf
i.e. the result of gconftool-2 --dump /apps/evolution
"""
class GConfEntries:
    def __init__(self, dom):
        self.dom = dom

    """Allow a visitor to visit each key.value pair in turn, allowing modifications,
    and removing any for which the visitor returns False"""
    def accept(self, visitor):
        gconfentrylistElement = self.dom.documentElement
        entrylistElement = gconfentrylistElement.getElementsByTagName("entrylist").item(0)
        base_key = entrylistElement.getAttribute("base")
        # traverse the values:
        for entryElement in entrylistElement.getElementsByTagName("entry"):
            keyElement = entryElement.getElementsByTagName("key").item(0)
            valueElement = entryElement.getElementsByTagName("value").item(0)
            if (not visitor.visitKeyValue(base_key+"/"+getTextBelow(keyElement), valueElement)):
                # remove this key/value pair:
                entrylistElement.removeChild(entryElement)

"""Construct by reading from standard input"""
class GConfEntriesStdin(GConfEntries):
    def __init__(self):
        stdinString = sys.stdin.read(-1)
        GConfEntries.__init__(self, parseString(stdinString))

"""Construct by reading from a file"""
class GConfEntriesFromFile(GConfEntries):
    def __init__(self, filename):
        f = open(filename, "r")
        content = f.read(-1)
        f.close()
        GConfEntries.__init__(self, parseString(content))
        

"""Visit an email <account> configuration"""
class MailAccountVisitor:
    def getAccountElement(self, dom):
        return dom.documentElement
    
    def getSourceElement(self, dom):
        accountElement = dom.documentElement
        sourceElement = accountElement.getElementsByTagName("source").item(0)
        return sourceElement
       
    def getSourceUrlText(self, dom):
        sourceElement = self.getSourceElement(dom)
        urlElement = sourceElement.getElementsByTagName("url").item(0)
        if urlElement==None:
            return None
        urlText = getTextBelow(urlElement)
        return urlText

    def setSourceUrlText(self, dom, urlText):
        sourceElement = self.getSourceElement(dom)
        urlElement = sourceElement.getElementsByTagName("url").item(0)
        setTextBelow(urlElement, urlText)

    def getTransportElement(self, dom):
        accountElement = dom.documentElement
        transportElement = accountElement.getElementsByTagName("transport").item(0)
        return transportElement
       
    def getTransportUrlText(self, dom):
        transportElement = self.getTransportElement(dom)
        urlElement = transportElement.getElementsByTagName("url").item(0)
        if urlElement==None:
            return None
        urlText = getTextBelow(urlElement)
        return urlText

    def setTransportUrlText(self, dom, urlText):
        transportElement = self.getTransportElement(dom)
        urlElement = transportElement.getElementsByTagName("url").item(0)
        setTextBelow(urlElement, urlText)

    def getIdentityElement(self, dom):
        accountElement = dom.documentElement
        identityElement = accountElement.getElementsByTagName("identity").item(0)
        return identityElement

    def getIdentityNameElement(self, dom):
        identityElement = self.getIdentityElement(dom)
        return identityElement.getElementsByTagName("name").item(0)
    
    def getIdentityAddrSpecElement(self, dom):
        identityElement = self.getIdentityElement(dom)
        return identityElement.getElementsByTagName("addr-spec").item(0)

    def getIdentityReplyToElement(self, dom):
        identityElement = self.getIdentityElement(dom)
        return identityElement.getElementsByTagName("reply-to").item(0)

    def getSourceUrlScheme(self, dom):
        urlText = self.getSourceUrlText(dom)
        if urlText==None:
            return None
        url = urlparse (urlText)
        return url[0]

"""Visit a <group> element containing <source> elements"""
class GroupedSourceVisitor:
    def visitGroup(self, outerVisitor, groupElement):
        return True

    def visitSource(self, outerVisitor, groupElement, sourceElement):
        raise "Not implemented"

    def isExchangeGroup(self, groupElement):
        if groupElement.getAttribute("base_uri")!="exchange://":            
            return False
        return True

    def isLDAPGroup(self, groupElement):
        if groupElement.getAttribute("base_uri")!="ldap://":
            return False
        return True
        
    
class AddressbookSourceVisitor(GroupedSourceVisitor):
    None
    
class CalendarSourceVisitor(GroupedSourceVisitor):
    None

class TasksSourceVisitor(GroupedSourceVisitor):
    None

"""A base class for visiting Account information.  Subclasses should implement 4 types of visitor class, one for each of the 4 types of account.  Similar in effect to a family of factory methods."""
class EvolutionAccountGConfVisitor:
    def visitKeyValue(self, key, valueElement):
        #print "key \"" + key + "\""
        #walk(valueElement, sys.stdout, 0)

        # Get rid of everything apart from certain keys:
        if key=="/apps/evolution/addressbook/sources":
            self.visitListOfXmlStrings(key, valueElement, EvolutionAccountGConfVisitor.addressbook_source_callback)
            return True

        if key=="/apps/evolution/mail/accounts":            
            self.visitListOfXmlStrings(key, valueElement, EvolutionAccountGConfVisitor.mail_account_callback)
            return True

        if key=="/apps/evolution/calendar/sources":
            self.visitListOfXmlStrings(key, valueElement, EvolutionAccountGConfVisitor.calendar_source_callback)
            return True

        if key=="/apps/evolution/tasks/sources":
            self.visitListOfXmlStrings(key, valueElement, EvolutionAccountGConfVisitor.tasks_source_callback)
            return True

        # Get rid of this; let the defaults handle it
        return False

    def visitListOfXmlStrings(self, key, valueElement, value_callback):
        #print "key \"" + key + "\""
        listElement = valueElement.getElementsByTagName("list").item(0)
        for subValueElement in listElement.getElementsByTagName("value"):
            stringElement = subValueElement.getElementsByTagName("string").item(0)
            xmlSource = getTextBelow(stringElement)
            dom = parseString(xmlSource)
            if value_callback(self, dom):
                setTextBelow(stringElement, dom.toxml())
            else:
                listElement.removeChild(subValueElement)

    """Visit a <group> element containing a list of <source> elements"""
    def visitGroupedSourcesXml(self, dom, sourceVisitor):
        groupElement =  dom.documentElement;
        if not sourceVisitor.visitGroup(self, groupElement):
            return False

        # Visit each source in the group:
        for sourceElement in groupElement.getElementsByTagName("source"):
            if (not sourceVisitor.visitSource(self, groupElement, sourceElement)):
                # remove this key/value pair:
                groupElement.removeChild(sourceElement)

        return True

    def addressbook_source_callback(visitor, dom):
        sourceVisitor = visitor.ImplAddressbookSourceVisitor()
        return visitor.visitGroupedSourcesXml(dom, sourceVisitor)

    def mail_account_callback(visitor, dom):
        mailVisitor = visitor.ImplMailAccountVisitor();
        return mailVisitor.visitXml(visitor, dom)

    def calendar_source_callback(visitor, dom):
        sourceVisitor = visitor.ImplCalendarSourceVisitor()
        return visitor.visitGroupedSourcesXml(dom, sourceVisitor)

    def tasks_source_callback(visitor, dom):
        sourceVisitor = visitor.ImplTasksSourceVisitor()
        return visitor.visitGroupedSourcesXml(dom, sourceVisitor)



syntax highlighted by Code2HTML, v. 0.9.1