/*
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. The name "Exolab" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of Intalio, Inc. For written permission,
* please contact info@exolab.org.
*
* 4. Products derived from this Software may not be called "Exolab"
* nor may "Exolab" appear in their names without prior written
* permission of Intalio, Inc. Exolab is a registered
* trademark of Intalio, Inc.
*
* 5. Due credit should be given to the Exolab Project
* (http://www.exolab.org/).
*
* THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 1999-2004 (C) Intalio, Inc. All Rights Reserved.
*
* This file was originally developed by Keith Visco during the course
* of employment at Intalio Inc.
* Portions of this file developed by Keith Visco after Jan 19 2005 are
* Copyright (C) 2005 Keith Visco. All Rights Reserverd.
*
* $Id$
*/
package org.exolab.castor.builder.info;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.castor.core.nature.PropertyHolder;
import org.exolab.castor.builder.factory.FieldMemberAndAccessorFactory;
import org.exolab.castor.builder.info.nature.XMLInfoNature;
import org.exolab.castor.builder.types.XSType;
import org.exolab.javasource.JType;
/**
* A class for representing field members of a class. FieldInfo objects hold all
* the information required about a member in order to be able to produce
* XML data binding (marshal/unmarshal) and validation code.
*
* @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
* @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
*/
public class FieldInfo implements XMLInfo, PropertyHolder {
/**
* Map holding the properties set and read by Natures.
*/
private Map<String, Object> _properties = new HashMap<String, Object>();
/**
* Set holding applicable natures.
*/
private Set<String> _natures = new HashSet<String>();
/** The Read / Getter method flag. */
public static final int READ_METHOD = 1;
/** The Write / Setter method flag. */
public static final int WRITE_METHOD = 2;
/** The Read and Write methods flags. */
public static final int READ_WRITE_METHODS = 3;
/** Method prefixes for "Add" methods. */
protected static final String METHOD_PREFIX_ADD = "add";
/** Method prefixes for "Delete" methods. */
protected static final String METHOD_PREFIX_DELETE = "delete";
/** Method prefixes for "Get" methods. */
protected static final String METHOD_PREFIX_GET = "get";
/** Method prefixes for "Has" methods. */
protected static final String METHOD_PREFIX_HAS = "has";
/** Method prefixes for "Set" methods. */
protected static final String METHOD_PREFIX_SET = "set";
/** Method prefixes for "Is" methods. */
protected static final String METHOD_PREFIX_IS = "is";
/** The Java name for Members described by this FieldInfo. */
private String _name = null;
/**
* {@link ClassInfo} instance which 'own' (declares) this
* {@link FieldInfo}.
*/
private ClassInfo _declaringClassInfo = null;
/** JavaDoc comment. */
private String _comment = null;
/** The default value for this FieldInfo. */
private String _default = null;
/** The fixed production for this FieldInfo. */
private String _fixed = null;
/** A flag to indicate a final member. */
private boolean _final = false;
/** The methods flags, indicates which methods to create. */
private int _methods = READ_WRITE_METHODS;
/** A reference to the FieldInfo instance within the same class. */
private FieldInfo _fieldInfoReference = null;
/** A flag to indicate a static member. */
private boolean _static = false;
/** Flags whether or not the a MarshalDescriptor should be created for this FieldInfo. */
private boolean _transient = false;
/** A flag to indicate a bound property. */
private boolean _bound = false;
/** A flag to indicate a container field. */
private boolean _isContainer = false;
/**
* The fully qualified name of the XMLFieldHandler (if any)
* to use in the generated descriptor.
*/
private String _fieldHandler;
/** A boolean to indicate that this field represents a "nillable" field. */
private boolean _nillable = false;
/** The fully qualified name of the Validator (if any) to use in the generated descriptor. */
private String _validator;
/** Visibility of this FieldInfo. */
private String _visibility = "private";
/**
* Factory responsible for creating a {@link JField} out of a
* {@link FieldInfo}.
*/
private FieldMemberAndAccessorFactory _memberAndAccessorFactory;
/**
* Holds the possible substitution groups for this class.
*/
private List<String> _substitutionGroupMembers = new LinkedList<String>();
/**
* Creates a new FieldInfo with the given XML Schema type and the given
* member name. Adds the {@link XMLInfoNature} for legacy compliance.
*
* @param type
* the XML Schema type of this member
* @param name
* the name of the member
* @param memberAndAccessorFactory
* the FieldMemberAndAccessorFactory to be used
*/
public FieldInfo(final XSType type, final String name,
final FieldMemberAndAccessorFactory memberAndAccessorFactory) {
this._name = name;
this._memberAndAccessorFactory = memberAndAccessorFactory;
this.addNature(XMLInfoNature.class.getName());
XMLInfoNature xmlNature = new XMLInfoNature(this);
xmlNature.setSchemaType(type);
} //-- FieldInfo
/**
* Returns the FieldMemberAndAccessorFactory instance to use to create
* a JField out of this FieldInfo.
* @return the suitable FieldMemberAndAccessorFactory
*/
public FieldMemberAndAccessorFactory getMemberAndAccessorFactory() {
return _memberAndAccessorFactory;
}
/**
* Returns the default value for this FieldInfo.
*
* @return the default value for this FieldInfo, or null if no default value
* was set;
*/
public final String getDefaultValue() {
return _default;
}
/**
* Returns the fixed production for this FieldInfo, or null if no fixed
* value has been specified.
* <p>
* NOTE: Fixed values are NOT the same as default values
*
* @return the fixed value for this FieldInfo
*/
public final String getFixedValue() {
return _fixed;
}
/**
* Returns the name of the delete method for this FieldInfo.
* @return the name of the delete method for this FieldInfo.
*/
public final String getDeleteMethodName() {
return METHOD_PREFIX_DELETE + getMethodSuffix();
} //-- getDeleteMethodName
/**
* Returns the name of the has method for this FieldInfo.
* @return the name of the has method for this FieldInfo.
*/
public final String getHasMethodName() {
return METHOD_PREFIX_HAS + getMethodSuffix();
} //-- getHasMethodName
/**
* Returns the name of the read method for this FieldInfo.
* @return the name of the read method for this FieldInfo.
*/
public final String getReadMethodName() {
return METHOD_PREFIX_GET + getMethodSuffix();
} //-- getReadMethodName
/**
* Returns the fully qualified name of the Validator to use.
*
* @return the fully qualified name of the Validator to use.
*/
public final String getValidator() {
return _validator;
}
/**
* Returns the name of the write method for this FieldInfo.
* @return the name of the write method for this FieldInfo.
*/
public final String getWriteMethodName() {
if (new XMLInfoNature(this).isMultivalued()) {
return METHOD_PREFIX_ADD + getMethodSuffix();
}
return METHOD_PREFIX_SET + getMethodSuffix();
} //-- getWriteMethodName
/**
* Get the 'is' method for this FieldInfo.
*
* @return the name of the 'is' method for this FieldInfo
*/
public final String getIsMethodName() {
return METHOD_PREFIX_IS + getMethodSuffix();
}
/**
* Returns the fully qualified name of the XMLFieldHandler to use.
*
* @return the fully qualified name of the XMLFieldHandler to use.
*/
public final String getXMLFieldHandler() {
return _fieldHandler;
}
/**
* Returns the comment associated with this Member.
*
* @return the comment associated with this Member, or null.
* if one has not been set.
*/
public final String getComment() {
return _comment;
} //-- getComment
/**
* Returns the methods flag that indicates which.
*
* methods will be created.
*
* @return the methods flag
*/
public final int getMethods() {
return _methods;
} //-- getMethods
/**
* Returns the name of this FieldInfo.
*
* @return the name of this FieldInfo.
*/
public final String getName() {
return this._name;
} //-- getName
/**
* Returns true if this FieldInfo represents a bound property.
*
* @return true if this FieldInfo represents a bound property.
*/
public final boolean isBound() {
return _bound;
} //-- isBound
/**
* Returns true if this FieldInfo describes a container class. A container
* class is a class which should not be marshalled as XML, but whose members
* should be.
*
* @return true if this ClassInfo describes a container class.
*/
public final boolean isContainer() {
return _isContainer;
} //-- isContainer
/**
* Returns true if the "has" and "delete" methods are needed for the field
* associated with this FieldInfo.
*
* @return true if the has and delete methods are needed.
*/
public final boolean requiresHasAndDeleteMethods() {
XSType xsType = new XMLInfoNature(this).getSchemaType();
JType jType = xsType.getJType();
return ((!xsType.isEnumerated()) && jType.isPrimitive());
} //-- requiresHasAndDeleteMethods
/**
* Returns true if this field represents a nillable field. A nillable field
* is a field that can have null content (see XML Schema 1.0 definition of
* nillable).
*
* @return true if nillable, otherwise false.
* @see #setNillable(boolean)
*/
public final boolean isNillable() {
return _nillable;
} //-- isNillable
/**
* Returns true if this FieldInfo is a transient member. Transient members
* are members which should be ignored by the Marshalling framework.
*
* @return true if this FieldInfo is transient.
*/
public final boolean isTransient() {
return (_transient || _final || _static);
} //-- isTransient
/**
* Sets the comment for this Member.
* @param comment the comment or description for this Member
*/
public final void setComment(final String comment) {
_comment = comment;
} //-- setComment
/**
* Returns the ClassInfo to which this Member was declared, for inheritance reasons.
* @return the ClassInfo to which this Member was declared.
*/
public final ClassInfo getDeclaringClassInfo() {
return this._declaringClassInfo;
} //-- getDeclaringClassInfo
/**
* Sets whether or not this FieldInfo represents a bound property.
*
* @param bound the flag when true indicates that this FieldInfo represents a
* bound property.
*/
public final void setBound(final boolean bound) {
_bound = bound;
} //-- setBound
/**
* Sets whether or not this FieldInfo describes a container field. A
* container field is a field which should not be marshalled directly as
* XML, but whose members should be. By default this is false.
*
* @param isContainer
* the boolean value when true indicates this class should be a
* container class.
*/
public final void setContainer(final boolean isContainer) {
_isContainer = isContainer;
} //-- setContainer
/**
* Sets the {@link ClassInfo} of the class that declares this field.
* @param declaringClassInfo The {@link ClassInfo} of the declaring class.
*/
public final void setDeclaringClassInfo(final ClassInfo declaringClassInfo) {
this._declaringClassInfo = declaringClassInfo;
}
/**
* Sets the default value for this FieldInfo.
* @param defaultValue the default value
*/
public final void setDefaultValue(final String defaultValue) {
this._default = defaultValue;
}
/**
* Sets the "final" status of this FieldInfo. Final members are also
* transient.
*
* @param isFinal
* the boolean indicating the final status, if true this
* FieldInfo will be treated as final.
*/
public final void setFinal(final boolean isFinal) {
this._final = isFinal;
} //-- isFinal
/**
* Sets the fixed value in which instances of this field type must lexically
* match. NOTE: This is not the same as default value!
*
* @param fixedValue
* the fixed production for this FieldInfo
*/
public final void setFixedValue(final String fixedValue) {
this._fixed = fixedValue;
} //-- setFixedValue
/**
* Sets which methods to create: READ_METHOD, WRITE_METHOD,
* READ_WRITE_METHODS.
*
* @param methods a flag describing which methods to create.
*/
public final void setMethods(final int methods) {
_methods = methods;
} //-- setMethods
/**
* Sets whether or not this field can be nillable.
*
* @param nillable
* a boolean that when true means the field may be nil.
* @see #isNillable()
*/
public final void setNillable(final boolean nillable) {
_nillable = nillable;
} //-- setNillable
/**
* Sets the name of the field within the same class that is a reference to
* this field.
*
* @param fieldInfo {@link FieldInfo} for the referencing field (within the same class).
*/
public final void setFieldInfoReference(final FieldInfo fieldInfo) {
_fieldInfoReference = fieldInfo;
}
/**
* Sets the "static" status of this FieldInfo. Static members are also
* transient.
*
* @param isStatic the boolean indicating the static status, if true this
* FieldInfo will be treated as static
*/
public final void setStatic(final boolean isStatic) {
this._static = isStatic;
} //-- setStatic
/**
* Sets the transient status of this FieldInfo.
*
* @param isTransient the boolean indicating the transient status, if true this
* FieldInfo will be treated as transient
*/
public final void setTransient(final boolean isTransient) {
this._transient = isTransient;
} //-- setTransient
/**
* Sets the name of the Validator to use.
*
* @param validator the fully qualified name of the validator to use.
*/
public final void setValidator(final String validator) {
_validator = validator;
}
/**
* Sets the name of the XMLfieldHandler to use.
*
* @param handler the fully qualified name of the handler to use.
*/
public final void setXMLFieldHandler(final String handler) {
_fieldHandler = handler;
}
/**
* Returns the method suffix for creating method names.
*
* @return the method suffix used when creating method names.
*/
public String getMethodSuffix() {
if (_name.startsWith("_")) {
return _memberAndAccessorFactory.getJavaNaming().toJavaClassName(_name.substring(1));
}
return _memberAndAccessorFactory.getJavaNaming().toJavaClassName(_name);
}
/**
* Sets the visibility of this FieldInfo.
*
* @param visibility the visibility of this FieldInfo.
*/
public final void setVisibility(final String visibility) {
_visibility = visibility;
}
/**
* Sets the possible substitution groups for this class.
* @param substitutionGroupMembers Possible substitution groups for this class.
*/
public void setSubstitutionGroupMembers(final List<String> substitutionGroupMembers) {
this._substitutionGroupMembers = substitutionGroupMembers;
}
/**
* Returns the possible substitution groups for this class.
* @return the possible substitution groups for this class.
*/
public List<String> getSubstitutionGroupMembers() {
return this._substitutionGroupMembers;
}
/**
* Indicates whether this field is static.
* @return True if this field is static.
*/
public boolean isStatic() {
return _static;
}
/**
* Indicates whether this field is final.
* @return True if this field is final.
*/
public boolean isFinal() {
return _final;
}
/**
* Returns this field's 'visibility'.
* @return This field's visibility.
*/
public Object getVisibility() {
return _visibility;
}
/**
* Returns the reference to the {@link FieldInfo} instance within the same class.
* @return the reference to the {@link FieldInfo} instance
*/
public FieldInfo getFieldInfoReference() {
return _fieldInfoReference;
}
/**
* @see org.exolab.castor.builder.info.nature.PropertyHolder#
* getProperty(java.lang.String)
* @param name
* of the property
* @return value of the property
*/
public final Object getProperty(final String name) {
return _properties.get(name);
}
/**
* @see org.exolab.castor.builder.info.nature.PropertyHolder#
* setProperty(java.lang.String, java.lang.Object)
* @param name
* of the property
* @param value
* of the property
*/
public final void setProperty(final String name, final Object value) {
_properties.put(name, value);
}
/**
* @see org.exolab.castor.builder.info.nature.NatureExtendable#
* addNature(java.lang.String)
* @param nature
* ID of the Nature
*/
public final void addNature(final String nature) {
_natures.add(nature);
}
/**
* @see org.exolab.castor.builder.info.nature.NatureExtendable#
* hasNature(java.lang.String)
* @param nature
* ID of the Nature
* @return true if the Nature ID was added.
*/
public final boolean hasNature(final String nature) {
return _natures.contains(nature);
}
}