1 /*
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Intalio, Inc. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Intalio, Inc. Exolab is a registered
23 * trademark of Intalio, Inc.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 1999-2004 (C) Intalio, Inc. All Rights Reserved.
42 *
43 * This file was originally developed by Keith Visco during the course
44 * of employment at Intalio Inc.
45 * Portions of this file developed by Keith Visco after Jan 19 2005 are
46 * Copyright (C) 2005 Keith Visco. All Rights Reserverd.
47 *
48 * $Id$
49 */
50 package org.exolab.castor.builder.info;
51
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.LinkedList;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Set;
58
59 import org.castor.core.nature.PropertyHolder;
60 import org.exolab.castor.builder.factory.FieldMemberAndAccessorFactory;
61 import org.exolab.castor.builder.info.nature.XMLInfoNature;
62 import org.exolab.castor.builder.types.XSType;
63 import org.exolab.javasource.JType;
64
65 /**
66 * A class for representing field members of a class. FieldInfo objects hold all
67 * the information required about a member in order to be able to produce
68 * XML data binding (marshal/unmarshal) and validation code.
69 *
70 * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
71 * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
72 */
73 public class FieldInfo implements XMLInfo, PropertyHolder {
74 /**
75 * Map holding the properties set and read by Natures.
76 */
77 private Map<String, Object> _properties = new HashMap<String, Object>();
78
79 /**
80 * Set holding applicable natures.
81 */
82 private Set<String> _natures = new HashSet<String>();
83
84 /** The Read / Getter method flag. */
85 public static final int READ_METHOD = 1;
86 /** The Write / Setter method flag. */
87 public static final int WRITE_METHOD = 2;
88 /** The Read and Write methods flags. */
89 public static final int READ_WRITE_METHODS = 3;
90
91 /** Method prefixes for "Add" methods. */
92 protected static final String METHOD_PREFIX_ADD = "add";
93 /** Method prefixes for "Delete" methods. */
94 protected static final String METHOD_PREFIX_DELETE = "delete";
95 /** Method prefixes for "Get" methods. */
96 protected static final String METHOD_PREFIX_GET = "get";
97 /** Method prefixes for "Has" methods. */
98 protected static final String METHOD_PREFIX_HAS = "has";
99 /** Method prefixes for "Set" methods. */
100 protected static final String METHOD_PREFIX_SET = "set";
101 /** Method prefixes for "Is" methods. */
102 protected static final String METHOD_PREFIX_IS = "is";
103
104 /** The Java name for Members described by this FieldInfo. */
105 private String _name = null;
106
107 /**
108 * {@link ClassInfo} instance which 'own' (declares) this
109 * {@link FieldInfo}.
110 */
111 private ClassInfo _declaringClassInfo = null;
112
113 /** JavaDoc comment. */
114 private String _comment = null;
115
116 /** The default value for this FieldInfo. */
117 private String _default = null;
118 /** The fixed production for this FieldInfo. */
119 private String _fixed = null;
120 /** A flag to indicate a final member. */
121 private boolean _final = false;
122 /** The methods flags, indicates which methods to create. */
123 private int _methods = READ_WRITE_METHODS;
124 /** A reference to the FieldInfo instance within the same class. */
125 private FieldInfo _fieldInfoReference = null;
126 /** A flag to indicate a static member. */
127 private boolean _static = false;
128 /** Flags whether or not the a MarshalDescriptor should be created for this FieldInfo. */
129 private boolean _transient = false;
130 /** A flag to indicate a bound property. */
131 private boolean _bound = false;
132 /** A flag to indicate a container field. */
133 private boolean _isContainer = false;
134 /**
135 * The fully qualified name of the XMLFieldHandler (if any)
136 * to use in the generated descriptor.
137 */
138 private String _fieldHandler;
139 /** A boolean to indicate that this field represents a "nillable" field. */
140 private boolean _nillable = false;
141 /** The fully qualified name of the Validator (if any) to use in the generated descriptor. */
142 private String _validator;
143 /** Visibility of this FieldInfo. */
144 private String _visibility = "private";
145
146 /**
147 * Factory responsible for creating a {@link JField} out of a
148 * {@link FieldInfo}.
149 */
150 private FieldMemberAndAccessorFactory _memberAndAccessorFactory;
151
152 /**
153 * Holds the possible substitution groups for this class.
154 */
155 private List<String> _substitutionGroupMembers = new LinkedList<String>();
156
157 /**
158 * Creates a new FieldInfo with the given XML Schema type and the given
159 * member name. Adds the {@link XMLInfoNature} for legacy compliance.
160 *
161 * @param type
162 * the XML Schema type of this member
163 * @param name
164 * the name of the member
165 * @param memberAndAccessorFactory
166 * the FieldMemberAndAccessorFactory to be used
167 */
168 public FieldInfo(final XSType type, final String name,
169 final FieldMemberAndAccessorFactory memberAndAccessorFactory) {
170 this._name = name;
171 this._memberAndAccessorFactory = memberAndAccessorFactory;
172 this.addNature(XMLInfoNature.class.getName());
173 XMLInfoNature xmlNature = new XMLInfoNature(this);
174 xmlNature.setSchemaType(type);
175 } //-- FieldInfo
176
177
178 /**
179 * Returns the FieldMemberAndAccessorFactory instance to use to create
180 * a JField out of this FieldInfo.
181 * @return the suitable FieldMemberAndAccessorFactory
182 */
183 public FieldMemberAndAccessorFactory getMemberAndAccessorFactory() {
184 return _memberAndAccessorFactory;
185 }
186
187 /**
188 * Returns the default value for this FieldInfo.
189 *
190 * @return the default value for this FieldInfo, or null if no default value
191 * was set;
192 */
193 public final String getDefaultValue() {
194 return _default;
195 }
196
197 /**
198 * Returns the fixed production for this FieldInfo, or null if no fixed
199 * value has been specified.
200 * <p>
201 * NOTE: Fixed values are NOT the same as default values
202 *
203 * @return the fixed value for this FieldInfo
204 */
205 public final String getFixedValue() {
206 return _fixed;
207 }
208
209 /**
210 * Returns the name of the delete method for this FieldInfo.
211 * @return the name of the delete method for this FieldInfo.
212 */
213 public final String getDeleteMethodName() {
214 return METHOD_PREFIX_DELETE + getMethodSuffix();
215 } //-- getDeleteMethodName
216
217 /**
218 * Returns the name of the has method for this FieldInfo.
219 * @return the name of the has method for this FieldInfo.
220 */
221 public final String getHasMethodName() {
222 return METHOD_PREFIX_HAS + getMethodSuffix();
223 } //-- getHasMethodName
224
225 /**
226 * Returns the name of the read method for this FieldInfo.
227 * @return the name of the read method for this FieldInfo.
228 */
229 public final String getReadMethodName() {
230 return METHOD_PREFIX_GET + getMethodSuffix();
231 } //-- getReadMethodName
232
233 /**
234 * Returns the fully qualified name of the Validator to use.
235 *
236 * @return the fully qualified name of the Validator to use.
237 */
238 public final String getValidator() {
239 return _validator;
240 }
241
242 /**
243 * Returns the name of the write method for this FieldInfo.
244 * @return the name of the write method for this FieldInfo.
245 */
246 public final String getWriteMethodName() {
247 if (new XMLInfoNature(this).isMultivalued()) {
248 return METHOD_PREFIX_ADD + getMethodSuffix();
249 }
250 return METHOD_PREFIX_SET + getMethodSuffix();
251 } //-- getWriteMethodName
252
253 /**
254 * Get the 'is' method for this FieldInfo.
255 *
256 * @return the name of the 'is' method for this FieldInfo
257 */
258 public final String getIsMethodName() {
259 return METHOD_PREFIX_IS + getMethodSuffix();
260 }
261
262 /**
263 * Returns the fully qualified name of the XMLFieldHandler to use.
264 *
265 * @return the fully qualified name of the XMLFieldHandler to use.
266 */
267 public final String getXMLFieldHandler() {
268 return _fieldHandler;
269 }
270
271 /**
272 * Returns the comment associated with this Member.
273 *
274 * @return the comment associated with this Member, or null.
275 * if one has not been set.
276 */
277 public final String getComment() {
278 return _comment;
279 } //-- getComment
280
281 /**
282 * Returns the methods flag that indicates which.
283 *
284 * methods will be created.
285 *
286 * @return the methods flag
287 */
288 public final int getMethods() {
289 return _methods;
290 } //-- getMethods
291
292 /**
293 * Returns the name of this FieldInfo.
294 *
295 * @return the name of this FieldInfo.
296 */
297 public final String getName() {
298 return this._name;
299 } //-- getName
300
301 /**
302 * Returns true if this FieldInfo represents a bound property.
303 *
304 * @return true if this FieldInfo represents a bound property.
305 */
306 public final boolean isBound() {
307 return _bound;
308 } //-- isBound
309
310 /**
311 * Returns true if this FieldInfo describes a container class. A container
312 * class is a class which should not be marshalled as XML, but whose members
313 * should be.
314 *
315 * @return true if this ClassInfo describes a container class.
316 */
317 public final boolean isContainer() {
318 return _isContainer;
319 } //-- isContainer
320
321 /**
322 * Returns true if the "has" and "delete" methods are needed for the field
323 * associated with this FieldInfo.
324 *
325 * @return true if the has and delete methods are needed.
326 */
327 public final boolean requiresHasAndDeleteMethods() {
328 XSType xsType = new XMLInfoNature(this).getSchemaType();
329 JType jType = xsType.getJType();
330 return ((!xsType.isEnumerated()) && jType.isPrimitive());
331 } //-- requiresHasAndDeleteMethods
332
333 /**
334 * Returns true if this field represents a nillable field. A nillable field
335 * is a field that can have null content (see XML Schema 1.0 definition of
336 * nillable).
337 *
338 * @return true if nillable, otherwise false.
339 * @see #setNillable(boolean)
340 */
341 public final boolean isNillable() {
342 return _nillable;
343 } //-- isNillable
344
345 /**
346 * Returns true if this FieldInfo is a transient member. Transient members
347 * are members which should be ignored by the Marshalling framework.
348 *
349 * @return true if this FieldInfo is transient.
350 */
351 public final boolean isTransient() {
352 return (_transient || _final || _static);
353 } //-- isTransient
354
355 /**
356 * Sets the comment for this Member.
357 * @param comment the comment or description for this Member
358 */
359 public final void setComment(final String comment) {
360 _comment = comment;
361 } //-- setComment
362
363 /**
364 * Returns the ClassInfo to which this Member was declared, for inheritance reasons.
365 * @return the ClassInfo to which this Member was declared.
366 */
367 public final ClassInfo getDeclaringClassInfo() {
368 return this._declaringClassInfo;
369 } //-- getDeclaringClassInfo
370
371 /**
372 * Sets whether or not this FieldInfo represents a bound property.
373 *
374 * @param bound the flag when true indicates that this FieldInfo represents a
375 * bound property.
376 */
377 public final void setBound(final boolean bound) {
378 _bound = bound;
379 } //-- setBound
380
381 /**
382 * Sets whether or not this FieldInfo describes a container field. A
383 * container field is a field which should not be marshalled directly as
384 * XML, but whose members should be. By default this is false.
385 *
386 * @param isContainer
387 * the boolean value when true indicates this class should be a
388 * container class.
389 */
390 public final void setContainer(final boolean isContainer) {
391 _isContainer = isContainer;
392 } //-- setContainer
393
394 /**
395 * Sets the {@link ClassInfo} of the class that declares this field.
396 * @param declaringClassInfo The {@link ClassInfo} of the declaring class.
397 */
398 public final void setDeclaringClassInfo(final ClassInfo declaringClassInfo) {
399 this._declaringClassInfo = declaringClassInfo;
400 }
401
402 /**
403 * Sets the default value for this FieldInfo.
404 * @param defaultValue the default value
405 */
406 public final void setDefaultValue(final String defaultValue) {
407 this._default = defaultValue;
408 }
409
410 /**
411 * Sets the "final" status of this FieldInfo. Final members are also
412 * transient.
413 *
414 * @param isFinal
415 * the boolean indicating the final status, if true this
416 * FieldInfo will be treated as final.
417 */
418 public final void setFinal(final boolean isFinal) {
419 this._final = isFinal;
420 } //-- isFinal
421
422 /**
423 * Sets the fixed value in which instances of this field type must lexically
424 * match. NOTE: This is not the same as default value!
425 *
426 * @param fixedValue
427 * the fixed production for this FieldInfo
428 */
429 public final void setFixedValue(final String fixedValue) {
430 this._fixed = fixedValue;
431 } //-- setFixedValue
432
433 /**
434 * Sets which methods to create: READ_METHOD, WRITE_METHOD,
435 * READ_WRITE_METHODS.
436 *
437 * @param methods a flag describing which methods to create.
438 */
439 public final void setMethods(final int methods) {
440 _methods = methods;
441 } //-- setMethods
442
443 /**
444 * Sets whether or not this field can be nillable.
445 *
446 * @param nillable
447 * a boolean that when true means the field may be nil.
448 * @see #isNillable()
449 */
450 public final void setNillable(final boolean nillable) {
451 _nillable = nillable;
452 } //-- setNillable
453
454 /**
455 * Sets the name of the field within the same class that is a reference to
456 * this field.
457 *
458 * @param fieldInfo {@link FieldInfo} for the referencing field (within the same class).
459 */
460 public final void setFieldInfoReference(final FieldInfo fieldInfo) {
461 _fieldInfoReference = fieldInfo;
462 }
463
464 /**
465 * Sets the "static" status of this FieldInfo. Static members are also
466 * transient.
467 *
468 * @param isStatic the boolean indicating the static status, if true this
469 * FieldInfo will be treated as static
470 */
471 public final void setStatic(final boolean isStatic) {
472 this._static = isStatic;
473 } //-- setStatic
474
475 /**
476 * Sets the transient status of this FieldInfo.
477 *
478 * @param isTransient the boolean indicating the transient status, if true this
479 * FieldInfo will be treated as transient
480 */
481 public final void setTransient(final boolean isTransient) {
482 this._transient = isTransient;
483 } //-- setTransient
484
485 /**
486 * Sets the name of the Validator to use.
487 *
488 * @param validator the fully qualified name of the validator to use.
489 */
490 public final void setValidator(final String validator) {
491 _validator = validator;
492 }
493
494 /**
495 * Sets the name of the XMLfieldHandler to use.
496 *
497 * @param handler the fully qualified name of the handler to use.
498 */
499 public final void setXMLFieldHandler(final String handler) {
500 _fieldHandler = handler;
501 }
502
503 /**
504 * Returns the method suffix for creating method names.
505 *
506 * @return the method suffix used when creating method names.
507 */
508 public String getMethodSuffix() {
509 if (_name.startsWith("_")) {
510 return _memberAndAccessorFactory.getJavaNaming().toJavaClassName(_name.substring(1));
511 }
512 return _memberAndAccessorFactory.getJavaNaming().toJavaClassName(_name);
513 }
514
515 /**
516 * Sets the visibility of this FieldInfo.
517 *
518 * @param visibility the visibility of this FieldInfo.
519 */
520 public final void setVisibility(final String visibility) {
521 _visibility = visibility;
522 }
523
524 /**
525 * Sets the possible substitution groups for this class.
526 * @param substitutionGroupMembers Possible substitution groups for this class.
527 */
528 public void setSubstitutionGroupMembers(final List<String> substitutionGroupMembers) {
529 this._substitutionGroupMembers = substitutionGroupMembers;
530 }
531
532 /**
533 * Returns the possible substitution groups for this class.
534 * @return the possible substitution groups for this class.
535 */
536 public List<String> getSubstitutionGroupMembers() {
537 return this._substitutionGroupMembers;
538 }
539
540 /**
541 * Indicates whether this field is static.
542 * @return True if this field is static.
543 */
544 public boolean isStatic() {
545 return _static;
546 }
547
548 /**
549 * Indicates whether this field is final.
550 * @return True if this field is final.
551 */
552 public boolean isFinal() {
553 return _final;
554 }
555
556 /**
557 * Returns this field's 'visibility'.
558 * @return This field's visibility.
559 */
560 public Object getVisibility() {
561 return _visibility;
562 }
563
564 /**
565 * Returns the reference to the {@link FieldInfo} instance within the same class.
566 * @return the reference to the {@link FieldInfo} instance
567 */
568 public FieldInfo getFieldInfoReference() {
569 return _fieldInfoReference;
570 }
571
572 /**
573 * @see org.exolab.castor.builder.info.nature.PropertyHolder#
574 * getProperty(java.lang.String)
575 * @param name
576 * of the property
577 * @return value of the property
578 */
579 public final Object getProperty(final String name) {
580 return _properties.get(name);
581 }
582
583 /**
584 * @see org.exolab.castor.builder.info.nature.PropertyHolder#
585 * setProperty(java.lang.String, java.lang.Object)
586 * @param name
587 * of the property
588 * @param value
589 * of the property
590 */
591 public final void setProperty(final String name, final Object value) {
592 _properties.put(name, value);
593 }
594
595 /**
596 * @see org.exolab.castor.builder.info.nature.NatureExtendable#
597 * addNature(java.lang.String)
598 * @param nature
599 * ID of the Nature
600 */
601 public final void addNature(final String nature) {
602 _natures.add(nature);
603 }
604
605 /**
606 * @see org.exolab.castor.builder.info.nature.NatureExtendable#
607 * hasNature(java.lang.String)
608 * @param nature
609 * ID of the Nature
610 * @return true if the Nature ID was added.
611 */
612 public final boolean hasNature(final String nature) {
613 return _natures.contains(nature);
614 }
615
616 }