You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by el...@apache.org on 2001/01/17 21:46:13 UTC

cvs commit: xml-xerces/java/src/org/apache/xerces/validators/datatype DecimalDatatypeValidator.java DoubleDatatypeValidator.java FloatDatatypeValidator.java ListDatatypeValidator.java UnionDatatypeValidator.java

elena       01/01/17 12:46:12

  Modified:    java/src/org/apache/xerces/validators/datatype
                        DecimalDatatypeValidator.java
                        DoubleDatatypeValidator.java
                        FloatDatatypeValidator.java
                        ListDatatypeValidator.java
                        UnionDatatypeValidator.java
  Log:
  The changes allow enumeration facet to be checked against value space of a content.
  Previously, we would only do string comparison which would give
  incorrect results.
  
  Similar changes should be done for RecurringDuration (as well as any other
  datatypes for which two or more literal denote the same value).
  
  Revision  Changes    Path
  1.16      +43 -17    xml-xerces/java/src/org/apache/xerces/validators/datatype/DecimalDatatypeValidator.java
  
  Index: DecimalDatatypeValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/DecimalDatatypeValidator.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- DecimalDatatypeValidator.java	2000/10/17 00:52:38	1.15
  +++ DecimalDatatypeValidator.java	2001/01/17 20:46:02	1.16
  @@ -74,7 +74,7 @@
    * @author Ted Leung
    * @author Jeffrey Rodriguez
    * @author Mark Swinkles - List Validation refactoring
  - * @version $Id: DecimalDatatypeValidator.java,v 1.15 2000/10/17 00:52:38 jeffreyr Exp $
  + * @version $Id: DecimalDatatypeValidator.java,v 1.16 2001/01/17 20:46:02 elena Exp $
    */
   
   public class DecimalDatatypeValidator extends AbstractDatatypeValidator {
  @@ -261,19 +261,36 @@
        */
   
       public Object validate(String content, Object state) throws InvalidDatatypeValueException {
  +        //REVISIT: should we pass state?
  +        checkContentEnum(content, state, null);
  +        return null;
  +    }
  +
  +
  +    /**
  +     * validate if the content is valid against base datatype and facets (if any)
  +     * this function might be called directly from UnionDatatype or ListDatatype     
  +     * 
  +     * @param content A string containing the content to be validated
  +     * @param enumeration A vector with enumeration strings  
  +     * @exception throws InvalidDatatypeException if the content is
  +     *  is not a W3C decimal type;
  +     * @exception throws InvalidDatatypeFacetException if enumeration is not BigDecimal
  +     */
   
  +    protected void checkContentEnum(String content, Object state, Vector enumeration) 
  +                                           throws InvalidDatatypeValueException{
           if ( this.fBaseValidator != null ) {//validate against parent type if any
  -            //System.out.println( "validator = " + this.fBaseValidator );
  -            this.fBaseValidator.validate( content, state );
  +            ((DecimalDatatypeValidator)this.fBaseValidator).checkContentEnum( content, state, enumeration );
           }
   
  -
           if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
               if ( fRegex == null || fRegex.matches( content) == false )
                   throw new InvalidDatatypeValueException("Value'"+content+
                       "' does not match regular expression facet " + fRegex.getPattern() );
           }
   
  +         
           BigDecimal d = null; // Is content a Decimal 
           try {
               d = new BigDecimal( stripPlusIfPresent( content));
  @@ -283,14 +300,22 @@
                                                                       DatatypeMessageProvider.MSG_NONE,
                                                                       new Object[] { "'" + content +"'"}));
           }
  -        //} 
  -        //catch (IOException ex ) {
  -        //  throw new InvalidDatatypeValueException(
  -        //  getErrorString(DatatypeMessageProvider.NotDecimal,
  -        // DatatypeMessageProvider.MSG_NONE,
  -        //                       new Object[] { "'" + content +"'"}));
  -        //}
  -
  +        
  +        if (enumeration != null) { //the call was made from List or Union
  +            int size= enumeration.size();
  +            BigDecimal[]     enumDecimal  = new BigDecimal[size];
  +            int i = 0;
  +            try {
  +                for ( ; i < size; i++) 
  +                    enumDecimal[i] = new BigDecimal( stripPlusIfPresent(((String) enumeration.elementAt(i))));
  +            } catch (NumberFormatException nfe) {
  +                   throw new InvalidDatatypeValueException(
  +                                                                getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  +                                                                                DatatypeMessageProvider.MSG_NONE,
  +                                                                                new Object [] { enumeration.elementAt(i)}));
  +            }
  +            enumCheck(d, enumDecimal);
  +        }
   
           if ( isScaleDefined == true ) {
               if (d.scale() > fScale)
  @@ -311,9 +336,10 @@
           }
           boundsCheck(d);
           if (  fEnumDecimal != null )
  -            enumCheck(d);
  +            enumCheck(d, fEnumDecimal);
               
  -        return null;
  +        return;
  +
       }
   
       /*
  @@ -381,9 +407,9 @@
   
       }
   
  -    private void enumCheck(BigDecimal v) throws InvalidDatatypeValueException {
  -        for (int i = 0; i < fEnumDecimal.length; i++) {
  -            if (v.equals(fEnumDecimal[i] ))
  +    private void enumCheck(BigDecimal v, BigDecimal[] enum) throws InvalidDatatypeValueException {
  +        for (int i = 0; i < enum.length; i++) {
  +            if (v.equals(enum[i] ))
               {
                   return;
               }
  
  
  
  1.11      +57 -9     xml-xerces/java/src/org/apache/xerces/validators/datatype/DoubleDatatypeValidator.java
  
  Index: DoubleDatatypeValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/DoubleDatatypeValidator.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- DoubleDatatypeValidator.java	2000/10/17 23:27:11	1.10
  +++ DoubleDatatypeValidator.java	2001/01/17 20:46:03	1.11
  @@ -69,7 +69,7 @@
    * @author Ted Leung
    * @author Jeffrey Rodriguez
    * @author Mark Swinkles - List Validation refactoring
  - * @version $Id: DoubleDatatypeValidator.java,v 1.10 2000/10/17 23:27:11 jeffreyr Exp $
  + * @version $Id: DoubleDatatypeValidator.java,v 1.11 2001/01/17 20:46:03 elena Exp $
    */
   
   public class DoubleDatatypeValidator extends AbstractDatatypeValidator {
  @@ -216,15 +216,34 @@
        *  is not a W3C real type
        */
   
  -    public Object validate(String content, Object state) 
  -    throws InvalidDatatypeValueException {
  +    public Object validate(String content, Object state) throws InvalidDatatypeValueException {
  +              
  +        checkContentEnum (content, state, null);
  +        return null;
  +    }
  +
  +
  +     /**
  +     * validate if the content is valid against base datatype and facets (if any)
  +     * this function might be called directly from UnionDatatype or ListDatatype  
  +     * 
  +     * @param content A string containing the content to be validated
  +     * @param enumeration A vector with enumeration strings  
  +     * @exception throws InvalidDatatypeException if the content is
  +     *  is not a W3C decimal type;
  +     * @exception throws InvalidDatatypeFacetException if enumeration is not double
  +     */
  +
  +    protected void checkContentEnum(String content, Object state, Vector enumeration) throws InvalidDatatypeValueException {
  +        if ( this.fBaseValidator != null ) { //validate against parent type if any
  +            ((DoubleDatatypeValidator)this.fBaseValidator).checkContentEnum( content, state, enumeration);
  +        }
           if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
               if ( fRegex == null || fRegex.matches( content) == false )
                   throw new InvalidDatatypeValueException("Value'"+content+
                                                           "does not match regular expression facet" + fPattern );
           }
   
  -
           double d = 0.0;
           try {
               d = Double.valueOf(content).doubleValue();
  @@ -242,14 +261,43 @@
                                                             new Object [] { content}));
                  }
           }
  +
  +        if (enumeration != null) { //the call was made from List or union
  +           int size = enumeration.size();
  +           double[] enumDoubles = new double[size];
  +           int i=0;
  +           try {
  +                for (; i < size; i++)
  +                     enumDoubles[i] = Double.valueOf((String) enumeration.elementAt(i)).doubleValue();
  +           }  catch (NumberFormatException nfe) {
  +                 if( content.equals("INF") ){
  +                   enumDoubles[i]=Double.POSITIVE_INFINITY;
  +               } else if( content.equals("-INF") ){
  +                   enumDoubles[i]=Double.NEGATIVE_INFINITY;
  +               } else if( content.equals("NaN" ) ) {
  +                   enumDoubles[i]=Double.NaN;
  +               } else {
  +                   throw new InvalidDatatypeValueException(
  +                   getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  +                                  DatatypeMessageProvider.MSG_NONE,
  +                                  new Object [] { enumeration.elementAt(i)}));
  +               }
  +           }
  +
  +
  +
  +           enumCheck(d, enumDoubles);
  +       }
  +
           boundsCheck(d);
   
           if (((fFacetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ) )
  -            enumCheck(d);
  +            enumCheck(d, fEnumDoubles);
   
  -        return null;
  +        
       }
   
  +
       // Private Methods start here
   
   
  @@ -322,9 +370,9 @@
   
       }
   
  -    private void enumCheck(double v) throws InvalidDatatypeValueException {
  -        for (int i = 0; i < fEnumDoubles.length; i++) {
  -            if (v == fEnumDoubles[i]) return;
  +    private void enumCheck(double v, double[] enumDoubles) throws InvalidDatatypeValueException {
  +        for (int i = 0; i < enumDoubles.length; i++) {
  +            if (v == enumDoubles[i]) return;
           }
           throw new InvalidDatatypeValueException(
                                                  getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  
  
  
  1.12      +93 -39    xml-xerces/java/src/org/apache/xerces/validators/datatype/FloatDatatypeValidator.java
  
  Index: FloatDatatypeValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/FloatDatatypeValidator.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- FloatDatatypeValidator.java	2000/10/17 00:52:39	1.11
  +++ FloatDatatypeValidator.java	2001/01/17 20:46:04	1.12
  @@ -71,7 +71,7 @@
    * @author Ted Leung
    * @author Jeffrey Rodriguez
    * @author Mark Swinkles - List Validation refactoring
  - * @version  $Id: FloatDatatypeValidator.java,v 1.11 2000/10/17 00:52:39 jeffreyr Exp $
  + * @version  $Id: FloatDatatypeValidator.java,v 1.12 2001/01/17 20:46:04 elena Exp $
    */
   
   public class FloatDatatypeValidator extends AbstractDatatypeValidator {
  @@ -204,7 +204,18 @@
                                                                                       DatatypeMessageProvider.MSG_NONE,
                                                                                       new Object [] { v.elementAt(i)}));
                           } catch (NumberFormatException nfe) {
  -                            System.out.println("Internal Error parsing enumerated values for real type");
  +                            if( v.elementAt(i).equals("INF") ){
  +                                fEnumFloats[i] = Float.POSITIVE_INFINITY;
  +                            } else if( v.elementAt(i).equals("-INF")){
  +                                fEnumFloats[i] = Float.NEGATIVE_INFINITY;
  +                            } else if( v.elementAt(i).equals("NaN")) {
  +                                fEnumFloats[i] = Float.NaN;
  +                            } else {
  +                                //REVISIT: parser will reparse and report error several times
  +                                throw new InvalidDatatypeFacetException( getErrorString(
  +                                    DatatypeMessageProvider.IllegalFacetValue, 
  +                                    DatatypeMessageProvider.MSG_NONE, new Object [] {v.elementAt(i), "enumeration"}));
  +                            }
                           }
                   }
               }
  @@ -230,10 +241,85 @@
        */
       public Object validate(String content, Object state) 
       throws InvalidDatatypeValueException {
  -        checkContent(  content );
  +        checkContentEnum (content, state, null);
           return null;
       }
   
  +     /**
  +     * validate if the content is valid against base datatype and facets (if any)
  +     * this function might be called directly from UnionDatatype or ListDatatype 
  +     * 
  +     * @param content A string containing the content to be validated
  +     * @param enumeration A vector with enumeration strings  
  +     * @exception throws InvalidDatatypeException if the content is
  +     *  is not a W3C decimal type;
  +     * @exception throws InvalidDatatypeFacetException if enumeration is not float
  +     */
  +     protected void checkContentEnum(String content, Object state, Vector enumeration) 
  +                                                      throws InvalidDatatypeValueException{
  +       if ( this.fBaseValidator != null ) { //validate against parent type if any
  +             ((FloatDatatypeValidator)this.fBaseValidator).checkContentEnum( content, state, enumeration);
  +       }
  +
  +       if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
  +               if ( fRegex == null || fRegex.matches( content) == false )
  +                   throw new InvalidDatatypeValueException("Value'"+content+
  +                                                           "does not match regular expression facet" + fPattern );
  +       }
  +
  +        float f = 0;
  +        try {
  +                f = Float.valueOf(content).floatValue();
  +        } catch (NumberFormatException nfe) {
  +                if( content.equals("INF") ){
  +                    f=Float.POSITIVE_INFINITY;
  +                } else if( content.equals("-INF") ){
  +                    f=Float.NEGATIVE_INFINITY;
  +                } else if( content.equals("NaN" ) ) {
  +                    f=Float.NaN;
  +                } else {
  +                    throw new InvalidDatatypeValueException(
  +                                  getErrorString(DatatypeMessageProvider.NotFloat,
  +                                                 DatatypeMessageProvider.MSG_NONE,
  +                                                           new Object [] { content}));
  +                }
  +        }
  +        
  +        //enumeration is passed from List or Union datatypes
  +        if (enumeration != null) {
  +            int size =  enumeration.size();
  +            float[]     enumFloats = new float[size];
  +            int i=0;
  +            try {
  +                for (; i < size; i++)
  +                    enumFloats[i] = Float.valueOf((String) enumeration.elementAt(i)).floatValue();
  +            
  +            } catch (NumberFormatException nfe) {
  +                if( enumeration.elementAt(i).equals("INF") ){
  +                    enumFloats[i] = Float.POSITIVE_INFINITY;
  +                } else if( enumeration.elementAt(i).equals("-INF")){
  +                    enumFloats[i] = Float.NEGATIVE_INFINITY;
  +                } else if( enumeration.elementAt(i).equals("NaN")) {
  +                    enumFloats[i] = Float.NaN;
  +                } else {
  +                    throw new InvalidDatatypeValueException(
  +                                    getErrorString(DatatypeMessageProvider.InvalidEnumValue,
  +                                                   DatatypeMessageProvider.MSG_NONE,
  +                                                   new Object [] { enumeration.elementAt(i)}));
  +                }
  +            }
  +            enumCheck(f, enumFloats);
  +        }
  +
  +        boundsCheck(f);
  +
  +        if (((fFacetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ) )
  +                enumCheck(f, fEnumFloats);
  +    }
  +
  +
  +
  +
       /*
        * check that a facet is in range, assumes that facets are compatible -- compatibility ensured by setFacets
        */
  @@ -329,9 +415,9 @@
       }
   
   
  -    private void enumCheck(float v) throws InvalidDatatypeValueException {
  -       for (int i = 0; i < fEnumFloats.length; i++) {
  -           if (v == fEnumFloats[i]) return;
  +    private void enumCheck(float v, float[] enumFloats) throws InvalidDatatypeValueException {
  +       for (int i = 0; i < enumFloats.length; i++) {
  +           if (v == enumFloats[i]) return;
          }
          throw new InvalidDatatypeValueException(
                                                 getErrorString(DatatypeMessageProvider.NotAnEnumValue,
  @@ -352,39 +438,7 @@
       private void setBasetype(DatatypeValidator base) {
           fBaseValidator =  base;
       }
  -
  -    private  void checkContent( String content )throws InvalidDatatypeValueException {
  -        if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
  -                if ( fRegex == null || fRegex.matches( content) == false )
  -                    throw new InvalidDatatypeValueException("Value'"+content+
  -                                                            "does not match regular expression facet" + fPattern );
  -            }
  -
  -
  -            float f = 0;
  -            try {
  -                //System.out.println("content = " + content );
  -                f = Float.valueOf(content).floatValue();
  -                //System.out.println("f = " + f );
  -            } catch (NumberFormatException nfe) {
  -                if( content.equals("INF") ){
  -                    f=Float.POSITIVE_INFINITY;
  -                } else if( content.equals("-INF") ){
  -                    f=Float.NEGATIVE_INFINITY;
  -                } else if( content.equals("NaN" ) ) {
  -                    f=Float.NaN;
  -                } else {
  -                    throw new InvalidDatatypeValueException(
  -                                  getErrorString(DatatypeMessageProvider.NotFloat,
  -                                                 DatatypeMessageProvider.MSG_NONE,
  -                                                           new Object [] { content}));
  -                }
  -            }
  -            boundsCheck(f);
   
  -            if (((fFacetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ) )
  -                enumCheck(f);
  -
  -    }
  +    
   
   }
  
  
  
  1.5       +159 -55   xml-xerces/java/src/org/apache/xerces/validators/datatype/ListDatatypeValidator.java
  
  Index: ListDatatypeValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/ListDatatypeValidator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ListDatatypeValidator.java	2000/12/06 02:50:33	1.4
  +++ ListDatatypeValidator.java	2001/01/17 20:46:05	1.5
  @@ -72,7 +72,7 @@
    * StringValidator validates that XML content is a W3C string type.
    * @author Jeffrey Rodriguez
    * @author Mark Swinkles - List Validation refactoring
  - * @version $Id: ListDatatypeValidator.java,v 1.4 2000/12/06 02:50:33 jeffreyr Exp $
  + * @version $Id: ListDatatypeValidator.java,v 1.5 2001/01/17 20:46:05 elena Exp $
    */
   public class ListDatatypeValidator extends AbstractDatatypeValidator{
       private Locale     fLocale          = null;
  @@ -84,12 +84,11 @@
       private String     fPattern          = null;
       private Vector     fEnumeration      = null;
       private int        fFacetsDefined    = 0;
  -    private boolean    fDerivedByList    = false;//default
  -
  +    private boolean    fDerivedByList    = false; //false: derivation by restriction
  +                                                  //true: list decl
       private RegularExpression fRegex         = null;
  -
  -
   
  +    
   
       public  ListDatatypeValidator () throws InvalidDatatypeFacetException{
           this( null, null, false ); // Native, No Facets defined, Restriction
  @@ -97,7 +96,7 @@
       }
   
       public ListDatatypeValidator ( DatatypeValidator base, Hashtable facets, 
  -                                     boolean derivedByList ) throws InvalidDatatypeFacetException {
  +    boolean derivedByList ) throws InvalidDatatypeFacetException {
   
           setBasetype( base ); // Set base type 
   
  @@ -143,18 +142,18 @@
               if (((fFacetsDefined & DatatypeValidator.FACET_LENGTH ) != 0 ) ) {
                   if (((fFacetsDefined & DatatypeValidator.FACET_MAXLENGTH ) != 0 ) ) {
                       throw new InvalidDatatypeFacetException(
  -                                                            "It is an error for both length and maxLength to be members of facets." );  
  +                    "It is an error for both length and maxLength to be members of facets." );  
                   } else if (((fFacetsDefined & DatatypeValidator.FACET_MINLENGTH ) != 0 ) ) {
                       throw new InvalidDatatypeFacetException(
  -                                                            "It is an error for both length and minLength to be members of facets." );
  +                    "It is an error for both length and minLength to be members of facets." );
                   }
               }
   
               if ( ( (fFacetsDefined & ( DatatypeValidator.FACET_MINLENGTH |
  -                                        DatatypeValidator.FACET_MAXLENGTH) ) != 0 ) ) {
  +            DatatypeValidator.FACET_MAXLENGTH) ) != 0 ) ) {
                   if ( fMinLength > fMaxLength ) {
                       throw new InvalidDatatypeFacetException( "Value of minLength = " + fMinLength +
  -                                                                "must be greater that the value of maxLength" + fMaxLength );
  +                    "must be greater that the value of maxLength" + fMaxLength );
                   }
               }
           }// End of Facets Setting
  @@ -174,13 +173,13 @@
        */
       public Object validate(String content, Object state)  throws InvalidDatatypeValueException
       {
  -         if ( content == null && state != null ) {
  +        if ( content == null && state != null ) {
               this.fBaseValidator.validate( content, state );//Passthrough setup information
                                                             //for state validators
  -         }else{
  -            checkContent( content, state );
  -         }
  -         return null;
  +        } else{
  +            checkContentEnum( content, state , null); 
  +        }
  +        return null;
       }
   
   
  @@ -233,61 +232,166 @@
           return newObj;
       }
   
  -    // Private methods
  -    private void checkContent( String content,  Object state )throws InvalidDatatypeValueException
  -    {
  -        StringTokenizer parsedList = new StringTokenizer( content );
  -        try {
  -            int numberOfTokens =  parsedList.countTokens();
  -            if ( (fFacetsDefined & DatatypeValidator.FACET_MAXLENGTH) != 0 ) {
  -                if ( numberOfTokens > fMaxLength ) {
  -                    throw new InvalidDatatypeValueException("Value '"+content+
  -                                                            "' with length ='"+  numberOfTokens + "' tokens"+
  -                                                            "' exceeds maximum length facet of '"+fMaxLength+"' tokens.");
  +    /**
  +     * validate that a content is valid against base datatype and facets (if any) 
  +     * 
  +     * @param content A string containing the content to be validated
  +     * @param state used with IDREF(s) datatypes
  +     * @param enumeration enumeration facet
  +     * @exception throws InvalidDatatypeException if the content is not valid
  +     * @exception InvalidDatatypeValueException
  +     */
  +     protected void checkContentEnum( String content,  Object state, Vector enumeration )
  +                                throws InvalidDatatypeValueException {
  +            
  +            //REVISIT: attemt to make enumeration to be validated against value space.
  +            //a redesign of Datatypes might help to reduce complexity of this validation
  +        StringTokenizer parsedList = null;
  +        int numberOfTokens = 0;
  +        parsedList= new StringTokenizer( content );
  +        numberOfTokens =  parsedList.countTokens();
  +        
  +        if (!this.fDerivedByList) { 
  +            //<simpleType name="fRestriction"><restriction base="fList">...</restriction></simpleType>
  +            try {
  +                if ( (fFacetsDefined & DatatypeValidator.FACET_MAXLENGTH) != 0 ) {
  +                    if ( numberOfTokens > fMaxLength ) {
  +                        throw new InvalidDatatypeValueException("Value '"+content+
  +                        "' with length ='"+  numberOfTokens + "' tokens"+
  +                        "' exceeds maximum length facet of '"+fMaxLength+"' tokens.");
  +                    }
                   }
  -            }
  -            if ( (fFacetsDefined & DatatypeValidator.FACET_MINLENGTH) != 0 ) {
  -                if ( numberOfTokens < fMinLength ) {
  -                    throw new InvalidDatatypeValueException("Value '"+content+
  -                                                            "' with length ='"+ numberOfTokens+ "' tokens" +
  -                                                            "' is less than minimum length facet of '"+fMinLength+"' tokens." );
  +                if ( (fFacetsDefined & DatatypeValidator.FACET_MINLENGTH) != 0 ) {
  +                    if ( numberOfTokens < fMinLength ) {
  +                        throw new InvalidDatatypeValueException("Value '"+content+
  +                        "' with length ='"+ numberOfTokens+ "' tokens" +
  +                        "' is less than minimum length facet of '"+fMinLength+"' tokens." );
  +                    }
                   }
  -            }
   
  -            if ( (fFacetsDefined & DatatypeValidator.FACET_LENGTH) != 0 ) {
  -                if ( numberOfTokens != fLength ) {
  -                    throw new InvalidDatatypeValueException("Value '"+content+
  -                                                            "' with length ='"+ numberOfTokens+ "' tokens" +
  -                                                            "' is not equal to length facet of '"+fLength+"' tokens.");
  +                if ( (fFacetsDefined & DatatypeValidator.FACET_LENGTH) != 0 ) {
  +                    if ( numberOfTokens != fLength ) {
  +                        throw new InvalidDatatypeValueException("Value '"+content+
  +                        "' with length ='"+ numberOfTokens+ "' tokens" +
  +                        "' is not equal to length facet of '"+fLength+"' tokens.");
  +                    }
                   }
  -            }
  -
  -            if ( (fFacetsDefined & DatatypeValidator.FACET_ENUMERATION) != 0 ) {
  -                // Enumerations are defined in the value space so the contains method
  -                // of vector doesn't really do the right thing, we really should check using compare
  -                if ( fEnumeration.contains( content ) == false )
  -                    throw new InvalidDatatypeValueException("Value '"+
  -                                                            content+"' must be one of "+fEnumeration);
  +                if (enumeration!=null) {
  +                    if (!verifyEnum(enumeration)) {
  +                        throw new InvalidDatatypeValueException("Enumeration '" +enumeration+"' for value '" +content+
  +                        "' is based on enumeration '"+fEnumeration+"'");
  +                    }
  +                }else {
  +                    enumeration = (fEnumeration!=null) ? fEnumeration : null;
  +                }
  +                                      
  +                // enumeration must be passed till we know what "itemType" is
  +                // to be able to validate against value space
  +                ((ListDatatypeValidator)this.fBaseValidator).checkContentEnum( content, state, enumeration );
  +            } catch ( NoSuchElementException e ) {
  +                e.printStackTrace();
               }
  -            
  -            if (this.fDerivedByList) {
  -                while ( parsedList.hasMoreTokens() ) {       //Check each token in list against base type
  +        } 
  +        else { 
  +            //the case:
  +            //<simpleType name="fList"><list itemType="float"/></simpleType>
  +            if (enumeration !=null) {
  +                StringTokenizer eTokens = null; //temporary list of enumeration tokens 
  +                StringTokenizer cTokens = null; //list of content tokens
  +                String token= null;  //content token
  +                String eToken= null; //enumeration token
  +                boolean valid = true;
  +
  +                int eSize = enumeration.size(); 
  +                Vector enumTemp = new Vector(); //temporary vector to store enumeration token
  +                enumTemp.setSize(1);
  +                String currentEnumeration = null; //enum value: <enumeration value="1 2 3"/>
  +                
  +                for (int i=0;i<eSize;i++) { //loop through each enumeration
  +                    currentEnumeration = (String)enumeration.elementAt(i);
  +                    eTokens = new StringTokenizer (currentEnumeration);
  +                    valid = true;
  +                    cTokens=parsedList;
  +                    
  +                    if (numberOfTokens == eTokens.countTokens()) {
  +                        try {
  +                            //try string comparison first
  +                            if (currentEnumeration.equals(content)) {
  +                                for (int k=0; k<numberOfTokens;k++) { //validate against base type each token
  +                                    if ( this.fBaseValidator != null ) {
  +                                        this.fBaseValidator.validate( cTokens.nextToken(), state );
  +                                    }
  +                                }
  +                            } else  { //content="1.0 2" ; enumeration = "1 2"
  +                                for (int j=0;j<numberOfTokens;j++) {
  +                                    token = cTokens.nextToken();
  +                                    eToken = eTokens.nextToken();
  +                                    enumTemp.setElementAt(eToken,0);
  +                                    //REVISIT: RecurringDuration..
  +                                    if (fBaseValidator instanceof DecimalDatatypeValidator) {
  +                                        ((DecimalDatatypeValidator)fBaseValidator).checkContentEnum(token, state, enumTemp);
  +                                    } else if (fBaseValidator instanceof FloatDatatypeValidator) {
  +                                        ((FloatDatatypeValidator)fBaseValidator).checkContentEnum(token, state, enumTemp);
  +                                    } else if (fBaseValidator instanceof DoubleDatatypeValidator) {
  +                                        ((DoubleDatatypeValidator)fBaseValidator).checkContentEnum(token, state, enumTemp);
  +                                    } else { 
  +                                        if (!token.equals(eToken)) { //validate enumeration for all other types
  +                                            throw new InvalidDatatypeValueException("Value '"+content+ "' must be one of "+enumeration);
  +                                        }
  +                                        this.fBaseValidator.validate( token, state );
  +                                    }
  +                                }
  +                            }
  +                        } catch (InvalidDatatypeValueException e) {
  +                            valid = false;
  +                        }
  +                    } else //numOfTokens in enumeration != numOfTokens in content
  +                        valid = false;
  +                    if (valid) break;
  +                } //end for loop
  +                if (!valid) {
  +                    throw new InvalidDatatypeValueException("Value '"+content+ "' does not match list type");
  +                }
  +            }//enumeration != null
  +            else {   //no enumeration
  +                for (int k=0; k<numberOfTokens;k++) {
                       if ( this.fBaseValidator != null ) {//validate against parent type if any
                           this.fBaseValidator.validate( parsedList.nextToken(), state );
                       }
                   }
               }
  -            else {
  -                if ( this.fBaseValidator != null ) {//validate against parent type if any
  -                    this.fBaseValidator.validate( content, state );
  +
  +        } //end native list type
  +
  +    } //end checkContentEnum
  +
  +
  +
  +    // Private methods
  +    /**
  +    * check if enum is subset of fEnumeration
  +    * enum 1: <enumeration value="1 2"/>
  +    * enum 2: <enumeration value="1.0 2"/>
  +    *
  +    * @param enumeration facet
  +    *
  +    * @returns true if enumeration is subset of fEnumeration, false otherwise
  +    */    
  +    private boolean verifyEnum (Vector enum){
  +
  +        /* REVISIT: won't work for list datatypes in some cases: */
  +        if ((fFacetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0) {
  +            for (Enumeration e = enum.elements() ; e.hasMoreElements() ;) {
  +                if (fEnumeration.contains(e.nextElement()) == false) {
  +                    return false;                             
                   }
               }
  -                
  -        } catch ( NoSuchElementException e ) {
  -            e.printStackTrace();
           }
  +        return true;
       }
   
  +
  +    
       private void setBasetype( DatatypeValidator base) {
           fBaseValidator = base;
       }
  
  
  
  1.3       +95 -66    xml-xerces/java/src/org/apache/xerces/validators/datatype/UnionDatatypeValidator.java
  
  Index: UnionDatatypeValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/validators/datatype/UnionDatatypeValidator.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- UnionDatatypeValidator.java	2000/12/15 23:03:47	1.2
  +++ UnionDatatypeValidator.java	2001/01/17 20:46:07	1.3
  @@ -84,7 +84,6 @@
       private String     fPattern          = null;
       private Vector     fEnumeration      = null;
       private int        fFacetsDefined    = 0;
  -    private boolean    fDerivedByUnion    = false; //default
   
       private StringBuffer errorMsg = null;   
       private RegularExpression fRegex         = null;
  @@ -95,11 +94,9 @@
   
       }
   
  -    public UnionDatatypeValidator ( DatatypeValidator base, Hashtable facets, 
  -                                    boolean derivedBy ) throws InvalidDatatypeFacetException {
  -        setBasetype( base ); // Set base type 
  -        fDerivedByUnion = derivedBy;  // always false - derived datatype
   
  +    public UnionDatatypeValidator ( DatatypeValidator base, Hashtable facets, boolean derivedBy ) throws InvalidDatatypeFacetException {
  +        setBasetype( base );  
           //facets allowed are: pattern & enumeration
           if ( facets != null ) {
               for ( Enumeration e = facets.keys(); e.hasMoreElements(); ) {
  @@ -107,13 +104,15 @@
                   if ( key.equals(SchemaSymbols.ELT_ENUMERATION) ) {
                       fFacetsDefined += DatatypeValidator.FACET_ENUMERATION;
                       fEnumeration    = (Vector)facets.get(key);
  -                } else if ( key.equals(SchemaSymbols.ELT_PATTERN) ) {
  +                }
  +                else if ( key.equals(SchemaSymbols.ELT_PATTERN) ) {
                       fFacetsDefined += DatatypeValidator.FACET_PATTERN;
                       fPattern = (String)facets.get(key);
                       fRegex   = new RegularExpression(fPattern, "X");
   
   
  -                } else {
  +                }
  +                else {
                       throw new InvalidDatatypeFacetException("invalid facet tag : " + key);
                   }
               } //end for
  @@ -127,7 +126,6 @@
           if ( base !=null ) {
               fValidatorsSize = base.size();
               fBaseValidators = new Vector(fValidatorsSize);
  -            fDerivedByUnion = true;  //native union decl
               fBaseValidators = base;
   
           }
  @@ -150,8 +148,9 @@
           if ( content == null && state != null ) {
               this.fBaseValidator.validate( content, state );//Passthrough setup information
               //for state validators
  -        } else {
  -            checkContent( content, state);
  +        }
  +        else {
  +            checkContentEnum( content, state, false , null );
           }
           return(null);
       }
  @@ -196,92 +195,122 @@
               newObj.fPattern          =  this.fPattern;
               newObj.fEnumeration      =  this.fEnumeration;
               newObj.fFacetsDefined    =  this.fFacetsDefined;
  -            newObj.fDerivedByUnion   =  this.fDerivedByUnion;
  -        } catch ( InvalidDatatypeFacetException ex ) {
  +        }
  +        catch ( InvalidDatatypeFacetException ex ) {
               ex.printStackTrace();
           }
           return(newObj);
   
       }
   
  -    // Private methods
  -
   
  -    private void checkContent( String content,  Object state ) throws InvalidDatatypeValueException
  -    {
  -        //Facet pattern can be checked here
  -        //Facet enumeration requires to know if valiadation occurs against ListDatatype
  -        if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
  -            if ( fRegex == null || fRegex.matches( content) == false )
  -                throw new InvalidDatatypeValueException("Value '"+content+
  -                                                        "' does not match regular expression facet '" + fPattern + "'." );
  -        }
  -
  -        //validate against parent type
  -        if ( this.fBaseValidator != null ) {
  -            ((UnionDatatypeValidator)this.fBaseValidator).checkContent( content, state , fPattern, fEnumeration );
  +    /**
  +    * check if enum is subset of fEnumeration
  +    * enum 1: <enumeration value="1 2"/>
  +    * enum 2: <enumeration value="1.0 2"/>
  +    *
  +    * @param enumeration facet
  +    *
  +    * @returns true if enumeration is subset of fEnumeration, false otherwise
  +    */
  +    private boolean verifyEnum (Vector enum){
  +        /* REVISIT: won't work for list datatypes in some cases: */
  +        if ((fFacetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0) {
  +            for (Enumeration e = enum.elements() ; e.hasMoreElements() ;) {
  +                if (fEnumeration.contains(e.nextElement()) == false) {
  +                    return false;                             
  +                }
  +            }
           }
  +        return true;
       }
  -
   
  -    private void checkContent( String content,  Object state, String pattern, Vector enum ) throws InvalidDatatypeValueException
  +    /**
  +     * validate if the content is valid against base datatype and facets (if any) 
  +     * 
  +     * @param content A string containing the content to be validated
  +     * @param pattern: true if pattern facet was applied, false otherwise
  +     * @param enumeration enumeration facet
  +     * @exception throws InvalidDatatypeException if the content is not valid
  +     */
  +    private void checkContentEnum( String content,  Object state, boolean pattern, Vector enumeration ) throws InvalidDatatypeValueException
       {
  +        // for UnionDatatype we have to wait till the union baseValidators are known, thus
  +        // if the content is valid "against" ListDatatype, but pattern was applied - report an error. To do so we pass @param pattern;
  +        // pass @param enumeration so that when base Datatype is known, we would validate enumeration/content
  +        // against value space as well
           int index = -1; //number of validators
           boolean valid=false; 
           DatatypeValidator currentDV = null;
  -        while ( (fValidatorsSize-1) > index++ ) {  //check content against each validator in Union     
  -            currentDV =  (DatatypeValidator)this.fBaseValidators.elementAt(index);
  -            if ( valid ) {//content is valid
  -                break;
  +        if (fBaseValidator !=null) {  //restriction  of union datatype
  +            if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
  +                if ( fRegex == null || fRegex.matches( content) == false )
  +                    throw new InvalidDatatypeValueException("Value '"+content+
  +                    "' does not match regular expression facet '" + fPattern + "'." );
  +                pattern = true;
               }
  +
  +            if (enumeration!=null) {
  +                if (!verifyEnum(enumeration)) {
  +                    throw new InvalidDatatypeValueException("Enumeration '" +enumeration+"' for value '" +content+
  +                    "' is based on enumeration '"+fEnumeration+"'");
  +                }
  +            }
  +            else {
  +                enumeration = (fEnumeration!=null) ? fEnumeration : null;
  +            }
  +            ((UnionDatatypeValidator)this.fBaseValidator).checkContentEnum( content, state, pattern, enumeration  );
  +            return;
  +        }
  +        // native union type
  +        while ( (fValidatorsSize-1) > index++ ) {  
  +
  +            // check content against each base validator in Union
  +            // report an error only in case content is not valid against all base datatypes.
  +            currentDV =  (DatatypeValidator)this.fBaseValidators.elementAt(index);
  +            if ( valid ) break;
               try {
                   if ( currentDV instanceof ListDatatypeValidator ) {
  -                    if ( pattern != null ) {
  +                    if ( pattern ) {
                           throw new InvalidDatatypeValueException("Facet \"Pattern\" can not be applied to a list datatype" );  
  -                    } else if ( enum != null ) {  //Check each token against enumeration  
  -                        StringTokenizer parsedList = new StringTokenizer( content );
  -                        String token = null;
  -                        while ( parsedList.hasMoreTokens() ) {       //Check each token in list against base type
  -                            token = parsedList.nextToken();
  -                            if ( enum.contains( token ) == false ) {
  -                                throw new InvalidDatatypeValueException("Value '"+
  -                                                                        content+"' must be one of "+enum);
  -                            }
  -                        }
                       }
  -                    ((ListDatatypeValidator)currentDV).validate( content, state );
  +                    ((ListDatatypeValidator)currentDV).checkContentEnum( content, state, enumeration );
                   }
  -
                   else if ( currentDV instanceof UnionDatatypeValidator ) {
  -                    ((UnionDatatypeValidator)currentDV).checkContent( content, state, pattern, enum );
  -                } else {
  -                    if ( enum != null ) {
  -                        if ( enum.contains( content ) == false )
  -                            throw new InvalidDatatypeValueException("Value '"+
  -                                                                    content+"' must be one of " 
  -                                                                    + enum);
  -
  +                    ((UnionDatatypeValidator)currentDV).checkContentEnum( content, state, pattern, enumeration );
  +                }
  +                else {
  +                    if (enumeration!=null) {
  +                        if (currentDV instanceof DecimalDatatypeValidator) {
  +                            ((DecimalDatatypeValidator)currentDV).checkContentEnum(content, state, enumeration);
  +                        }
  +                        else if (currentDV instanceof FloatDatatypeValidator) {
  +                            ((FloatDatatypeValidator)currentDV).checkContentEnum(content, state, enumeration);
  +                        }
  +                        else if (currentDV instanceof DoubleDatatypeValidator) {
  +                            ((DoubleDatatypeValidator)currentDV).checkContentEnum(content, state, enumeration);
  +                        }
  +                        else {
  +                            if (enumeration.contains( content ) == false) {
  +                                throw new InvalidDatatypeValueException("Value '"+content+ "' must be one of "+ enumeration);
  +                            }
  +                            ((DatatypeValidator)currentDV).validate( content, state );
  +                        }   
                       }
  -                    ((DatatypeValidator)currentDV).validate( content, state );
  +                    else {
  +                        ((DatatypeValidator)currentDV).validate( content, state );
  +                    }
                   }
                   valid=true;
   
  -            } catch ( InvalidDatatypeValueException e ) {
  -                //REVIST: is it the right way to record error messages?
  -                if ( errorMsg == null ) {
  -                    errorMsg = new StringBuffer();
  -                }
  -                errorMsg.append('\n');
  -                errorMsg.append(e.getMessage());
  -                valid=false;
  +            }
  +            catch ( InvalidDatatypeValueException e ) {
               }
           }
           if ( !valid ) {
  -            throw new InvalidDatatypeValueException( this.errorMsg.toString());  
  +            throw new InvalidDatatypeValueException( "Content '"+content+"' does not match any union types" );  
           }
       }
  -
  -
   
   
       private void setBasetype( DatatypeValidator base) {