diff --git a/product/ERP5Form/ListBox.py b/product/ERP5Form/ListBox.py
index 89d21ff5d20820f652849fad3b555b198b629a7c..c023ec0bcf87f66243c4ad0ee0cdbd73e24f1f1b 100644
--- a/product/ERP5Form/ListBox.py
+++ b/product/ERP5Form/ListBox.py
@@ -391,40 +391,19 @@ class ListBoxWidget(Widget.Widget):
 
 ListBoxWidgetInstance = ListBoxWidget()
 
-class VolatileCachingMethod:
-  """This class caches the result of a callable object, and behaves like a method.
-     Unlike ERP5Type's CachingMethod, this cache is volatile, namely, the cached
-     data is removed immediately when an object which stores the cached data is deleted.
-     Naturally, the object (self) should not be a persistent object.
+def lazyMethod(func):
+  """Return a function which stores a computed value in an instance
+  at the first call.
   """
-  def __init__(self, callable_object):
-    """Generate the key for the cache.
-    """
-    self.method = callable_object
-    self.key = '_cache_' + str(id(callable_object))
-
-  def __call__(self, instance):
-    """Call the callable object passed to __init__, if the result is not cached.
-
-    For now, this does not take any extra argument, because it is not necessary
-    at the moment.
-    """
+  key = '_cache_' + str(id(func))
+  def decorated(self, *args, **kw):
     try:
-      return getattr(instance, self.key)
+      return getattr(self, key)
     except AttributeError:
-      result = self.method(instance)
-      setattr(instance, self.key, result)
+      result = func(self, *args, **kw)
+      setattr(self, key, result)
       return result
-
-class InstanceMethod:
-  """This class makes it possible to pass an instance object implicitly to a method.
-  """
-  def __init__(self, instance, method):
-    self.instance = instance
-    self.method = method
-
-  def __call__(self):
-    return self.method(self.instance)
+  return decorated
 
 class ListBoxRenderer:
   """This class deals with rendering of a ListBox field.
@@ -440,13 +419,6 @@ class ListBoxRenderer:
     self.field = field
     self.request = REQUEST
 
-    # Because it is not easy to pass an instance object implicitly to a method
-    # with no side effect, tweak VolatileCachingMethod objects here for this instance.
-    for k in dir(self):
-      v = getattr(self, k)
-      if isinstance(v, VolatileCachingMethod):
-        setattr(self, k, InstanceMethod(self, v))
-
   def getPhysicalPath(self):
     """
       Return the path of form we render.
@@ -470,21 +442,21 @@ class ListBoxRenderer:
       value = self.getForm().aq_parent
     return value
 
-  getContext = VolatileCachingMethod(getContext)
+  getContext = lazyMethod(getContext)
 
   def getForm(self):
     """Return the form which contains the ListBox.
     """
     return self.field.aq_parent
 
-  getForm = VolatileCachingMethod(getForm)
+  getForm = lazyMethod(getForm)
 
   def getEncoding(self):
     """Retutn the encoding of strings in the fields. Default to UTF-8.
     """
     return self.getPortalObject().getProperty('management_page_charset', 'utf-8')
 
-  getEncoding = VolatileCachingMethod(getEncoding)
+  getEncoding = lazyMethod(getEncoding)
 
   def isReset(self):
     """Determine if the ListBox should be reset.
@@ -492,14 +464,14 @@ class ListBoxRenderer:
     reset = self.request.get('reset', 0)
     return (reset not in (0, '0'))
 
-  isReset = VolatileCachingMethod(isReset)
+  isReset = lazyMethod(isReset)
 
   def getFieldErrorDict(self):
     """Return a dictionary of errors.
     """
     return self.request.get('field_errors', {})
 
-  getFieldErrorDict = VolatileCachingMethod(getFieldErrorDict)
+  getFieldErrorDict = lazyMethod(getFieldErrorDict)
 
   def getUrl(self):
     """
@@ -511,7 +483,7 @@ class ListBoxRenderer:
     return '%s/%s' % (self.getContext().absolute_url(),
                       self.request.other.get('current_form_id', 'view'))
 
-  getUrl = VolatileCachingMethod(getUrl)
+  getUrl = lazyMethod(getUrl)
 
   def getRequestedSelectionName(self):
     """Return a selection name which may be passed by a request.
@@ -527,77 +499,77 @@ class ListBoxRenderer:
 
     return selection_name
 
-  getRequestedSelectionName = VolatileCachingMethod(getRequestedSelectionName)
+  getRequestedSelectionName = lazyMethod(getRequestedSelectionName)
 
   def getSelectionIndex(self):
     """Return the index of a requested selection, or None if not specified.
     """
     return self.request.get('selection_index', None)
 
-  getSelectionIndex = VolatileCachingMethod(getSelectionIndex)
+  getSelectionIndex = lazyMethod(getSelectionIndex)
 
   def getReportDepth(self):
     """Return the depth of reports, or None if not specified.
     """
     return self.request.get('report_depth', None)
 
-  getReportDepth = VolatileCachingMethod(getReportDepth)
+  getReportDepth = lazyMethod(getReportDepth)
 
   def getPortalObject(self):
     """Return the portal object.
     """
     return self.getContext().getPortalObject()
 
-  getPortalObject = VolatileCachingMethod(getPortalObject)
+  getPortalObject = lazyMethod(getPortalObject)
 
   def getPortalUrlString(self):
     """Return the URL of the portal as a string.
     """
     return self.getPortalObject().portal_url()
 
-  getPortalUrlString = VolatileCachingMethod(getPortalUrlString)
+  getPortalUrlString = lazyMethod(getPortalUrlString)
 
   def getCategoryTool(self):
     """Return the Category Tool.
     """
     return self.getPortalObject().portal_categories
 
-  getCategoryTool = VolatileCachingMethod(getCategoryTool)
+  getCategoryTool = lazyMethod(getCategoryTool)
 
   def getDomainTool(self):
     """Return the Domain Tool.
     """
     return self.getPortalObject().portal_domains
 
-  getDomainTool = VolatileCachingMethod(getDomainTool)
+  getDomainTool = lazyMethod(getDomainTool)
 
   def getCatalogTool(self):
     """Return the Catalog Tool.
     """
     return self.getPortalObject().portal_catalog
 
-  getCatalogTool = VolatileCachingMethod(getCatalogTool)
+  getCatalogTool = lazyMethod(getCatalogTool)
 
   def getSelectionTool(self):
     """Return the Selection Tool.
     """
     return self.getPortalObject().portal_selections
 
-  getSelectionTool = VolatileCachingMethod(getSelectionTool)
+  getSelectionTool = lazyMethod(getSelectionTool)
 
   def getId(self):
     """Return the id of the field. Usually, "listbox".
     """
     return self.field.id
 
-  getId = VolatileCachingMethod(getId)
+  getId = lazyMethod(getId)
 
   def getTitle(self):
     """Return the title. Make sure that it is in unicode.
     """
     return unicode(self.field.get_value('title'), self.getEncoding())
 
-  getTitle = VolatileCachingMethod(getTitle)
+  getTitle = lazyMethod(getTitle)
 
   def getMaxLineNumber(self):
     """Return the maximum number of lines shown in a page.
@@ -610,14 +582,14 @@ class ListBoxRenderer:
     """
     return self.field.get_value('search')
 
-  showSearchLine = VolatileCachingMethod(showSearchLine)
+  showSearchLine = lazyMethod(showSearchLine)
 
   def showSelectColumn(self):
     """Return a boolean that represents whether a select column is displayed or not.
     """
     return self.field.get_value('select')
 
-  showSelectColumn = VolatileCachingMethod(showSelectColumn)
+  showSelectColumn = lazyMethod(showSelectColumn)
 
   def showStat(self):
     """Return a boolean that represents whether a stat line is displayed or not.
@@ -627,42 +599,42 @@ class ListBoxRenderer:
     """
     return (self.getStatMethod() is not None) and (len(self.getStatColumnList()) > 0)
 
-  showStat = VolatileCachingMethod(showStat)
+  showStat = lazyMethod(showStat)
 
   def isDomainTreeSupported(self):
     """Return a boolean that represents whether a domain tree is supported or not.
     """
     return (self.field.get_value('domain_tree') and len(self.getDomainRootList()) > 0)
 
-  isDomainTreeSupported = VolatileCachingMethod(isDomainTreeSupported)
+  isDomainTreeSupported = lazyMethod(isDomainTreeSupported)
 
   def isReportTreeSupported(self):
     """Return a boolean that represents whether a report tree is supported or not.
     """
     return (self.field.get_value('report_tree') and len(self.getReportRootList()) > 0)
 
-  isReportTreeSupported = VolatileCachingMethod(isReportTreeSupported)
+  isReportTreeSupported = lazyMethod(isReportTreeSupported)
 
   def isDomainTreeMode(self):
     """Return whether the current mode is domain tree mode or not.
     """
     return self.isDomainTreeSupported() and self.getSelection().domain_tree_mode
 
-  isDomainTreeMode = VolatileCachingMethod(isDomainTreeMode)
+  isDomainTreeMode = lazyMethod(isDomainTreeMode)
 
   def isReportTreeMode(self):
     """Return whether the current mode is report tree mode or not.
     """
     return self.isReportTreeSupported() and self.getSelection().report_tree_mode
 
-  isReportTreeMode = VolatileCachingMethod(isReportTreeMode)
+  isReportTreeMode = lazyMethod(isReportTreeMode)
 
   def getDefaultParamList(self):
     """Return the list of default parameters.
     """
     return self.field.get_value('default_params')
 
-  getDefaultParamList = VolatileCachingMethod(getDefaultParamList)
+  getDefaultParamList = lazyMethod(getDefaultParamList)
 
   def getListMethodName(self):
     """Return the name of the list method. If not defined, return None.
@@ -674,7 +646,7 @@ class ListBoxRenderer:
       name = list_method
     return name or None
 
-  getListMethodName = VolatileCachingMethod(getListMethodName)
+  getListMethodName = lazyMethod(getListMethodName)
 
   def getCountMethodName(self):
     """Return the name of the count method. If not defined, return None.
@@ -686,7 +658,7 @@ class ListBoxRenderer:
       name = count_method
     return name or None
 
-  getCountMethodName = VolatileCachingMethod(getCountMethodName)
+  getCountMethodName = lazyMethod(getCountMethodName)
 
   def getStatMethodName(self):
     """Return the name of the stat method. If not defined, return None.
@@ -698,14 +670,14 @@ class ListBoxRenderer:
       name = stat_method
     return name or None
 
-  getStatMethodName = VolatileCachingMethod(getStatMethodName)
+  getStatMethodName = lazyMethod(getStatMethodName)
 
   def getSelectionName(self):
     """Return the selection name.
     """
     return self.field.get_value('selection_name')
 
-  getSelectionName = VolatileCachingMethod(getSelectionName)
+  getSelectionName = lazyMethod(getSelectionName)
 
   def getMetaTypeList(self):
     """Return the list of meta types for filtering. Return None when empty.
@@ -713,7 +685,7 @@ class ListBoxRenderer:
     meta_types = [c[0] for c in self.field.get_value('meta_types')]
     return meta_types or None
 
-  getMetaTypeList = VolatileCachingMethod(getMetaTypeList)
+  getMetaTypeList = lazyMethod(getMetaTypeList)
 
   def getPortalTypeList(self):
     """Return the list of portal types for filtering. Return None when empty.
@@ -721,7 +693,7 @@ class ListBoxRenderer:
     portal_types = [c[0] for c in self.field.get_value('portal_types')]
     return portal_types or None
 
-  getPortalTypeList = VolatileCachingMethod(getPortalTypeList)
+  getPortalTypeList = lazyMethod(getPortalTypeList)
 
   def getColumnList(self):
     """Return the columns. Make sure that the titles are in unicode.
@@ -729,7 +701,7 @@ class ListBoxRenderer:
     columns = self.field.get_value('columns')
     return [(str(c[0]), unicode(c[1], self.getEncoding())) for c in columns]
 
-  getColumnList = VolatileCachingMethod(getColumnList)
+  getColumnList = lazyMethod(getColumnList)
 
   def getAllColumnList(self):
     """Return the all columns. Make sure that the titles are in unicode.
@@ -741,7 +713,7 @@ class ListBoxRenderer:
                               if c[0] not in all_column_id_set])
     return all_column_list
 
-  getAllColumnList = VolatileCachingMethod(getAllColumnList)
+  getAllColumnList = lazyMethod(getAllColumnList)
 
   def getStatColumnList(self):
     """Return the stat columns. Fall back to all the columns if empty.
@@ -753,7 +725,7 @@ class ListBoxRenderer:
       stat_column_list = [(c[0], c[0]) for c in self.getAllColumnList()]
     return stat_column_list
 
-  getStatColumnList = VolatileCachingMethod(getStatColumnList)
+  getStatColumnList = lazyMethod(getStatColumnList)
 
   def getUrlColumnList(self):
     """Return the url columns. Make sure that it is an empty list, when not defined.
@@ -761,14 +733,14 @@ class ListBoxRenderer:
     url_columns = self.field.get_value('url_columns')
     return url_columns or []
 
-  getUrlColumnList = VolatileCachingMethod(getUrlColumnList)
+  getUrlColumnList = lazyMethod(getUrlColumnList)
 
   def getDefaultSortColumnList(self):
     """Return the default sort columns.
     """
     return self.field.get_value('sort')
 
-  getDefaultSortColumnList = VolatileCachingMethod(getDefaultSortColumnList)
+  getDefaultSortColumnList = lazyMethod(getDefaultSortColumnList)
 
   def getDomainRootList(self):
     """Return the domain root list. Make sure that the titles are in unicode.
@@ -776,7 +748,7 @@ class ListBoxRenderer:
     domain_root_list = self.field.get_value('domain_root_list')
     return [(str(c[0]), unicode(c[1], self.getEncoding())) for c in domain_root_list]
 
-  getDomainRootList = VolatileCachingMethod(getDomainRootList)
+  getDomainRootList = lazyMethod(getDomainRootList)
 
   def getReportRootList(self):
     """Return the report root list. Make sure that the titles are in unicode.
@@ -784,7 +756,7 @@ class ListBoxRenderer:
     report_root_list = self.field.get_value('report_root_list')
     return [(str(c[0]), unicode(c[1], self.getEncoding())) for c in report_root_list]
 
-  getReportRootList = VolatileCachingMethod(getReportRootList)
+  getReportRootList = lazyMethod(getReportRootList)
 
   def getSearchColumnIdSet(self):
     """Return the set of the ids of the search columns. Fall back to the catalog schema, if not defined.
@@ -796,7 +768,7 @@ class ListBoxRenderer:
       search_column_id_list = self.getCatalogTool().schema()
     return set(search_column_id_list)
 
-  getSearchColumnIdSet = VolatileCachingMethod(getSearchColumnIdSet)
+  getSearchColumnIdSet = lazyMethod(getSearchColumnIdSet)
 
   def getSortColumnIdSet(self):
     """Return the set of the ids of the sort columns. Fall back to search column ids, if not defined.
@@ -808,7 +780,7 @@ class ListBoxRenderer:
       sort_column_id_set = self.getSearchColumnIdSet()
     return sort_column_id_set
 
-  getSortColumnIdSet = VolatileCachingMethod(getSortColumnIdSet)
+  getSortColumnIdSet = lazyMethod(getSortColumnIdSet)
 
   def getEditableColumnIdSet(self):
     """Return the set of the ids of the editable columns.
@@ -816,7 +788,7 @@ class ListBoxRenderer:
     editable_columns = self.field.get_value('editable_columns')
     return set([c[0] for c in editable_columns])
 
-  getEditableColumnIdSet = VolatileCachingMethod(getEditableColumnIdSet)
+  getEditableColumnIdSet = lazyMethod(getEditableColumnIdSet)
 
   def getListActionUrl(self):
     """Return the URL of the list action.
@@ -828,7 +800,7 @@ class ListBoxRenderer:
       list_action_part_list.append('?reset=1')
     return ''.join(list_action_part_list)
 
-  getListActionUrl = VolatileCachingMethod(getListActionUrl)
+  getListActionUrl = lazyMethod(getListActionUrl)
 
   # Whether the selection object is initialized.
   is_selection_initialized = False
@@ -878,21 +850,21 @@ class ListBoxRenderer:
 
     return selection
 
-  getSelection = VolatileCachingMethod(getSelection)
+  getSelection = lazyMethod(getSelection)
 
   def getCheckedUidList(self):
     """Return the list of checked uids.
     """
     return self.getSelection().getCheckedUids()
 
-  getCheckedUidList = VolatileCachingMethod(getCheckedUidList)
+  getCheckedUidList = lazyMethod(getCheckedUidList)
 
   def getCheckedUidSet(self):
     """Return the set of checked uids.
     """
     return set(self.getCheckedUidList())
 
-  getCheckedUidSet = VolatileCachingMethod(getCheckedUidSet)
+  getCheckedUidSet = lazyMethod(getCheckedUidSet)
 
   def getSelectedColumnList(self):
     """Return the list of selected columns.
@@ -901,7 +873,7 @@ class ListBoxRenderer:
                                                        columns = self.getColumnList(),
                                                        REQUEST = self.request)
 
-  getSelectedColumnList = VolatileCachingMethod(getSelectedColumnList)
+  getSelectedColumnList = lazyMethod(getSelectedColumnList)
 
   def getColumnAliasList(self):
     """Return the list of column aliases for SQL, because SQL does not allow a symbol to contain dots.
@@ -911,7 +883,7 @@ class ListBoxRenderer:
       alias_list.append(sql.replace('.', '_'))
     return alias_list
 
-  getColumnAliasList = VolatileCachingMethod(getColumnAliasList)
+  getColumnAliasList = lazyMethod(getColumnAliasList)
 
   def getParamDict(self):
     """Return a dictionary of parameters.
@@ -1010,7 +982,7 @@ class ListBoxRenderer:
       del params['select_expression']
     return params
 
-  getParamDict = VolatileCachingMethod(getParamDict)
+  getParamDict = lazyMethod(getParamDict)
 
   def getEditableField(self, alias):
     """Get an editable field for column, using column alias.
@@ -1039,7 +1011,7 @@ class ListBoxRenderer:
 
     return list_method
 
-  getListMethod = VolatileCachingMethod(getListMethod)
+  getListMethod = lazyMethod(getListMethod)
 
   def getCountMethod(self):
     """Return the count method object.
@@ -1061,7 +1033,7 @@ class ListBoxRenderer:
 
     return count_method
 
-  getCountMethod = VolatileCachingMethod(getCountMethod)
+  getCountMethod = lazyMethod(getCountMethod)
 
   def getStatMethod(self):
     """Return the stat method object.
@@ -1083,7 +1055,7 @@ class ListBoxRenderer:
 
     return stat_method
 
-  getStatMethod = VolatileCachingMethod(getStatMethod)
+  getStatMethod = lazyMethod(getStatMethod)
 
   def getDomainSelection(self):
     """Return a DomainSelection object wrapped with the context.
@@ -1119,7 +1091,7 @@ class ListBoxRenderer:
 
       return DomainSelection(domain_dict = root_dict).__of__(self.getContext())
 
-  getDomainSelection = VolatileCachingMethod(getDomainSelection)
+  getDomainSelection = lazyMethod(getDomainSelection)
 
   def getStatSelectExpression(self):
     """Return a string which expresses the information retrieved by SELECT for
@@ -1148,7 +1120,7 @@ class ListBoxRenderer:
 
     return ', '.join(select_expression_list)
 
-  getStatSelectExpression = VolatileCachingMethod(getStatSelectExpression)
+  getStatSelectExpression = lazyMethod(getStatSelectExpression)
 
   def makeReportTreeList(self, root_dict = None, report_path = None, base_category = None, depth = 0,
                          unfolded_list = (), is_report_opened = True, sort_on = (('id', 'ASC'),)):
@@ -1293,7 +1265,7 @@ class ListBoxRenderer:
         domain_path = None
     return domain_path
 
-  getSelectedDomainPath = VolatileCachingMethod(getSelectedDomainPath)
+  getSelectedDomainPath = lazyMethod(getSelectedDomainPath)
 
   def getSelectedReportPath(self):
     """Return a selected report path.
@@ -1310,7 +1282,7 @@ class ListBoxRenderer:
 
     return selection.getReportPath(default = default_selection_report_path)
 
-  getSelectedReportPath = VolatileCachingMethod(getSelectedReportPath)
+  getSelectedReportPath = lazyMethod(getSelectedReportPath)
 
   def getLabelValueList(self):
     """Return a list of values, where each value is a tuple consisting of an property id, a title and a string which
@@ -1733,13 +1705,6 @@ class ListBoxRendererLine:
     self.depth = depth
     self.domain_title = domain_title
 
-    # Because it is not easy to pass an instance object implicitly to a method
-    # with no side effect, tweak VolatileCachingMethod objects here for this instance.
-    for k in dir(self):
-      v = getattr(self, k)
-      if isinstance(v, VolatileCachingMethod):
-        setattr(self, k, InstanceMethod(self, v))
-
   def getBrain(self):
     """Return the brain. This can be identical to a real object.
     """
@@ -1753,21 +1718,21 @@ class ListBoxRendererLine:
     except AttributeError:
       return self.obj
 
-  getObject = VolatileCachingMethod(getObject)
+  getObject = lazyMethod(getObject)
 
   def getUid(self):
     """Return the uid of the object.
     """
     return getattr(aq_base(self.obj), 'uid', None)
 
-  getUid = VolatileCachingMethod(getUid)
+  getUid = lazyMethod(getUid)
 
   def getUrl(self):
     """Return the absolute URL path of the object
     """
     return self.getBrain().getUrl()
 
-  getUrl = VolatileCachingMethod(getUrl)
+  getUrl = lazyMethod(getUrl)
 
   def isSummary(self):
     """Return whether this line is a summary or not.
@@ -2168,18 +2133,18 @@ class ListBoxHTMLRenderer(ListBoxRenderer):
 
     return start
 
-  getLineStart = VolatileCachingMethod(getLineStart)
+  getLineStart = lazyMethod(getLineStart)
 
   def getMaxLineNumber(self):
     """Return the maximum number of lines shown in a page.
     """
-    list_lines =self.getParamDict().get('list_lines', None)
+    list_lines = self.getParamDict().get('list_lines', None)
     if list_lines is not None:
       # it's possible to override max lines from selection parameters
       return int(list_lines)
     return self.field.get_value('lines')
 
-  getMaxLineNumber = VolatileCachingMethod(getMaxLineNumber)
+  getMaxLineNumber = lazyMethod(getMaxLineNumber)
 
   def getMD5Checksum(self):
     """Generate a MD5 checksum against checked uids. This is used to confirm