source: products/quintagroup.catalogupdater/trunk/quintagroup/catalogupdater/utility.py @ 1765

Last change on this file since 1765 was 1764, checked in by mylan, 14 years ago

Added subtransaction support to utility

  • Property svn:eol-style set to native
File size: 4.2 KB
Line 
1import logging, types
2import transaction
3from zope.interface import implements
4from zope.component import queryMultiAdapter
5from plone.indexer.interfaces import IIndexableObject
6
7from Missing import MV
8from Acquisition import aq_inner
9from Acquisition import aq_parent
10
11from Products.CMFCore.utils import getToolByName
12from Products.ZCatalog.Catalog import safe_callable
13from Products.CMFPlone.CatalogTool import register_bbb_indexers
14from Products.CMFPlone.CatalogTool import _old_IIndexableObjectWrapper
15
16from quintagroup.catalogupdater.interfaces import ICatalogUpdater
17
18LOG = logging.getLogger('quintagroup.catalogupdater')
19
20
21class CatalogUpdaterUtility(object):
22
23    implements(ICatalogUpdater)
24
25    def validate(self, cat, cols):
26        # Validate catalog and column name
27        AVAIL_COLTYPES = list(types.StringTypes) + [types.ListType, types.TupleType]
28
29        _cat = getattr(cat, '_catalog', None)
30        if _cat is None:
31            raise AttributeError("%s - is not ZCatalog based catalog" % cat)
32
33        if not type(cols) in AVAIL_COLTYPES:
34            raise TypeError("'columns' parameter must be one of the following " \
35                "types: %s" % AVAIL_COLTYPES)
36        # Normalize columns
37        if type(cols) in types.StringTypes:
38            cols = [cols,]
39        # Check is every column present in the catalog
40        for col in cols:
41            if not _cat.schema.has_key(col):
42                raise AttributeError("'%s' - not presented column in %s catalog " % (col, cat))
43
44        return _cat, cols
45
46    def getWrapedObject(self, obj, portal, catalog):
47       # Returned wrapped 'obj' object with IIndexable wrapper
48       w = obj
49       if not IIndexableObject.providedBy(obj):
50            # BBB: Compatibility wrapper lookup. Should be removed in Plone 4.
51            register_bbb_indexers()
52            wrapper = queryMultiAdapter((obj, portal), _old_IIndexableObjectWrapper)
53            if wrapper is not None:
54                w = wrapper
55            else:
56                # This is the CMF 2.2 compatible approach, which should be used going forward
57                wrapper = queryMultiAdapter((obj, catalog), IIndexableObject)
58                if wrapper is not None:
59                    w = wrapper
60       return w
61
62
63    def updateMetadata4All(self, catalog, columns):
64        """ Look into appropriate method of ICatalogUpdate interface
65        """
66
67        _catalog, columns = self.validate(catalog, columns)
68
69        portal = getToolByName(catalog, 'portal_url').getPortalObject()
70        root = aq_parent(portal)
71       
72        data = _catalog.data
73        schema = _catalog.schema
74        paths = _catalog.paths
75        # For subtransaction support
76        threshold = getattr(catalog, 'threshold', 10000)
77        _v_total = 0
78        _v_transaction = None
79
80        # For each catalog record update metadata
81        for rid, md in data.items():
82            # get an object
83            obj_uid = paths[rid]
84            try:
85                obj = root.unrestrictedTraverse(obj_uid)
86                obj = self.getWrapedObject(obj, portal, catalog)
87            except:
88                LOG.error('updateMetadata4All could not resolve '
89                          'an object from the uid %r.' % obj_uid)
90                continue
91
92            mdlist = list(md)
93            for column in columns:
94                # calculate the column value
95                attr=getattr(obj, column, MV)
96                if(attr is not MV and safe_callable(attr)): attr=attr()
97                # Update metadata value
98                indx = schema[column]
99                mdlist[indx] = attr
100
101            # Update catalog record
102            data[rid] = tuple(mdlist)
103
104            # Steeled from ZCatalog
105            if threshold is not None:
106                # figure out whether or not to commit a subtransaction.
107                t = id(transaction.get())
108                if t != _v_transaction:
109                    _v_total = 0
110                _v_transaction = t
111                _v_total = _v_total + 1
112                if _v_total > threshold:
113                    transaction.savepoint(optimistic=True)
114                    catalog._p_jar.cacheGC()
115                    _v_total = 0
116                    LOG.info('commiting subtransaction')
117
Note: See TracBrowser for help on using the repository browser.