/*
 * Copyright 2006 Assaf Arkin, Keith Visco, Ralf Joachim
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.exolab.castor.xml;

import java.util.List;

import org.exolab.castor.mapping.FieldDescriptor;
import org.exolab.castor.xml.util.XMLFieldDescriptorImpl;

/**
 * XML field descriptor. Wraps {@link FieldDescriptor} and adds
 * XML-related information, type conversion, and so on.
 *
 * @author <a href="mailto:arkin AT intalio DOT com">Assaf Arkin</a>
 * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
 * @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a>
 * @version $Revision: 8690 $ $Date: 2004-09-17 00:47:41 -0600 (Fri, 17 Sep 2004) $
 */
public interface XMLFieldDescriptor extends FieldDescriptor {
    /** The xml:space property. */
    String PROPERTY_XML_SPACE = "xml:space";

    /** The xml:lang property. */
    String PROPERTY_XML_LANG = "xml:lang";

    /**
     * Returns the index within the constructor argument array where the value
     * of this field should be. A value less than zero indicates that the value
     * of this field is set via a normal setter method and not via the
     * constructor.
     * <p>
     * Note: This only applies to attribute mapped fields at this time.
     *
     * @return the index within the constructor argument array for this field.
     * @see #isConstructorArgument()
     */
    int getConstructorArgumentIndex();

    /**
     * Returns true if the value of the field represented by this descriptor
     * should be set via the constructor of the containing class. This is only
     * valid for attribute mapped fields.
     *
     * @return true if the value of the field represented by this descriptor
     *         should be set via the constructor of the containing class.
     */
    boolean isConstructorArgument();

    /**
     * Returns the "relative" XML path for the field being described.
     * <p>
     * In most cases, this will be null. However sometimes a field may be mapped
     * to a nested element. In which case the value returned by this method
     * should be the nested element name. If more than one level of nesting is
     * needed each nested element name should be separated by by a path
     * separator (forward slash '/').
     * <p>
     * The location path name is "relative" to the parent Class. The name of the
     * parent must not be included in the path.
     * <p>
     * For example, give the following two classes:
     * <pre>
     *    class Root {
     *        Bar bar;
     *    }
     *
     *    class Bar {
     *       String value;
     *    }
     * </pre>
     *
     * And the following XML:
     *
     * <pre>
     *    &lt;root&gt;
     *       &lt;foo&gt;
     *          &lt;bar&gt; value of bar &lt;/bar&gt;
     *       &lt;/foo&gt;
     *    &lt;/root&gt;
     * </pre>
     *
     * Since &lt;foo&gt; has no associated class, the path for 'bar' would be: "foo"
     *
     * @return The "relative" XML path for the field being described.
     */
    String getLocationPath();

    /**
     * Return the "suggested" namespace prefix to use when marshaling as XML.
     *
     * @return the "suggested" namespace prefix.
     */
    String getNameSpacePrefix();

    /**
     * Returns the namespace URI to be used when marshaling and unmarshaling as
     * XML.
     *
     * @return the namespace URI.
     */
    String getNameSpaceURI();

    /**
     * Returns the node type of the field being described. The {@link NodeType}
     * represents the type of node that the field will be marshaled into XML as.
     *
     * @return the {@link NodeType} of the Field being described.
     */
    NodeType getNodeType();

    /**
     * Returns the value property with the given name or null if no such
     * property exists. This method is useful for future evolutions of this
     * interface as well as for user-defined extensions. See class declared
     * properties for built-in properties.
     *
     * @param propertyName the name of the property whose value should be
     *        returned.
     *
     * @return the value of the property, or null.
     */
    String getXMLProperty(String propertyName);

    /**
     * Returns the XML Schema type of the XML field being described.
     *
     * @return the XML Schema type of the XML field being described.
     */
    String getSchemaType();

    /**
     * Returns a specific validator for the field described by this descriptor.
     * A null value may be returned if no specific validator exists.
     *
     * @return the field validator for the described field
     */
    FieldValidator getValidator();

    /**
     * Returns the XML Name for the field being described.
     *
     * @return the XML name.
     */
    String getXMLName();

    /**
     * Returns true if the field described by this descriptor is a container
     * field. A container is a field that is not a first-class object,
     * and should therefore have no XML representation.
     *
     * @return true if the field is a container
     */
    boolean isContainer();

    /**
     * Returns the incremental flag which when true indicates that this member
     * may be safely added before the unmarshaler is finished unmarshaling it.
     *
     * @return true if the Object can safely be added before the unmarshaler is
     *         finished unmarshaling the Object.
     */
    boolean isIncremental();

    /**
     * Returns true if the field described by this descriptor is Map or
     * Hashtable. If this method returns true, it must also return true for any
     * call to {@link #isMultivalued}.
     *
     * @return true if the field described by this desciptor is a Map or
     *         Hashtable, otherwise false.
     */
    boolean isMapped();

    /**
     * Returns true if the field described by this descriptor can contain more
     * than one value.
     *
     * @return true if the field described by this descriptor can contain more
     *         than one value
     */
    boolean isMultivalued();

    /**
     * Returns true if the field described by this descriptor may be nillable. A
     * nillable field is one that may have empty content and still be valid.
     * Please see the XML Schema 1.0 Recommendation for more information on
     * nillable.
     *
     * @return true if the field may be nillable.
     */
    boolean isNillable();

    /**
     * Returns true if the field described by this descriptor is a reference
     * (ie. IDREF) to another object in the "Object Model" (e.g., XML tree).
     *
     * @return true if the field described by this descriptor is a reference to
     *         another object in the "Object Model"
     */
    boolean isReference();

    /**
     * Returns true if this descriptor can be used to handle elements or
     * attributes with the given XML name. By default this method simply
     * compares the given XML name with the internal XML name. This method can
     * be overridden to provide more complex matching.
     *
     * @param xmlName the XML name to compare
     * @return true if this descriptor can be used to handle elements or
     *         attributes with the given XML name.
     */
    boolean matches(String xmlName);

    /**
     * Returns true if this descriptor can be used to handle elements or
     * attributes with the given XML name. By default this method simply
     * compares the given XML name with the internal XML name. This method can
     * be overridden to provide more complex matching.
     *
     * @param xmlName the XML name to compare
     * @param namespace the namespace URI
     *
     * @return true if this descriptor can be used to handle elements or
     *         attributes with the given XML name.
     */
    boolean matches(String xmlName, String namespace);
    
    /**
     * Returns the possible substitution groups for this class.
     * @return the possible substitution groups for this class.
     */
    List<String> getSubstitutes();

    /**
     * Sets the possible substitution groups for this class.
     * @param substitutes Possible substitution groups for this class.
     */
    void setSubstitutes(List<String> substitutes); 

    /**
     * Sets whether the field described by this {@link XMLFieldDescriptorImpl} is
     * created as a result of a <xs:list> definition.
     * @param derivedFromXSList A boolean value, true or false.
     */
    void setDerivedFromXSList(boolean derivedFromXSList);

    /**
     * Indicates whether the field described by this {@link XMLFieldDescriptorImpl} is
     * created as a result of a <xs:list> definition.
     * @param derivedFromXSList Trueif the field described by this {@link XMLFieldDescriptorImpl} is
     * created as a result of a <xs:list> definition.
.
     */
    boolean isDerivedFromXSList();
    
    /**
     * Returns the component type of this {@link XMLFieldDescriptor} instance, if 
     * the field described represents a collection of values.
     * @return The collection's component type.
     * @see XMLFieldDescriptor#getSchemaType()
     */
    String getComponentType();

    
}
