1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__="""ToOneRelationship
15
16 ToOneRelationship is a class used on a RelationshipManager
17 to give it toOne management Functions.
18 """
19
20 import logging
21 log = logging.getLogger("zen.Relations")
22
23
24
25 from RelationshipBase import RelationshipBase
26
27 from Globals import InitializeClass
28 from Globals import DTMLFile
29 from AccessControl import ClassSecurityInfo
30 from App.Dialogs import MessageDialog
31 from Acquisition import aq_base
32
33 from zExceptions import NotFound
34 from Products.ZenRelations.Exceptions import *
35 from Products.ZenUtils.Utils import unused, getObjByPath
36
43
44
45
46 addToOneRelationship = DTMLFile('dtml/addToOneRelationship',globals())
47
48
50 """ToOneRelationship represents a to one Relationship
51 on a RelationshipManager"""
52
53 meta_type = 'ToOneRelationship'
54
55 security = ClassSecurityInfo()
56
57
59 self.id = id
60 self.obj = None
61
62
64 """return the related object when a ToOne relation is called"""
65
66
67
68 return self.obj
69
70
72 """does this relation point to the object passed"""
73 return self.obj == obj
74
75
76 - def _add(self, obj):
77 """add a to one side of a relationship
78 if a relationship already exists clear it"""
79 if obj == self.obj: raise RelationshipExistsError
80 self._remoteRemove()
81 self.obj = aq_base(obj)
82 self.__primary_parent__._p_changed = True
83
84
86 """remove the to one side of a relationship"""
87 if obj == None or obj == self.obj:
88 self.obj = None
89 self.__primary_parent__._p_changed = True
90 else:
91 raise ObjectNotFound( "object %s was not found on %s" % (obj, self))
92
93
95 """clear the remote side of this relationship"""
96 if self.obj:
97 if obj != None and obj != self.obj:
98 raise ObjectNotFound(
99 "object %s was not found on %s it has object %s" %
100 (obj.getPrimaryId(), self.getPrimaryId(),
101 self.obj.getPrimaryId()))
102 remoteRel = getattr(aq_base(self.obj), self.remoteName())
103 remoteRel._remove(self.__primary_parent__)
104
105
106 security.declareProtected('View', 'getRelatedId')
113
114
116 """
117 Create ToOne copy. If this is the one side of one to many
118 we set our side of the relation to point towards the related
119 object (maintain the relationship across the copy).
120 """
121 rel = self.__class__(self.id)
122 rel.__primary_parent__ = container
123 rel = rel.__of__(container)
124 if (self.remoteTypeName() == "ToMany" and self.obj):
125 rel.addRelation(self.obj)
126 return rel
127
128
130 """Don't do anything here because we have on containment"""
131 pass
132
134 """Don't do anything here because we have on containment"""
135 pass
136
138 """
139 There are 4 possible states during when beforeDelete is called.
140 They are defined by the attribute _operation and can be:
141 -1 = object being deleted remove relation
142 0 = copy, 1 = move, 2 = rename
143 Any state less than 1 will provoke deletion of the remote end of the
144 relationship.
145 ToOne doesn't call beforeDelete on its related object because its
146 not a container.
147 """
148 unused(container)
149 if (getattr(item, "_operation", -1) < 1
150 and self.remoteTypeName() != 'ToManyCont'):
151 self._remoteRemove()
152
153
155 """ZMI function to return the workspace of the related object"""
156 if self.obj:
157 objurl = self.obj.getPrimaryUrlPath()
158 REQUEST['RESPONSE'].redirect(objurl+'/manage_workspace')
159 else:
160 return MessageDialog(
161 title = "No Relationship Error",
162 message = "This relationship does not currently point" \
163 " to an object",
164 action = "manage_main")
165
166
167 - def manage_main(self, REQUEST=None):
168 """ZMI function to redirect to parent relationship manager"""
169 REQUEST['RESPONSE'].redirect(
170 self.getPrimaryParent().getPrimaryUrlPath()+'/manage_workspace')
171
172
173
174 security.declareProtected('View', 'getPrimaryLink')
176 """get the link tag of a related object"""
177 link = ""
178 if self.obj:
179 if not self.obj.checkRemotePerm("View", self.obj):
180 link = self.obj.id
181 else:
182 link = "<a href='%s'>%s</a>" % (self.obj.getPrimaryUrlPath(),
183 self.obj.id)
184 return link
185
186
188 """Return the primary URL for our related object.
189 """
190 return self.obj.getPrimaryUrlPath()
191
192
194 """return an xml representation of a ToOneRelationship
195 <toone id='cricket'>
196 /Monitors/Cricket/crk0.srv.hcvlny.cv.net
197 </toone>"""
198 from RelSchema import ToManyCont
199 if not self.obj or self.remoteType()==ToManyCont: return
200 ofile.write("<toone id='%s' objid='%s'/>\n" % (
201 self.id, self.obj.getPrimaryId()))
202
203
205 """Check to make sure that relationship bidirectionality is ok.
206 """
207 if not self.obj: return
208 log.debug("checking relation: %s", self.id)
209
210 try:
211 ppath = self.obj.getPrimaryPath()
212 getObjByPath(self, ppath)
213 except (KeyError, NotFound):
214 log.error("object %s in relation %s has been deleted " \
215 "from its primary path",
216 self.obj.getPrimaryId(), self.getPrimaryId())
217 if repair:
218 log.warn("removing object %s from relation %s",
219 self.obj.getPrimaryId(), self.getPrimaryId())
220 self.obj = None
221
222 if not self.obj: return
223
224 rname = self.remoteName()
225 rrel = getattr(self.obj, rname)
226 parobj = self.getPrimaryParent()
227 if not rrel.hasobject(parobj):
228 log.error("remote relation %s doesn't point back to %s",
229 rrel.getPrimaryId(), self.getPrimaryId())
230 if repair:
231 log.warn("reconnecting relation %s to relation %s",
232 rrel.getPrimaryId(), self.getPrimaryId())
233 rrel._add(parobj)
234
235
236 InitializeClass(ToOneRelationship)
237