/*
 * Copyright 2007 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.builder.types;

import java.util.Enumeration;

import org.exolab.castor.xml.schema.Facet;
import org.exolab.castor.xml.schema.SimpleType;
import org.exolab.javasource.JSourceCode;
import org.exolab.javasource.JType;

/**
 * The base XML Schema Type class.
 * 
 * @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: 7943 $ $Date: 2005-03-05 06:42:06 -0700 (Sat, 05 Mar 2005) $
 */
public abstract class XSType {
    //--------------------------------------------------------------------------
    
    // special types

    /** Value meaning the type is unassigned. */
    public static final short NULL = -1;

    /** A user-defined type. */
    public static final short CLASS = 0;

    // primitive types
    
    /** xsd:string. */
    public static final short STRING_TYPE = 1;
    
    /** xsd:duration. */
    public static final short DURATION_TYPE = 2;
    
    /** xsd:dateTime. */
    public static final short DATETIME_TYPE = 3;
    
    /** xsd:time. */
    public static final short TIME_TYPE = 4;
    
    /** xsd:date. */
    public static final short DATE_TYPE = 5;
    
    /** xsd:gYearMonth. */
    public static final short GYEARMONTH_TYPE = 6;
    
    /** xsd:gYear. */
    public static final short GYEAR_TYPE = 7;
    
    /** xsd:gMonthDay. */
    public static final short GMONTHDAY_TYPE = 8;
    
    /** xsd:gDay. */
    public static final short GDAY_TYPE = 9;
    
    /** xsd:gMonth. */
    public static final short GMONTH_TYPE = 10;
    
    /** xsd:boolean. */
    public static final short BOOLEAN_TYPE = 11;
    
    /** xsd:base64Binary. */
    public static final short BASE64BINARY_TYPE = 12;
    
    /** xsd:hexBinary. */
    public static final short HEXBINARY_TYPE = 13;
    
    /** xsd:float. */
    public static final short FLOAT_TYPE = 14;
    
    /** xsd:double. */
    public static final short DOUBLE_TYPE = 15;
    
    /** xsd:decimal. */
    public static final short DECIMAL_TYPE = 16;
    
    /** xsd:anyURI. */
    public static final short ANYURI_TYPE = 17;
    
    /** xsd:QName. */
    public static final short QNAME_TYPE = 18;
    
    /** xsd:notation. */
    public static final short NOTATION_TYPE = 19;

    // derived types
    
    /** xsd:normalizedString. */
    public static final short NORMALIZEDSTRING_TYPE = 20;
    
    /** xsd:token. */
    public static final short TOKEN_TYPE = 21;
    
    /** xsd:language. */
    public static final short LANGUAGE_TYPE = 22;
    
    /** xsd:name. */
    public static final short NAME_TYPE = 23;
    
    /** xsd:NCNAME. */
    public static final short NCNAME_TYPE = 24;
    
    /** xsd:ID. */
    public static final short ID_TYPE = 25;
    
    /** xsd:IDREF. */
    public static final short IDREF_TYPE = 26;
    
    /** xsd:IDREFS. */
    public static final short IDREFS_TYPE = 27;
    
    /** xsd:ENTITY. */
    public static final short ENTITY = 28;
    
    /** xsd:ENTITIES. */
    public static final short ENTITIES = 29;
    
    /** xsd:NMTOKEN. */
    public static final short NMTOKEN_TYPE = 30;
    
    /** xsd:NMTOKENS. */
    public static final short NMTOKENS_TYPE = 31;
    
    /** xsd:integer. */
    public static final short INTEGER_TYPE = 32;
    
    /** xsd:nonPositiveInteger. */
    public static final short NON_POSITIVE_INTEGER_TYPE = 33;
    
    /** xsd:negativeInteger. */
    public static final short NEGATIVE_INTEGER_TYPE = 34;
    
    /** xsd:long. */
    public static final short LONG_TYPE = 35;
    
    /** xsd:int. */
    public static final short INT_TYPE = 36;
    
    /** xsd:short. */
    public static final short SHORT_TYPE = 37;
    
    /** xsd:byte. */
    public static final short BYTE_TYPE = 38;
    
    /** xsd:nonNegativeInteger. */
    public static final short NON_NEGATIVE_INTEGER_TYPE = 39;
    
    /** xsd:positiveInteger. */
    public static final short POSITIVE_INTEGER_TYPE = 44;
    
    /** A collection type. */
    public static final short COLLECTION = 45;
    
    /** xsd:unsignedLong. */
    public static final short UNSIGNED_LONG_TYPE = 46;
    
    /** xsd:unsignedShort. */
    public static final short UNSIGNED_SHORT_TYPE = 47;

    /** xsd:unsignedByte. */
    public static final short UNSIGNED_BYTE_TYPE = 48;

    /** xsd:unsignedInt. */
    public static final short UNSIGNED_INT_TYPE = 49;
    
    //--------------------------------------------------------------------------

    /** Flag signaling an enumerated type. */
    private boolean _enumerated = false;

    //--------------------------------------------------------------------------

    /**
     * Returns true if this XSType represents an enumerated type.
     * 
     * @return True if this XSType represents an enumerated type.
     */
    public final boolean isEnumerated() {
        return _enumerated;
    }

    /**
     * Sets the enumerated flag for this XSClass.
     *
     * @param enumerated A boolean indicating whether or not this XSClass represents an
     *        enumerated type.
     */
    public final void setAsEnumerated(final boolean enumerated) {
        _enumerated = enumerated;
    }

    //--------------------------------------------------------------------------

    /**
     * Returns the name of this XSType.
     * 
     * @return The name of this XSType.
     */
    public abstract String getName();

    /**
     * Returns the type of this XSType.
     * 
     * @return the type of this XSType.
     */
    public abstract short getType();

    /**
     * Returns true if this XSType represents a primitive type.
     * 
     * @return True if this XSType represents a primitive type.
     */
    public abstract boolean isPrimitive();
    
    /**
     * Returns true if the XSType represents an XML Schema date/time type.
     * 
     * @return True if the XSType represents an XML Schema date/time type.
     */
    public abstract boolean isDateTime();

    /**
     * Returns true if this XSType represents a collection.
     * 
     * @return True if this XSType represents a collection.
     */
    public boolean isCollection() {
        return false;
    }
    
    /**
     * Returns the JType that this XSType represents.
     * 
     * @return The JType that this XSType represents.
     */
    public abstract JType getJType();

    /**
     * Returns the Java code neccessary to create a new instance of the JType
     * associated with this XSType.
     *
     * @return The Java code neccessary to create a new instance.
     */
    public abstract String newInstanceCode();

    /**
     * Returns the string necessary to convert an instance of this XSType to an
     * Object. This method is really only useful for primitive types.
     *
     * @param variableName The name of the instance variable.
     * @return The String necessary to convert an instance of this XSType to an Object.
     */
    public abstract String createToJavaObjectCode(final String variableName);

    /**
     * Returns the string necessary to convert an Object to an instance of this
     * XSType. This method is really only useful for primitive types.
     *
     * @param variableName The name of the Object.
     * @return The String necessary to convert an Object to an instance of this XSType.
     */
    public abstract String createFromJavaObjectCode(final String variableName);

    //--------------------------------------------------------------------------

    /**
     * Creates source code for an additional constructor that deals with default
     * values as specified in the XML schema instance.
     * @param variableName Name of the constructor argument.
     * @return Source code for dealing with default values.
     */
    public String createDefaultValueWithString(final String variableName) {
        return " new " + getJType() + "(" + variableName + ")";
    }
    
    /**
     * Reads and sets the facets for XSType.
     * 
     * @param simpleType The SimpleType containing the facets.
     */
    public final void setFacets(final SimpleType simpleType) {
        Enumeration<Facet> enumeration = simpleType.getEffectiveFacets();
        while (enumeration.hasMoreElements()) {
            setFacet(enumeration.nextElement());
        }
    }

    /**
     * Set the given facet for XSType if applicable.
     * 
     * @param facet The facet to set for XSType.
     */
    protected abstract void setFacet(final Facet facet);
    
    /**
     * Creates the validation code for an instance of this XSType. If necessary the validation
     * code should create a newly configured TypeValidator, that should then be added to a
     * FieldValidator instance whose name is provided.
     *
     * @param jsc The JSourceCode to fill in.
     * @param fixedValue A fixed value to use if any.
     * @param validatorInstanceName The name of the FieldValidator that the configured
     *        TypeValidator should be added to.
     */
    public abstract void validationCode(final JSourceCode jsc,
            final String fixedValue, final String validatorInstanceName);

    //--------------------------------------------------------------------------
}
