KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > ejb > cmp3 > metadata > accessors > BasicAccessor


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors;
23
24 import java.io.Serializable JavaDoc;
25
26 import javax.persistence.Column;
27 import javax.persistence.Enumerated;
28 import javax.persistence.EnumType;
29 import javax.persistence.GeneratedValue;
30 import javax.persistence.Id;
31 import javax.persistence.Lob;
32 import javax.persistence.Temporal;
33 import javax.persistence.Version;
34
35 import oracle.toplink.essentials.descriptors.TimestampLockingPolicy;
36 import oracle.toplink.essentials.descriptors.VersionLockingPolicy;
37
38 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor;
39 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataAccessibleObject;
40
41 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataColumn;
42
43 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataConstants;
44 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataHelper;
45
46 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.sequencing.MetadataGeneratedValue;
47
48 import oracle.toplink.essentials.internal.helper.Helper;
49 import oracle.toplink.essentials.internal.helper.DatabaseField;
50
51 import oracle.toplink.essentials.mappings.converters.EnumTypeConverter;
52 import oracle.toplink.essentials.mappings.converters.SerializedObjectConverter;
53 import oracle.toplink.essentials.mappings.converters.TypeConversionConverter;
54
55 import oracle.toplink.essentials.mappings.DirectToFieldMapping;
56
57 import oracle.toplink.essentials.internal.helper.DatabaseField;
58
59 /**
60  * An relational accessor.
61  *
62  * @author Guy Pelletier
63  * @since TopLink EJB 3.0 Reference Implementation
64  */

65 public class BasicAccessor extends NonRelationshipAccessor {
66     /**
67      * INTERNAL:
68      */

69     public BasicAccessor(MetadataAccessibleObject accessibleObject, ClassAccessor classAccessor) {
70         super(accessibleObject, classAccessor);
71     }
72     
73     /**
74      * INTERNAL: (Overridden in XMLBasicAccessor)
75      * Build a metadata column.
76      */

77     protected MetadataColumn getColumn() {
78         Column column = getAnnotation(Column.class);
79         return new MetadataColumn(column, this);
80     }
81     
82     /**
83      * INTERNAL:
84      * Process column details from an @Column or column element into a
85      * MetadataColumn and return it. This will set correct metadata and log
86      * defaulting messages to the user.
87      *
88      * NOTE: This method will be called for on columns loaded from an accessor
89      * and those loaded from an attribute override.
90      */

91     public DatabaseField getDatabaseField() {
92          // Check if we have an attribute override first, otherwise process for
93
// a column.
94
MetadataColumn column;
95          
96         if (m_descriptor.hasAttributeOverrideFor(getAttributeName())) {
97             column = m_descriptor.getAttributeOverrideFor(getAttributeName());
98         } else {
99             column = getColumn();
100         }
101         
102         // Get the actual database field and apply any defaults.
103
DatabaseField field = column.getDatabaseField();
104         
105         // Set the correct field name, defaulting and logging when necessary.
106
field.setName(getName(field.getName(), column.getUpperCaseAttributeName(), m_logger.COLUMN));
107         
108         // Make sure this is a table name on the field.
109
if (field.getTableName().equals("")) {
110             field.setTableName(m_descriptor.getPrimaryTableName());
111         }
112                     
113         return field;
114      }
115      
116     /**
117      * INTERNAL: (Overridden in XMLBasicAccessor)
118      */

119      public String JavaDoc getEnumeratedType() {
120         Enumerated enumerated = getAnnotation(Enumerated.class);
121         
122         if (enumerated == null) {
123             return EnumType.ORDINAL.name();
124         } else {
125             return enumerated.value().name();
126         }
127      }
128      
129     /**
130      * INTERNAL:
131      * Return the temporal type for this accessor. Assumes there is a @Temporal.
132      */

133     public String JavaDoc getTemporalType() {
134         Temporal temporal = getAnnotation(Temporal.class);
135         return temporal.value().name();
136     }
137     
138     /**
139      * INTERNAL: (Overridden in XMLBasicAccessor)
140      * Method to check if an annotated element has an @Enumerated.
141      */

142     public boolean hasEnumerated() {
143         return isAnnotationPresent(Enumerated.class);
144     }
145     
146     /**
147      * INTERNAL: (Overridden in XMLBasicAccessor)
148      * Return true if this accessor represents a temporal mapping.
149      */

150     public boolean hasTemporal() {
151         return isAnnotationPresent(Temporal.class);
152     }
153     
154     /**
155      * INTERNAL:
156      */

157      public boolean isBasic() {
158         return true;
159      }
160      
161     /**
162      * INTERNAL:
163      * Return true if this represents an enum type mapping. Will return true
164      * if the accessor's reference class is an enum or if an enumerated
165      * sub-element exists.
166      */

167      public boolean isEnumerated() {
168         return hasEnumerated() || MetadataHelper.isValidEnumeratedType(getReferenceClass());
169      }
170      
171     /**
172      * INTERNAL: (Overridden in XMLBasicAccessor)
173      * Return true if this accessor represents an id field.
174      */

175     public boolean isId() {
176         return isAnnotationPresent(Id.class);
177     }
178     
179     /**
180      * INTERNAL: (Overridden in XMLBasicAccessor)
181      * Return true if this accessor represents an BLOB/CLOB mapping.
182      */

183     public boolean isLob() {
184         return isAnnotationPresent(Lob.class);
185     }
186     
187     /**
188      * INTERNAL:
189      * Return true if this accessor represents a serialized mapping.
190      */

191     public boolean isSerialized() {
192         return MetadataHelper.isValidSerializedType(getReferenceClass());
193     }
194     
195     /**
196      * INTERNAL:
197      * Return true if this accessor represents a temporal mapping.
198      */

199     public boolean isTemporal() {
200         return hasTemporal() || MetadataHelper.isValidTemporalType(getReferenceClass());
201     }
202     
203     /**
204      * INTERNAL: (Overridden in XMLBasicAccessor)
205      * Return true if this accessor represents an optimistic locking field.
206      */

207     public boolean isVersion() {
208         return isAnnotationPresent(Version.class);
209     }
210     
211     /**
212      * INTERNAL:
213      * Process a basic accessor.
214      */

215     public void process() {
216         // Process the @Column or column element if there is one.
217
DatabaseField field = getDatabaseField();
218             
219         // Process an @Version or version element if there is one.
220
if (isVersion()) {
221             if (m_descriptor.usesOptimisticLocking()) {
222                 // Ignore the version locking if it is already set.
223
m_logger.logWarningMessage(m_logger.IGNORE_VERSION_LOCKING, this);
224             } else {
225                 processVersion(field);
226             }
227         } else if (isId()) {
228             // Process an @Id or id element.
229
processId(field);
230         }
231                 
232         if (m_descriptor.hasMappingForAttributeName(getAttributeName())) {
233             // Ignore the mapping if one already exists for it.
234
m_logger.logWarningMessage(m_logger.IGNORE_MAPPING, this);
235         } else {
236             // Process a DirectToFieldMapping, that is a Basic that could
237
// be used in conjunction with a Lob, Temporal, Enumerated
238
// or inferred to be used with a serialized mapping.
239
processDirectToFieldMapping(field);
240         }
241     }
242     
243     /**
244      * INTERNAL:
245      * Process a Serialized or Basic into a DirectToFieldMapping. If neither
246      * is found a DirectToFieldMapping is created regardless.
247      */

248     protected void processDirectToFieldMapping(DatabaseField field) {
249         DirectToFieldMapping mapping = new DirectToFieldMapping();
250         mapping.setField(field);
251         mapping.setIsReadOnly(field.isReadOnly());
252         mapping.setAttributeName(getAttributeName());
253         mapping.setIsOptional(isOptional());
254         
255         if (usesIndirection()) {
256             m_logger.logWarningMessage(m_logger.IGNORE_BASIC_FETCH_LAZY, this);
257         }
258         
259         // Will check for PROPERTY access
260
setAccessorMethods(mapping);
261         
262         // Check for an enum first since it will fall into a serializable
263
// mapping otherwise (Enums are serialized)
264
if (isEnumerated()) {
265             processEnumerated(mapping);
266         } else if (isLob()) {
267             processLob(mapping);
268         } else if (isTemporal()) {
269             processTemporal(mapping);
270         } else if (isSerialized()) {
271             processSerialized(mapping);
272         }
273         
274         // Add the mapping to the descriptor.
275
m_descriptor.addMapping(mapping);
276     }
277     
278     /**
279      * INTERNAL:
280      * Process an @Enumerated. The method may still be called if no @Enumerated
281      * has been specified but the accessor's reference class is a valid
282      * enumerated type.
283      */

284     protected void processEnumerated(DirectToFieldMapping mapping) {
285         // If this accessor is tagged as an enumerated type, validate the
286
// reference class.
287
if (hasEnumerated()) {
288             if (! MetadataHelper.isValidEnumeratedType(getReferenceClass())) {
289                 m_validator.throwInvalidTypeForEnumeratedAttribute(getJavaClass(), mapping.getAttributeName(), getReferenceClass());
290             }
291         }
292         
293         // Set a EnumTypeConverter on the mapping.
294
mapping.setConverter(new EnumTypeConverter(mapping, getReferenceClassName(), getEnumeratedType().equals(EnumType.ORDINAL.name())));
295     }
296     
297     /**
298      * INTERNAL: (Overridden In XMLBasicAccessor)
299      * Process a @GeneratedValue.
300      */

301     protected void processGeneratedValue(DatabaseField field) {
302         GeneratedValue generatedValue = getAnnotation(GeneratedValue.class);
303         
304         if (generatedValue != null) {
305             processGeneratedValue(new MetadataGeneratedValue(generatedValue), field);
306         }
307     }
308     
309     /**
310      * INTERNAL:
311      */

312     protected void processGeneratedValue(MetadataGeneratedValue generatedValue, DatabaseField sequenceNumberField) {
313         // Set the sequence number field on the descriptor.
314
DatabaseField existingSequenceNumberField = m_descriptor.getSequenceNumberField();
315         
316         if (existingSequenceNumberField == null) {
317             m_descriptor.setSequenceNumberField(sequenceNumberField);
318             getProject().addGeneratedValue(generatedValue, getJavaClass());
319         } else {
320             m_validator.throwOnlyOneGeneratedValueIsAllowed(getJavaClass(), existingSequenceNumberField.getQualifiedName(), sequenceNumberField.getQualifiedName());
321         }
322     }
323     
324     /**
325      * INTERNAL:
326      * Process an @Id or id element if there is one.
327      */

328     protected void processId(DatabaseField field) {
329         if (m_descriptor.ignoreIDs()) {
330             // Project XML merging. XML wins, ignore annotations/orm xml.
331
m_logger.logWarningMessage(m_logger.IGNORE_PRIMARY_KEY, this);
332         } else {
333             String JavaDoc attributeName = getAttributeName();
334             
335             if (m_descriptor.hasEmbeddedIdAttribute()) {
336                 // We found both an Id and an EmbeddedId, throw an exception.
337
m_validator.throwEmbeddedIdAndIdFound(getJavaClass(), m_descriptor.getEmbeddedIdAttributeName(), attributeName);
338             }
339             
340             // If this entity has a pk class, we need to validate our ids.
341
m_descriptor.validatePKClassId(attributeName, getReferenceClass());
342         
343             // Store the Id attribute name. Used with validation and OrderBy.
344
m_descriptor.addIdAttributeName(attributeName);
345
346             // Add the primary key field to the descriptor.
347
m_descriptor.addPrimaryKeyField(field);
348     
349             // Process the generated value for this id.
350
processGeneratedValue(field);
351             
352             // Process a table generator.
353
processTableGenerator();
354             
355             // Process a sequence generator.
356
processSequenceGenerator();
357         }
358     }
359     
360     /**
361      * INTERNAL:
362      * Process a @Lob or lob sub-element. The lob must be specified to process
363      * and create a lob type mapping.
364      */

365     protected void processLob(DirectToFieldMapping mapping) {
366         // Set the field classification type on the mapping based on the
367
// referenceClass type.
368
if (MetadataHelper.isValidClobType(getReferenceClass())) {
369             mapping.setFieldClassification(java.sql.Clob JavaDoc.class);
370         } else if (MetadataHelper.isValidBlobType(getReferenceClass())) {
371             mapping.setFieldClassification(java.sql.Blob JavaDoc.class);
372         } else {
373             // The referenceClass is neither a valide BLOB or CLOB attribute.
374
m_validator.throwInvalidTypeForLOBAttribute(getJavaClass(), mapping.getAttributeName(), getReferenceClass());
375         }
376         
377         // Set a TypeConversionConverter on the mapping.
378
mapping.setConverter(new TypeConversionConverter(mapping));
379     }
380     
381     /**
382      * INTERNAL:
383      * Process a potential serializable attribute. If the class implements
384      * the Serializable interface then set a SerializedObjectConverter on
385      * the mapping.
386      */

387     protected void processSerialized(DirectToFieldMapping mapping) {
388         if (Helper.classImplementsInterface(getReferenceClass(), Serializable JavaDoc.class)) {
389             mapping.setConverter(new SerializedObjectConverter(mapping));
390         } else {
391             m_validator.throwInvalidTypeForSerializedAttribute(getJavaClass(), mapping.getAttributeName(), getReferenceClass());
392         }
393     }
394     
395     /**
396      * INTERNAL:
397      * Process a temporal type accessor.
398      */

399     protected void processTemporal(DirectToFieldMapping mapping) {
400         if (hasTemporal()) {
401             if (MetadataHelper.isValidTemporalType(getReferenceClass())) {
402                 // Set a TypeConversionConverter on the mapping.
403
mapping.setConverter(new TypeConversionConverter(mapping));
404                 mapping.setFieldClassification(MetadataHelper.getFieldClassification(getTemporalType()));
405             } else {
406                 m_validator.throwInvalidTypeForTemporalAttribute(getJavaClass(), getAttributeName(), getReferenceClass());
407             }
408         } else {
409             m_validator.throwNoTemporalTypeSpecified(getJavaClass(), getAttributeName());
410         }
411     }
412     
413     /**
414      * INTERNAL:
415      */

416     protected void processVersion(DatabaseField field) {
417         Class JavaDoc lockType = getRawClass();
418         field.setType(lockType);
419         
420         if (MetadataHelper.isValidVersionLockingType(lockType)) {
421             m_descriptor.setOptimisticLockingPolicy(new VersionLockingPolicy(field));
422         } else if (MetadataHelper.isValidTimstampVersionLockingType(lockType)) {
423             m_descriptor.setOptimisticLockingPolicy(new TimestampLockingPolicy(field));
424         } else {
425             m_validator.throwInvalidTypeForVersionAttribute(getJavaClass(), getAttributeName(), lockType);
426         }
427     }
428 }
429
Popular Tags