KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > schema > validation > ValidatingSchemaHandler


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.schema.validation;
24
25 import java.net.MalformedURLException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.StringTokenizer JavaDoc;
30
31 import org.xml.sax.*;
32 import org.xml.sax.helpers.AttributesImpl JavaDoc;
33 import org.xquark.schema.*;
34 import org.xquark.schema.datatypes.PrimitiveType;
35 import org.xquark.schema.datatypes.QName;
36 import org.xquark.util.NamespaceContextHandler;
37
38 public class ValidatingSchemaHandler extends NamespaceContextHandler implements ValidationContextProvider {
39     private static final String JavaDoc RCSRevision = "$Revision: 1.4 $";
40     private static final String JavaDoc RCSName = "$Name: $";
41
42     private SchemaValidationContext svContext;
43     private SchemaManager manager;
44     private SchemaLocator locator;
45     private ContentIterator iterator = null;
46     private boolean nilElement = false;
47     private boolean afterStart = false;
48
49     private HashSet JavaDoc namespaces = new HashSet JavaDoc();
50
51     private StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
52     private AttributesImpl JavaDoc attributes = new AttributesImpl JavaDoc();
53     private boolean extendsInfoset = false;
54     private boolean strictAssess = true;
55
56     private boolean debug = false;
57
58     private Locator docLocator = null;
59     private String JavaDoc defaultDocumentBase = null;
60     private String JavaDoc documentBase = null;
61     private URL JavaDoc base = null;
62
63     private StringBuffer JavaDoc errBuffer = new StringBuffer JavaDoc();
64     private boolean isCharactersValid = true;
65     private String JavaDoc errCode = null;
66     private ElementDeclaration errDecl = null;
67     private Type errType = null;
68
69     public ValidatingSchemaHandler(SchemaValidationContext svContext) {
70         this(svContext, svContext, true);
71     }
72
73     public ValidatingSchemaHandler(SchemaValidationContext svContext, boolean strict) {
74         this(svContext, svContext, strict);
75     }
76
77     public ValidatingSchemaHandler(SchemaValidationContext svContext, SchemaLocator locator) {
78         this(svContext, locator, true);
79     }
80
81     public ValidatingSchemaHandler(SchemaValidationContext svContext, SchemaLocator locator, boolean strict) {
82         super();
83         this.svContext = svContext;
84         this.manager = svContext.getSchemaManager();
85         this.locator = locator;
86         strictAssess = strict;
87         iterator = new ElementTreeContentIterator(manager, strictAssess);
88     }
89
90     public void setDebug(boolean b) {
91         debug = b;
92     }
93
94     public boolean isDebug() {
95         return debug;
96     }
97
98     public void setDocumentLocator(Locator locator) {
99         docLocator = locator;
100         super.setDocumentLocator(locator);
101     }
102
103     public String JavaDoc getDocumentBase() {
104         if (documentBase != null)
105             return documentBase;
106         else
107             return defaultDocumentBase;
108     }
109
110     public void setDocumentBase(String JavaDoc documentBase) {
111         defaultDocumentBase = documentBase;
112     }
113
114     public java.util.Map JavaDoc getNotationDeclarations() {
115         return null;
116     }
117
118     public void startDocument() throws SAXException {
119         super.startDocument();
120         iterator = new ElementTreeContentIterator(manager, strictAssess);
121         nilElement = false;
122         buffer.setLength(0);
123         documentBase = defaultDocumentBase;
124         if (docLocator != null && docLocator.getSystemId() != null)
125             documentBase = docLocator.getSystemId();
126         if (documentBase != null) {
127             try {
128                 base = new URL JavaDoc(documentBase);
129             } catch (MalformedURLException JavaDoc ex) {
130                 //reportError(new SAXParseException("Invalid document base: "+documentBase, docLocator));
131
}
132         }
133         namespaces.clear();
134         svContext.reset(this);
135         locator.clearSchemaLocations();
136     }
137
138     public void endDocument() throws SAXException {
139         documentBase = null;
140         base = null;
141         super.endDocument();
142     }
143
144     public void startElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName, Attributes atts)
145         throws SAXException {
146         if (debug)
147             System.err.println("startElement: " + localName);
148
149         // test if there is an error in precedent element
150
if (!isCharactersValid) {
151             isCharactersValid = true;
152             if (errCode.indexOf("elt") == -1)
153                 invalidValue(errBuffer.toString(), errDecl, errType, new SchemaException(errCode, errType));
154             else
155                 invalidValue(errBuffer.toString(), errDecl, errType, new SchemaException(errCode, errDecl));
156             errBuffer.setLength(0);
157         }
158
159         // Normalize empty namespace to null
160
String JavaDoc ns = null;
161         if (namespaceURI != null && namespaceURI.length() == 0)
162             ns = null;
163         else
164             ns = namespaceURI;
165
166         // Retrieves any schema locations specified in attributes
167
addSchemaLocations(atts);
168         // Add namespace to list of encountered namespaces (used to avoid schema locations appearing after ns)
169
namespaces.add(ns);
170         // Retrieve enclosing element info
171
Type type = svContext.getElementType();
172         ElementDeclaration matchedDecl = svContext.getElementDeclaration();
173         // This is applied to the enclosing element
174
if (nilElement) {
175             // unexpected element
176
invalidElement("cvc-elt.3.2.1", matchedDecl);
177             nilElement = false;
178         }
179
180         svContext.pushElementInfoset(ns, localName);
181         Type localType = null;
182         String JavaDoc xsiType = atts.getValue(SchemaConstants.XSI_URI, SchemaConstants.XSI_TYPE_ATTR);
183         // Used to hold a type resolution exception until the matched declaration is known
184
SchemaException typeResolutionException = null;
185         if (xsiType != null) {
186             try {
187                 localType = resolveTypeRef(xsiType);
188             } catch (SchemaException se) {
189                 typeResolutionException = se;
190             }
191         }
192
193         // Load schema if needed
194
try {
195             manager.loadSchema(locator, ns);
196         } catch (SAXException ex) {
197             reportInvalidSchemaError(ns, ex);
198         }
199
200         try {
201             iterator.startElement(ns, localName, localType, xsiType != null);
202         } catch (SchemaException se) {
203             // matchedDecl refers to the enclosing element
204
invalidContent(localName, matchedDecl, type, se);
205         }
206
207         // use the newly found validation info
208
type = iterator.getType();
209         matchedDecl = (ElementDeclaration) iterator.getMatchedDeclaration();
210
211         // Handle pending exception on local type resolution
212
if (typeResolutionException != null) {
213             typeResolutionException.setInvalidObject(matchedDecl);
214             invalidType(xsiType, typeResolutionException);
215         }
216
217         // Check process contents type
218
int process = iterator.getProcessContents();
219         if (strictAssess && process == SchemaConstants.STRICT && matchedDecl == null && type == null) {
220             invalidElement("cvc-assess-elt.1.1", null);
221             invalidElement("cvc-assess-elt.1.2", null);
222         }
223
224         // check if it's a nillable element
225
nilElement =
226             SchemaConstants.TRUE_VALUE.equals(atts.getValue(SchemaConstants.XSI_URI, SchemaConstants.XSI_NIL_ATTR));
227         if (nilElement && matchedDecl != null) {
228             if (!matchedDecl.isNillable()) {
229                 // Illegal nil element
230
invalidElement("cvc-elt.3.1", matchedDecl);
231             }
232             if (matchedDecl.getFixedValue() != null) {
233                 invalidElement("cvc-elt.3.2.2", matchedDecl);
234             }
235         }
236         svContext.initElementValidationInfo(matchedDecl, type, nilElement, process);
237         atts = validateAttributes(matchedDecl, type, atts);
238         super.startElement(namespaceURI, localName, qName, atts);
239         // Used to handle mixed case
240
// (normalized value is buffered only when element has no children)
241
afterStart = true;
242         buffer.setLength(0);
243     }
244
245     private void addSchemaLocations(Attributes atts) throws SAXException {
246         String JavaDoc schemaLocations = atts.getValue(SchemaConstants.XSI_URI, SchemaConstants.XSI_SCHEMA_LOCATION_ATTR);
247         String JavaDoc noNamespaceSchemaLocation =
248             atts.getValue(SchemaConstants.XSI_URI, SchemaConstants.XSI_NO_NAMESPACE_SCHEMA_LOCATION_ATTR);
249         if (schemaLocations != null) {
250             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(schemaLocations);
251             while (tok.hasMoreTokens()) {
252                 String JavaDoc ns = tok.nextToken();
253                 if (namespaces.contains(ns)) {
254                     String JavaDoc errMsg =
255                         "Location information for schema " + ns + " cannot appear after assessment has begun";
256                     throw new SAXException(errMsg);
257                 }
258                 if (!tok.hasMoreTokens()) {
259                     String JavaDoc errMsg = "Odd number of values in schemaLocation attribute. " + schemaLocations;
260                     throw new SAXException(errMsg);
261                 }
262                 String JavaDoc loc = tok.nextToken();
263                 URL JavaDoc uri = null;
264                 try {
265                     uri = new URL JavaDoc(base, loc);
266                     locator.addSchemaLocation(ns, uri.toString());
267                 } catch (MalformedURLException JavaDoc ex) {
268                     // if invalid URI, ignore it
269
}
270             }
271         }
272         if (noNamespaceSchemaLocation != null) {
273             if (namespaces.contains(null)) {
274                 String JavaDoc errMsg =
275                     "Location information for schema without namespace cannot appear after assessment has begun";
276                 throw new SAXException(errMsg);
277             }
278             URL JavaDoc uri = null;
279             try {
280                 uri = new URL JavaDoc(base, noNamespaceSchemaLocation);
281                 locator.addSchemaLocation(null, uri.toString());
282             } catch (MalformedURLException JavaDoc ex) {
283                 // if invalid URI, ignore it
284
}
285         }
286     }
287
288     private Type resolveTypeRef(String JavaDoc xsiType) throws SchemaException, SAXException {
289         SimpleType validator = manager.getQNameType();
290         xsiType = validator.normalizedValue(xsiType);
291         QName qName = null;
292         try {
293             qName = (QName) validator.convert(xsiType, false, this);
294         } catch (SchemaException se) {
295             throw new SchemaException("cvc-elt.4.1", se);
296         }
297         String JavaDoc uri = qName.getNamespaceURI();
298         String JavaDoc typeName = qName.getLocalName();
299         Schema schema = null;
300         Type result = null;
301         try {
302             schema = manager.loadSchema(locator, uri);
303         } catch (SAXException ex) {
304             reportInvalidSchemaError(uri, ex);
305         }
306         if (schema != null)
307             result = schema.getType(typeName);
308         if (result == null) {
309             throw new SchemaException("cvc-elt.4.2", new SchemaException("cvc-resolve-instance.1", (Object JavaDoc) xsiType));
310         } else {
311             return result;
312         }
313     }
314
315     public void characters(char[] ch, int start, int len) throws SAXException {
316         if (debug)
317             System.err.println("Characters: " + new String JavaDoc(ch, start, len));
318         if (len == 0)
319             return;
320
321         Type type = svContext.getElementType();
322         ElementDeclaration matchedDecl = svContext.getElementDeclaration();
323
324         // check nilElement
325
if (nilElement) {
326             // unexpected content
327
isCharactersValid = false;
328             errBuffer.append(ch, start, len);
329             errCode = "cvc-elt.3.2.1";
330             errDecl = matchedDecl;
331             errType = type;
332         }
333
334         if (type == null) {
335             super.characters(ch, start, len);
336             return;
337         }
338
339         switch (type.getContentType()) {
340             case SchemaConstants.EMPTY :
341                 isCharactersValid = false;
342                 errBuffer.append(ch, start, len);
343                 errCode = "cvc-complex-type.2.1";
344                 errDecl = matchedDecl;
345                 errType = type;
346                 super.characters(ch, start, len);
347                 break;
348             case SchemaConstants.ELEMENT_ONLY :
349                 boolean bWhitespaceOnly = true;
350                 for (int i = start; i < start + len; i++) {
351                     if (!PrimitiveType.isXMLWhitespace(ch[i]))
352                         bWhitespaceOnly = false;
353                 }
354                 if (bWhitespaceOnly) {
355                     super.ignorableWhitespace(ch, start, len);
356                 } else {
357                     isCharactersValid = false;
358                     errBuffer.append(ch, start, len);
359                     errCode = "cvc-complex-type.2.3";
360                     errDecl = matchedDecl;
361                     errType = type;
362                     super.characters(ch, start, len);
363                 }
364                 break;
365             case SchemaConstants.MIXED :
366                 if (afterStart && matchedDecl != null && matchedDecl.getFixedValue() != null)
367                     buffer.append(ch, start, len);
368                 super.characters(ch, start, len);
369                 break;
370             case SchemaConstants.TEXT_ONLY :
371                 // content type is simple type
372
buffer.append(ch, start, len);
373                 super.characters(ch, start, len);
374                 break;
375         }
376     }
377
378     public void endElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName) throws SAXException {
379         if (debug)
380             System.err.println("endElement: " + localName);
381
382         // test if there is an error in precedent element
383
if (!isCharactersValid) {
384             isCharactersValid = true;
385             if (errCode.indexOf("elt") == -1)
386                 invalidValue(errBuffer.toString(), errDecl, errType, new SchemaException(errCode, errType));
387             else
388                 invalidValue(errBuffer.toString(), errDecl, errType, new SchemaException(errCode, errDecl));
389             errBuffer.setLength(0);
390         }
391
392         Type type = svContext.getElementType();
393         ElementDeclaration matchedDecl = svContext.getElementDeclaration();
394
395         validateValue(type, matchedDecl);
396
397         try {
398             iterator.endElement(namespaceURI, localName);
399         } catch (SchemaException se) {
400             if (!nilElement)
401                 invalidContent(localName, matchedDecl, type, se);
402         }
403         try {
404             svContext.checkIdentityConstraints();
405         } catch (SchemaException se) {
406             reportValidationError(se);
407         }
408         // This step computes the final validity of the element
409
svContext.computeValidationInfo();
410
411         super.endElement(namespaceURI, localName, qName);
412
413         svContext.popElementInfoset();
414         nilElement = false;
415         afterStart = false;
416         buffer.setLength(0);
417     }
418
419     private void validateValue(Type type, ElementDeclaration matchedDecl) throws SAXException {
420         if (type == null
421             || type.getContentType() == SchemaConstants.EMPTY
422             || type.getContentType() == SchemaConstants.ELEMENT_ONLY
423             || nilElement) {
424             buffer.setLength(0);
425             return;
426         }
427         if (!afterStart) {
428             if (matchedDecl != null && matchedDecl.getFixedValue() != null)
429                 invalidElement("cvc-elt.5.2.2.1", matchedDecl);
430             buffer.setLength(0);
431             return;
432         }
433
434         Object JavaDoc actualValue = null;
435         if (buffer.length() == 0 && matchedDecl != null && matchedDecl.getValueConstraint() != null) {
436             // Use default value
437
String JavaDoc normalizedValue = matchedDecl.getValueConstraint();
438             if (type != matchedDecl.getType()) {
439                 try {
440                     normalizedValue = type.validateDefault(normalizedValue, this);
441                 } catch (SchemaException se) {
442                     invalidElement("cvc-elt.5.1.1", matchedDecl, se);
443                 }
444             }
445             if (extendsInfoset)
446                 super.characters(normalizedValue.toCharArray(), 0, normalizedValue.length());
447             buffer.append(normalizedValue);
448             if (type.getContentType() == SchemaConstants.TEXT_ONLY) {
449                 try {
450                     actualValue = checkValueValid(type.getValueType(), buffer, -1);
451                     svContext.setSchemaSpecified(-1, true);
452                 } catch (SchemaException se) {
453                     invalidElement("cvc-elt.5.1.2", matchedDecl, se);
454                 }
455             }
456         } else {
457             // use infoset
458
if (type.getContentType() == SchemaConstants.TEXT_ONLY) {
459                 try {
460                     actualValue = checkValueValid(type.getValueType(), buffer, -1);
461                     svContext.setSchemaSpecified(-1, false);
462                 } catch (SchemaException se) {
463                     invalidValue(buffer.toString(), matchedDecl, type, se);
464                 }
465                 if (actualValue != null && matchedDecl != null && matchedDecl.getFixedValue() != null) {
466                     if (!matchedDecl.getFixedValue().equals(type.toXMLString(actualValue)))
467                         invalidValue(
468                             buffer.toString(),
469                             matchedDecl,
470                             type,
471                             new SchemaException("cvc-elt.5.2.2.2.2", matchedDecl));
472                 }
473             } else if (
474                 matchedDecl != null
475                     && matchedDecl.getFixedValue() != null
476                     && !buffer.toString().equals(matchedDecl.getFixedValue())) {
477                 invalidValue(
478                     buffer.toString(),
479                     matchedDecl,
480                     type,
481                     new SchemaException("cvc-elt.5.2.2.2.1", matchedDecl));
482             }
483         }
484
485         // check if this element is defined in IdentityConstraint
486
if (actualValue != null && matchedDecl != null) {
487             try {
488                 svContext.checkKeyValue(actualValue);
489             } catch (SchemaException se) {
490                 reportValidationError("Error while processing value -> '" + actualValue + "'", se);
491             }
492         }
493     }
494
495     /**
496      * This method modifies its value parameter
497      */

498     private Object JavaDoc checkValueValid(SimpleType type, StringBuffer JavaDoc value, int attrIndex) throws SchemaException {
499         ValidationInfo info = type.validate(value, true, this);
500         SimpleType realType = info.getValidationType();
501         Object JavaDoc result = info.getActualValue();
502         if (realType != type)
503             svContext.setMemberType(attrIndex, realType);
504         svContext.setNormalizedValue(attrIndex, info.getNormalizedValue());
505         svContext.setActualValue(attrIndex, result);
506         return result;
507     }
508
509     private Attributes validateAttributes(ElementDeclaration matchedDecl, Type type, Attributes atts)
510         throws SAXException {
511         if (atts == null)
512             return null;
513         if (type == null || type.isSimpleType()) {
514             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
515             attributes.clear();
516             for (int i = 0; i < atts.getLength(); i++) {
517                 String JavaDoc namespace = atts.getURI(i);
518                 String JavaDoc localName = atts.getLocalName(i);
519                 String JavaDoc attrValue = atts.getValue(i);
520                 attributes.addAttribute(namespace, localName, atts.getQName(i), atts.getType(i), attrValue);
521                 if (SchemaConstants.XMLNS_URI.equals(namespace) || SchemaConstants.XMLNS_PREFIX.equals(localName))
522                     continue;
523                 AttributeDeclaration attrDecl = null;
524                 if (!SchemaConstants.XSI_URI.equals(namespace)) {
525                     if (namespace.length() == 0)
526                         namespace = null;
527                     if (type != null) {
528                         invalidAttribute(
529                             namespace,
530                             localName,
531                             atts.getValue(i),
532                             matchedDecl,
533                             type,
534                             new SchemaException("cvc-type.3.1.1", type));
535                     } else {
536                         Schema schema = null;
537                         try {
538                             schema = manager.loadSchema(locator, namespace);
539                         } catch (SAXException ex) {
540                             //reportInvalidSchemaError(namespace, ex);
541
}
542                         if (schema != null)
543                             attrDecl = schema.getAttributeDeclaration(localName);
544                     }
545                 } else {
546                     attrDecl = manager.getAttributeDeclaration(namespace, localName);
547                     if (attrDecl == null) {
548                         invalidAttribute(
549                             namespace,
550                             localName,
551                             attrValue,
552                             matchedDecl,
553                             null,
554                             new SchemaException("cvc-assess-attr.1", (Object JavaDoc) null));
555                     }
556                 }
557                 int index = svContext.addAttributePSVI(namespace, localName, attrDecl, true);
558                 if (attrDecl != null) {
559                     buffer.setLength(0);
560                     buffer.append(attrValue);
561                     Object JavaDoc actualValue = validateAttribute(matchedDecl, null, attrDecl, buffer, index);
562                     if (actualValue != null) {
563                         svContext.setSchemaSpecified(index, false);
564                         attributes.setValue(i, buffer.toString());
565                         if (attrDecl.getFixedValue() != null) {
566                             Type attrType = attrDecl.getType();
567                             if (!attrDecl.getFixedValue().equals(attrType.toXMLString(actualValue))) {
568                                 SchemaException attributeException = new SchemaException("cvc-attribute.4", attrDecl);
569                                 invalidAttribute(
570                                     namespace,
571                                     localName,
572                                     attrValue,
573                                     matchedDecl,
574                                     type,
575                                     attributeException);
576                                 svContext.addErrorCodes(index, attributeException);
577                             }
578                         }
579                     }
580                     svContext.computeAttributeValidationInfo(index);
581                 }
582             }
583             return attributes;
584         } else {
585             ComplexType ctype = (ComplexType) type;
586             boolean wildIDFound = false;
587             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
588             attributes.clear();
589             for (int i = 0; i < atts.getLength(); i++) {
590                 String JavaDoc namespace = atts.getURI(i);
591                 String JavaDoc localName = atts.getLocalName(i);
592                 String JavaDoc attrValue = atts.getValue(i);
593                 attributes.addAttribute(namespace, localName, atts.getQName(i), atts.getType(i), attrValue);
594                 if (SchemaConstants.XMLNS_URI.equals(namespace) || SchemaConstants.XMLNS_PREFIX.equals(localName))
595                     continue;
596                 AttributeDeclaration attrDecl = null;
597                 boolean strictWildcard = false;
598                 if (!SchemaConstants.XSI_URI.equals(namespace)) {
599                     if (namespace.length() == 0)
600                         namespace = null;
601                     attrDecl = ctype.getAttributeDeclaration(namespace, localName);
602                     if (attrDecl == null) {
603                         Wildcard wildcard = ctype.getAttributeWildcard();
604                         Schema schema = null;
605                         if (wildcard == null) {
606                             invalidAttribute(
607                                 namespace,
608                                 localName,
609                                 attrValue,
610                                 matchedDecl,
611                                 ctype,
612                                 new SchemaException("cvc-complex-type.3.2.1", ctype));
613                         } else if (!wildcard.isAllowed(namespace)) {
614                             SchemaException wildEx =
615                                 new SchemaException(wildcard.checkNamespaceAllowed(namespace), wildcard);
616                             invalidAttribute(
617                                 namespace,
618                                 localName,
619                                 attrValue,
620                                 matchedDecl,
621                                 ctype,
622                                 new SchemaException("cvc-complex-type.3.2.2", ctype, wildEx));
623                         } else if (wildcard.getProcessContents() != SchemaConstants.SKIP) {
624                             try {
625                                 schema = manager.loadSchema(locator, namespace);
626                             } catch (SAXException ex) {
627                                 reportInvalidSchemaError(namespace, ex);
628                             }
629                             if (schema != null)
630                                 attrDecl = schema.getAttributeDeclaration(localName);
631                             if (wildcard.getProcessContents() == SchemaConstants.STRICT) {
632                                 strictWildcard = true;
633                                 if (strictAssess && attrDecl == null) {
634                                     invalidAttribute(
635                                         namespace,
636                                         localName,
637                                         attrValue,
638                                         matchedDecl,
639                                         ctype,
640                                         new SchemaException("cvc-assess-attr.1", (Object JavaDoc) null));
641                                 }
642                             }
643                             boolean isID = attrDecl != null && attrDecl.getType().isDerivedFrom(manager.getIDType());
644                             if (isID) {
645                                 if (wildIDFound)
646                                     invalidAttribute(
647                                         namespace,
648                                         localName,
649                                         attrValue,
650                                         matchedDecl,
651                                         ctype,
652                                         new SchemaException("cvc-complex-type.5.1", ctype));
653                                 else {
654                                     if (ctype.getIDAttribute() != null)
655                                         invalidAttribute(
656                                             namespace,
657                                             localName,
658                                             attrValue,
659                                             matchedDecl,
660                                             ctype,
661                                             new SchemaException("cvc-complex-type.5.2", ctype));
662                                     wildIDFound = true;
663                                 }
664                             }
665                         }
666                     }
667                 } else {
668                     strictWildcard = true;
669                     attrDecl = manager.getAttributeDeclaration(namespace, localName);
670                     if (attrDecl == null) {
671                         invalidAttribute(
672                             namespace,
673                             localName,
674                             attrValue,
675                             matchedDecl,
676                             null,
677                             new SchemaException("cvc-assess-attr.1", (Object JavaDoc) null));
678                     }
679                 }
680                 int index = svContext.addAttributePSVI(namespace, localName, attrDecl, strictWildcard);
681                 if (attrDecl != null) {
682                     buffer.setLength(0);
683                     buffer.append(attrValue);
684                     Object JavaDoc actualValue = validateAttribute(matchedDecl, ctype, attrDecl, buffer, index);
685                     if (actualValue != null) {
686                         svContext.setSchemaSpecified(index, false);
687                         attributes.setValue(i, buffer.toString());
688                         if (attrDecl.getFixedValue() != null) {
689                             Type attrType = attrDecl.getType();
690                             if (!attrDecl.getFixedValue().equals(attrType.toXMLString(actualValue))) {
691                                 SchemaException attributeException = new SchemaException("cvc-attribute.4", attrDecl);
692                                 invalidAttribute(
693                                     namespace,
694                                     localName,
695                                     attrValue,
696                                     matchedDecl,
697                                     ctype,
698                                     attributeException);
699                                 svContext.addErrorCodes(index, attributeException);
700                             }
701                         }
702                     }
703                     svContext.computeAttributeValidationInfo(index);
704                 }
705             }
706             Iterator JavaDoc it = ctype.getRequiredAndDefaultAttributes().iterator();
707             while (it.hasNext()) {
708                 AttributeDeclaration decl = (AttributeDeclaration) it.next();
709                 String JavaDoc ns = decl.getNamespace();
710                 if (ns == null)
711                     ns = "";
712                 int index = atts.getIndex(ns, decl.getName());
713                 if (index == -1) {
714                     if (decl.getUse() == SchemaConstants.REQUIRED) {
715                         invalidContent(
716                             decl.getName(),
717                             matchedDecl,
718                             ctype,
719                             new SchemaException("cvc-complex-type.4", ctype));
720                     }
721                     if (decl.getValueConstraint() != null) {
722                         if (extendsInfoset)
723                             attributes.addAttribute(ns, decl.getName(), "", "CDATA", decl.getValueConstraint());
724                         int attrIndex = svContext.addAttributePSVI(decl.getNamespace(), decl.getName(), decl, true);
725                         buffer.setLength(0);
726                         buffer.append(decl.getValueConstraint());
727                         if (validateAttribute(matchedDecl, ctype, decl, buffer, attrIndex) != null)
728                             svContext.setSchemaSpecified(attrIndex, true);
729                     }
730                 }
731             }
732             return attributes;
733         }
734     }
735
736     private Object JavaDoc validateAttribute(
737         ElementDeclaration matchedDecl,
738         ComplexType ctype,
739         AttributeDeclaration decl,
740         StringBuffer JavaDoc buffer,
741         int index)
742         throws SAXException {
743         Object JavaDoc actualValue = null;
744         Type attrType = decl.getType();
745         try {
746             actualValue = checkValueValid(attrType.getValueType(), buffer, index);
747             if (ctype != null && decl == ctype.getNotationAttribute()) {
748                 svContext.setNotation(ctype.getSchema().getNotationDeclaration(buffer.toString()));
749             }
750         } catch (SchemaException se) {
751             SchemaException attributeException = new SchemaException("cvc-attribute.3", decl, se);
752             invalidAttribute(
753                 decl.getNamespace(),
754                 decl.getName(),
755                 buffer.toString(),
756                 matchedDecl,
757                 ctype,
758                 attributeException);
759             svContext.addErrorCodes(index, attributeException);
760         }
761         // check if this element is defined in IdentityConstraint
762
if (actualValue != null && !(SchemaConstants.XSI_URI.equals(decl.getNamespace()))) {
763             try {
764                 svContext.checkKeyValue(decl, actualValue);
765             } catch (SchemaException se) {
766                 reportValidationError("Error while processing value -> '" + actualValue + "'", se);
767             }
768         }
769         return actualValue;
770     }
771
772     private void invalidContent(String JavaDoc localName, ElementDeclaration decl, Type type, SchemaException se)
773         throws SAXException {
774         if (se.getErrorCode() == null && se.getExceptions() != null) {
775             java.util.Iterator JavaDoc it = se.getExceptions().iterator();
776             while (it.hasNext())
777                 invalidContent(localName, decl, type, (SchemaException) it.next());
778             return;
779         }
780         SchemaException exception = se;
781         if (!exception.getErrorCode().startsWith("cvc-elt")) {
782             if (!exception.getErrorCode().startsWith("cvc-type"))
783                 exception = new SchemaException("cvc-type.3.2", type, exception);
784             if (decl != null)
785                 exception = new SchemaException("cvc-elt.5.2.1", decl, exception);
786         }
787         svContext.addErrorCodes(-1, exception);
788         reportValidationError("Error while processing localName -> " + localName, exception);
789     }
790
791     private void invalidValue(String JavaDoc value, ElementDeclaration decl, Type type, SchemaException se)
792         throws SAXException {
793         SchemaException exception = se;
794         if (!exception.getErrorCode().startsWith("cvc-elt")) {
795             if (!exception.getErrorCode().startsWith("cvc-type")) {
796                 if (type.isSimpleType()) {
797                     exception = new SchemaException("cvc-type.3.1.3", type, exception);
798                 } else {
799                     if (!exception.getErrorCode().startsWith("cvc-complex-type"))
800                         exception = new SchemaException("cvc-complex-type.2.2", type, exception);
801                     exception = new SchemaException("cvc-type.3.2", type, exception);
802                 }
803             }
804             if (decl != null)
805                 exception = new SchemaException("cvc-elt.5.2.1", decl, exception);
806         }
807         svContext.addErrorCodes(-1, exception);
808         reportValidationError("Error while processing value -> '" + value + "'", exception);
809     }
810
811     private void invalidAttribute(
812         String JavaDoc namespace,
813         String JavaDoc localName,
814         String JavaDoc value,
815         ElementDeclaration decl,
816         Type type,
817         SchemaException se)
818         throws SAXException {
819         SchemaException exception = se;
820         if (type != null && !exception.getErrorCode().startsWith("cvc-elt")) {
821             if (!exception.getErrorCode().startsWith("cvc-type")) {
822                 if (!type.isSimpleType()) {
823                     if (!exception.getErrorCode().startsWith("cvc-complex-type"))
824                         exception = new SchemaException("cvc-complex-type.3.1", type, exception);
825                     exception = new SchemaException("cvc-type.3.2", type, exception);
826                 }
827             }
828             if (decl != null)
829                 exception = new SchemaException("cvc-elt.5.2.1", decl, exception);
830         }
831         svContext.addErrorCodes(-1, exception);
832         String JavaDoc message = "Error while processing attribute -> ";
833         if (namespace != null && namespace.length() > 0) {
834             String JavaDoc prefix = getPrefix(namespace);
835             if (prefix != null && prefix.length() > 0)
836                 message += prefix + ":";
837         }
838         message += localName + "=\"" + value + "\"";
839         reportValidationError(message, exception);
840     }
841
842     private void invalidType(String JavaDoc type, SchemaException exception) throws SAXException {
843         svContext.addErrorCodes(-1, exception);
844         String JavaDoc message = "Error while resolving type -> " + type;
845         reportValidationError(message, exception);
846     }
847
848     private void invalidElement(String JavaDoc errCode, Object JavaDoc object) throws SAXException {
849         invalidElement(new SchemaException(errCode, object));
850     }
851
852     private void invalidElement(String JavaDoc errCode, Object JavaDoc object, SchemaException e) throws SAXException {
853         invalidElement(new SchemaException(errCode, object, e));
854     }
855
856     private void invalidElement(SchemaException se) throws SAXException {
857         svContext.addErrorCodes(-1, se);
858         reportValidationError(se);
859     }
860
861     private void reportInvalidSchemaError(String JavaDoc namespace, SAXException ex) throws SAXException {
862         reportError(new SAXParseException("Invalid schema for namespace {" + namespace + "}", docLocator, ex));
863     }
864
865     private void reportValidationError(SchemaException se) throws SAXException {
866         reportValidationError(null, se);
867     }
868
869     private void reportValidationError(String JavaDoc message, SchemaException se) throws SAXException {
870         if (message != null)
871             message += "\n" + se.getMessage();
872         reportError(new SAXParseException(message, docLocator, se));
873     }
874
875     private void reportError(SAXParseException ex) throws SAXException {
876         if (getPluggedErrorHandler() != null) {
877             getPluggedErrorHandler().error(ex);
878         }
879     }
880
881 }
882
Popular Tags