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