/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml.xsd.typeprovider; import gw.internal.xml.xsd.typeprovider.simplevaluefactory.GosuEnumSimpleValueFactory; import gw.internal.xml.xsd.typeprovider.simplevaluefactory.XmlSimpleValueFactory; import gw.internal.xml.xsd.typeprovider.simplevaluefactory.additional.DateXmlSimpleValueFactory; import gw.lang.reflect.IEnumType; import gw.lang.reflect.IType; import gw.lang.reflect.TypeSystem; import gw.util.Pair; import gw.xml.XmlException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.xml.XMLConstants; import javax.xml.namespace.QName; public class XmlSchemaTypeToGosuTypeMappings { private static Map<QName, XmlSimpleValueFactory> _schemaToGosu; private static Map<IType, Pair<QName, XmlSimpleValueFactory>> _gosuToSchema; private static boolean _initialized = false; public static void maybeInit() { if ( ! _initialized ) { _initialized = true; _schemaToGosu = new HashMap<QName, XmlSimpleValueFactory>(); _gosuToSchema = new HashMap<IType, Pair<QName, XmlSimpleValueFactory>>(); map( "boolean", XmlSimpleValueFactory.BOOLEAN_INSTANCE, true, true ); map( "byte", XmlSimpleValueFactory.BYTE_INSTANCE, true, true ); map( "decimal", XmlSimpleValueFactory.DECIMAL_INSTANCE, true, true ); map( "double", XmlSimpleValueFactory.DOUBLE_INSTANCE, true, true ); map( "float", XmlSimpleValueFactory.FLOAT_INSTANCE, true, true ); map( "int", XmlSimpleValueFactory.INT_INSTANCE, true, true ); map( "integer", XmlSimpleValueFactory.INTEGER_INSTANCE, true, true ); map( "long", XmlSimpleValueFactory.LONG_INSTANCE, true, true ); map( "short", XmlSimpleValueFactory.SHORT_INSTANCE, true, true ); map( "unsignedLong", XmlSimpleValueFactory.UNSIGNEDLONG_INSTANCE, true, false ); map( "unsignedInt", XmlSimpleValueFactory.UNSIGNEDINT_INSTANCE, true, false ); map( "unsignedShort", XmlSimpleValueFactory.UNSIGNEDSHORT_INSTANCE, true, false ); map( "unsignedByte", XmlSimpleValueFactory.UNSIGNEDBYTE_INSTANCE, true, false ); map( "date", XmlSimpleValueFactory.DATE_INSTANCE, true, true ); map( "dateTime", XmlSimpleValueFactory.DATETIME_INSTANCE, true, true ); map( "time", XmlSimpleValueFactory.TIME_INSTANCE, true, true ); map( "gYearMonth", XmlSimpleValueFactory.GYEARMONTH_INSTANCE, true, true ); map( "gYear", XmlSimpleValueFactory.GYEAR_INSTANCE, true, true ); map( "gMonthDay", XmlSimpleValueFactory.GMONTHDAY_INSTANCE, true, true ); map( "gDay", XmlSimpleValueFactory.GDAY_INSTANCE, true, true ); map( "gMonth", XmlSimpleValueFactory.GMONTH_INSTANCE, true, true ); map( "duration", XmlSimpleValueFactory.DURATION_INSTANCE, true, true ); map( "base64Binary", XmlSimpleValueFactory.BASE64BINARY_INSTANCE, true, true ); map( "hexBinary", XmlSimpleValueFactory.HEXBINARY_INSTANCE, true, true ); map( "anyURI", XmlSimpleValueFactory.ANYURI_INSTANCE, true, true ); map( "QName", XmlSimpleValueFactory.QNAME_INSTANCE, true, true ); map( "ID", XmlSimpleValueFactory.ID_INSTANCE, true, false ); map( "IDREF", XmlSimpleValueFactory.IDREF_INSTANCE, true, false ); map( "string", XmlSimpleValueFactory.STRING_INSTANCE, true, true ); map( "anySimpleType", XmlSimpleValueFactory.STRING_INSTANCE, true, false ); // Though the following is technically correct, javax.xml.namespace.QName will never be used in practice, // since NOTATION MUST be restricted by an enumeration per spec, so the user will see an enumeration instead. map( "NOTATION", XmlSimpleValueFactory.QNAME_INSTANCE, true, false ); // additional mappings for supporting GX and webservices map( "dateTime", new DateXmlSimpleValueFactory(), false, true ); // additional mappings for supporting configuration files map(gw.internal.schema.gw.xsd.gw.gw_schema_additions.types.simple.EncodedString.$QNAME, XmlSimpleValueFactory.ENCODED_STRING_INSTANCE, true, false ); } } public static void map( String localPart, XmlSimpleValueFactory valueFactory, boolean mapSchemaType, boolean mapGosuType ) { map(new QName( XMLConstants.W3C_XML_SCHEMA_NS_URI, localPart), valueFactory, mapSchemaType, mapGosuType); } public static void map(QName qName, XmlSimpleValueFactory valueFactory, boolean mapSchemaType, boolean mapGosuType) { maybeInit(); if ( mapSchemaType ) { XmlSimpleValueFactory oldSchemaType = _schemaToGosu.put(qName, valueFactory ); if ( oldSchemaType != null ) { throw new IllegalArgumentException( "Schema type already mapped: " + qName); } } if ( mapGosuType ) { IType gosuType = valueFactory.getGosuValueType(); Pair<QName, XmlSimpleValueFactory> oldGosuType = _gosuToSchema.put( gosuType, new Pair<QName, XmlSimpleValueFactory>(qName, valueFactory ) ); if ( oldGosuType != null ) { throw new IllegalArgumentException( "Gosu type already mapped: " + gosuType ); } } } public static XmlSimpleValueFactory schemaToGosu( QName qname ) { maybeInit(); return _schemaToGosu.get( qname ); } public static Pair<QName, XmlSimpleValueFactory> gosuToSchemaIfValid( IType gosuType ) { if (gosuType == null) { return null; } maybeInit(); if ( gosuType.isPrimitive() ) { gosuType = TypeSystem.getBoxType( gosuType ); } else if ( gosuType.isEnum() ) { return new Pair<QName, XmlSimpleValueFactory>( new QName( XMLConstants.W3C_XML_SCHEMA_NS_URI, "string" ), new GosuEnumSimpleValueFactory( (IEnumType) gosuType ) ); } return _gosuToSchema.get( gosuType ); } public static Pair<QName, XmlSimpleValueFactory> gosuToSchema( IType gosuType ) { Pair<QName, XmlSimpleValueFactory> schemaTypePair = gosuToSchemaIfValid( gosuType ); if ( schemaTypePair == null ) { throw new XmlException( "Unable to map " + gosuType + " to a schema type" ); } return schemaTypePair; } public static Set<IType> getSupportedGosuTypes() { return Collections.unmodifiableSet( _gosuToSchema.keySet() ); } }