diff --git a/product/ERP5Workflow/Document/Worklist.py b/product/ERP5Workflow/Document/Worklist.py
index a0b3820f82e6a60d2f9fc80ccb2b2f8e92a468cb..10584795b7e4acce9898850197c52b05018190fc 100644
--- a/product/ERP5Workflow/Document/Worklist.py
+++ b/product/ERP5Workflow/Document/Worklist.py
@@ -2,6 +2,7 @@
 #
 # Copyright (c) 2006 Nexedi SARL and Contributors. All Rights Reserved.
 #                    Romain Courteaud <romain@nexedi.com>
+#               2015 Wenjie Zheng <wenjie.zheng@tiolive.com>
 #
 # WARNING: This program as such is intended to be used by professional
 # programmers who take the whole responsability of assessing all potential
@@ -27,9 +28,17 @@
 ##############################################################################
 
 from AccessControl import ClassSecurityInfo
-
+from Acquisition import aq_inner
+from Acquisition import aq_parent
 from Products.ERP5Type import Permissions, PropertySheet
 from Products.ERP5Type.XMLObject import XMLObject
+from Products.ERP5Type.patches.Expression import Expression_createExprContext
+from Products.DCWorkflow.Expression import Expression
+from Products.DCWorkflow.Expression import StateChangeInfo
+from Products.DCWorkflow.Guard import Guard
+from Products.DCWorkflow.permissions import ManagePortal
+from Persistence import PersistentMapping
+from Products.CMFCore.utils import getToolByName
 
 class Worklist(XMLObject):
     """
@@ -42,6 +51,14 @@ class Worklist(XMLObject):
     isPortalContent = 1
     isRADContent = 1
 
+    description = ''
+    var_matches = None  # Compared with catalog when set.
+    actbox_name = ''
+    actbox_url = ''
+    actbox_icon = ''
+    actbox_category = 'global'
+    guard = None
+
     # Declarative security
     security = ClassSecurityInfo()
     security.declareObjectProtected(Permissions.AccessContentsInformation)
@@ -52,4 +69,120 @@ class Worklist(XMLObject):
                PropertySheet.XMLObject,
                PropertySheet.CategoryCore,
                PropertySheet.DublinCore,
+               PropertySheet.Worklist,
     )
+
+    def getGuard(self):
+        if self.guard is not None:
+            return self.guard
+        else:
+            return Guard().__of__(self)  # Create a temporary guard.
+
+    def getGuardSummary(self):
+        res = None
+        if self.guard is not None:
+            res = self.guard.getSummary()
+        return res
+
+    def getAvailableCatalogVars(self):
+        res = []
+        res.append(self.getParentValue().getStateBaseCategory())
+        for vdef in self.getParentValue().contentValues(portal_type="Variable"):
+            id = vdef.getId()
+            if vdef.for_catalog:
+                res.append(id)
+        res.sort()
+        return res
+
+    def getVarMatchKeys(self):
+        if self.var_matches:
+            return self.var_matches.keys()
+        else:
+            return []
+
+    def getVarMatch(self, id):
+        if self.var_matches:
+            matches = self.var_matches.get(id, ())
+            if not isinstance(matches, (tuple, Expression)):
+                # Old version, convert it.
+                matches = (matches,)
+                self.var_matches[id] = matches
+            return matches
+        else:
+            return ()
+
+    def getVarMatchText(self, id):
+        values = self.getVarMatch(id)
+        if isinstance(values, Expression):
+            return values.text
+        return '; '.join(values)
+
+    def setProperties(self, description,
+                      actbox_name='', actbox_url='', actbox_category='global',
+                      actbox_icon='', props=None, REQUEST=None):
+        '''
+        '''
+        if props is None:
+            props = REQUEST
+        self.description = str(description)
+        for key in self.getAvailableCatalogVars():
+            # Populate var_matches.
+            # add field in real time
+            fieldname = 'var_match_%s' % key
+            v = props.get(fieldname, '')
+            if v:
+                if not self.var_matches:
+                    self.var_matches = PersistentMapping()
+
+                if tales_re.match(v).group(1):
+                    # Found a TALES prefix
+                    self.var_matches[key] = Expression(v)
+                else:
+                    # Falling back to formatted string
+                    v = [ var.strip() for var in v.split(';') ]
+                    self.var_matches[key] = tuple(v)
+
+            else:
+                if self.var_matches and self.var_matches.has_key(key):
+                    del self.var_matches[key]
+        self.actbox_name = str(actbox_name)
+        self.actbox_url = str(actbox_url)
+        self.actbox_category = str(actbox_category)
+        self.actbox_icon = str(actbox_icon)
+        g = Guard()
+        if g.changeFromProperties(props or REQUEST):
+            self.guard = g
+        else:
+            self.guard = None
+        if REQUEST is not None:
+            return self.manage_properties(REQUEST, 'Properties changed.')
+
+    def search(self, info=None, **kw):
+        """ Perform the search corresponding to this worklist
+
+        Returns sequence of ZCatalog brains
+        - info is a mapping for resolving formatted string variable references
+        - additional keyword/value pairs may be used to restrict the query
+        """
+        if not self.var_matches:
+            return
+
+        if info is None:
+            info = {}
+
+        catalog = getToolByName(self, 'portal_catalog')
+        criteria = {}
+
+        for key, values in self.var_matches.items():
+            if isinstance(values, Expression):
+                wf = self.getParent()
+                portal = wf._getPortalRoot()
+                context = Expression_createExprContext(StateChangeInfo(portal, wf))
+                criteria[key] = values(context)
+            else:
+                criteria[key] = [x % info for x in values]
+
+        criteria.update(kw)
+
+        return catalog.searchResults(**criteria)
+