# Copyright (c) 2010 Infrae. All rights reserved.
# See also LICENSE.txt
# $Id: metadata_extract.py 41091 2010-04-02 12:04:50Z sylvain $

from zope.app.locales.extract import find_files
from zope.i18nmessageid import Message
import xml.sax
from xml.sax.handler import feature_namespaces
from xml.sax.handler import ContentHandler
import traceback

TRANSLATABLE_PROPERTIES = ['title', 'description']

class NonMetadataXMLError(Exception):
    pass


def metadata_strings(dir, domain):
    catalog = {}
    # unfortunately since .xml is used for *both* silva export testfiles
    # *and* metadata descriptions, we get far too many files.
    # the handler tries to detect non metadata xml and bails out if so
    # as a hack
    for filename in find_files(dir, '*.xml'):
        try:
            try:
                extract_ids(filename, catalog, domain)
            except NonMetadataXMLError:
                pass
        except: # Hee hee, I love bare excepts!
            print 'There was an error processing', filename
            traceback.print_exc()
    return catalog



class MetadataXMLHandler(ContentHandler):

    def __init__(self, filepath, catalog, i18n_domain):
        self._catalog = catalog
        self._tags = {}
        self._field_name = None
        self._stack = []
        self._attr_stack = []
        self._locator = None
        self._filepath = filepath
        self._i18n_domain = i18n_domain

    def setDocumentLocator(self, locator):
        self._locator = locator

    def isInTag(self, name):
        return self._tags.has_key((None, name))

    def enterTag(self, name, attrs):
        self._tags[name] = True
        self._stack.append(name)
        self._attr_stack.append(attrs)

    def exitTag(self, name):
        del self._tags[name]
        self._stack.pop()
        self._attr_stack.pop()

    def hasAttrValue(self, name, value):
        attrs = self._attr_stack[-1]
        return attrs.get((None, name)) == value

    def getAttrValue(self, name):
        return self._attr_stack[-1].get((None, name))

    def startElementNS(self, name, qname, attrs):
        self.enterTag(name, attrs)
        if not self.isInTag('metadata_set'):
            raise NonMetadataXMLError
        if self.isInTag('field_values') and self.isInTag('value'):
            for name in TRANSLATABLE_PROPERTIES:
                if self.hasAttrValue('key', name):
                    message_id = Message(self.getAttrValue('value'),
                                         domain=self._i18n_domain)
                    if not self._catalog.has_key(message_id):
                        self._catalog[message_id] = []
                    number = self._locator.getLineNumber()
                    self._catalog[message_id].append((self._filepath, number))

    def endElementNS(self, name, qname):
        self.exitTag(name)


def extract_ids(filename, catalog, i18n_domain):
    handler = MetadataXMLHandler(filename, catalog, i18n_domain)
    parser = xml.sax.make_parser()
    parser.setFeature(feature_namespaces, 1)
    parser.setContentHandler(handler)
    handler.setDocumentLocator(parser)
    f = open(filename, 'r')
    parser.parse(f)
    f.close()


