KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > validators > datatype > ListDatatypeValidator


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.enhydra.apache.xerces.validators.datatype;
59
60 import java.util.Enumeration JavaDoc;
61 import java.util.Hashtable JavaDoc;
62 import java.util.NoSuchElementException JavaDoc;
63 import java.util.StringTokenizer JavaDoc;
64 import java.util.Vector JavaDoc;
65
66 import org.enhydra.apache.xerces.utils.regex.RegularExpression;
67 import org.enhydra.apache.xerces.validators.schema.SchemaSymbols;
68
69 /**
70  * StringValidator validates that XML content is a W3C string type.
71  * @author Elena Litani
72  * @author Jeffrey Rodriguez
73  * @author Mark Swinkles - List Validation refactoring
74  * @version $Id: ListDatatypeValidator.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
75  */

76 public class ListDatatypeValidator extends AbstractDatatypeValidator{
77     
78     private int fLength = 0;
79     private int fMaxLength = Integer.MAX_VALUE;
80     private int fMinLength = 0;
81     private Vector JavaDoc fEnumeration = null;
82
83     public ListDatatypeValidator () throws InvalidDatatypeFacetException{
84         this( null, null, false ); // Native, No Facets defined, Restriction
85

86     }
87
88     public ListDatatypeValidator ( DatatypeValidator base, Hashtable JavaDoc facets,
89     boolean derivedByList ) throws InvalidDatatypeFacetException {
90
91         fBaseValidator = base; // Set base type
92

93         if ( facets != null ){
94             for (Enumeration JavaDoc e = facets.keys(); e.hasMoreElements();) {
95                 String JavaDoc key = (String JavaDoc) e.nextElement();
96                 if ( key.equals(SchemaSymbols.ELT_LENGTH) ) {
97                     fFacetsDefined |= DatatypeValidator.FACET_LENGTH;
98                     String JavaDoc lengthValue = (String JavaDoc)facets.get(key);
99                     try {
100                         fLength = Integer.parseInt( lengthValue );
101                     } catch (NumberFormatException JavaDoc nfe) {
102                         throw new InvalidDatatypeFacetException("Length value '"+lengthValue+"' is invalid.");
103                     }
104                     if ( fLength < 0 )
105                         throw new InvalidDatatypeFacetException("Length value '"+lengthValue+"' must be a nonNegativeInteger.");
106
107                 }
108                 else if (key.equals(SchemaSymbols.ELT_MINLENGTH) ) {
109                     fFacetsDefined |= DatatypeValidator.FACET_MINLENGTH;
110                     String JavaDoc minLengthValue = (String JavaDoc)facets.get(key);
111                     try {
112                         fMinLength = Integer.parseInt( minLengthValue );
113                     } catch (NumberFormatException JavaDoc nfe) {
114                         throw new InvalidDatatypeFacetException("maxLength value '"+minLengthValue+"' is invalid.");
115                     }
116                 }
117                 else if (key.equals(SchemaSymbols.ELT_MAXLENGTH) ) {
118                     fFacetsDefined |= DatatypeValidator.FACET_MAXLENGTH;
119                     String JavaDoc maxLengthValue = (String JavaDoc)facets.get(key);
120                     try {
121                         fMaxLength = Integer.parseInt( maxLengthValue );
122                     } catch (NumberFormatException JavaDoc nfe) {
123                         throw new InvalidDatatypeFacetException("maxLength value '"+maxLengthValue+"' is invalid.");
124                     }
125                 }
126                 else if (key.equals(SchemaSymbols.ELT_ENUMERATION)) {
127                     fFacetsDefined |= DatatypeValidator.FACET_ENUMERATION;
128                     fEnumeration = (Vector JavaDoc)facets.get(key);
129                 }
130                 else if ( key.equals(SchemaSymbols.ELT_PATTERN) ) {
131                     fFacetsDefined |= DatatypeValidator.FACET_PATTERN;
132                     fPattern = (String JavaDoc)facets.get(key);
133                     if ( fPattern != null )
134                         fRegex = new RegularExpression(fPattern, "X");
135                 }
136                else {
137                 throw new InvalidDatatypeFacetException( getErrorString(DatatypeMessageProvider.ILLEGAL_LIST_FACET,
138                                                                         DatatypeMessageProvider.MSG_NONE, new Object JavaDoc[] { key }));
139                }
140             }
141             if (((fFacetsDefined & DatatypeValidator.FACET_LENGTH ) != 0 ) ) {
142                 if (((fFacetsDefined & DatatypeValidator.FACET_MAXLENGTH ) != 0 ) ) {
143                     throw new InvalidDatatypeFacetException(
144                     "It is an error for both length and maxLength to be members of facets." );
145                 } else if (((fFacetsDefined & DatatypeValidator.FACET_MINLENGTH ) != 0 ) ) {
146                     throw new InvalidDatatypeFacetException(
147                     "It is an error for both length and minLength to be members of facets." );
148                 }
149             }
150
151             if ( ( (fFacetsDefined & ( DatatypeValidator.FACET_MINLENGTH |
152             DatatypeValidator.FACET_MAXLENGTH) ) != 0 ) ) {
153                 if ( fMinLength > fMaxLength ) {
154                     throw new InvalidDatatypeFacetException( "Value of minLength = " + fMinLength +
155                     "must be greater that the value of maxLength" + fMaxLength );
156                 }
157             }
158
159             // check 4.3.5.c0 must: enumeration values from the value space of base
160
//REVISIT: we should try either to delay it till validate() or
161
// store enumeration values in _value_space
162
// otherwise we end up creating and throwing objects
163
if ( base != null &&
164                 (fFacetsDefined & DatatypeValidator.FACET_ENUMERATION) != 0 &&
165                 (fEnumeration != null) ) {
166                 int i = 0;
167                 try {
168                     for (; i < fEnumeration.size(); i++) {
169                         base.validate ((String JavaDoc)fEnumeration.elementAt(i), null);
170                     }
171                 } catch ( Exception JavaDoc idve ){
172                     throw new InvalidDatatypeFacetException( "Value of enumeration = '" + fEnumeration.elementAt(i) +
173                                                              "' must be from the value space of base.");
174                 }
175             }
176         }// End of Facets Setting
177
}
178
179
180
181
182     /**
183      * validate that a string is a W3C string type
184      *
185      * @param content A string containing the content to be validated
186      * @param list
187      * @exception throws InvalidDatatypeException if the content is
188      * not a W3C string type
189      * @exception InvalidDatatypeValueException
190      */

191     public Object JavaDoc validate(String JavaDoc content, Object JavaDoc state) throws InvalidDatatypeValueException
192     {
193         if ( content == null && state != null ) {
194             this.fBaseValidator.validate( content, state );//Passthrough setup information
195
//for state validators
196
} else {
197             checkContentEnum( content, state , null);
198         }
199         return null;
200     }
201
202
203     /**
204      *
205      * @return A Hashtable containing the facets
206      * for this datatype.
207      */

208     public Hashtable JavaDoc getFacets(){
209         return null;
210     }
211
212     public int compare( String JavaDoc value1, String JavaDoc value2 ){
213         if (fBaseValidator instanceof ListDatatypeValidator) { //derived by restriction
214
return ((ListDatatypeValidator)this.fBaseValidator).compare( value1, value2 );
215         }
216         // <list> datatype
217
StringTokenizer JavaDoc pList1 = new StringTokenizer JavaDoc( value1 );
218         StringTokenizer JavaDoc pList2 = new StringTokenizer JavaDoc( value2 );
219         int numberOfTokens = pList1.countTokens();
220         if (numberOfTokens < pList2.countTokens()) {
221             return -1;
222         }
223         else if (numberOfTokens > pList2.countTokens()) {
224             return 1;
225         }
226         else { //compare each token
227
int i=0;
228             while(i++<numberOfTokens) {
229                 if ( this.fBaseValidator != null ) {
230                     int returnValue = this.fBaseValidator.compare( pList1.nextToken(), pList2.nextToken());
231                     if (returnValue!=0) {
232                         return returnValue; //REVISIT: does it make sense to return -1 or +1..?
233
}
234                 }
235                 
236             }
237             return 0;
238         }
239     }
240
241     /**
242    * Returns a copy of this object.
243    */

244     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
245         ListDatatypeValidator newObj = null;
246         try {
247             newObj = new ListDatatypeValidator();
248
249             newObj.fLocale = this.fLocale;
250             newObj.fBaseValidator = this.fBaseValidator;
251             newObj.fLength = this.fLength;
252             newObj.fMaxLength = this.fMaxLength;
253             newObj.fMinLength = this.fMinLength;
254             newObj.fPattern = this.fPattern;
255             newObj.fEnumeration = this.fEnumeration;
256             newObj.fFacetsDefined = this.fFacetsDefined;
257         } catch ( InvalidDatatypeFacetException ex) {
258             ex.printStackTrace();
259         }
260         return newObj;
261     }
262
263     /**
264      * validate that a content is valid against base datatype and facets (if any)
265      *
266      * @param content A string containing the content to be validated
267      * @param state used with IDREF(s) datatypes
268      * @param enumeration enumeration facet
269      * @exception throws InvalidDatatypeException if the content is not valid
270      * @exception InvalidDatatypeValueException
271      */

272      protected void checkContentEnum( String JavaDoc content, Object JavaDoc state, Vector JavaDoc enumeration )
273                                 throws InvalidDatatypeValueException {
274             
275             //REVISIT: attemt to make enumeration to be validated against value space.
276
//a redesign of Datatypes might help to reduce complexity of this validation
277

278          StringTokenizer JavaDoc parsedList = new StringTokenizer JavaDoc( content );
279          int numberOfTokens = parsedList.countTokens();
280          if (fBaseValidator instanceof ListDatatypeValidator) {
281             //<simpleType name="fRestriction"><restriction base="fList">...</restriction></simpleType>
282
try {
283                 if ( (fFacetsDefined & DatatypeValidator.FACET_MAXLENGTH) != 0 ) {
284                     if ( numberOfTokens > fMaxLength ) {
285                         throw new InvalidDatatypeValueException("Value '"+content+
286                         "' with length ='"+ numberOfTokens + "' tokens"+
287                         "' exceeds maximum length facet of '"+fMaxLength+"' tokens.");
288                     }
289                 }
290                 if ( (fFacetsDefined & DatatypeValidator.FACET_MINLENGTH) != 0 ) {
291                     if ( numberOfTokens < fMinLength ) {
292                         throw new InvalidDatatypeValueException("Value '"+content+
293                         "' with length ='"+ numberOfTokens+ "' tokens" +
294                         "' is less than minimum length facet of '"+fMinLength+"' tokens." );
295                     }
296                 }
297
298                 if ( (fFacetsDefined & DatatypeValidator.FACET_LENGTH) != 0 ) {
299                     if ( numberOfTokens != fLength ) {
300                         throw new InvalidDatatypeValueException("Value '"+content+
301                         "' with length ='"+ numberOfTokens+ "' tokens" +
302                         "' is not equal to length facet of '"+fLength+"' tokens.");
303                     }
304                 }
305                 if (enumeration!=null) {
306                     if (!verifyEnum(enumeration)) {
307                         throw new InvalidDatatypeValueException(
308                                                getErrorString(DatatypeMessageProvider.NOT_ENUM_VALUE,
309                                                               DatatypeMessageProvider.MSG_NONE,
310                                                               new Object JavaDoc [] { enumeration}));
311                     }
312                 }else {
313                     enumeration = (fEnumeration!=null) ? fEnumeration : null;
314                 }
315                                       
316                 // enumeration must be passed till we know what "itemType" is
317
// to be able to validate against value space
318
((ListDatatypeValidator)this.fBaseValidator).checkContentEnum( content, state, enumeration );
319             } catch ( NoSuchElementException JavaDoc e ) {
320                 e.printStackTrace();
321             }
322         }
323         else {
324             //the case:
325
//<simpleType name="fList"><list itemType="float"/></simpleType>
326

327             if (enumeration !=null) {
328                 StringTokenizer JavaDoc eTokens = null; //temporary list of enumeration tokens
329
StringTokenizer JavaDoc cTokens = null; //list of content tokens
330
String JavaDoc token= null; //content token
331
String JavaDoc eToken= null; //enumeration token
332
boolean valid = true;
333
334                 int eSize = enumeration.size();
335                 Vector JavaDoc enumTemp = new Vector JavaDoc(); //temporary vector to store enumeration token
336
enumTemp.setSize(1);
337                 String JavaDoc currentEnumeration = null; //enum value: <enumeration value="1 2 3"/>
338

339                 for (int i=0;i<eSize;i++) { //loop through each enumeration
340
currentEnumeration = (String JavaDoc)enumeration.elementAt(i);
341                     eTokens = new StringTokenizer JavaDoc (currentEnumeration);
342                     valid = true;
343
344                     cTokens = (i==0)?parsedList:new StringTokenizer JavaDoc( content );
345                     
346                     if (numberOfTokens == eTokens.countTokens()) {
347                         try {
348                             //try string comparison first
349
if (currentEnumeration.equals(content)) {
350                                 for (int k=0; k<numberOfTokens;k++) { //validate against base type each token
351
if ( this.fBaseValidator != null ) {
352                                         this.fBaseValidator.validate( cTokens.nextToken(), state );
353                                     }
354                                 }
355                             } else { //content="1.0 2" ; enumeration = "1 2"
356
for (int j=0;j<numberOfTokens;j++) {
357                                     token = cTokens.nextToken();
358                                     eToken = eTokens.nextToken();
359                                     enumTemp.setElementAt(eToken,0);
360                                     //REVISIT: date/time enumeration support
361
if (fBaseValidator instanceof AbstractNumericValidator) {
362                                         ((AbstractNumericValidator)fBaseValidator).checkContentEnum(token, state, enumTemp);
363                                     } else {
364                                         if (!token.equals(eToken)) { //validate enumeration for all other types
365
throw new InvalidDatatypeValueException("Value '"+content+ "' must be one of "+enumeration);
366                                         }
367                                         this.fBaseValidator.validate( token, state );
368                                     }
369                                 }
370                             }
371                         } catch (InvalidDatatypeValueException e) {
372                             valid = false;
373                         }
374                     } else //numOfTokens in enumeration != numOfTokens in content
375
valid = false;
376                     if (valid) break;
377                 } //end for loop
378
if (!valid) {
379                     throw new InvalidDatatypeValueException("Value '"+content+ "' does not match list type");
380                 }
381             }//enumeration != null
382
else { //no enumeration
383
for (int k=0; k<numberOfTokens;k++) {
384                     if ( this.fBaseValidator != null ) {//validate against parent type if any
385
this.fBaseValidator.validate( parsedList.nextToken(), state );
386                     }
387                 }
388             }
389
390         } //end native list type
391

392     } //end checkContentEnum
393

394
395
396     // Private methods
397
/**
398     * check if enum is subset of fEnumeration
399     * enum 1: <enumeration value="1 2"/>
400     * enum 2: <enumeration value="1.0 2"/>
401     *
402     * @param enumeration facet
403     *
404     * @returns true if enumeration is subset of fEnumeration, false otherwise
405     */

406     private boolean verifyEnum (Vector JavaDoc enumer){
407
408         /* REVISIT: won't work for list datatypes in some cases: */
409         if ((fFacetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0) {
410             for (Enumeration JavaDoc e = enumer.elements() ; e.hasMoreElements() ;) {
411                 if (fEnumeration.contains(e.nextElement()) == false) {
412                     return false;
413                 }
414             }
415         }
416         return true;
417     }
418
419
420 }
421
422
Popular Tags