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

Last change on this file since 1981 was 1981, checked in by fenix, 14 years ago

some code refactoring, made compatible with plone4

  • Property svn:eol-style set to native
File size: 4.7 KB
Line 
1import logging, types
2import transaction
3from zope.interface import implements
4from zope.component import getMultiAdapter
5from zope.component import queryMultiAdapter
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
13
14try:
15    from plone.indexer.interfaces import IIndexableObject
16except ImportError:
17    from plone.app.content.interfaces import IIndexableObjectWrapper \
18        as _old_IIndexableObjectWrapper
19    IS_NEW = False
20else:   
21    IS_NEW = True
22
23
24from quintagroup.catalogupdater.interfaces import ICatalogUpdater
25
26LOG = logging.getLogger('quintagroup.catalogupdater')
27
28
29class CatalogUpdaterUtility(object):
30
31    implements(ICatalogUpdater)
32
33    def validate(self, cat, cols):
34        # Validate catalog and column name
35        AVAIL_COLTYPES = list(types.StringTypes) + [types.ListType, types.TupleType]
36
37        _cat = getattr(cat, '_catalog', None)
38        if _cat is None:
39            raise AttributeError("%s - is not ZCatalog based catalog" % cat)
40
41        if not type(cols) in AVAIL_COLTYPES:
42            raise TypeError("'columns' parameter must be one of the following " \
43                "types: %s" % AVAIL_COLTYPES)
44        # Normalize columns
45        if type(cols) in types.StringTypes:
46            cols = [cols,]
47        # Check is every column present in the catalog
48        for col in cols:
49            if not _cat.schema.has_key(col):
50                raise AttributeError("'%s' - not presented column in %s catalog " % (col, cat))
51
52        return _cat, cols
53
54
55    def getWrappedObjectNew(self, obj, portal, catalog):
56        # Returned wrapped 'obj' object with IIndexable wrapper
57        wrapper = None
58        if not IIndexableObject.providedBy(obj):
59             # This is the CMF 2.2 compatible approach, which should be used going forward
60             wrapper = queryMultiAdapter((obj, catalog), IIndexableObject)
61        return wrapper and wrapper or obj
62
63    def getWrappedObjectOld(self, obj, portal, catalog):
64        # Returned wrapped 'obj' object with IIndexable wrapper
65        wf = getattr(self, 'portal_workflow', None)
66        # A comment for all the frustrated developers which aren't able to pin
67        # point the code which adds the review_state to the catalog. :)
68        # The review_state var and some other workflow vars are added to the
69        # indexable object wrapper throught the code in the following lines
70        if wf is not None:
71            vars = wf.getCatalogVariablesFor(obj)
72        else:
73            vars = {}
74       
75        w = getMultiAdapter((obj, portal), _old_IIndexableObjectWrapper)
76        w.update(vars)
77
78        return w
79
80
81    def updateMetadata4All(self, catalog, columns):
82        """ Look into appropriate method of ICatalogUpdate interface
83        """
84
85        _catalog, columns = self.validate(catalog, columns)
86
87        portal = getToolByName(catalog, 'portal_url').getPortalObject()
88        root = aq_parent(portal)
89       
90        data = _catalog.data
91        schema = _catalog.schema
92        paths = _catalog.paths
93        getWrappedObject = IS_NEW and self.getWrappedObjectNew or self.getWrappedObjectOld
94        # For subtransaction support
95        threshold = getattr(catalog, 'threshold', 10000)
96        _v_total = 0
97        _v_transaction = None
98
99        # For each catalog record update metadata
100        for rid, md in data.items():
101            # get an object
102            obj_uid = paths[rid]
103            try:
104                obj = root.unrestrictedTraverse(obj_uid)
105                obj = getWrappedObject(obj, portal, catalog)
106            except:
107                LOG.error('updateMetadata4All could not resolve '
108                          'an object from the uid %r.' % obj_uid)
109                continue
110
111            mdlist = list(md)
112            for column in columns:
113                # calculate the column value
114                attr=getattr(obj, column, MV)
115                if(attr is not MV and safe_callable(attr)): attr=attr()
116                # Update metadata value
117                indx = schema[column]
118                mdlist[indx] = attr
119
120            # Update catalog record
121            data[rid] = tuple(mdlist)
122
123            # Steeled from ZCatalog
124            if threshold is not None:
125                # figure out whether or not to commit a subtransaction.
126                t = id(transaction.get())
127                if t != _v_transaction:
128                    _v_total = 0
129                _v_transaction = t
130                _v_total = _v_total + 1
131                if _v_total > threshold:
132                    transaction.savepoint(optimistic=True)
133                    catalog._p_jar.cacheGC()
134                    _v_total = 0
135                    LOG.info('commiting subtransaction')
136
Note: See TracBrowser for help on using the repository browser.