KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999, 2000, 2001 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 import java.lang.reflect.Constructor JavaDoc;
60 import java.lang.reflect.InvocationTargetException JavaDoc;
61 import java.util.Hashtable JavaDoc;
62 import java.util.Vector JavaDoc;
63
64 import org.enhydra.apache.xerces.validators.schema.SchemaSymbols;
65
66
67 /**
68  *
69  * This class implements a factory of datatype validators. Internally the
70  * DatatypeValidators are kept in three registries:<BR>
71  * (i) DTDRegistry - stores DTD datatype validators
72  * <ii> SchemaRegistry - stores Schema datatype validators
73  * <iii> UserDefinedRegistry - stores Schema user defined datatypes.
74  * <BR>
75  * The above registries will be initialized on demand (for XML document with a DTD, only
76  * DTDRegistry will be initialized).
77  * <BR>
78  * <B>Note: </B>Between multiple parse() calls, only _user_defined_ registry will be reset.
79  * DTD registry and schema registry are initialized only once and are kept for the *life-time* of the parser .
80  * <BR>
81  * This implementation uses a Hahtable as a registry table but future implementation
82  * should use a lighter object, maybe a Map class ( not use a derived Map class
83  * because of JDK 1.1.8 no supporting Map).<BR>
84  * <BR>
85  * As the Parser parses an instance document it knows if validation needs
86  * to be checked. If no validation is necessary we should not instantiate a
87  * DatatypeValidatorFactoryImpl.<BR>
88  * <BR>
89  *
90  * @author Elena Litani
91  * @author Jeffrey Rodriguez
92  * @author Mark Swinkles - List Validation refactoring
93  * @version $Id: DatatypeValidatorFactoryImpl.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
94  */

95 public class DatatypeValidatorFactoryImpl implements DatatypeValidatorFactory {
96
97     private static final boolean fDebug = false;
98     private Hashtable JavaDoc fRegistry;
99     private Hashtable JavaDoc fDTDDatatypeRegistry;
100     private Hashtable JavaDoc fSchemaDatatypeRegistry;
101
102     // 0 -> not expanded, 1-> dtd registry ready, 2 -> schema registry ready
103
private byte fRegistryExpanded = 0;
104
105
106     // fSchemaValidation allows to determine between different parse() calls
107
// what registy can be accessable (e.g only DTDRegistry)
108
// 0 -> dtd validation, 1->schema validation
109
private byte fSchemaValidation = 0;
110
111     public DatatypeValidatorFactoryImpl() {
112         // registry for user-defined datatypes
113
fRegistry = new Hashtable JavaDoc(30);
114
115         // schema has total of 44 datatypes: primitive and derived
116
// note: for schema validation we always instantiate DTDDatatypes as well..
117
fSchemaDatatypeRegistry = new Hashtable JavaDoc (40);
118         // dtd has total of 9 datatypes
119
fDTDDatatypeRegistry = new Hashtable JavaDoc (10);
120     }
121
122     /**
123      * Initializes fDTDRegistry with (9) DTD related datatypes .
124      */

125     public void initializeDTDRegistry() {
126
127         //Register Primitive Datatypes
128

129         if ( fRegistryExpanded == 0 ) { //Core datatypes shared by DTD attributes and Schema
130
try {
131                 fDTDDatatypeRegistry.put("string", new StringDatatypeValidator() );
132                 fDTDDatatypeRegistry.put("ID", new IDDatatypeValidator());
133                 fDTDDatatypeRegistry.put("IDREF", new IDREFDatatypeValidator());
134                 fDTDDatatypeRegistry.put("ENTITY", new ENTITYDatatypeValidator());
135                 fDTDDatatypeRegistry.put("NOTATION", new NOTATIONDatatypeValidator());
136
137                 createDTDDatatypeValidator( "IDREFS", new IDREFDatatypeValidator(), null , true );
138
139                 createDTDDatatypeValidator( "ENTITIES", new ENTITYDatatypeValidator(), null, true );
140
141                 Hashtable JavaDoc facets = new Hashtable JavaDoc(2);
142                 facets.put(AbstractStringValidator.FACET_SPECIAL_TOKEN,
143                            AbstractStringValidator.SPECIAL_TOKEN_NMTOKEN);
144                 facets.put(SchemaSymbols.ELT_WHITESPACE, SchemaSymbols.ATT_COLLAPSE);
145                 createDTDDatatypeValidator("NMTOKEN", new StringDatatypeValidator(), facets, false );
146
147                 createDTDDatatypeValidator("NMTOKENS", getDatatypeValidator( "NMTOKEN" ), null, true );
148                 fRegistryExpanded = 1;
149             }
150             catch ( InvalidDatatypeFacetException ex ) {
151                 ex.printStackTrace();
152             }
153         }
154     }
155
156
157     /**
158      * Initializes fSchemaDatatypeRegistry with schema primitive and derived datatypes.
159      * See W3C Schema Datatype REC.
160      * If DTD registry is not initialized yet, this method will initialize it as well.
161      */

162     public void expandRegistryToFullSchemaSet() {
163         fSchemaValidation = 1;
164         //Register Primitive Datatypes
165
if ( fRegistryExpanded != 2 ) {
166             DatatypeValidator v;
167             try {
168                 //REVISIT: we want to create datatypes lazily
169
// esspecially for the types that are not often used
170
//
171
fSchemaDatatypeRegistry.put("anySimpleType", new AnySimpleType());
172                 fSchemaDatatypeRegistry.put("boolean", new BooleanDatatypeValidator());
173                 fSchemaDatatypeRegistry.put("float", new FloatDatatypeValidator());
174                 fSchemaDatatypeRegistry.put("double", new DoubleDatatypeValidator());
175                 fSchemaDatatypeRegistry.put("decimal", new DecimalDatatypeValidator());
176                 fSchemaDatatypeRegistry.put("hexBinary", new HexBinaryDatatypeValidator());
177                 fSchemaDatatypeRegistry.put("base64Binary", new Base64BinaryDatatypeValidator());
178                 fSchemaDatatypeRegistry.put("anyURI", new AnyURIDatatypeValidator());
179                 fSchemaDatatypeRegistry.put("QName", new QNameDatatypeValidator());
180                 fSchemaDatatypeRegistry.put("duration", new DurationDatatypeValidator());
181                 fSchemaDatatypeRegistry.put("gDay", new DayDatatypeValidator());
182                 fSchemaDatatypeRegistry.put("time", new TimeDatatypeValidator());
183                 fSchemaDatatypeRegistry.put("dateTime", new DateTimeDatatypeValidator());
184                 fSchemaDatatypeRegistry.put("date", new DateDatatypeValidator());
185                 fSchemaDatatypeRegistry.put("gMonthDay", new MonthDayDatatypeValidator());
186                 fSchemaDatatypeRegistry.put("gYearMonth", new YearMonthDatatypeValidator());
187                 fSchemaDatatypeRegistry.put("gYear", new YearDatatypeValidator());
188                 fSchemaDatatypeRegistry.put("gMonth", new MonthDatatypeValidator());
189
190                 if ( fRegistryExpanded == 0 ) {
191                     initializeDTDRegistry(); //Initialize common Schema/DTD Datatype validator set if not already initialized
192
}
193
194                 Hashtable JavaDoc facets = new Hashtable JavaDoc (2);
195                 facets.put(SchemaSymbols.ELT_WHITESPACE, SchemaSymbols.ATT_REPLACE);
196                 createSchemaDatatypeValidator("normalizedString", getDatatypeValidator("string"), facets, false);
197
198
199                 facets.clear();
200                 facets.put(SchemaSymbols.ELT_WHITESPACE, SchemaSymbols.ATT_COLLAPSE);
201                 createSchemaDatatypeValidator("token", getDatatypeValidator("string"), facets, false);
202
203                 facets.clear();
204                 facets.put(SchemaSymbols.ELT_WHITESPACE, SchemaSymbols.ATT_COLLAPSE);
205                 facets.put(SchemaSymbols.ELT_PATTERN , "([a-zA-Z]{2}|[iI]-[a-zA-Z]+|[xX]-[a-zA-Z]+)(-[a-zA-Z]+)*" );
206                 createSchemaDatatypeValidator("language", getDatatypeValidator("string") , facets, false );
207
208                 facets.clear();
209                 facets.put(SchemaSymbols.ELT_WHITESPACE, SchemaSymbols.ATT_COLLAPSE);
210                 facets.put(AbstractStringValidator.FACET_SPECIAL_TOKEN,
211                            AbstractStringValidator.SPECIAL_TOKEN_NAME);
212                 createSchemaDatatypeValidator("Name", getDatatypeValidator("string"), facets, false );
213
214                 facets.clear();
215                 facets.put(SchemaSymbols.ELT_WHITESPACE, SchemaSymbols.ATT_COLLAPSE);
216                 facets.put(AbstractStringValidator.FACET_SPECIAL_TOKEN,
217                            AbstractStringValidator.SPECIAL_TOKEN_NCNAME);
218                 createSchemaDatatypeValidator("NCName", getDatatypeValidator("string"), facets, false );
219
220                 facets.clear();
221                 facets.put(SchemaSymbols.ELT_FRACTIONDIGITS, "0");
222                 createSchemaDatatypeValidator("integer", getDatatypeValidator("decimal"), facets, false);
223
224
225                 facets.clear();
226                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE , "0" );
227                 createSchemaDatatypeValidator("nonPositiveInteger",
228                                               getDatatypeValidator("integer"), facets, false );
229
230
231                 facets.clear();
232                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE , "-1" );
233                 createSchemaDatatypeValidator("negativeInteger",
234                                               getDatatypeValidator( "nonPositiveInteger"), facets, false );
235
236                 facets.clear();
237                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE , "9223372036854775807");
238                 facets.put(SchemaSymbols.ELT_MININCLUSIVE, "-9223372036854775808");
239                 createSchemaDatatypeValidator("long", getDatatypeValidator( "integer"), facets, false );
240
241                 facets.clear();
242                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE , "2147483647");
243                 facets.put(SchemaSymbols.ELT_MININCLUSIVE, "-2147483648");
244                 createSchemaDatatypeValidator("int", getDatatypeValidator( "long"), facets,false );
245
246                 facets.clear();
247                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE , "32767");
248                 facets.put(SchemaSymbols.ELT_MININCLUSIVE, "-32768");
249                 createSchemaDatatypeValidator("short", getDatatypeValidator( "int"), facets, false );
250
251                 facets.clear();
252                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE , "127");
253                 facets.put(SchemaSymbols.ELT_MININCLUSIVE, "-128");
254                 createSchemaDatatypeValidator("byte",
255                                               getDatatypeValidator( "short"), facets, false );
256
257                 facets.clear();
258                 facets.put(SchemaSymbols.ELT_MININCLUSIVE, "0" );
259                 createSchemaDatatypeValidator("nonNegativeInteger",
260                                               getDatatypeValidator( "integer"), facets, false );
261
262                 facets.clear();
263                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE, "18446744073709551615" );
264                 createSchemaDatatypeValidator("unsignedLong",
265                                               getDatatypeValidator( "nonNegativeInteger"), facets, false );
266
267
268                 facets.clear();
269                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE, "4294967295" );
270                 createSchemaDatatypeValidator("unsignedInt",
271                                               getDatatypeValidator( "unsignedLong"), facets, false );
272
273
274                 facets.clear();
275                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE, "65535" );
276                 createSchemaDatatypeValidator("unsignedShort",
277                                               getDatatypeValidator( "unsignedInt"), facets, false );
278
279
280                 facets.clear();
281                 facets.put(SchemaSymbols.ELT_MAXINCLUSIVE, "255" );
282                 createSchemaDatatypeValidator("unsignedByte",
283                                               getDatatypeValidator( "unsignedShort"), facets, false );
284
285                 facets.clear();
286                 facets.put(SchemaSymbols.ELT_MININCLUSIVE, "1" );
287                 createSchemaDatatypeValidator("positiveInteger",
288                                               getDatatypeValidator( "nonNegativeInteger"), facets, false );
289
290                 // in the case of schema, ID/IDREF are of type NCNAME
291
((IDDatatypeValidator)getDatatypeValidator("ID")).setTokenType(AbstractStringValidator.SPECIAL_TOKEN_IDNCNAME);
292                 ((IDREFDatatypeValidator)getDatatypeValidator("IDREF")).setTokenType(AbstractStringValidator.SPECIAL_TOKEN_IDREFNCNAME);
293                 // set the NCName validator into QName validator
294
QNameDatatypeValidator.setNCNameValidator(getDatatypeValidator("NCName"));
295
296                 fRegistryExpanded = 2;
297             }
298             catch ( InvalidDatatypeFacetException ex ) {
299                 ex.printStackTrace();
300             }
301         }
302     }
303
304     /**
305      * An optimization option that we should write in the future is to separate the static list
306      * of Datatype Validators from the dynamic part where anonymous, and user derived datatype are
307      * kept, then when we resetRegistry only the dynamic part of the registry should be cleared.
308      * So we don't end up clearing the static part of the table over and over every time that we
309      * do a parse cycle.
310      */

311     public void resetRegistry() {
312         fRegistry.clear();
313         fSchemaValidation = 0;
314     }
315
316     public DatatypeValidator createDatatypeValidator(String JavaDoc typeName,
317                                                      DatatypeValidator base, Hashtable JavaDoc facets, boolean list ) throws InvalidDatatypeFacetException {
318         if ( base == null ) {
319             return null;
320         }
321         DatatypeValidator simpleType = createSchemaValidator(typeName, base, facets, list);
322         registerUserDefinedValidator(typeName, simpleType);
323         return simpleType;
324     }
325
326
327     public DatatypeValidator createDatatypeValidator(String JavaDoc typeName, Vector JavaDoc validators) {
328         DatatypeValidator simpleType = null;
329         if ( validators!=null ) {
330             simpleType = new UnionDatatypeValidator(validators);
331         }
332         if ( simpleType !=null ) {
333             registerUserDefinedValidator(typeName, simpleType);
334         }
335         return simpleType;
336     }
337
338
339     /**
340      * Searches different datatype registries depending on validation mode (schema or dtd)
341      *
342      * @param type
343      * @return
344      */

345     public DatatypeValidator getDatatypeValidator(String JavaDoc type) {
346         AbstractDatatypeValidator simpleType = null;
347         if ( type == null ) {
348             return null;
349         }
350         simpleType = (AbstractDatatypeValidator) fDTDDatatypeRegistry.get(type);
351         if ( simpleType == null && fSchemaValidation == 1 ) {
352             simpleType = (AbstractDatatypeValidator) fSchemaDatatypeRegistry.get(type);
353             if ( simpleType == null ) {
354                 return(DatatypeValidator) fRegistry.get(type);
355             }
356
357         }
358
359         return(DatatypeValidator)simpleType;
360
361     }
362
363
364     private DatatypeValidator createSchemaDatatypeValidator(String JavaDoc typeName,
365                                                             DatatypeValidator base, Hashtable JavaDoc facets, boolean list ) throws InvalidDatatypeFacetException {
366         DatatypeValidator primitive = createSchemaValidator(typeName, base, facets, list);
367         registerSchemaValidator(typeName, primitive);
368         return primitive;
369     }
370
371     private DatatypeValidator createDTDDatatypeValidator(String JavaDoc typeName,
372                                                          DatatypeValidator base, Hashtable JavaDoc facets, boolean list ) throws InvalidDatatypeFacetException {
373         DatatypeValidator primitive = createSchemaValidator(typeName, base, facets, list);
374         registerDTDValidator(typeName, primitive);
375         return primitive;
376     }
377
378     private DatatypeValidator createSchemaValidator (String JavaDoc typeName,
379                                                      DatatypeValidator base, Hashtable JavaDoc facets, boolean list ) throws InvalidDatatypeFacetException{
380
381         DatatypeValidator simpleType = null;
382         if ( list ) {
383             simpleType = new ListDatatypeValidator(base, facets, list);
384         }
385         else {
386             try {
387                 String JavaDoc value = (String JavaDoc)facets.get(SchemaSymbols.ELT_WHITESPACE);
388                 //for all datatypes other than string, we don't pass WHITESPACE Facet
389
//its value is always 'collapse' and cannot be reset by user
390

391                 if ( value != null && !(base instanceof StringDatatypeValidator) ) {
392                     if ( !value.equals(SchemaSymbols.ATT_COLLAPSE) )
393                         throw new InvalidDatatypeFacetException( "whiteSpace value '" + value +
394                                                                  "' for this type must be 'collapse'.");
395                     facets.remove(SchemaSymbols.ELT_WHITESPACE);
396                 }
397
398                 Class JavaDoc validatorDef = base.getClass();
399
400                 Class JavaDoc [] validatorArgsClass = new Class JavaDoc[] {
401                     org.enhydra.apache.xerces.validators.datatype.DatatypeValidator.class,
402                     java.util.Hashtable JavaDoc.class,
403                     boolean.class};
404
405                 Object JavaDoc [] validatorArgs = new Object JavaDoc[] { base, facets, Boolean.FALSE};
406                 Constructor JavaDoc validatorConstructor = validatorDef.getConstructor( validatorArgsClass );
407                 simpleType = ( DatatypeValidator ) createDatatypeValidator ( validatorConstructor, validatorArgs );
408             }
409             catch ( NoSuchMethodException JavaDoc e ) {
410                 e.printStackTrace();
411             }
412
413         }
414         return simpleType;
415     }
416
417     private void registerUserDefinedValidator (String JavaDoc typeName, DatatypeValidator simpleType) {
418         if ( simpleType != null ) {
419             fRegistry.put(typeName, simpleType);
420         }
421     }
422     private void registerSchemaValidator (String JavaDoc typeName, DatatypeValidator simpleType) {
423         if ( simpleType != null ) {
424             fSchemaDatatypeRegistry.put(typeName, simpleType);
425         }
426     }
427     private void registerDTDValidator (String JavaDoc typeName, DatatypeValidator simpleType) {
428         if ( simpleType != null ) {
429             fDTDDatatypeRegistry.put(typeName, simpleType);
430         }
431     }
432
433
434
435     private static Object JavaDoc createDatatypeValidator(Constructor JavaDoc validatorConstructor,
436                                                   Object JavaDoc[] arguments) throws InvalidDatatypeFacetException {
437         Object JavaDoc validator = null;
438         try {
439             validator = validatorConstructor.newInstance(arguments);
440         }
441         catch ( InstantiationException JavaDoc e ) {
442             if ( fDebug ) {
443                 e.printStackTrace();
444             }
445         }
446         catch ( IllegalAccessException JavaDoc e ) {
447             if ( fDebug ) {
448                 e.printStackTrace();
449             }
450         }
451         catch ( IllegalArgumentException JavaDoc e ) {
452             if ( fDebug ) {
453                 e.printStackTrace();
454             }
455         }
456         catch ( InvocationTargetException JavaDoc e ) {
457             if ( fDebug ) {
458                 System.out.println("!! The original error message is: " + e.getTargetException().getMessage() );
459                 e.getTargetException().printStackTrace();
460             }
461             else {
462                 throw new InvalidDatatypeFacetException( e.getTargetException().getMessage() );
463             }
464         }
465
466         return validator;
467     }
468
469 }
470
471
Popular Tags