Package org.exolab.castor.xml.schema

Source Code of org.exolab.castor.xml.schema.SimpleTypesFactory

/**
* 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-2002 (C) Intalio Inc. All Rights Reserved.
*
* $Id: SimpleTypesFactory.java 7951 2008-10-09 20:52:17Z wguttmn $
*/

package org.exolab.castor.xml.schema;

import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.castor.core.util.Messages;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.schema.simpletypes.AtomicType;
import org.exolab.castor.xml.schema.simpletypes.ListType;
import org.exolab.castor.xml.schema.simpletypes.RealType;
import org.exolab.castor.xml.schema.simpletypes.UrType;
import org.exolab.castor.xml.schema.simpletypes.factory.Type;
import org.exolab.castor.xml.schema.simpletypes.factory.TypeList;
import org.exolab.castor.xml.schema.simpletypes.factory.TypeProperty;
import org.xml.sax.InputSource;

/**
* SimpleTypesFactory provides code constants for every built
* in type defined in www.w3.org/TR/xmlschma-2-20000407
* USER_TYPE is used for user derived types.
*
* This factory can also create instances of classes derived from SimpleType
* that represent the simple types defined by xmlschema and those derived from them.
*
* @author <a href="mailto:berry@intalio.com">Arnaud Berry</a>
* @version $Revision: 7951 $ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
**/
public class SimpleTypesFactory {

    /**
     * The Logger instance to use.
     */
    private static final Log LOG = LogFactory.getLog(SimpleTypesFactory.class);
   
    //Type Codes:

    /**
     * This code is for errors or uninitialized types.
    **/
    public static final int INVALID_TYPE                = -1;

    /**
     * Simple type defined by the user
    **/
    public static final int USER_TYPE                     =  0;

    //Primitive types
    public static final int STRING_TYPE                   =  1;
    public static final int DURATION_TYPE                 =  2;
    public static final int DATETIME_TYPE                 =  3;
    public static final int TIME_TYPE                     =  4;
    public static final int DATE_TYPE                     =  5;
    public static final int GYEARMONTH_TYPE               =  6;
    public static final int GYEAR_TYPE                    =  7;
    public static final int GMONTHDAY_TYPE                =  8;
    public static final int GDAY_TYPE                     =  9;
    public static final int GMONTH_TYPE                   =  10;
    public static final int BOOLEAN_TYPE                  =  11;
    public static final int BASE64BINARY_TYPE             =  12;
    public static final int HEXBINARY_TYPE                =  13;
    public static final int FLOAT_TYPE                    =  14;
    public static final int DOUBLE_TYPE                   =  15;
    public static final int DECIMAL_TYPE                  =  16;
    public static final int ANYURI_TYPE                   =  17;
    public static final int QNAME_TYPE                    =  18;
    public static final int NOTATION_TYPE                 =  19;
    //Derived datatypes
    public static final int NORMALIZEDSTRING_TYPE         = 20;
    public static final int TOKEN_TYPE                    = 21;
    public static final int LANGUAGE_TYPE                 = 22;
    public static final int NAME_TYPE                     = 23;
    public static final int NCNAME_TYPE                   = 24;
    public static final int ID_TYPE                       = 25;
    public static final int IDREF_TYPE                    = 26;
    public static final int IDREFS_TYPE                   = 27;
    public static final int ENTITY_TYPE                   = 28;
    public static final int ENTITIES_TYPE                 = 29;
    public static final int NMTOKEN_TYPE                  = 30;
    public static final int NMTOKENS_TYPE                 = 31;
    public static final int INTEGER_TYPE                  = 32;
    public static final int NON_POSITIVE_INTEGER_TYPE     = 33;
    public static final int NEGATIVE_INTEGER_TYPE         = 34;
    public static final int LONG_TYPE                     = 35;
    public static final int INT_TYPE                      = 36;
    public static final int SHORT_TYPE                    = 37;
    public static final int BYTE_TYPE                     = 38;
    public static final int NON_NEGATIVE_INTEGER_TYPE     = 39;
    public static final int UNSIGNED_LONG_TYPE            = 40;
    public static final int UNSIGNED_INT_TYPE             = 41;
    public static final int UNSIGNED_SHORT_TYPE           = 42;
    public static final int UNSIGNED_BYTE_TYPE            = 43;
    public static final int POSITIVE_INTEGER_TYPE         = 44;

    public static final int ANYSIMPLETYPE_TYPE            = 100;

    /**
     * The resource location for the built-in types
     * property files
    **/
    static final String RESOURCE_LOCATION =
        "/org/exolab/castor/util/resources/";

    /**
     * The resource for the mapping properties
    **/
    static final String TYPE_MAPPINGS = RESOURCE_LOCATION +
        "SimpleTypesMapping.properties";

    /**
     * The resource for the Simple types
    **/
    static final String TYPE_DEFINITIONS = RESOURCE_LOCATION +
        "SimpleTypes.properties";
    /**
     * Holds simpletypesfactory.Type instances that record information about
     * xml schema built in types.
     */
    private static Hashtable _typesByName;

    /** Cross index for _typesByName to quickly get type information from its code*/
    private static Hashtable _typesByCode;

    /**
     * Log writer to report progress/errors. May be null.
     */
    private static PrintWriter _logWriter= new PrintWriter(System.out);

    /**
     * The built-in schema, hopefully only temporary
    **/
    private static final Schema _builtInSchema = new Schema();

     /**
     * Indicates if a type code corresponds to an xml schema built in type.
     * @param codeType The type code to check.
     * @return True if the given type code represents an XML schema built-in type.
     */
    public static boolean isBuiltInType(final int codeType) {
        return USER_TYPE < codeType;
    }

    /**
     * Tells if a type code corresponds to an xml schema (built-in)
     * primitive type.
     * @param codeType The type code to check.
     * @return True if the given type code represents an XML schema built-in primitive type.
     */
    public static boolean isPrimitiveType(final int codeType) {
        return (STRING_TYPE <= codeType) && (codeType <= NOTATION_TYPE);
    }
   
    /**
     * Tells if a type code corresponds to an xml schema (built-in)
     * numeric type.
     * @param codeType The type code to check.
     * @return True if the given type code represents an XML schema built-in numeric type.
     */
    public static boolean isNumericType(final int codeType) {
        return ((FLOAT_TYPE <= codeType) && (codeType <= DECIMAL_TYPE))
        || ((INTEGER_TYPE <= codeType) && (codeType <= POSITIVE_INTEGER_TYPE));
    }
   
    /**
     * Tells if a type code corresponds to an xml schema (built-in)
     * date/time type.
     * @param codeType The type code to check.
     * @return True if the given type code represents an XML schema built-in date/time type.
     */
    public static boolean isDateTimeType(final int codeType) {
        return (DURATION_TYPE <= codeType) && (codeType <= GMONTH_TYPE);
    }
   

    /**
     * Gets an instance of a class derived from {@link SimpleType} representing the
     * built in type which name is given as a parameter.
     * @param typeName Name of the simple type.
     * @return The {@link SimpleType} instance for the type name.
     */
    public SimpleType getBuiltInType(final String typeName) {
        Type type = getType(typeName);
        if (type == null) {
            return null;
        }
        return type.getSimpleType();
    }

   /**
     * Gets a built in type's name given its code.
     */
    public String getBuiltInTypeName(int builtInTypeCode) {
        Type type= getType(builtInTypeCode);
        if (type == null) return null;
        return type.getName();
    }


    /**
     * Creates an instance of a class derived from SimpleType, representing the
     * user type defined by the given name, baseName and derivation method.
     *
     * Package private (used by Schema and DeferredSimpleType).
     *
     * The given schema is used as the owning Schema document, yet a call to
     * schema.addSimpleType must till be made to add the SimpleType to the Schema.
     *
     * If the base type is not found in the schema, a DeferredSimpleType
     * will be returned if createDeferredSimpleType is true, null otherwise.
     *
     * @param schema the owning schema
     * @param name the name of the SimpleType
     * @param baseName the name of the SimpleType's base type
     * @param derivation the name of the derivation method (null/""/"list"/"restriction")
     * @param createDeferredSimpleType should the type be deferred if it can't be created.
     * @return the new SimpleType, or null if its parent could not be found.
    **/
    SimpleType createUserSimpleType( Schema schema,
                                     String name,
                                     String baseName,
                                     String derivation,
                                     boolean createDeferredSimpleType)
    {
        if ( (baseName == null) || (baseName.length() == 0) ) {
            //We need a base type name...
            sendToLog(Messages.format( "schema.noBaseType", name ));
            return null;
        }

        //Find the base type
        SimpleType baseType= schema.getSimpleType(baseName);
        if (baseType == null) {
            //couldn't find the base type, must be forward declared
            if (createDeferredSimpleType) { // => create a DeferredSimpleType
              DeferredSimpleType result= new DeferredSimpleType();
              result.setSchema(schema);
              result.setName(name);
              result.setBaseTypeName(baseName);
              result.setDerivationMethod(derivation);
              result.setTypeCode(USER_TYPE);
              return result;
             }
            return null;
        }

        return createUserSimpleType(schema, name, baseType, derivation);
    }

    /**
     * Creates an instance of a class derived from SimpleType, representing the
     * user type defined by the given name, baseName and derivation method.
     *
     * Package private (used by Schema and DeferredSimpleType).
     *
     * The given schema is used as the owning Schema document, yet a call to
     * schema#addSimpleType must still be made to add the SimpleType to the
     * Schema if the SimpleType is not anonymous.
     *
     * If the base type is not found in the schema, a DeferredSimpleType
     * will be returned if createDeferredSimpleType is true, null otherwise.
     *
     * @param schema the owning schema
     * @param name the name of the SimpleType
     * @param baseType the base type
     * @param derivation the name of the derivation method (null/""/"list"/"restriction")
     * @return the new SimpleType, or null if its parent could not be found.
    **/
    SimpleType createUserSimpleType( Schema schema,
                                     String name,
                                     SimpleType baseType,
                                     String derivation)
    {
        String internalName = name;
        if (name == null) internalName = "anonymous-simple-type";

        if ( (baseType == null) ) {
            //We need a base type
            sendToLog(Messages.format( "schema.noBaseType", internalName ));
            return null;
        }

        SimpleType result= null;

        if ( (derivation != null) && (derivation.equals(SchemaNames.LIST)) ) {
            //derive as list
            /* This doesn't seem valid based on the XML Schema
             * Recommendation, so I am commenting it out (kvisco)
            if ( !(baseType instanceof AtomicType) ) {
                //only lists of atomic values are allowed by the specification
                sendToLog( Messages.format("schema.deriveByListError",
                                           internalName,
                                           baseType.getName()) );
                return null;
            }
            */
            try {
                result= new ListType(schema);
            }
            catch(SchemaException sx) {
                sendToLog( Messages.format("schema.deriveByListError",
                                           internalName,
                                           baseType.getName()) );
                return null;
            }
            ((ListType)result).setItemType( baseType );
        } else {
            //derive as restriction (only derivation allowed apart from list for simple types)
           
            if (baseType instanceof Union) {
                //Stoil Valchkov (stoill@mail.bg) - this is my fix for union extension
                //if we have union - handle it here. it wont be found as buildInBaseType
                try {
                    result = new Union(schema);
                } catch (SchemaException sx) {
                    //Hmmm... error message is not perfect, but at least is something :)
                    sendToLog(Messages.format("schema.deriveByListError",
                                              internalName, baseType.getName()) );
                    return null;
                }
            } else {
                //Find the built in ancestor type
                SimpleType builtInBase= baseType.getBuiltInBaseType();
                if (builtInBase == null) {
                   sendToLog(Messages.format("schema.noBuiltInParent",
                                             internalName) );
                   return null;
                }
                //creates the instance of a class derived from SimpleType representing the new type.
                result= createInstance(schema, builtInBase.getName());
                if (result == null) {
                    throw new SimpleTypesFactoryException( Messages.message("schema.cantLoadBuiltInTypes") );
                }
            }
        }

        result.setSchema(schema);
      result.setName(name);
        result.setBaseType(baseType);
        result.setDerivationMethod(derivation);
        result.setTypeCode(USER_TYPE);
        return result;
    } //-- createUserSimpleType

    /**
     * Returns the log writer.
     */
    private PrintWriter getLogWriter()
    {
        return _logWriter;
    }

    /**
     * Sends a message to the log through the logWriter (if its not null)
     */
    private void sendToLog(String message)
    {
        PrintWriter logger= getLogWriter();
        if (logger != null) {
            logger.println(message);
            logger.flush();
        }
    }

    /**
     * Gets the informations about the built in type which name is provided
     * as input parameter.
     * Loads the types definitions if they were not yet loaded
     */
    private Type getType(String typeName)
    {
        if (_typesByName == null) {
            loadTypesDefinitions();
        }
        return (Type)_typesByName.get(typeName);
    }

    /**
     * Gets the informations about the built in type which code is provided
     * as input parameter.
     * Loads the types definitions if they were not yet loaded
     */
    private Type getType(int typeCode)
    {
        if (_typesByCode == null) {
            loadTypesDefinitions();
        }
        return (Type)_typesByCode.get(new Integer(typeCode));
    }

    /**
     * Loads the built in type definitions from their xml file and its mapping file
     * into the static fields typesByName and typeByCode. Loading is done only once.
     */
    private synchronized void loadTypesDefinitions() {
        if ( (_typesByName == null) && (_typesByCode == null) ) {
            InputStream is = null;

          try //Load the mapping file
            Mapping mapping= new Mapping(getClass().getClassLoader());

            is = this.getClass().getResourceAsStream(TYPE_MAPPINGS);
        mapping.loadMapping( new InputSource(is) );

                //unmarshall the list of built in simple types
            Unmarshaller unmarshaller= new Unmarshaller(TypeList.class);
            unmarshaller.setMapping(mapping);
            //-- turn off validation
            unmarshaller.setValidation(false);

                is = this.getClass().getResourceAsStream(TYPE_DEFINITIONS);
            TypeList typeList = (TypeList)unmarshaller.unmarshal( new org.xml.sax.InputSource(is) );

                //print what we just read (only in debug mode and if we have a logWriter)
            // TODO: Joachim 2007-09-04 remove me
                // LocalConfiguration config = LocalConfiguration.getInstance();
                if (LOG.isDebugEnabled()) {
                    LOG.debug(typeList.toString());
                }
            //if (config.debug() && getLogWriter()!= null) {
                //    typeList.Print(getLogWriter());
                //}

                //Store the types by name in the typesByName and typesByCode hashtables
                //and create for each its associated SimpleType instance.
                Vector types= typeList.getTypes();
                _typesByName= new Hashtable();
                _typesByCode= new Hashtable();
            for( int index= 0; index < types.size(); index++)
            {
                    Type type= (Type)(types.elementAt(index));
                    _typesByName.put(type.getName(), type);
                    type.setSimpleType(createSimpleType(_builtInSchema, type));
                    _typesByCode.put(new Integer( type.getSimpleType().getTypeCode() ), type);
                }
          }
          catch (Exception except) {
                //Of course, this should not happen if the config files are there.
              String err = Messages.message("schema.cantLoadBuiltInTypes")
                    + "; " + except;

                throw new SimpleTypesFactoryException( except, err );
          }
        }
    } //-- loadTypeDefinitions


    /**
     * Creates a SimpleType, valid only for built in types.
     */
    private SimpleType createSimpleType(Schema schema, Type type)
    {
        //Creates the instance of a class derived from SimpleType representing the type.
        SimpleType result= createInstance(schema, type.getName());

        if (result == null) {
            String err = Messages.message("schema.cantLoadBuiltInTypes");
            throw new SimpleTypesFactoryException( err );
        }

      result.setName(type.getName());

        //Load the result's typeCode
        int intCode;
        try {
            intCode= getClass().getDeclaredField(type.getCode()).getInt(null);
        }
        catch (Exception ex) {

            String error = Messages.message("schema.cantLoadBuiltInTypes")
                + ex;
            throw new SimpleTypesFactoryException(ex, error);
        }

        result.setTypeCode(intCode);

        //Find and set the result's SimpleType basetype (if any).
        if (type.getBase() != null) {
            result.setBaseType( getType(type.getBase()).getSimpleType() );
        }

        //Adds the facets to the result
        Vector facets = type.getFacet();
        FacetFactory facetFactory = FacetFactory.getInstance();
        for (int index = 0; index < facets.size(); index++) {
            TypeProperty prop = (TypeProperty) facets.elementAt(index);
            if (!prop.getPseudo()) {
                //adds a "real" facet (defined in the xml specs)
                Facet facet = facetFactory.createFacet(prop.getName(), prop.getValue());
                facet.setOwningType(result);
                result.addFacet(facet);
            } else {
                //sets the information linked with the pseudo facet
                if (RealType.class.isInstance(result)) {
                    RealType realResult = (RealType) result;
                    if (prop.getName().equals("minM")) {
                        realResult.setMinMantissa(Long.parseLong(prop.getValue()));
                    } else if (prop.getName().equals("maxM")) {
                        realResult.setMaxMantissa(Long.parseLong(prop.getValue()));
                    } else if (prop.getName().equals("minE")) {
                        realResult.setMinExponent(Long.parseLong(prop.getValue()));
                    } else if (prop.getName().equals("maxE")) {
                        realResult.setMaxExponent(Long.parseLong(prop.getValue()));
                    }
                }
            }
        }
        return result;
    }

    /**
     * Creates the correct instance for the given type name.
     * Valid only for built in type names.
     */
    private SimpleType createInstance(Schema schema, String builtInTypeName)
    {
        Type type= getType(builtInTypeName);

       //If the type is derived by list, return a new ListType.
        String derivation= type.getDerivedBy();
        ListType resultList = null;
        if ( (derivation != null) && (derivation.equals(SchemaNames.LIST)) ) {
            try {
                resultList = new ListType(schema);
            }
            catch(SchemaException sx) {
                //-- This should not happen...but who knows!
                throw new SimpleTypesFactoryException(sx);
            }
        }

        //Finds the primitive ancestor (defines the class that represents it)
        Class implClass= null;
        while (type != null) {
            if (type.getImplClass() != null) {
                implClass= type.getImplClass();
                break;
            }
            type= getType(type.getBase());
        }

        if (implClass == null) return null;

        SimpleType result;
        if (implClass.isAssignableFrom(UrType.class)) {
                try {
                     result = (UrType)implClass.newInstance();
                     result.setSchema(schema);
                }
                catch (Exception e) {
                    throw new SimpleTypesFactoryException(e);
                }
        }
        else {
             try {
                 result = (AtomicType)implClass.newInstance();
                 result.setSchema(schema);
             }
             catch (Exception except) {
                 except.printStackTrace();
                 result= null;
             }
             if (resultList != null) {
                  resultList.setItemType(result);
                  return resultList;
             }
        }
        return result;
    } //-- createInstance
} //-- class: SimpleTypesFactory

/**
* A RuntimeException which allows nested exceptions.
*
* @author <a href="arkin@intalio.com">Assaf Arkin</a>
* @author <a href="kvisco@intalio.com">Keith Visco</a>
* @version $Revision: 7951 $ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
*/
class SimpleTypesFactoryException extends RuntimeException {
    /** SerialVersionUID */
    private static final long serialVersionUID = -7343397006284999081L;

    /**
     * The exception which caused this Exception
    **/
    private Throwable  _exception;


    /**
     * Creates a new SimpleTypesFactoryException
     *
     * @param message the error message
    **/
    public SimpleTypesFactoryException( String message ) {
        super(message);
    } //-- SimpleTypesFactoryException


    /**
     * Creates a new SimpleTypesFactoryException
     *
     * @param exception the Exception which caused this Exception.
    **/
    public SimpleTypesFactoryException(Throwable exception) {
        super(exception.toString());
        _exception = exception;
    } //-- SimpleTypesFactoryException

    /**
     * Creates a new SimpleTypesFactoryException
     *
     * @param exception the Exception which caused this Exception.
     * @param message the error message
    **/
    public SimpleTypesFactoryException(Throwable exception, String message) {
        super( message );
        _exception = exception;
    } //-- SimpleTypesFactoryException


    /**
     * Returns the Exception which caused this Exception, or null if
     * no nested exception exists.
     *
     * @return the nested Exception.
    **/
    public Throwable getException() {
        return _exception;
    } //-- getException


    public void printStackTrace() {
        if ( _exception == null )
            super.printStackTrace();
        else
            _exception.printStackTrace();
    } //-- printStackTrace


    public void printStackTrace( PrintStream print ) {
        if ( _exception == null )
            super.printStackTrace( print );
        else
            _exception.printStackTrace( print );
    } //-- printStackTrace


    public void printStackTrace( PrintWriter print ) {
        if ( _exception == null )
            super.printStackTrace( print );
        else
            _exception.printStackTrace( print );
    } //-- printStackTrace


} //-- SimpleTypesFactoryException

TOP

Related Classes of org.exolab.castor.xml.schema.SimpleTypesFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.