/* * @(#)$Id: DatatypeFactory.java,v 1.38 2002/11/07 16:49:51 kk122374 Exp $ * * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the proprietary information of Sun Microsystems, Inc. * Use is subject to license terms. * */ package com.sun.msv.datatype.xsd; import java.util.Map; import java.util.Iterator; import java.util.Collection; import org.relaxng.datatype.DatatypeException; /** * Datatype object factory. * * <p> * Applications should use this class to get and derive DataType objects. * All methods are static. * * <p> * Derivation by restriction should be done by using {@link TypeIncubator}. * * @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a> */ public class DatatypeFactory { private DatatypeFactory(){} /** * derives a new type by list. * * See http://www.w3.org/TR/xmlschema-2#derivation-by-list for * what "derivation by list" means. * * @return * always return non-null value. If error occurs, * then an exception will be thrown. * * @param nsUri,newTypeName * (URI,local) pair as the * name of the new type. it can be set to null for an anonymous type. * @param itemType * Type of the list item. It must be an atom type which is implemented * in this package or derived from types implemented in this package. * You cannot use your own DataType implementation here. * * @exception BadTypeException * this exception is thrown when the derivation is illegal. * For example, when you try to derive a type from non-atom type. */ public static XSDatatype deriveByList( String nsUri, String newTypeName, XSDatatype itemType ) throws DatatypeException { // if the base type contains an error, avoid producing more errors. if(itemType instanceof ErrorType) return itemType; return new ListType(nsUri,newTypeName,(XSDatatypeImpl)itemType); } /** * @deprecated */ public static XSDatatype deriveByList( String newTypeName, XSDatatype itemType ) throws DatatypeException { return deriveByList("",newTypeName,itemType); } /** * derives a new type by union. * * See http://www.w3.org/TR/xmlschema-2#derivation-by-union for * what "derivation by union" means. * * @param newTypeName * name of the new type. it can be set to null to * indicate an anonymous type. * @param memberTypes * Types of the union member. It can be any type that implements DataType. * * @exception BadTypeException * this exception is thrown when the derivation is illegal. */ public static XSDatatype deriveByUnion( String nsUri, String newTypeName, XSDatatype[] memberTypes ) throws DatatypeException { // if the base type contains an error, avoid producing more errors. for( int i=0; i<memberTypes.length; i++ ) if(memberTypes[i] instanceof ErrorType) return memberTypes[i]; return new UnionType(nsUri,newTypeName,memberTypes); } /** * @deprecated */ public static XSDatatype deriveByUnion( String newTypeName, XSDatatype[] memberTypes ) throws DatatypeException { return deriveByUnion("",newTypeName,memberTypes); } /** @deprecated */ public static XSDatatype deriveByUnion( String newTypeName, Collection memberTypes ) throws DatatypeException { return deriveByUnion("",newTypeName,memberTypes); } public static XSDatatype deriveByUnion( String nsUri, String newTypeName, Collection memberTypes ) throws DatatypeException { XSDatatypeImpl[] m = new XSDatatypeImpl[memberTypes.size()]; int n=0; for( Iterator itr=memberTypes.iterator(); itr.hasNext(); n++ ) for( int i=0; i<m.length; i++ ) m[i] = (XSDatatypeImpl)itr.next(); return deriveByUnion(nsUri,newTypeName,m); } private static void add( Map m, XSDatatypeImpl type ) { final String name = type.getName(); if( name==null ) throw new IllegalArgumentException("anonymous type"); if( m.containsKey(name) ) // this error is considered as an assertion, // since this object doesn't allow external programs to // add types to the object. throw new IllegalArgumentException("multiple definition"); m.put( name, type ); } /** * obtain a built-in DataType object by its name. * For example, you can pass somethings like "token", "gYear", etc. * * @exception DatatypeException * If the type name is undefined. * @return * A non-null valid datatype object. */ public synchronized static XSDatatype getTypeByName( String dataTypeName ) throws DatatypeException { XSDatatype dt = (XSDatatype)builtinType.get(dataTypeName); if(dt!=null) return dt; try { // types may be not added to the map. if( dataTypeName.equals("float") ) add( builtinType, FloatType.theInstance ); else if( dataTypeName.equals("double") ) add( builtinType, DoubleType.theInstance ); else if( dataTypeName.equals("duration") ) add( builtinType, DurationType.theInstance ); else if( dataTypeName.equals("dateTime") ) add( builtinType, DateTimeType.theInstance ); else if( dataTypeName.equals("time") ) add( builtinType, TimeType.theInstance ); else if( dataTypeName.equals("date") ) add( builtinType, DateType.theInstance ); else if( dataTypeName.equals("gYearMonth") ) add( builtinType, GYearMonthType.theInstance ); else if( dataTypeName.equals("gYear") ) add( builtinType, GYearType.theInstance ); else if( dataTypeName.equals("gMonthDay") ) add( builtinType, GMonthDayType.theInstance ); else if( dataTypeName.equals("gDay") ) add( builtinType, GDayType.theInstance ); else if( dataTypeName.equals("gMonth") ) add( builtinType, GMonthType.theInstance ); else if( dataTypeName.equals("hexBinary") ) add( builtinType, HexBinaryType.theInstance ); else if( dataTypeName.equals("base64Binary") ) add( builtinType, Base64BinaryType.theInstance ); else if( dataTypeName.equals("anyURI") ) add( builtinType, AnyURIType.theInstance ); else if( dataTypeName.equals("ENTITY") ) add( builtinType, EntityType.theInstance ); else if( dataTypeName.equals("language") ) add( builtinType, LanguageType.theInstance ); else if( dataTypeName.equals("ID") ) add( builtinType, IDType.theInstance ); else if( dataTypeName.equals("IDREF") ) add( builtinType, IDREFType.theInstance ); else if( dataTypeName.equals("IDREFS") ) add( builtinType, createBuiltinList("IDREFS",IDREFType.theInstance) ); else if( dataTypeName.equals("ENTITIES") ) add( builtinType, createBuiltinList("ENTITIES",EntityType.theInstance) ); else if( dataTypeName.equals("NMTOKENS") ) add( builtinType, createBuiltinList("NMTOKENS",NmtokenType.theInstance) ); else if( dataTypeName.equals("NOTATION") ) add( builtinType, new StringType("NOTATION", WhiteSpaceProcessor.theCollapse, false) ); else if( dataTypeName.equals("nonPositiveInteger") ) add( builtinType, NonPositiveIntegerType.theInstance ); else if( dataTypeName.equals("unsignedLong") ) add( builtinType, UnsignedLongType.theInstance ); else if( dataTypeName.equals("unsignedInt") ) add( builtinType, UnsignedIntType.theInstance ); else if( dataTypeName.equals("unsignedShort") ) add( builtinType, UnsignedShortType.theInstance ); else if( dataTypeName.equals("unsignedByte") ) add( builtinType, UnsignedByteType.theInstance ); else if( dataTypeName.equals("anySimpleType") ) add( builtinType, SimpleURType.theInstance ); } catch( DatatypeException dte ) { // assertion failed throw new Error(); } dt = (XSDatatype)builtinType.get(dataTypeName); if(dt!=null) return dt; throw new DatatypeException("undefined type name:"+dataTypeName); } private static XSDatatypeImpl createBuiltinList( String name, XSDatatypeImpl item ) throws DatatypeException { TypeIncubator ti = new TypeIncubator(new ListType(null,null,item)); ti.addFacet("minLength","1",null); // wrap it by a proxy object so that // these objects will work as singleton. return new Proxy(XSDatatype.XMLSCHEMA_NSURI,name,ti.derive(null,null)) { private Object readResolve() { try { return DatatypeFactory.getTypeByName(getName()); } catch( DatatypeException e ) { e.printStackTrace(); throw new InternalError(e.getMessage()); } } }; } /** * a map that contains built in types. * * To speed up the boot process, only a handful types are added * at the first time. */ private static final Map builtinType = createInitialBuiltinTypesMap(); /** creates a map that contains frequently-used built-in types */ private static Map createInitialBuiltinTypesMap() { Map m = new java.util.HashMap(); // missing types are noted inline. add( m, StringType.theInstance ); add( m, BooleanType.theInstance ); add( m, NumberType.theInstance ); add( m, QnameType.theInstance ); add( m, NormalizedStringType.theInstance ); add( m, TokenType.theInstance ); add( m, NmtokenType.theInstance ); add( m, NameType.theInstance ); add( m, NcnameType.theInstance ); add( m, IntegerType.theInstance ); add( m, NegativeIntegerType.theInstance ); add( m, LongType.theInstance ); add( m, IntType.theInstance ); add( m, ShortType.theInstance ); add( m, ByteType.theInstance ); add( m, NonNegativeIntegerType.theInstance ); add( m, PositiveIntegerType.theInstance ); return m; } }