View Javadoc
1   package org.exolab.castor.mapping.loader;
2   
3   import java.util.Comparator;
4   import java.util.HashMap;
5   import java.util.HashSet;
6   import java.util.Map;
7   import java.util.Set;
8   
9   import org.exolab.castor.mapping.ClassDescriptor;
10  import org.exolab.castor.mapping.FieldDescriptor;
11  import org.exolab.castor.mapping.FieldHandler;
12  import org.exolab.castor.mapping.xml.types.FieldMappingCollectionType;
13  
14  public class FieldDescriptorImpl implements FieldDescriptor {
15  
16    /** A reference to the containing class descriptor (parent). */
17    private ClassDescriptor _parent;
18  
19    /** The name of the field. */
20    private String _fieldName;
21  
22    /** The type of the field. */
23    private Class<?> _fieldType;
24  
25    /** The type class descriptor, if this field is of a type known by a descriptor. */
26    private ClassDescriptor _classDescriptor;
27  
28    /** The field handler for get/set field value. */
29    private FieldHandler _handler;
30  
31    /** True if the field is transient and should not be saved/stored. */
32    private boolean _transient;
33  
34    /** True if the described field type is immutable. */
35    private boolean _immutable;
36  
37    /** True if the field type is required. */
38    private boolean _required;
39  
40    /** True if access to field is direct. */
41    private boolean _direct;
42  
43    /** True if access to field is lazy. */
44    private boolean _lazy;
45  
46    /** True if the object described by this descriptor is multi-valued. */
47    private boolean _multivalued;
48  
49    /** True if the field is part of the identity of the class. */
50    private boolean _identity;
51  
52    /** The name of a class that implements the {@link Comparator} interface. */
53    private String _comparator;
54  
55    /** The name of the 'getter' method used to obtain the value of a property. */
56    private String _getMethod;
57  
58    /** The name of the 'setter' method used to set the value of a property. */
59    private String _setMethod;
60  
61    /** The name of the 'create' method used to create an instance of a property. */
62    private String _createMethod;
63  
64    /** The type of the collection, if the field is multi-valued. */
65    private FieldMappingCollectionType _collection;
66  
67    /**
68     * Map holding the properties set and read by natures.
69     */
70    private Map<String, Object> _properties = new HashMap<String, Object>();
71  
72    /**
73     * Map holding the available natures.
74     */
75    private Set<String> _natures = new HashSet<String>();
76  
77    /**
78     * Creates a default instance of a field descriptor.
79     */
80    protected FieldDescriptorImpl() {}
81  
82    /**
83     * Constructs a new field descriptor.
84     *
85     * @param fieldName The field name
86     * @param typeInfo The field type information
87     * @param handler The field handler (may be null)
88     * @param isTransitive True if the field is transient
89     */
90    public FieldDescriptorImpl(final String fieldName, final TypeInfo typeInfo,
91        final FieldHandler handler, final boolean isTransitive) {
92  
93      if (fieldName == null) {
94        throw new IllegalArgumentException("Internal error. Field name not specified.");
95      }
96  
97      if (handler == null) {
98        throw new IllegalArgumentException("Internal error. No FieldHandler provided.");
99      }
100 
101     setFieldName(fieldName);
102     setFieldType(typeInfo.getFieldType());
103     setHandler(handler);
104     setTransient(isTransitive);
105     setImmutable(typeInfo.isImmutable());
106     setRequired(typeInfo.isRequired());
107     setMultivalued(typeInfo.getCollectionHandler() != null);
108   }
109 
110   /**
111    * @see org.exolab.castor.mapping.FieldDescriptor#setContainingClassDescriptor(
112    *      org.exolab.castor.mapping.ClassDescriptor) {@inheritDoc}
113    */
114   public final void setContainingClassDescriptor(final ClassDescriptor parent) {
115     _parent = parent;
116   }
117 
118   /**
119    * @see org.exolab.castor.mapping.FieldDescriptor#getContainingClassDescriptor() {@inheritDoc}
120    */
121   public final ClassDescriptor getContainingClassDescriptor() {
122     return _parent;
123   }
124 
125   /**
126    * Set the name of the field.
127    * 
128    * @param fieldName Field name.
129    */
130   public final void setFieldName(final String fieldName) {
131     _fieldName = fieldName;
132   }
133 
134   /**
135    * @see org.exolab.castor.mapping.FieldDescriptor#getFieldName() {@inheritDoc}
136    */
137   public final String getFieldName() {
138     return _fieldName;
139   }
140 
141   /**
142    * Set the type of the field.
143    * 
144    * @param fieldType Field type.
145    */
146   public final void setFieldType(final Class<?> fieldType) {
147     _fieldType = fieldType;
148   }
149 
150   /**
151    * @see org.exolab.castor.mapping.FieldDescriptor#getFieldType() {@inheritDoc}
152    */
153   public final Class<?> getFieldType() {
154     return _fieldType;
155   }
156 
157   /**
158    * Set the ClassDescriptor for the described field.
159    *
160    * @param classDescriptor The ClassDescriptor for the described field.
161    */
162   public final void setClassDescriptor(final ClassDescriptor classDescriptor) {
163     _classDescriptor = classDescriptor;
164   }
165 
166   /**
167    * @see org.exolab.castor.mapping.FieldDescriptor#getClassDescriptor() {@inheritDoc}
168    */
169   public final ClassDescriptor getClassDescriptor() {
170     return _classDescriptor;
171   }
172 
173   /**
174    * Set the FieldHandler for the field being described by this FieldDescriptor.
175    *
176    * @param handler The FieldHandler for the field being described.
177    */
178   public final void setHandler(final FieldHandler handler) {
179     _handler = handler;
180   }
181 
182   /**
183    * @see org.exolab.castor.mapping.FieldDescriptor#getHandler() {@inheritDoc}
184    */
185   public final FieldHandler getHandler() {
186     return _handler;
187   }
188 
189   /**
190    * Sets whether or not the describled field is 'transient'.
191    * 
192    * @param isTransient The flag indicating if the described field is 'transient'.
193    */
194   public final void setTransient(final boolean isTransient) {
195     _transient = isTransient;
196   }
197 
198   /**
199    * @see org.exolab.castor.mapping.FieldDescriptor#isTransient() {@inheritDoc}
200    */
201   public final boolean isTransient() {
202     return _transient;
203   }
204 
205   /**
206    * Set the immutable flag which indicates that changes to this Field result in a new Object to be
207    * created, such as java.lang.String. It serves to identify fields which should not be constructed
208    * until all the data is available.
209    * 
210    * @param immutable Flag which if true indicates that the field is immutable.
211    */
212   public final void setImmutable(final boolean immutable) {
213     _immutable = immutable;
214   }
215 
216   /**
217    * @see org.exolab.castor.mapping.FieldDescriptor#isImmutable() {@inheritDoc}
218    */
219   public final boolean isImmutable() {
220     return _immutable;
221   }
222 
223   /**
224    * Set whether or not the described field is required.
225    * 
226    * @param required The flag indicating whether or not the described field is required.
227    */
228   public final void setRequired(final boolean required) {
229     _required = required;
230   }
231 
232   /**
233    * @see org.exolab.castor.mapping.FieldDescriptor#isRequired() {@inheritDoc}
234    */
235   public final boolean isRequired() {
236     return _required;
237   }
238 
239   /**
240    * Set wheter the object described by this descriptor is multivalued or not.
241    * 
242    * @param multivalued True if the object described by this descriptor is multivalued.
243    */
244   public final void setMultivalued(final boolean multivalued) {
245     _multivalued = multivalued;
246   }
247 
248   /**
249    * @see org.exolab.castor.mapping.FieldDescriptor#isMultivalued() {@inheritDoc}
250    */
251   public final boolean isMultivalued() {
252     return _multivalued;
253   }
254 
255   /**
256    * Set wether the described field is part of the identity of the class it belongs to.
257    * 
258    * @param identity <code>true</code> if field is part of the classes identity.
259    */
260   public final void setIdentity(final boolean identity) {
261     _identity = identity;
262   }
263 
264   /**
265    * Is the described field is part of the identity of the class it belongs to?
266    * 
267    * @return <code>true</code> if field is part of the classes identity.
268    */
269   public final boolean isIdentity() {
270     return _identity;
271   }
272 
273   /**
274    * @see org.exolab.castor.builder.info.nature.PropertyHolder# getProperty(java.lang.String)
275    * @param name of the property
276    * @return value of the property
277    */
278   public Object getProperty(final String name) {
279     return _properties.get(name);
280   }
281 
282   /**
283    * @see org.exolab.castor.builder.info.nature.PropertyHolder# setProperty(java.lang.String,
284    *      java.lang.Object)
285    * @param name of the property
286    * @param value of the property
287    */
288   public void setProperty(final String name, final Object value) {
289     _properties.put(name, value);
290   }
291 
292   /**
293    * @see org.exolab.castor.builder.info.nature.NatureExtendable# addNature(java.lang.String)
294    * @param nature ID of the Nature
295    */
296   public void addNature(final String nature) {
297     _natures.add(nature);
298   }
299 
300   /**
301    * @see org.exolab.castor.builder.info.nature.NatureExtendable# hasNature(java.lang.String)
302    * @param nature ID of the Nature
303    * @return true if the Nature ID was added.
304    */
305   public boolean hasNature(final String nature) {
306     return _natures.contains(nature);
307   }
308 
309   public String getComparator() {
310     return _comparator;
311   }
312 
313   public void setComparator(String comparator) {
314     _comparator = comparator;
315   }
316 
317   public FieldMappingCollectionType getCollection() {
318     return _collection;
319   }
320 
321   public void setCollection(FieldMappingCollectionType collection) {
322     _collection = collection;
323   }
324 
325   public boolean isDirect() {
326     return _direct;
327   }
328 
329   public void setDirect(boolean direct) {
330     _direct = direct;
331   }
332 
333   public String getGetMethod() {
334     return _getMethod;
335   }
336 
337   public void setGetMethod(String getMethod) {
338     _getMethod = getMethod;
339   }
340 
341   public String getSetMethod() {
342     return _setMethod;
343   }
344 
345   public void setSetMethod(String setMethod) {
346     _setMethod = setMethod;
347   }
348 
349   public String getCreateMethod() {
350     return _createMethod;
351   }
352 
353   public void setCreateMethod(String createMethod) {
354     _createMethod = createMethod;
355   }
356 
357   public boolean isLazy() {
358     return _lazy;
359   }
360 
361   public void setLazy(boolean lazy) {
362     _lazy = lazy;
363   }
364 
365   public String toString() {
366     return new StringBuilder().append(getFieldName()).append('(').append(getFieldType().getName())
367         .append(')').toString();
368     // TODO[WG]: find a way to emit additional nature-specific information.
369     // try {
370     // Class natureClass =
371     // Class.forName("org.exolab.castor.jdo.engine.nature.FieldDescriptorJDONature");
372     // if (hasNature(natureClass.getName())) {
373     // FieldDescriptorJDONature jdoNature = new FieldDescriptorJDONature(this);
374     // buffer.append(jdoNature.getSQLName() == null ? "" : " AS "
375     // + jdoNature.getSQLName()[0]);
376     // }
377     // } catch (ClassNotFoundException e) {
378     // // ignore
379     // }
380   }
381 
382 }