package org.exolab.castor.mapping.loader; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.exolab.castor.mapping.ClassDescriptor; import org.exolab.castor.mapping.FieldDescriptor; import org.exolab.castor.mapping.FieldHandler; import org.exolab.castor.mapping.xml.types.FieldMappingCollectionType; public class FieldDescriptorImpl implements FieldDescriptor { /** A reference to the containing class descriptor (parent). */ private ClassDescriptor _parent; /** The name of the field. */ private String _fieldName; /** The type of the field. */ private Class<?> _fieldType; /** The type class descriptor, if this field is of a type known by a descriptor. */ private ClassDescriptor _classDescriptor; /** The field handler for get/set field value. */ private FieldHandler _handler; /** True if the field is transient and should not be saved/stored. */ private boolean _transient; /** True if the described field type is immutable. */ private boolean _immutable; /** True if the field type is required. */ private boolean _required; /** True if access to field is direct. */ private boolean _direct; /** True if access to field is lazy. */ private boolean _lazy; /** True if the object described by this descriptor is multi-valued. */ private boolean _multivalued; /** True if the field is part of the identity of the class. */ private boolean _identity; /** The name of a class that implements the {@link Comparator} interface. */ private String _comparator; /** The name of the 'getter' method used to obtain the value of a property. */ private String _getMethod; /** The name of the 'setter' method used to set the value of a property. */ private String _setMethod; /** The name of the 'create' method used to create an instance of a property. */ private String _createMethod; /** The type of the collection, if the field is multi-valued. */ private FieldMappingCollectionType _collection; /** * Map holding the properties set and read by natures. */ private Map<String, Object> _properties = new HashMap<String, Object>(); /** * Map holding the available natures. */ private Set<String> _natures = new HashSet<String>(); /** * Creates a default instance of a field descriptor. */ protected FieldDescriptorImpl() { } /** * Constructs a new field descriptor. * * @param fieldName The field name * @param typeInfo The field type information * @param handler The field handler (may be null) * @param isTransitive True if the field is transient */ public FieldDescriptorImpl(final String fieldName, final TypeInfo typeInfo, final FieldHandler handler, final boolean isTransitive) { if (fieldName == null) { throw new IllegalArgumentException("Internal error. Field name not specified."); } if (handler == null) { throw new IllegalArgumentException("Internal error. No FieldHandler provided."); } setFieldName(fieldName); setFieldType(typeInfo.getFieldType()); setHandler(handler); setTransient(isTransitive); setImmutable(typeInfo.isImmutable()); setRequired(typeInfo.isRequired()); setMultivalued(typeInfo.getCollectionHandler() != null); } /** * @see org.exolab.castor.mapping.FieldDescriptor#setContainingClassDescriptor( * org.exolab.castor.mapping.ClassDescriptor) * {@inheritDoc} */ public final void setContainingClassDescriptor(final ClassDescriptor parent) { _parent = parent; } /** * @see org.exolab.castor.mapping.FieldDescriptor#getContainingClassDescriptor() * {@inheritDoc} */ public final ClassDescriptor getContainingClassDescriptor() { return _parent; } /** * Set the name of the field. * * @param fieldName Field name. */ public final void setFieldName(final String fieldName) { _fieldName = fieldName; } /** * @see org.exolab.castor.mapping.FieldDescriptor#getFieldName() * {@inheritDoc} */ public final String getFieldName() { return _fieldName; } /** * Set the type of the field. * * @param fieldType Field type. */ public final void setFieldType(final Class<?> fieldType) { _fieldType = fieldType; } /** * @see org.exolab.castor.mapping.FieldDescriptor#getFieldType() * {@inheritDoc} */ public final Class<?> getFieldType() { return _fieldType; } /** * Set the ClassDescriptor for the described field. * * @param classDescriptor The ClassDescriptor for the described field. */ public final void setClassDescriptor(final ClassDescriptor classDescriptor) { _classDescriptor = classDescriptor; } /** * @see org.exolab.castor.mapping.FieldDescriptor#getClassDescriptor() * {@inheritDoc} */ public final ClassDescriptor getClassDescriptor() { return _classDescriptor; } /** * Set the FieldHandler for the field being described by this FieldDescriptor. * * @param handler The FieldHandler for the field being described. */ public final void setHandler(final FieldHandler handler) { _handler = handler; } /** * @see org.exolab.castor.mapping.FieldDescriptor#getHandler() * {@inheritDoc} */ public final FieldHandler getHandler() { return _handler; } /** * Sets whether or not the describled field is 'transient'. * * @param isTransient The flag indicating if the described field is 'transient'. */ public final void setTransient(final boolean isTransient) { _transient = isTransient; } /** * @see org.exolab.castor.mapping.FieldDescriptor#isTransient() * {@inheritDoc} */ public final boolean isTransient() { return _transient; } /** * Set the immutable flag which indicates that changes to this Field result in a * new Object to be created, such as java.lang.String. It serves to identify fields * which should not be constructed until all the data is available. * * @param immutable Flag which if true indicates that the field is immutable. */ public final void setImmutable(final boolean immutable) { _immutable = immutable; } /** * @see org.exolab.castor.mapping.FieldDescriptor#isImmutable() * {@inheritDoc} */ public final boolean isImmutable() { return _immutable; } /** * Set whether or not the described field is required. * * @param required The flag indicating whether or not the described field is required. */ public final void setRequired(final boolean required) { _required = required; } /** * @see org.exolab.castor.mapping.FieldDescriptor#isRequired() * {@inheritDoc} */ public final boolean isRequired() { return _required; } /** * Set wheter the object described by this descriptor is multivalued or not. * * @param multivalued True if the object described by this descriptor is multivalued. */ public final void setMultivalued(final boolean multivalued) { _multivalued = multivalued; } /** * @see org.exolab.castor.mapping.FieldDescriptor#isMultivalued() * {@inheritDoc} */ public final boolean isMultivalued() { return _multivalued; } /** * Set wether the described field is part of the identity of the class it belongs to. * * @param identity <code>true</code> if field is part of the classes identity. */ public final void setIdentity(final boolean identity) { _identity = identity; } /** * Is the described field is part of the identity of the class it belongs to? * * @return <code>true</code> if field is part of the classes identity. */ public final boolean isIdentity() { return _identity; } /** * @see org.exolab.castor.builder.info.nature.PropertyHolder# * getProperty(java.lang.String) * @param name * of the property * @return value of the property */ public 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 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 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 boolean hasNature(final String nature) { return _natures.contains(nature); } public String getComparator() { return _comparator; } public void setComparator(String comparator) { _comparator = comparator; } public FieldMappingCollectionType getCollection() { return _collection; } public void setCollection(FieldMappingCollectionType collection) { _collection = collection; } public boolean isDirect() { return _direct; } public void setDirect(boolean direct) { _direct = direct; } public String getGetMethod() { return _getMethod; } public void setGetMethod(String getMethod) { _getMethod = getMethod; } public String getSetMethod() { return _setMethod; } public void setSetMethod(String setMethod) { _setMethod = setMethod; } public String getCreateMethod() { return _createMethod; } public void setCreateMethod(String createMethod) { _createMethod = createMethod; } public boolean isLazy() { return _lazy; } public void setLazy(boolean lazy) { _lazy = lazy; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(getFieldName() + "(" + getFieldType().getName() + ")"); // TODO[WG]: find a way to emit additional nature-specific information. // try { // Class natureClass = Class.forName("org.exolab.castor.jdo.engine.nature.FieldDescriptorJDONature"); // if (hasNature(natureClass.getName())) { // FieldDescriptorJDONature jdoNature = new FieldDescriptorJDONature(this); // buffer.append(jdoNature.getSQLName() == null ? "" : " AS " // + jdoNature.getSQLName()[0]); // } // } catch (ClassNotFoundException e) { // // ignore // } return buffer.toString(); } }