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