Package Products :: Package ZenRelations :: Module ToManyContRelationship
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenRelations.ToManyContRelationship

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  __doc__="""$Id: ToManyRelationship.py,v 1.48 2003/11/12 22:05:48 edahl Exp $""" 
 15   
 16  __version__ = "$Revision: 1.48 $"[11:-2] 
 17   
 18  import logging 
 19  log = logging.getLogger("zen.Relations") 
 20   
 21  from Globals import DTMLFile 
 22  from Globals import InitializeClass 
 23  from AccessControl import ClassSecurityInfo 
 24  from Acquisition import aq_base 
 25  from OFS.ObjectManager import checkValidId, BeforeDeleteException 
 26  from ZODB.POSException import ConflictError 
 27   
 28  import OFS.subscribers 
 29  from OFS.event import ObjectWillBeAddedEvent 
 30  from OFS.event import ObjectWillBeRemovedEvent 
 31  from zope.event import notify 
 32  from zope.app.container.contained import ObjectAddedEvent 
 33  from zope.app.container.contained import ObjectRemovedEvent 
 34  from zope.app.container.contained import ContainerModifiedEvent 
 35  from zope.app.container.contained import dispatchToSublocations 
 36   
 37  from BTrees.OOBTree import OOBTree 
 38   
 39  from ToManyRelationshipBase import ToManyRelationshipBase 
 40   
 41  from Products.ZenRelations.Exceptions import * 
 42   
 43  from Products.ZenUtils.Utils import unused 
 44   
45 -def manage_addToManyContRelationship(context, id, REQUEST=None):
46 """factory for ToManyRelationship""" 47 rel = ToManyContRelationship(id) 48 context._setObject(rel.id, rel) 49 if REQUEST: 50 REQUEST['RESPONSE'].redirect(context.absolute_url()+'/manage_main') 51 return rel.id
52 53 54 addToManyContRelationship = DTMLFile('dtml/addToManyContRelationship',globals()) 55 56
57 -class ToManyContRelationship(ToManyRelationshipBase):
58 """ 59 ToManyContRelationship is the ToMany side of a realtionship that 60 contains its related objects (like the normal Zope ObjectManager) 61 """ 62 63 meta_type = "ToManyContRelationship" 64 65 security = ClassSecurityInfo() 66 67
68 - def __init__(self, id):
69 """set our instance values""" 70 self.id = id 71 self._objects = OOBTree()
72 73
74 - def __call__(self):
75 """when we are called return our related object in our aq context""" 76 return [ob.__of__(self) for ob in self._objects.values()]
77 78
79 - def __getattr__(self, name):
80 """look in the two object stores for related objects""" 81 if self.__dict__.has_key("_objects"): 82 objects = self.__dict__['_objects'] 83 if objects.has_key(name): return objects[name] 84 raise AttributeError( "Unable to find the attribute '%s'" % name )
85 86
87 - def __hasattr__(self, name):
88 """check to see if we have an object by an id 89 this will fail if passed a short id and object is stored 90 with fullid (ie: it is related not contained) 91 use hasobject to get around this issue""" 92 return self._objects.has_key(name)
93 94
95 - def hasobject(self, obj):
96 "check to see if we have this object" 97 return self._objects.get(obj.id) == obj
98 99
100 - def addRelation(self, obj):
101 """Override base to run manage_afterAdd like ObjectManager""" 102 notify(ObjectWillBeAddedEvent(obj, self, obj.getId())) 103 ToManyRelationshipBase.addRelation(self, obj) 104 obj = obj.__of__(self) 105 notify(ObjectAddedEvent(obj, self, obj.getId())) 106 notify(ContainerModifiedEvent(self))
107 108
109 - def _setObject(self,id,object,roles=None,user=None,set_owner=1):
110 """ObjectManager interface to add contained object.""" 111 unused(user, roles, set_owner) 112 object.__primary_parent__ = aq_base(self) 113 self.addRelation(object) 114 return object.getId()
115 116
117 - def manage_afterAdd(self, item, container):
118 # Don't do recursion anymore, a subscriber does that. 119 pass
120 manage_afterAdd.__five_method__ = True 121
122 - def manage_afterClone(self, item):
123 # Don't do recursion anymore, a subscriber does that. 124 pass
125 manage_afterClone.__five_method__ = True 126
127 - def manage_beforeDelete(self, item, container):
128 # Don't do recursion anymore, a subscriber does that. 129 pass
130 manage_beforeDelete.__five_method__ = True 131
132 - def _add(self,obj):
133 """add an object to one side of a ToManyContRelationship. 134 """ 135 id = obj.id 136 if self._objects.has_key(id): 137 raise RelationshipExistsError 138 v=checkValidId(self, id) 139 if v is not None: id=v 140 self._objects[id] = aq_base(obj) 141 obj = aq_base(obj).__of__(self)
142 143
144 - def _remove(self, obj=None):
145 """remove object from our side of a relationship""" 146 if obj: objs = [obj] 147 else: objs = self.objectValuesAll() 148 for robj in objs: 149 notify(ObjectWillBeRemovedEvent(robj, self, robj.getId())) 150 if obj: 151 id = obj.id 152 if not self._objects.has_key(id): 153 raise ObjectNotFound( 154 "object %s not found on %s" % ( 155 obj.getPrimaryId(), self.getPrimaryId())) 156 del self._objects[id] 157 else: 158 self._objects = OOBTree() 159 self.__primary_parent__._p_changed = True 160 for robj in objs: 161 notify(ObjectRemovedEvent(robj, self, robj.getId())) 162 notify(ContainerModifiedEvent(self))
163 164
165 - def _remoteRemove(self, obj=None):
166 """remove an object from the far side of this relationship 167 if no object is passed in remove all objects""" 168 if obj: 169 if not self._objects.has_key(obj.id): 170 raise ObjectNotFound("object %s not found on %s" % ( 171 obj.getPrimaryId(), self.getPrimaryId())) 172 objs = [obj] 173 else: objs = self.objectValuesAll() 174 remoteName = self.remoteName() 175 for obj in objs: 176 rel = getattr(obj, remoteName) 177 rel._remove(self.__primary_parent__)
178 179
180 - def _getOb(self, id, default=zenmarker):
181 """look up in our local store and wrap in our aq_chain""" 182 if self._objects.has_key(id): 183 return self._objects[id].__of__(self) 184 elif default == zenmarker: 185 raise AttributeError( "Unable to find %s" % id ) 186 return default
187 188 189 security.declareProtected('View', 'objectIds')
190 - def objectIds(self, spec=None):
191 """only return contained objects""" 192 if spec: 193 if type(spec)==type('s'): spec=[spec] 194 return [obj.id for obj in self._objects.values() \ 195 if obj.meta_type in spec] 196 return [ k for k in self._objects.keys() ]
197 objectIdsAll = objectIds 198 199 200 security.declareProtected('View', 'objectValues')
201 - def objectValues(self, spec=None):
202 """override to only return owned objects for many to many rel""" 203 if spec: 204 if type(spec)==type('s'): spec=[spec] 205 return [ob.__of__(self) for ob in self._objects.values() \ 206 if ob.meta_type in spec] 207 return [ob.__of__(self) for ob in self._objects.values()]
208 security.declareProtected('View', 'objectValuesAll') 209 objectValuesAll = objectValues 210 211
212 - def objectValuesGen(self):
213 """Generator that returns all related objects.""" 214 for obj in self._objects.values(): 215 yield obj.__of__(self)
216 217
218 - def objectItems(self, spec=None):
219 """over ride to only return owned objects for many to many rel""" 220 if spec: 221 if type(spec)==type('s'): spec=[spec] 222 return [(key,value.__of__(self)) \ 223 for (key,value) in self._objects.items() \ 224 if value.meta_type in spec] 225 return [(key,value.__of__(self)) \ 226 for (key,value) in self._objects.items()]
227 objectItemsAll = objectItems 228 229 230 #FIXME - need to make this work 231 # def all_meta_types(self, interfaces=None): 232 # mts = [] 233 # for mt in ToManyRelationshipBase.all_meta_types(self, interfaces): 234 # if (mt.has_key('instance') and mt['instance']): 235 # for cl in self.sub_classes: 236 # if checkClass(mt['instance'], cl): 237 # mts.append(mt) 238 # return mts 239 240
241 - def _getCopy(self, container):
242 """ 243 make new relation add copies of contained objs 244 and refs if the relation is a many to many 245 """ 246 rel = self.__class__(self.id) 247 rel.__primary_parent__ = container 248 rel = rel.__of__(container) 249 norelcopy = getattr(self, 'zNoRelationshipCopy', []) 250 if self.id in norelcopy: return rel 251 for oobj in self.objectValuesAll(): 252 cobj = oobj._getCopy(rel) 253 rel._setObject(cobj.id, cobj) 254 return rel
255 256
257 - def exportXml(self, ofile, ignorerels=[]):
258 """Return an xml representation of a ToManyContRelationship 259 <tomanycont id='interfaces'> 260 <object id='hme0' 261 module='Products.Confmon.IpInterface' class='IpInterface'> 262 <property></property> etc.... 263 </object> 264 </tomanycont> 265 """ 266 if self.countObjects() == 0: return 267 ofile.write("<tomanycont id='%s'>\n" % self.id) 268 for obj in self.objectValues(): 269 obj.exportXml(ofile, ignorerels) 270 ofile.write("</tomanycont>\n")
271 272 273 InitializeClass(ToManyContRelationship) 274 275
276 -class ToManyContSublocations(object):
277 """ 278 Adapter so the event dispatching can propagate to children. 279 """
280 - def __init__(self, container):
281 self.container = container
282 - def sublocations(self):
283 return (ob for ob in self.container.objectValuesAll())
284