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

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