1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jdo.impl.model.jdo.caching;
18
19 import org.apache.jdo.model.java.JavaType;
20 import org.apache.jdo.model.ModelException;
21 import org.apache.jdo.model.jdo.JDOClass;
22 import org.apache.jdo.model.jdo.JDOField;
23 import org.apache.jdo.model.jdo.JDOIdentityType;
24 import org.apache.jdo.model.jdo.JDOMember;
25 import org.apache.jdo.model.jdo.JDOProperty;
26
27 import org.apache.jdo.impl.model.jdo.JDOClassImplDynamic;
28
29 /***
30 * An instance of this class represents the JDO metadata of a persistence
31 * capable class. This caching implementation caches any calulated
32 * value to avoid re-calculating it if it is requested again.
33 *
34 * @author Michael Bouschen
35 * @since 1.1
36 * @version 2.0
37 */
38 public class JDOClassImplCaching extends JDOClassImplDynamic
39 {
40
41 /*** Flag indicating whether the objectIdClass is resolved already. */
42 private boolean objectIdClassResolved = false;
43
44 /*** Flag indicating whether the pcSuperclass is resolved already. */
45 private boolean pcSuperclassResolved = false;
46
47 /*** Array of declared managed fields, sorted by name (see JDO spec). */
48 private JDOField[] declaredManagedFields;
49
50 /***
51 * Array of managed fields, incluing inherited fields. The fields are
52 * sorted by name (see JDO Spec) per class in the inheritance hierarchy.
53 */
54 private JDOField[] managedFields;
55
56 /***
57 * Array of persistent fields, incluing inherited fields. The fields are
58 * sorted by name (see JDO Spec) per class in the inheritance hierarchy.
59 */
60 private JDOField[] persistentFields;
61
62 /*** Primary key fields. */
63 private JDOField[] primaryKeyFields;
64
65 /*** Persistent relationship fields. */
66 private JDOField[] persistentRelationshipFields;
67
68 /*** Default fetch group fields. */
69 private JDOField[] defaultFetchGroupFields;
70
71 /*** Number of inherited fields. */
72 private int inheritedManagedFieldCount = -1;
73
74 /*** Field numbers of managed fields. */
75 private int[] managedFieldNumbers;
76
77 /*** Field numbers of PERSISTENT fields. */
78 private int[] persistentFieldNumbers;
79
80 /*** Field numbers of primaryKey fields. */
81 private int[] primaryKeyFieldNumbers;
82
83 /*** Field numbers of managed non primaryKey fields. */
84 private int[] nonPrimaryKeyFieldNumbers;
85
86 /*** Field numbers of persistent non primaryKey fields. */
87 private int[] persistentNonPrimaryKeyFieldNumbers;
88
89 /*** Field numbers of persistent relationship fields. */
90 private int[] persistentRelationshipFieldNumbers;
91
92 /*** Field numbers of persistent, serializable fields. */
93 private int[] persistentSerializableFieldNumbers;
94
95 /*** Flag indicating wthere field numbers are calculated already. */
96 private boolean fieldNumbersCalculated = false;
97
98 /*** Constructor. */
99 protected JDOClassImplCaching(String name) {
100 super(name);
101 }
102
103 /*** Constructor for inner classes. */
104 protected JDOClassImplCaching(String name, JDOClass declaringClass) {
105 super(name, declaringClass);
106 }
107
108 /***
109 * Get the short name of this JDOClass. The short name defaults to the
110 * unqualified class name, if not explicitly set by method
111 * {@link #setShortName(String shortName)}.
112 * @return the short name of this JDOClass.
113 */
114 public String getShortName() {
115 if (shortName == null) {
116 shortName = super.getShortName();
117 }
118 return shortName;
119 }
120
121 /***
122 * Get the JDO identity type of this JDOClass.
123 * The identity type of the least-derived persistence-capable class defines
124 * the identity type for all persistence-capable classes that extend it.
125 * The identity type of the least-derived persistence-capable class is
126 * defaulted to {@link JDOIdentityType#APPLICATION} if objectid-class is
127 * specified, and {@link JDOIdentityType#DATASTORE}, if not.
128 * @return the JDO identity type, one of
129 * {@link JDOIdentityType#APPLICATION},
130 * {@link JDOIdentityType#DATASTORE}, or
131 * {@link JDOIdentityType#NONDURABLE}
132 */
133 public int getIdentityType() {
134 if (identityType == JDOIdentityType.UNSPECIFIED) {
135 identityType = super.getIdentityType();
136 }
137 return identityType;
138 }
139
140 /***
141 * Get the JavaType representation of the object identity class
142 * (primary key class) for this JDOClass.
143 * @return the JavaType representation of the object identity class.
144 */
145 public JavaType getObjectIdClass() {
146 if (!objectIdClassResolved) {
147 objectIdClassResolved = true;
148 objectIdClass = super.getObjectIdClass();
149 }
150 return objectIdClass;
151 }
152
153 /***
154 * Returns the JDOClass instance for the persistence-capable superclass
155 * of this JDOClass. If this class does not have a persistence-capable
156 * superclass then <code>null</code> is returned.
157 * @return the JDClass instance of the persistence-capable superclass
158 * or <code>null</code> if there is no persistence-capable superclass
159 */
160 public JDOClass getPersistenceCapableSuperclass() {
161 if(!pcSuperclassResolved) {
162 pcSuperclass = super.getPersistenceCapableSuperclass();
163 }
164 return pcSuperclass;
165 }
166
167 /***
168 * Provides the JavaType representaion corresponding to this JDOClass.
169 * <p>
170 * Note the difference between Object.getClass() and this method. The
171 * former returns the class of the object in hand, this returns the class
172 * of the object represented by this meta data.
173 * @return the JavaType object corresponding to this JDOClass.
174 */
175 public JavaType getJavaType() {
176 if (javaType == null) {
177 javaType = super.getJavaType();
178 }
179 return javaType;
180 }
181
182 /***
183 * Remove the supplied member from the collection of members maintained by
184 * this JDOClass.
185 * @param member the member to be removed
186 * @exception ModelException if impossible
187 */
188 public void removeDeclaredMember(JDOMember member) throws ModelException {
189 if ((member instanceof JDOField) && fieldNumbersCalculated) {
190 throw new ModelException(
191 msg.msg("EXC_CannotRemoveJDOField"));
192 }
193
194
195 declaredManagedFields = null;
196 managedFields = null;
197 persistentFields = null;
198 primaryKeyFields = null;
199 persistentRelationshipFields = null;
200 defaultFetchGroupFields = null;
201
202 super.removeDeclaredMember(member);
203 }
204
205 /***
206 * This method returns a JDOField instance for the field with the specified
207 * name. If this JDOClass already declares such a field, the existing
208 * JDOField instance is returned. Otherwise, it creates a new JDOField
209 * instance, sets its declaringClass and returns the new instance.
210 * <P>
211 * Note, if the field numbers for the managed fields of this JDOClass are
212 * calculated, this methid will fail to create a new JDOField. Any new field
213 * would possibly invalidate existing field number
214 * @param name the name of the field
215 * @exception ModelException if impossible
216 */
217 public JDOField createJDOField(String name) throws ModelException {
218 if ((getDeclaredField(name) == null) && fieldNumbersCalculated) {
219 throw new ModelException(
220 msg.msg("EXC_CannotCreateJDOField"));
221 }
222 return super.createJDOField(name);
223 }
224
225 /***
226 * Returns the collection of managed JDOField instances declared by this
227 * JDOClass in the form of an array. The returned array does not include
228 * inherited fields. A field is a managed field, if it has the
229 * persistence-modifier
230 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or
231 * {@link org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}.
232 * The position of the fields in the returned array equals their
233 * relative field number as returned by
234 * {@link JDOField#getRelativeFieldNumber()}. The following holds
235 * true for any field in the returned array:
236 * <ul>
237 * <li> <code>getDeclaredManagedFields()[i].getRelativeFieldNumber()
238 * == i</code>
239 * <li> <code>getDeclaredManagedFields()[field.getRelativeFieldNumber()]
240 * == field</code>
241 * </ul>
242 * @return the managed fields declared by this JDOClass
243 */
244 public JDOField[] getDeclaredManagedFields() {
245 if (declaredManagedFields == null) {
246 declaredManagedFields = super.getDeclaredManagedFields();
247 }
248 return declaredManagedFields;
249 }
250
251 /***
252 * Returns the collection of managed JDOField instances of this JDOClass
253 * in the form of an array. The returned array includes inherited fields.
254 * A field is a managed field, if it has the persistence-modifier
255 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or
256 * {@link org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}.
257 * The position of the fields in the returned array equals their
258 * absolute field number as returned by
259 * {@link JDOField#getFieldNumber()}. The following holds true for
260 * any field in the returned array:
261 * <ul>
262 * <li> <code>getManagedFields()[i].getFieldNumber() == i</code>
263 * <li> <code>getManagedFields()[field.getFieldNumber()] == field</code>
264 * </ul>
265 * @return the managed fields of this JDOClass
266 */
267 public JDOField[] getManagedFields() {
268 if (managedFields == null) {
269 managedFields = super.getManagedFields();
270 }
271 return managedFields;
272 }
273
274 /***
275 * Returns the collection of persistent JDOField instances of this JDOClass
276 * in the form of an array. The returned array includes inherited fields.
277 * A field is a persistent field, if it has the persistence-modifier
278 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
279 * Please note, the position of the fields in the returned array might not
280 * equal their absolute field number as returned by
281 * {@link JDOField#getFieldNumber()}.
282 * @return the persistent fields of this JDOClass
283 */
284 public JDOField[] getPersistentFields() {
285 if (persistentFields == null) {
286 persistentFields = super.getPersistentFields();
287 }
288 return persistentFields;
289 }
290
291 /***
292 * Returns the collection of identifying fields of this JDOClass in the form
293 * of an array. The method returns the JDOField instances defined as
294 * primary key fields (see {@link JDOField#isPrimaryKey}).
295 * @return the identifying fields of this JDOClass
296 */
297 public JDOField[] getPrimaryKeyFields() {
298 if (primaryKeyFields == null) {
299 primaryKeyFields = super.getPrimaryKeyFields();
300 }
301 return primaryKeyFields;
302 }
303
304 /***
305 * Returns the collection of persistent relationship fields of this JDOClass
306 * in the form of an array. The method returns the JDOField instances
307 * defined as relationship (method {@link JDOField#getRelationship} returns
308 * a non null value) and having the persistence-modifier
309 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
310 * @return the persistent relationship fields of this JDOClass
311 */
312 public JDOField[] getPersistentRelationshipFields() {
313 if (persistentRelationshipFields == null) {
314 persistentRelationshipFields =
315 super.getPersistentRelationshipFields();
316 }
317 return persistentRelationshipFields;
318 }
319
320 /***
321 * Returns the collection of default fetch group fields of this JDOClass
322 * in the form of an array. The method returns the JDOField instances
323 * defined as part of the default fetch group
324 * (method {@link JDOField#isDefaultFetchGroup} returns <code>true</code>.
325 * @return the default fetch group fields of this JDOClass
326 * @since 1.1
327 */
328 public JDOField[] getDefaultFetchGroupFields() {
329 if (defaultFetchGroupFields == null) {
330 defaultFetchGroupFields = super.getDefaultFetchGroupFields();
331 }
332 return defaultFetchGroupFields;
333 }
334
335 /***
336 * Returns an array of absolute field numbers of the managed fields of this
337 * JDOClass. The returned array includes field numbers of inherited fields.
338 * A field is a managed field, if it has the persistence-modifier
339 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or
340 * {@link org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}.
341 * Only managed fields have a valid field number, thus the field number in
342 * the returned array equals its index:
343 * <br>
344 * <code>getManagedFields()[i] == i</code>
345 */
346 public int[] getManagedFieldNumbers() {
347 if (managedFieldNumbers == null) {
348 managedFieldNumbers = super.getManagedFieldNumbers();
349 }
350 return managedFieldNumbers;
351 }
352
353 /***
354 * Returns an array of absolute field numbers of the persistent fields of
355 * this JDOClass. The returned array includes field numbers of inherited
356 * fields. A persistent field has the persistence-modifier
357 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
358 */
359 public int[] getPersistentFieldNumbers()
360 {
361 if (persistentFieldNumbers == null) {
362 persistentFieldNumbers = super.getPersistentFieldNumbers();
363 }
364 return persistentFieldNumbers;
365 }
366
367 /***
368 * Returns an array of absolute field numbers of the identifying fields
369 * of this JDOClass. A field number is included in the returned array,
370 * iff the corresponding JDOField instance is defined as primary key field
371 * (see {@link JDOField#isPrimaryKey}).
372 * @return array of numbers of the identifying fields
373 */
374 public int[] getPrimaryKeyFieldNumbers() {
375 if (primaryKeyFieldNumbers == null) {
376 primaryKeyFieldNumbers = super.getPrimaryKeyFieldNumbers();
377 }
378 return primaryKeyFieldNumbers;
379 }
380
381 /***
382 * Returns an array of absolute field numbers of the non identifying,
383 * persistent fields of this JDOClass. A field number is included in the
384 * returned array, iff the corresponding JDOField instance is persistent and
385 * not a not a primary key field (see {@link JDOField#isPrimaryKey}).
386 * A field is a persistent field, if it has the persistence-modifier
387 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or
388 * (see {@link JDOField#getPersistenceModifier}).
389 * @return array of numbers of the non identifying, persistent fields
390 */
391 public int[] getPersistentNonPrimaryKeyFieldNumbers() {
392 if (persistentNonPrimaryKeyFieldNumbers == null) {
393 persistentNonPrimaryKeyFieldNumbers =
394 super.getPersistentNonPrimaryKeyFieldNumbers();
395 }
396 return persistentNonPrimaryKeyFieldNumbers;
397 }
398
399 /***
400 * Returns an array of absolute field numbers of persistent relationship
401 * fields of this JDOClass. A field number is included in the returned
402 * array, iff the corresponding JDOField instance is a relationship (method
403 * {@link JDOField#getRelationship} returns a non null value) and has the
404 * persistence-modifier
405 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
406 * @return the field numbers of the persistent relationship fields
407 */
408 public int[] getPersistentRelationshipFieldNumbers() {
409 if (persistentRelationshipFieldNumbers == null) {
410 persistentRelationshipFieldNumbers =
411 super.getPersistentRelationshipFieldNumbers();
412 }
413 return persistentRelationshipFieldNumbers;
414 }
415
416 /***
417 * Returns an array of absolute field numbers of persistent, serializable
418 * fields of this JDOClass. A field number is included in the returned
419 * array, iff the corresponding JDOField instance is serializable (method
420 * {@link JDOField#isSerializable} returns <code>true</code>) and has the
421 * persistence-modifier
422 * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
423 * @return the field numbers of serializable fields
424 */
425 public int[] getPersistentSerializableFieldNumbers() {
426 if (persistentSerializableFieldNumbers == null) {
427 persistentSerializableFieldNumbers =
428 super.getPersistentSerializableFieldNumbers();
429 }
430 return persistentSerializableFieldNumbers;
431 }
432
433 /***
434 * Returns the number of inherited managed fields for this class.
435 * @return number of inherited fields
436 */
437 public synchronized int getInheritedManagedFieldCount() {
438
439 if (inheritedManagedFieldCount < 0) {
440 inheritedManagedFieldCount = super.getInheritedManagedFieldCount();
441 }
442 return inheritedManagedFieldCount;
443 }
444
445
446
447 /***
448 * This method calculates the relative field number of the
449 * declared managed fields of this JDOClass and uddates the
450 * relativeFieldNumber property of the JDOField instance.
451 */
452 protected void calculateFieldNumbers() {
453 if (!fieldNumbersCalculated) {
454 fieldNumbersCalculated = true;
455 JDOField[] fields = getDeclaredManagedFields();
456
457 for (int i = 0; i < fields.length; i++) {
458 ((JDOFieldImplCaching)fields[i]).setRelativeFieldNumber(i);
459 }
460 }
461 }
462
463 /***
464 * Returns a new instance of the JDOClass implementation class.
465 */
466 protected JDOClass newJDOClassInstance(String name) {
467 return new JDOClassImplCaching(name, this);
468 }
469
470 /***
471 * Returns a new instance of the JDOField implementation class.
472 */
473 protected JDOField newJDOFieldInstance(String name) {
474 return new JDOFieldImplCaching(name, this);
475 }
476
477 /***
478 * Returns a new instance of the JDOProperty implementation class.
479 */
480 protected JDOProperty newJDOPropertyInstance(String name) {
481 return new JDOPropertyImplCaching(name, this);
482 }
483
484 /***
485 * Returns a new instance of the JDOProperty implementation class.
486 */
487 protected JDOProperty newJDOPropertyInstance(
488 String name, JDOField associatedJDOField) throws ModelException {
489 return new JDOAssociatedPropertyImplCaching(
490 name, this, associatedJDOField);
491 }
492 }