1
2
3
4
5
6
7
8
9
10
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
43
44
45 addToManyContRelationship = DTMLFile('dtml/addToManyContRelationship',globals())
46
47
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
60 """set our instance values"""
61 self.id = id
62 self._objects = OOBTree()
63
64
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
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
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
87 "check to see if we have this object"
88 return self._objects.get(obj.id) == obj
89
90
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
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
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
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
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
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
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')
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')
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
226 """Generator that returns all related objects."""
227 for obj in self._objects.values():
228 yield obj.__of__(self)
229
230
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
244
245
246
247
248
249
250
251
252
253
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
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