1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.jdo.impl.model.jdo;
19
20 import org.apache.jdo.model.ModelException;
21 import org.apache.jdo.model.java.JavaType;
22 import org.apache.jdo.model.jdo.JDOClass;
23 import org.apache.jdo.model.jdo.JDOField;
24 import org.apache.jdo.model.jdo.JDORelationship;
25
26 /***
27 * JDORelationship is the super interface for all interfaces representing
28 * JDO relationship metadata of a managed field of a persistence capable class.
29 *
30 * @author Michael Bouschen
31 * @version 2.0
32 */
33 public abstract class JDORelationshipImpl extends JDOElementImpl
34 implements JDORelationship {
35
36 /*** Property lowerBound. No default. */
37 private int lowerBound;
38
39 /*** Property upperBound. No default. */
40 private int upperBound;
41
42 /*** Relationship JDOField<->JDORelationship. */
43 private JDOField declaringField;
44
45 /*** Relationship JDORelationship<->JDORelationship. */
46 protected JDORelationship mappedBy;
47
48 /*** Name of the field which is the inverse relationship */
49 private String inverseName;
50
51 /*** Relationship JDORelationship<->JDORelationship. */
52 protected JDORelationship inverse;
53
54 /***
55 * Get the lower cardinality bound for this relationship element.
56 * @return the lower cardinality bound
57 */
58 public int getLowerBound() {
59 return lowerBound;
60 }
61
62 /***
63 * Set the lower cardinality bound for this relationship element.
64 * @param lowerBound an integer indicating the lower cardinality bound
65 */
66 public void setLowerBound(int lowerBound) {
67 this.lowerBound = lowerBound;
68 }
69
70 /***
71 * Get the upper cardinality bound for this relationship element.
72 * @return the upper cardinality bound
73 */
74 public int getUpperBound() {
75 return upperBound;
76 }
77
78 /***
79 * Set the upper cardinality bound for this relationship element.
80 * @param upperBound an integer indicating the upper cardinality bound
81 */
82 public void setUpperBound(int upperBound)
83 {
84 this.upperBound = upperBound;
85 }
86
87 /***
88 * Get the declaring field of this JDORelationship.
89 * @return the field that owns this JDORelationship, or <code>null</code>
90 * if the element is not attached to any field
91 */
92 public JDOField getDeclaringField() {
93 return declaringField;
94 }
95
96 /***
97 * Set the declaring field of this JDORelationship.
98 * @param declaringField the declaring field of this relationship element
99 */
100 public void setDeclaringField(JDOField declaringField) {
101 this.declaringField = declaringField;
102 }
103
104 /***
105 * Get the JDOClass corresponding to the type or element of this
106 * relationship.
107 * @return the related class
108 */
109 public JDOClass getRelatedJDOClass() {
110 JavaType relatedType = getRelatedJavaType();
111
112 if (relatedType != null) {
113 JDOClass myClass = getDeclaringField().getDeclaringClass();
114 String relatedTypeName = relatedType.getName();
115
116 if (relatedTypeName.equals(myClass.getName()))
117 return myClass;
118
119 return myClass.getDeclaringModel().getJDOClass(relatedTypeName);
120 }
121
122 return null;
123 }
124
125 /***
126 * Get the mappedBy relationship. If there is no mappedBy relationship
127 * set, the method checks the mappedBy name as specified in the declaring
128 * field and resolves the relationship. The method return
129 * <code>null</code> if there is no mappedBy relationship set and there
130 * is no mappedBy name specified on the declaring field.
131 * @return the mappedBy relationship if available; <code>null</code>
132 * otherwise.
133 */
134 public JDORelationship getMappedBy() {
135 if (mappedBy != null) {
136
137 return mappedBy;
138 }
139
140
141 JDOField field = getDeclaringField();
142 String mappedByName = field.getMappedByName();
143 if (mappedByName != null) {
144
145
146 return getInverseRelationship();
147 }
148
149 return null;
150 }
151
152 /***
153 * Set the mappedBy relationship for this relationship. This method
154 * automatically updates the mappedBy name of the declaring field of this
155 * relationship.
156 * @param mappedBy the mappedBy relationship.
157 * @exception ModelException if impossible
158 */
159 public void setMappedBy(JDORelationship mappedBy) throws ModelException {
160 this.mappedBy = mappedBy;
161 String mappedByName = null;
162 if (mappedBy != null) {
163 JDOField declaringField = mappedBy.getDeclaringField();
164 if (declaringField != null) {
165 mappedByName = declaringField.getName();
166 }
167 }
168 getDeclaringField().setMappedByName(mappedByName);
169 setInverseRelationship(mappedBy);
170 }
171
172 /***
173 * Get the relative name of the inverse relationship field for this
174 * relationship. In the case of two-way relationships, the two
175 * relationships involved are inverses of each other. If this
176 * relationship element does not participate in a two-way relationship,
177 * this returns <code>null</code>. Note that it is possible to have
178 * this method return a value, but because of the combination of
179 * related class and lookup, there may be no corresponding
180 * JDORelationship which can be found.
181 * @return the relative name of the inverse JDORelationship
182 * @see #getInverseRelationship
183 */
184 public String getInverseRelationshipName() {
185 if (inverseName != null) {
186
187 return inverseName;
188 }
189
190 JDOField declaringField = getDeclaringField();
191 String mappedByName = declaringField.getMappedByName();
192 if (mappedByName != null) {
193
194 return mappedByName;
195 }
196
197
198
199 UnresolvedRelationshipHelper info = getUnresolvedRelationshipHelper();
200
201
202 JDOField inverseField =
203 info.resolve(declaringField.getName(), getRelatedJDOClass());
204 if (inverseField != null) {
205
206 inverseName = inverseField.getName();
207 return inverseName;
208 }
209
210
211 return null;
212 }
213
214 /***
215 * Get the inverse JDORelationship in the case of a two-way relationship.
216 * @return the inverse relationship
217 */
218 public JDORelationship getInverseRelationship() {
219 if (inverse != null) {
220
221 return inverse;
222 }
223
224
225 String fieldName = getInverseRelationshipName();
226 if (fieldName != null) {
227 JDOClass relatedClass = getRelatedJDOClass();
228 JDOField relatedField = relatedClass.getField(fieldName);
229 if (relatedField != null)
230 return relatedField.getRelationship();
231 }
232 return null;
233 }
234
235 /***
236 * Set the inverse JDORelationship in the case of a two-way relationship.
237 * The two relationship elements involved are set as inverses of each
238 * other and the old inverse is unset.
239 * <p>
240 * Warning: this methods casts the existing and the specified inverse
241 * relationship instance to JDORelationshipImpl.
242 * @param inverseRelationship the inverse relationship
243 */
244 public void setInverseRelationship(JDORelationship inverseRelationship)
245 throws ModelException {
246
247
248
249
250
251
252 if (this.inverse == inverseRelationship) {
253 return;
254 }
255
256
257 JDORelationshipImpl old =
258 (JDORelationshipImpl) getInverseRelationship();
259 if (old != null) {
260 if (this.equals(old.getInverseRelationship()))
261 old.changeInverseRelationship(null);
262 }
263
264
265 changeInverseRelationship(inverseRelationship);
266
267
268 if (inverseRelationship != null) {
269 ((JDORelationshipImpl) inverseRelationship).
270 changeInverseRelationship(this);
271 }
272 }
273
274 /***
275 * Determines whether this side of a two-way relationship is the
276 * owning side.
277 * @return <code>true</code> if this side is the owning side;
278 * <code>false</code> otherwise.
279 */
280 public boolean isOwner() {
281 return getMappedBy() == null;
282 }
283
284 /***
285 * Determines whether this JDORelationship represents a reference
286 * relationship or not. A return of <code>true</code> means this
287 * JDORelationship is a JDOReference instance.
288 * @return <code>true</code> if this JDORelationship represents a
289 * reference relationship; <code>false</code> otherwise.
290 */
291 public boolean isJDOReference() {
292 return false;
293 }
294
295 /***
296 * Determines whether this JDORelationship represents a collection
297 * relationship or not. A return of <code>true</code> means this
298 * JDORelationship is a JDOCollection instance.
299 * @return <code>true</code> if this JDORelationship represents a
300 * collection relationship; <code>false</code> otherwise.
301 */
302 public boolean isJDOCollection() {
303 return false;
304 }
305
306 /***
307 * Determines whether this JDORelationship represents an array
308 * relationship or not. A return of <code>true</code> means this
309 * JDORelationship is a JDOArray instance.
310 * @return <code>true</code> if this JDORelationship represents an
311 * array relationship; <code>false</code> otherwise.
312 */
313 public boolean isJDOArray() {
314 return false;
315 }
316
317 /***
318 * Determines whether this JDORelationship represents a map
319 * relationship or not. A return of <code>true</code> means this
320 * JDORelationship is a JDOMap instance.
321 * @return <code>true</code> if this JDORelationship represents a
322 * map relationship; <code>false</code> otherwise.
323 */
324 public boolean isJDOMap() {
325 return false;
326 }
327
328
329
330 /***
331 * Get the type representation of the relationship. This will be
332 * the JavaType for references, the element type for collections
333 * and arrays, and the value type for maps.
334 * @return the relationship type
335 */
336 public abstract JavaType getRelatedJavaType();
337
338 /*** Changes the inverse relationship element for this relationship
339 * element.
340 * This method is invoked for both sides from
341 * {@link #setInverseRelationship} and should handle setting the
342 * internal variable.
343 * @param inverseRelationship - a relationship element to be used as the
344 * inverse for this relationship element or <code>null</code> if this
345 * relationship element does not participate in a two-way relationship.
346 * @exception ModelException if impossible
347 */
348 private void changeInverseRelationship(JDORelationship
349 inverseRelationship) throws ModelException {
350 this.inverse = inverseRelationship;
351 this.inverseName = ((inverseRelationship == null) ? null :
352 inverseRelationship.getDeclaringField().getName());
353 }
354
355 /***
356 * Returns the UnresolvedRelationshipHelper instance from the declaring
357 * field.
358 * @return the current UnresolvedRelationshipHelper
359 */
360 private UnresolvedRelationshipHelper getUnresolvedRelationshipHelper() {
361 return ((JDOFieldImplDynamic) getDeclaringField()).
362 getUnresolvedRelationshipHelper();
363 }
364 }