/* * @(#)$Id: PatternFacet.java,v 1.21 2002/09/08 16:13:02 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.io.IOException; import java.io.ObjectInputStream; import java.util.Vector; import java.util.regex.PatternSyntaxException; import java.util.regex.Pattern; import org.relaxng.datatype.ValidationContext; import org.relaxng.datatype.DatatypeException; /** * "pattern" facet validator * * "pattern" is a constraint facet which is applied against lexical space. * See http://www.w3.org/TR/xmlschema-2/#dt-pattern for the spec * * @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a> */ public final class PatternFacet extends DataTypeWithLexicalConstraintFacet { /** * actual object that performs regular expression validation. * one of the item has to match */ private transient Pattern[] exps; public Pattern[] getRegExps() { return exps; } /** * string representations of the above RegularExpressions. * this representation is usually human friendly than * the one generated by RegularExpression.toString method. */ final public String[] patterns; /** * @param regularExpressions * Vector of XMLSchema-compiliant regular expression * (see http://www.w3.org/TR/xmlschema-2/#dt-regex ) * There patterns are considered as an 'OR' set. */ public PatternFacet( String nsUri, String typeName, XSDatatypeImpl baseType, TypeIncubator facets ) throws DatatypeException { super( nsUri, typeName, baseType, FACET_PATTERN, facets ); // TODO : am I supposed to implement my own regexp validator? // at this time, I use Xerces' one. Vector regExps = facets.getVector(FACET_PATTERN); patterns = (String[]) regExps.toArray(new String[regExps.size()]); try { compileRegExps(); } catch( PatternSyntaxException pe ) { // in case regularExpression is not a correct pattern throw new DatatypeException( localize( ERR_PARSE_ERROR, pe.getMessage() ) ); } } /** Compiles all the regular expressions. */ private void compileRegExps() throws PatternSyntaxException { exps = new Pattern[patterns.length]; for(int i=0;i<exps.length;i++) exps[i] = Pattern.compile(patterns[i]); // loosened facet check is almost impossible for pattern facet. // ignore it for now. } protected void diagnoseByFacet(String content, ValidationContext context) throws DatatypeException { if( checkLexicalConstraint(content) ) return; if( exps.length==1 ) throw new DatatypeException( DatatypeException.UNKNOWN, localize(ERR_PATTERN_1,patterns[0]) ); else throw new DatatypeException( DatatypeException.UNKNOWN, localize(ERR_PATTERN_MANY) ); } protected final boolean checkLexicalConstraint( String literal ) { // makes sure that at least one of the patterns is satisfied. // regexp can be not thread-safe. Make sure only one thread uses it // at any given time. synchronized(this) { for( int i=0; i<exps.length; i++ ) if(exps[i].matcher(literal).matches()) return true; } // otherwise fail return false; } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); compileRegExps(); } }