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