/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml.xsd.typeprovider.validator; import gw.internal.ext.org.apache.xerces.impl.xpath.regex.RegularExpression; import gw.internal.xml.xsd.typeprovider.schema.*; import gw.xml.XmlSimpleValueException; import gw.xml.XmlSimpleValue; import gw.internal.xml.XmlSimpleValueValidationContext; import gw.internal.xml.XmlDeserializationContext; import gw.internal.xml.XmlSimpleValueValidationContext; import gw.internal.xml.xsd.typeprovider.XmlWhitespaceHandling; import gw.internal.xml.xsd.typeprovider.primitive.XmlSchemaPrimitiveType; import gw.internal.xml.xsd.typeprovider.XmlWhitespaceHandling; import gw.internal.xml.xsd.typeprovider.simplevaluefactory.XmlSimpleValueFactory; import gw.xml.XmlSimpleValue; import gw.xml.XmlSimpleValueException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class XmlSimpleTypeSimpleValueValidator extends XmlSimpleValueValidator { private final XmlSimpleValueValidator _parent; private final XmlSchemaPrimitiveType _primitiveType; private final XmlSimpleValueFactory _valueFactory; private final List<ValidationStep> _validationSteps; private final XmlWhitespaceHandling _whitespace; public XmlSimpleTypeSimpleValueValidator( XmlSchemaPrimitiveType primitiveType, XmlSimpleValueValidator parent, List<XmlSchemaFacet> facets, XmlSimpleValueFactory valueFactory ) { _primitiveType = primitiveType; _parent = parent; _valueFactory = valueFactory; List<ValidationStep> validationSteps = new ArrayList<ValidationStep>(); StringBuilder patterns = null; Set<String> enumerationOptions = null; XmlWhitespaceHandling whitespace = null; for ( XmlSchemaFacet facet : facets ) { if ( facet instanceof XmlSchemaEnumerationFacet ) { if ( enumerationOptions == null ) { enumerationOptions = new HashSet<String>(); // this simple type uses enumerations, so initialize with a mutable set } XmlSchemaEnumerationFacet enumFacet = (XmlSchemaEnumerationFacet) facet; XmlDeserializationContext context = new XmlDeserializationContext( null ); for ( Map.Entry<String, String> entry : enumFacet.getNamespaceContext().entrySet() ) { context.addNamespace( entry.getKey(), entry.getValue() ); } XmlSimpleValue simpleValue = _valueFactory.deserialize( context, facet.getValue(), false ); enumerationOptions.add( simpleValue.getStringValue() ); } else if ( facet instanceof XmlSchemaPatternFacet ) { if ( patterns == null ) { patterns = new StringBuilder(); } else { patterns.append( '|' ); } patterns.append( facet.getValue() ); } else if ( facet instanceof XmlSchemaWhiteSpaceFacet ) { whitespace = XmlWhitespaceHandling.valueOf( facet.getValue() ); } else { validationSteps.add( new FacetValidationStep( facet ) ); } } if ( enumerationOptions != null ) { // validate that value matches enumeration final Set<String> fEnumerationOptions = enumerationOptions; validationSteps.add( new ValidationStep() { @Override public void validate( String value, XmlSimpleValueValidationContext validationContext, XmlSchemaPrimitiveType primitiveType ) { if ( ! fEnumerationOptions.contains( value ) ) { StringBuilder sb = new StringBuilder(); for ( String option : fEnumerationOptions ) { if ( sb.length() > 0 ) { sb.append( ", " ); } sb.append( option ); } throw new XmlSimpleValueException( "value does not match enumeration [ " + sb + " ]" ); } } } ); } if ( patterns != null ) { final String regexString = patterns.toString(); final RegularExpression regex = new RegularExpression( regexString, "X" ); validationSteps.add( new ValidationStep() { @Override public void validate( String value, XmlSimpleValueValidationContext validationContext, XmlSchemaPrimitiveType primitiveType ) { if ( ! regex.matches( value ) ) { throw new XmlSimpleValueException( "value does not match pattern " + regexString ); } } } ); } _whitespace = whitespace; // reduce size of validation steps by reconstructing list _validationSteps = validationSteps.isEmpty() ? Collections.<ValidationStep>emptyList() : new ArrayList<ValidationStep>( validationSteps ); } public void validate( String value, XmlSimpleValueValidationContext validationContext ) throws XmlSimpleValueException { final XmlSchemaPrimitiveType primitiveType = getPrimitiveType(); String collapsedValue = collapseWhitespace( value, validationContext ); primitiveType.validate( collapsedValue ); for ( ValidationStep validationStep : _validationSteps ) { validationStep.validate( collapsedValue, validationContext, primitiveType ); } if ( _parent != null ) { _parent.validate( value, validationContext ); } } public XmlSchemaPrimitiveType getPrimitiveType() { return _primitiveType == null ? _parent.getPrimitiveType() : _primitiveType; } @Override protected XmlWhitespaceHandling getWhitespaceHandling( String value ) { if ( _whitespace != null ) { return _whitespace; } return _parent == null ? XmlWhitespaceHandling.preserve : _parent.getWhitespaceHandling( value ); } private interface ValidationStep { void validate( String value, XmlSimpleValueValidationContext validationContext, XmlSchemaPrimitiveType primitiveType ); } private class FacetValidationStep implements ValidationStep { private final XmlSchemaFacet _facet; public FacetValidationStep( XmlSchemaFacet facet ) { _facet = facet; } @Override public void validate( String value, XmlSimpleValueValidationContext validationContext, XmlSchemaPrimitiveType primitiveType ) { XmlSchemaFacetValidator.validate( _facet, collapseWhitespace( value, validationContext ), validationContext, primitiveType ); } } }