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