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,
91 final TypeInfo typeInfo,
92 final FieldHandler handler,
93 final boolean isTransitive) {
94
95 if (fieldName == null) {
96 throw new IllegalArgumentException("Internal error. Field name not specified.");
97 }
98
99 if (handler == null) {
100 throw new IllegalArgumentException("Internal error. No FieldHandler provided.");
101 }
102
103 setFieldName(fieldName);
104 setFieldType(typeInfo.getFieldType());
105 setHandler(handler);
106 setTransient(isTransitive);
107 setImmutable(typeInfo.isImmutable());
108 setRequired(typeInfo.isRequired());
109 setMultivalued(typeInfo.getCollectionHandler() != null);
110 }
111
112 /**
113 * @see org.exolab.castor.mapping.FieldDescriptor#setContainingClassDescriptor(
114 * org.exolab.castor.mapping.ClassDescriptor)
115 * {@inheritDoc}
116 */
117 public final void setContainingClassDescriptor(final ClassDescriptor parent) {
118 _parent = parent;
119 }
120
121 /**
122 * @see org.exolab.castor.mapping.FieldDescriptor#getContainingClassDescriptor()
123 * {@inheritDoc}
124 */
125 public final ClassDescriptor getContainingClassDescriptor() {
126 return _parent;
127 }
128
129 /**
130 * Set the name of the field.
131 *
132 * @param fieldName Field name.
133 */
134 public final void setFieldName(final String fieldName) {
135 _fieldName = fieldName;
136 }
137
138 /**
139 * @see org.exolab.castor.mapping.FieldDescriptor#getFieldName()
140 * {@inheritDoc}
141 */
142 public final String getFieldName() {
143 return _fieldName;
144 }
145
146 /**
147 * Set the type of the field.
148 *
149 * @param fieldType Field type.
150 */
151 public final void setFieldType(final Class<?> fieldType) {
152 _fieldType = fieldType;
153 }
154
155 /**
156 * @see org.exolab.castor.mapping.FieldDescriptor#getFieldType()
157 * {@inheritDoc}
158 */
159 public final Class<?> getFieldType() {
160 return _fieldType;
161 }
162
163 /**
164 * Set the ClassDescriptor for the described field.
165 *
166 * @param classDescriptor The ClassDescriptor for the described field.
167 */
168 public final void setClassDescriptor(final ClassDescriptor classDescriptor) {
169 _classDescriptor = classDescriptor;
170 }
171
172 /**
173 * @see org.exolab.castor.mapping.FieldDescriptor#getClassDescriptor()
174 * {@inheritDoc}
175 */
176 public final ClassDescriptor getClassDescriptor() {
177 return _classDescriptor;
178 }
179
180 /**
181 * Set the FieldHandler for the field being described by this FieldDescriptor.
182 *
183 * @param handler The FieldHandler for the field being described.
184 */
185 public final void setHandler(final FieldHandler handler) {
186 _handler = handler;
187 }
188
189 /**
190 * @see org.exolab.castor.mapping.FieldDescriptor#getHandler()
191 * {@inheritDoc}
192 */
193 public final FieldHandler getHandler() {
194 return _handler;
195 }
196
197 /**
198 * Sets whether or not the describled field is 'transient'.
199 *
200 * @param isTransient The flag indicating if the described field is 'transient'.
201 */
202 public final void setTransient(final boolean isTransient) {
203 _transient = isTransient;
204 }
205
206 /**
207 * @see org.exolab.castor.mapping.FieldDescriptor#isTransient()
208 * {@inheritDoc}
209 */
210 public final boolean isTransient() {
211 return _transient;
212 }
213
214 /**
215 * Set the immutable flag which indicates that changes to this Field result in a
216 * new Object to be created, such as java.lang.String. It serves to identify fields
217 * which should not be constructed until all the data is available.
218 *
219 * @param immutable Flag which if true indicates that the field is immutable.
220 */
221 public final void setImmutable(final boolean immutable) {
222 _immutable = immutable;
223 }
224
225 /**
226 * @see org.exolab.castor.mapping.FieldDescriptor#isImmutable()
227 * {@inheritDoc}
228 */
229 public final boolean isImmutable() {
230 return _immutable;
231 }
232
233 /**
234 * Set whether or not the described field is required.
235 *
236 * @param required The flag indicating whether or not the described field is required.
237 */
238 public final void setRequired(final boolean required) {
239 _required = required;
240 }
241
242 /**
243 * @see org.exolab.castor.mapping.FieldDescriptor#isRequired()
244 * {@inheritDoc}
245 */
246 public final boolean isRequired() {
247 return _required;
248 }
249
250 /**
251 * Set wheter the object described by this descriptor is multivalued or not.
252 *
253 * @param multivalued True if the object described by this descriptor is multivalued.
254 */
255 public final void setMultivalued(final boolean multivalued) {
256 _multivalued = multivalued;
257 }
258
259 /**
260 * @see org.exolab.castor.mapping.FieldDescriptor#isMultivalued()
261 * {@inheritDoc}
262 */
263 public final boolean isMultivalued() {
264 return _multivalued;
265 }
266
267 /**
268 * Set wether the described field is part of the identity of the class it belongs to.
269 *
270 * @param identity <code>true</code> if field is part of the classes identity.
271 */
272 public final void setIdentity(final boolean identity) {
273 _identity = identity;
274 }
275
276 /**
277 * Is the described field is part of the identity of the class it belongs to?
278 *
279 * @return <code>true</code> if field is part of the classes identity.
280 */
281 public final boolean isIdentity() {
282 return _identity;
283 }
284
285 /**
286 * @see org.exolab.castor.builder.info.nature.PropertyHolder#
287 * getProperty(java.lang.String)
288 * @param name
289 * of the property
290 * @return value of the property
291 */
292 public Object getProperty(final String name) {
293 return _properties.get(name);
294 }
295
296 /**
297 * @see org.exolab.castor.builder.info.nature.PropertyHolder#
298 * setProperty(java.lang.String, java.lang.Object)
299 * @param name
300 * of the property
301 * @param value
302 * of the property
303 */
304 public void setProperty(final String name, final Object value) {
305 _properties.put(name, value);
306 }
307
308 /**
309 * @see org.exolab.castor.builder.info.nature.NatureExtendable#
310 * addNature(java.lang.String)
311 * @param nature
312 * ID of the Nature
313 */
314 public void addNature(final String nature) {
315 _natures.add(nature);
316 }
317
318 /**
319 * @see org.exolab.castor.builder.info.nature.NatureExtendable#
320 * hasNature(java.lang.String)
321 * @param nature
322 * ID of the Nature
323 * @return true if the Nature ID was added.
324 */
325 public boolean hasNature(final String nature) {
326 return _natures.contains(nature);
327 }
328
329 public String getComparator() {
330 return _comparator;
331 }
332
333 public void setComparator(String comparator) {
334 _comparator = comparator;
335 }
336
337 public FieldMappingCollectionType getCollection() {
338 return _collection;
339 }
340
341 public void setCollection(FieldMappingCollectionType collection) {
342 _collection = collection;
343 }
344
345 public boolean isDirect() {
346 return _direct;
347 }
348
349 public void setDirect(boolean direct) {
350 _direct = direct;
351 }
352
353 public String getGetMethod() {
354 return _getMethod;
355 }
356
357 public void setGetMethod(String getMethod) {
358 _getMethod = getMethod;
359 }
360
361 public String getSetMethod() {
362 return _setMethod;
363 }
364
365 public void setSetMethod(String setMethod) {
366 _setMethod = setMethod;
367 }
368
369 public String getCreateMethod() {
370 return _createMethod;
371 }
372
373 public void setCreateMethod(String createMethod) {
374 _createMethod = createMethod;
375 }
376
377 public boolean isLazy() {
378 return _lazy;
379 }
380
381 public void setLazy(boolean lazy) {
382 _lazy = lazy;
383 }
384
385 public String toString() {
386 StringBuffer buffer = new StringBuffer();
387 buffer.append(getFieldName() + "(" + getFieldType().getName() + ")");
388 // TODO[WG]: find a way to emit additional nature-specific information.
389 // try {
390 // Class natureClass = Class.forName("org.exolab.castor.jdo.engine.nature.FieldDescriptorJDONature");
391 // if (hasNature(natureClass.getName())) {
392 // FieldDescriptorJDONature jdoNature = new FieldDescriptorJDONature(this);
393 // buffer.append(jdoNature.getSQLName() == null ? "" : " AS "
394 // + jdoNature.getSQLName()[0]);
395 // }
396 // } catch (ClassNotFoundException e) {
397 // // ignore
398 // }
399 return buffer.toString();
400 }
401
402 }