Back to index

plone3  3.1.7
annotations.py
Go to the documentation of this file.
00001 ################################################################################
00002 #
00003 # Copyright (c) 2002-2005, Benjamin Saller <bcsaller@ideasuite.com>, and
00004 #                              the respective authors. All rights reserved.
00005 # For a list of Archetypes contributors see docs/CREDITS.txt.
00006 #
00007 # Redistribution and use in source and binary forms, with or without
00008 # modification, are permitted provided that the following conditions are met:
00009 #
00010 # * Redistributions of source code must retain the above copyright notice, this
00011 #   list of conditions and the following disclaimer.
00012 # * Redistributions in binary form must reproduce the above copyright notice,
00013 #   this list of conditions and the following disclaimer in the documentation
00014 #   and/or other materials provided with the distribution.
00015 # * Neither the name of the author nor the names of its contributors may be used
00016 #   to endorse or promote products derived from this software without specific
00017 #   prior written permission.
00018 #
00019 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00020 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00022 # FOR A PARTICULAR PURPOSE.
00023 #
00024 ################################################################################
00025 
00026 from UserDict import DictMixin
00027 
00028 from BTrees.OOBTree import OOBTree
00029 from Acquisition import Explicit
00030 from Acquisition import aq_base
00031 from AccessControl import ClassSecurityInfo
00032 from Globals import InitializeClass
00033 
00034 from Products.Archetypes.interfaces.annotations import IATAnnotations
00035 from Products.Archetypes.interfaces.annotations import IATAnnotatable
00036 
00037 # annotation keys
00038 AT_ANN_STORAGE = 'Archetypes.storage.AnnotationStorage'
00039 AT_MD_STORAGE  = 'Archetypes.storage.MetadataAnnotationStorage'
00040 AT_FIELD_MD    = 'Archetypes.field.Metadata'
00041 AT_REF         = 'Archetypes.referenceEngine.Reference'
00042 
00043 # all keys so someone can test against this list
00044 AT_ANN_KEYS = (AT_ANN_STORAGE, AT_MD_STORAGE, AT_FIELD_MD, AT_REF)
00045 
00046 class ATAnnotations(DictMixin, Explicit):
00047     """Store annotations in the '__annotations__' attribute on a IATAnnotatable
00048        object.
00049     """
00050     __implements__ = IATAnnotations
00051     __used_for__ = IATAnnotatable
00052 
00053     security = ClassSecurityInfo()
00054     security.declareObjectPrivate()
00055 
00056     def __init__(self, obj):
00057         self._obj = aq_base(obj)
00058 
00059     # basic methods required for DictMixin
00060 
00061     def __nonzero__(self):
00062         return bool(getattr(self._obj, '__annotations__', False))
00063 
00064     def get(self, key, default=None):
00065         annotations = getattr(self._obj, '__annotations__', None)
00066         if not annotations:
00067             return default
00068 
00069         return annotations.get(key, default)
00070 
00071     def __getitem__(self, key):
00072         annotations = getattr(self._obj, '__annotations__', None)
00073         if annotations is None:
00074             raise KeyError, key
00075 
00076         return annotations[key]
00077 
00078     def keys(self):
00079         annotations = getattr(self._obj, '__annotations__', None)
00080         if annotations is None:
00081             return []
00082 
00083         return annotations.keys()
00084 
00085     def __setitem__(self, key, value):
00086         if not isinstance(key, basestring):
00087             raise TypeError('ATAnnotations key must be a string')
00088         try:
00089             annotations = self._obj.__annotations__
00090         except AttributeError:
00091             annotations = self._obj.__annotations__ = OOBTree()
00092 
00093         annotations[key] = value
00094 
00095     def __delitem__(self, key):
00096         try:
00097             annotation = self._obj.__annotations__
00098         except AttributeError:
00099             raise KeyError, key
00100 
00101         del annotation[key]
00102 
00103     # additional methods
00104 
00105     def set(self, key, value):
00106         self[key] = value
00107 
00108     def getSubkey(self, key, subkey, default=None):
00109         """Get annotations using a key and onesubkey
00110         """
00111         if isinstance(subkey, basestring):
00112             k = '%s-%s' % (key, subkey)
00113             return self.get(k, default)
00114         else:
00115             raise TypeError('Invalid subkey type %s, must be string type' % type(subkey))
00116 
00117     def setSubkey(self, key, value, subkey):
00118         """Stores data using a key and one subkey
00119         """
00120         if isinstance(subkey, basestring):
00121             k = '%s-%s' % (key, subkey)
00122             self[k] = value
00123         else:
00124             raise TypeError('Invalid subkey type %s, must be string type' % type(subkey))
00125 
00126     def delSubkey(self, key, subkey):
00127         """Removes a subkey
00128         """
00129         if isinstance(subkey, basestring):
00130             k = '%s-%s' % (key, subkey)
00131             del self[k]
00132         else:
00133             raise TypeError('Invalid subkey type %s, must be string type' % type(subkey))
00134 
00135     def hasSubkey(self, key, subkey):
00136         """Checks for the existence of a sub key
00137         """
00138         if isinstance(subkey, basestring):
00139             k = '%s-%s' % (key, subkey)
00140             return self.has_key(k)
00141         else:
00142             raise TypeError('Invalid subkey type %s, must be string type' % type(subkey))
00143 
00144     def getObject(self):
00145         return self._obj
00146         
00147     def getAnnotationObject(self):
00148         try:
00149             return self._obj.__annotations__
00150         except AttributeError:
00151             return None
00152 
00153     # DictMixin does define the following methods:
00154     #def __iter__(self):
00155     #def has_key(self, key):
00156     #def __contains__(self, key):
00157     #def iteritems(self):
00158     #def iterkeys(self):
00159     #def itervalues(self):
00160     #def values(self):
00161     #def items(self):    
00162     #def clear(self):
00163     #def setdefault(self, key, default):
00164     #def pop(self, key, *args):
00165     #def popitem(self):
00166     #def update(self, other):
00167     #def get(self, key, default=None):
00168     #def __repr__(self):
00169     #def __cmp__(self, other):
00170     #def __len__(self):
00171 
00172 InitializeClass(ATAnnotations)
00173 
00174 def getAnnotation(obj):
00175      """Get an ATAnnotation object for obj
00176      """
00177      return ATAnnotations(obj).__of__(obj)
00178