diff --git a/product/ERP5/Tool/UrlRegistryTool.py b/product/ERP5/Tool/UrlRegistryTool.py new file mode 100644 index 0000000000000000000000000000000000000000..9b83582a1cede9e72854735842eea9c6859b99cc --- /dev/null +++ b/product/ERP5/Tool/UrlRegistryTool.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2006-2010 Nexedi SA and Contributors. All Rights Reserved. +# Nicolas Delaby <nicolas@nexedi.com> +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from AccessControl import ClassSecurityInfo +from Products.ERP5Type.Globals import InitializeClass +from Products.ERP5Type.Tool.BaseTool import BaseTool +from Products.ERP5Type import Permissions +from Acquisition import Implicit +from BTrees.OOBTree import OOBTree +from warnings import warn + +ACTIVITY_GROUPING_COUNT = 200 + +class UrlRegistryTool(BaseTool): + """ + """ + title = 'Url Registry Tool' + id = 'portal_url_registry' + meta_type = 'ERP5 Url Registry Tool' + portal_type = 'Url Registry Tool' + + # Declarative Security + security = ClassSecurityInfo() + # How manage security to avoid clearing content by disallowed users ? + + _url_reference_mapping = 'url_reference_mapping' + + def __init__(self, id=None): + if id is not None: + self.id = id + self._initBTree() + + def _initBTree(self): + """ + Initialise a HBTree like object. + The first level of BTrees has namespace value as key. + BTree{ + namespace: BTree{key: value}, + namespace: BTree{key: value} + } + """ + self._global_mapping_storage = OOBTree() + + def _getMappingDict(self): + """ + Return a dict like object. + """ + portal_preferences = self.getPortalObject().portal_preferences + reference_mapping_namespace = self._url_reference_mapping + preferred_namespace = portal_preferences.getPreferredIngestionNamespace('') + namespace = reference_mapping_namespace + preferred_namespace + return BTreeMappingDict(namespace).__of__(self) + + security.declareProtected(Permissions.AccessContentsInformation, + 'getURLMappingContainerFromContext') + def getURLMappingContainerFromContext(self, context): + """ + Return the container of mapping according given context. + This will interrogate crawling policy (based on predicate) + and return an persistent object. + It can be an external_source, a module, a tool, or any document. + + context - a context to test predicates + """ + warn('context argument ignored', DeprecationWarning) + return self + + + security.declareProtected(Permissions.ManagePortal, + 'clearUrlRegistryTool') + def clearUrlRegistryTool(self, context=None): + """ + Unregister all namespaces. + """ + if context is not None: + warn('context argument ignored', DeprecationWarning) + self._initBTree() + + security.declareProtected(Permissions.ModifyPortalContent, + 'registerURL') + def registerURL(self, url, reference, context=None): + """ + Compute namespace key. + Then associate url with reference in Persistent Mapping + in context of user system preference. + """ + if context is not None: + warn('context argument ignored', DeprecationWarning) + mapping = self._getMappingDict() + if url in mapping.keys() and mapping[url] == reference: + # No need to update mapping + return + mapping[url] = reference + + security.declareProtected(Permissions.AccessContentsInformation, + 'getReferenceFromURL') + def getReferenceFromURL(self, url, context=None): + """ + Return reference according provided url, + in context of user's system preference. + """ + if context is not None: + warn('context argument ignored', DeprecationWarning) + return self._getMappingDict()[url] + + security.declareProtected(Permissions.AccessContentsInformation, + 'getReferenceList') + def getReferenceList(self, context=None): + """ + Return all references according to the given context. + """ + if context is not None: + warn('context argument ignored', DeprecationWarning) + return self._getMappingDict().values() + + + security.declareProtected(Permissions.AccessContentsInformation, + 'getURLListFromReference') + def getURLListFromReference(self, reference, context=None): + """ + """ + if context is not None: + warn('context argument ignored', DeprecationWarning) + mapping = self._getMappingDict() + url_list = [] + for url, stored_reference in mapping.iteritems(): + if reference == stored_reference: + url_list.append(url) + return url_list + + def updateUrlRegistryTool(self): + """ + Fetch all document path, then call in activities + Base_registerUrl on all of them (grouped by reference) + to fill in portal_url_registry. + """ + portal = self.getPortalObject() + portal_type_list = portal.getPortalDocumentTypeList() + if portal_type_list: + object_list = portal.portal_catalog(portal_type=portal_type_list, + group_by='reference', + limit=None) + object_list_len = len(object_list) + portal_activities = portal.portal_activities + object_path_list = [x.path for x in object_list] + for i in xrange(0, object_list_len, ACTIVITY_GROUPING_COUNT): + current_path_list = object_path_list[i:i+ACTIVITY_GROUPING_COUNT] + portal_activities.activate(activity='SQLQueue', priority=3)\ + .callMethodOnObjectList(current_path_list, + 'Base_registerUrl') + + +class BTreeMappingDict(Implicit): + """ + Strictly follows dict API + """ + def __init__(self, namespace): + self.namespace = namespace + Implicit.__init__(self) + + def _getStorage(self): + """ + return the BTree sub-level + create it if does not exists. + """ + btree = self.aq_parent._global_mapping_storage + if self.namespace not in btree: + btree[self.namespace] = OOBTree() + return btree[self.namespace] + + def __len__(self): + return len(self._getStorage()) + + def keys(self): + return self._getStorage().keys() + + def values(self): + return self._getStorage().values() + + def items(self): + return self._getStorage().items() + + def __getitem__(self, key): + return self._getStorage()[key] + + def __contains__(self, key): + return key in self._getStorage().keys() + + def get(self, key, default=None): + return self._getStorage().get(key, default) + + def __setitem__(self, key, value): + self._getStorage()[key] = value + + def __delitem__(self, key): + del self._getStorage()[key] + +InitializeClass(UrlRegistryTool)