/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml.xsd.typeprovider.primitive; import gw.internal.xml.xsd.typeprovider.simplevaluefactory.DoubleSimpleValueFactory; import gw.internal.xml.xsd.typeprovider.simplevaluefactory.FloatSimpleValueFactory; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.java.IJavaType; import gw.lang.reflect.java.JavaTypes; import gw.lang.reflect.java.JavaTypes; import gw.xml.XmlSimpleValueException; import java.math.BigDecimal; import java.net.URI; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import javax.xml.XMLConstants; import javax.xml.namespace.QName; public enum XmlSchemaPrimitiveType { // todo dlank - double check all "ordered" primitives in xml schema schema, and add comparators for them STRING( "string", null ), // not ordered BOOLEAN( "boolean", null ), // not ordered FLOAT( "float", null ), // totally ordered DOUBLE( "double", null ), // totally ordered DECIMAL( "decimal", new XmlSchemaDecimalComparator() ), DURATION( "duration", null ), // partially ordered DATETIME( "dateTime", null ), // partially ordered TIME( "time", null ), // partially ordered DATE( "date", null ), // partially ordered GYEARMONTH( "gYearMonth", null ), // partially ordered GYEAR( "gYear", null ), // partially ordered GMONTHDAY( "gMonthDay", null ), // partially ordered GDAY( "gDay", null ), // partially ordered GMONTH( "gMonth", null ), // partially ordered HEXBINARY( "hexBinary", null ), // not ordered BASE64BINARY( "base64Binary", null ), // not ordered ANYURI( "anyURI", null ), // not ordered QNAME( "QName", null ), // not ordered NOTATION( "NOTATION", null ), // not ordered LIST( null, null ), // not ordered UNION( null, null ), // not ordered ANYSIMPLETYPE( "anySimpleType", null ); // Does not exist in schema schema private static final Map<QName, XmlSchemaPrimitiveType> _typesByQName = new HashMap<QName, XmlSchemaPrimitiveType>(); private final String _localPart; private final Comparator<String> _valueComparator; static { for ( XmlSchemaPrimitiveType type : values() ) { if ( type._localPart != null ) { _typesByQName.put( new QName( XMLConstants.W3C_XML_SCHEMA_NS_URI, type._localPart ), type ); } } } XmlSchemaPrimitiveType( String localPart, Comparator<String> valueComparator ) { _localPart = localPart; _valueComparator = valueComparator; } public static XmlSchemaPrimitiveType get( QName qName ) { return _typesByQName.get( qName ); } public QName getQName() { return new QName( XMLConstants.W3C_XML_SCHEMA_NS_URI, _localPart ); } public Comparator<String> getValueComparator() { return _valueComparator; } public void validate( String value ) { switch ( this ) { case ANYSIMPLETYPE: // nothing to do break; case ANYURI: try { new URI( value ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:anyURI", ex ); } break; case BASE64BINARY: // not going to bother here - could affect performance on large byte arrays break; case BOOLEAN: try { Boolean.valueOf( value ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:boolean", ex ); } break; case DATE: try { create( value, "gw.xml.date.XmlDate" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:date", ex ); } break; case DATETIME: try { create( value, "gw.xml.date.XmlDateTime" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:dateTime", ex ); } break; case DECIMAL: try { new BigDecimal( value ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:decimal", ex ); } break; case DOUBLE: try { DoubleSimpleValueFactory.parseDouble( value ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:double", ex ); } break; case DURATION: try { create( value, "gw.xml.date.XmlDuration" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:duration", ex ); } break; case FLOAT: try { FloatSimpleValueFactory.parseFloat( value ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:float", ex ); } break; case GDAY: try { create( value, "gw.xml.date.XmlDay" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:gDay", ex ); } break; case GMONTH: try { create( value, "gw.xml.date.XmlMonth" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:gMonth", ex ); } break; case GMONTHDAY: try { create( value, "gw.xml.date.XmlMonthDay" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:gMonthDay", ex ); } break; case GYEAR: try { create( value, "gw.xml.date.XmlYear" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:gYear", ex ); } break; case GYEARMONTH: try { create( value, "gw.xml.date.XmlYearMonth" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:gYearMonth", ex ); } break; case HEXBINARY: // not going to bother here - could affect performance on large byte arrays break; case LIST: // will be handled by item types break; case NOTATION: // From spec: For some datatypes, notably QName and NOTATION, the mapping from lexical representations to values is context-dependent; for these types, no canonical mapping is defined. break; case QNAME: // From spec: For some datatypes, notably QName and NOTATION, the mapping from lexical representations to values is context-dependent; for these types, no canonical mapping is defined. break; case STRING: // nothing to do break; case TIME: try { create( value, "gw.xml.date.XmlTime" ); } catch ( Exception ex ) { throw new XmlSimpleValueException( "Invalid xsd:time", ex ); } break; case UNION: // will be handled by member types break; } } private void create( String value, String typeName ) { TypeSystem.getByFullName( typeName ).getTypeInfo().getConstructor( JavaTypes.STRING() ).getConstructor().newInstance( value ); } }