KickJava   Java API By Example, From Geeks To Geeks.

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


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.URL JavaDoc;
26 import java.util.*;
27
28 import org.xml.sax.InputSource JavaDoc;
29 import org.xml.sax.SAXException JavaDoc;
30 import org.xml.sax.XMLReader JavaDoc;
31 import org.xquark.schema.*;
32 import org.xquark.util.NamespaceContext;
33
34 public class SchemaValidationContext
35     extends DefaultSchemaLocator
36     implements NamespaceContext, PSVInfoSetProvider {
37     private static final String JavaDoc RCSRevision = "$Revision: 1.5 $";
38     private static final String JavaDoc RCSName = "$Name: $";
39
40     private SchemaManager manager;
41     private NamespaceContext nsContext = null;
42     private ArrayList infoset = new ArrayList(32);
43     private int level = 0;
44     private int validationContext = -1;
45     private HashSet IDSet = new HashSet();
46     private HashSet pendingRefs = new HashSet();
47
48     // load schema from namespace ? true, yes; false, no
49
private boolean bLoadSchemaFromNamespace = false;
50
51     /**
52      * Creates new SchemaValidationContext
53      */

54
55     public SchemaValidationContext() {
56         this(new SchemaManager());
57     }
58
59     public SchemaValidationContext(SchemaManager manager) {
60         this.manager = manager;
61         reset(null);
62     }
63
64     public void setLoadSchemaFromNamespace(boolean flag) {
65         bLoadSchemaFromNamespace = flag;
66     }
67
68     public boolean isLoadSchemaFromNamespace() {
69         return bLoadSchemaFromNamespace;
70     }
71
72     public InputSource JavaDoc resolveLocation(String JavaDoc namespace, URL JavaDoc location) {
73         if (!bLoadSchemaFromNamespace && location.toString().equals(namespace))
74             return null;
75         else
76             return super.resolveLocation(namespace, location);
77     }
78
79     public XMLReader JavaDoc getSchemaReader() throws SAXException JavaDoc {
80         // before gerSchemaReader, validate source
81
// source is a schmema input source
82
SchemaValidationContext context = new SchemaValidationContext();
83         ValidatingSchemaFilter filter =
84             new ValidatingSchemaFilter(super.getSchemaReader(), context, true);
85         return filter;
86         // return super.getSchemaReader();
87
}
88
89     public ElementPSVInfoset getCurrentInfoset() {
90         return getInfoset(level);
91     }
92
93     public ElementPSVInfoset getParentInfoset() {
94         return getInfoset(level - 1);
95     }
96
97     public ElementPSVInfoset getInfoset(ElementDeclaration decl) {
98         for (int i = level; i >= 0; i--) {
99             ElementPSVInfoset result = (ElementPSVInfoset) infoset.get(i);
100             if (result.getDeclaration() == decl)
101                 return result;
102         }
103         return null;
104     }
105
106     public ElementPSVInfoset getInfoset(int index) {
107         if (index < 0 || index > level)
108             return null;
109         return (ElementPSVInfoset) infoset.get(index);
110     }
111
112     public SchemaManager getSchemaManager() {
113         return manager;
114     }
115
116     /* (non-Javadoc)
117      * @see org.xquark.xml.util.NamespaceContext#getNamespaceURI(java.lang.String)
118      */

119     public String JavaDoc getNamespaceURI(String JavaDoc prefix) {
120         return nsContext != null ? nsContext.getNamespaceURI(prefix) : null;
121     }
122
123     /* (non-Javadoc)
124      * @see org.xquark.xml.util.NamespaceContext#getNamespaceURI(java.lang.String)
125      */

126     public Collection getNamespaceURIs() {
127         return nsContext != null ? nsContext.getNamespaceURIs() : null;
128     }
129
130     /* (non-Javadoc)
131      * @see org.xquark.xml.util.NamespaceContext#getPrefix(java.lang.String)
132      */

133     public String JavaDoc getPrefix(String JavaDoc uri) {
134         return nsContext != null ? nsContext.getPrefix(uri) : null;
135     }
136
137     /* (non-Javadoc)
138      * @see org.xquark.xml.util.NamespaceContext#getPrefixes()
139      */

140     public Collection getPrefixes() {
141         return nsContext != null ? nsContext.getPrefixes() : null;
142     }
143
144     /* (non-Javadoc)
145      * @see org.xquark.xml.util.NamespaceContext#getPrefixes(java.lang.String)
146      */

147     public Collection getPrefixes(String JavaDoc uri) {
148         return nsContext != null ? nsContext.getPrefixes(uri) : null;
149     }
150
151     /* (non-Javadoc)
152      * @see org.xquark.xml.util.NamespaceContext#getDeclaredPrefixes()
153      */

154     public List getDeclaredPrefixes() {
155         return nsContext != null ? nsContext.getDeclaredPrefixes() : null;
156     }
157
158     // This section contains (non-public) methods used by ValidatingSchemaFilter
159

160     void reset(NamespaceContext nc) {
161         nsContext = nc;
162         level = 0;
163         // validationContext = -1;
164
validationContext = 1;
165         IDSet.clear();
166         pendingRefs.clear();
167         infoset.clear();
168         infoset.add(new ElementPSVInfosetImpl());
169     }
170
171     public void pushElementInfoset(String JavaDoc namespace, String JavaDoc localName) {
172         level++;
173         if (level == infoset.size())
174             infoset.add(new ElementPSVInfosetImpl());
175         ((ElementPSVInfosetImpl) getCurrentInfoset()).initialize(
176             namespace,
177             localName);
178     }
179
180     public void popElementInfoset() {
181         ((ElementPSVInfosetImpl) getCurrentInfoset()).cleanup();
182         level--;
183         /* This is commented out as validationContext is the level at which assessment
184          * began, not the one at which it was successful
185         if (level < validationContext)
186           validationContext = -1;
187         */

188     }
189
190     ElementDeclaration getElementDeclaration() {
191         return (ElementDeclaration) getCurrentInfoset().getDeclaration();
192     }
193
194     Type getElementType() {
195         return getCurrentInfoset().getType();
196     }
197
198     public void initElementValidationInfo(
199         ElementDeclaration matchedDecl,
200         Type type,
201         boolean isNil,
202         int process) {
203         ElementPSVInfosetImpl psvi =
204             (ElementPSVInfosetImpl) getCurrentInfoset();
205         psvi.setField(-1, PSVInfosetImpl.DECLARATION, matchedDecl);
206         psvi.setType(type);
207         psvi.setNil(isNil);
208         //@@ Normally, we should use temporary variables to store VALIDITY and VALIDATION_ATTEMPTED,
209
// which should only be available at the end of the element processing.
210
if (matchedDecl == null && type == null) {
211             psvi.setField(
212                 -1,
213                 PSVInfosetImpl.VALIDATION_ATTEMPTED,
214                 PSVInfoset.NONE);
215             psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.NOTKNOWN);
216         } else {
217             psvi.setField(
218                 -1,
219                 PSVInfosetImpl.VALIDATION_ATTEMPTED,
220                 PSVInfoset.FULL);
221             psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.VALID);
222         }
223         psvi.setProcess(process);
224
225         /* This is commented out as validationContext is the level at which assessment
226          * began, not the one at which it was successful
227         if (validationContext == -1 && matchedDecl != null) {
228           validationContext = level;
229           IDSet.clear();
230           pendingRefs.clear();
231         }
232         */

233         if (matchedDecl != null
234             && matchedDecl.getIdentityConstraints() != null) {
235             psvi.addIdentityConstraints(matchedDecl.getIdentityConstraints());
236         }
237     }
238
239     void computeValidationInfo() {
240         ElementPSVInfosetImpl psvi =
241             (ElementPSVInfosetImpl) getCurrentInfoset();
242         ElementPSVInfosetImpl parentPsvi =
243             (ElementPSVInfosetImpl) getParentInfoset();
244         if (psvi.getErrorCodes() != null) {
245             psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID);
246         }
247         if (psvi.getValidity() == PSVInfoset.INVALID
248             || (psvi.getValidity() == PSVInfoset.NOTKNOWN
249                 && psvi.getProcess() == SchemaConstants.STRICT))
250             parentPsvi.setField(
251                 -1,
252                 PSVInfosetImpl.VALIDITY,
253                 PSVInfoset.INVALID);
254         if (psvi.getValidationAttempted()
255             != parentPsvi.getValidationAttempted())
256             parentPsvi.setField(
257                 -1,
258                 PSVInfosetImpl.VALIDATION_ATTEMPTED,
259                 PSVInfoset.PARTIAL);
260     }
261
262     public int addAttributePSVI(
263         String JavaDoc namespace,
264         String JavaDoc localName,
265         AttributeDeclaration attrDecl,
266         boolean strict) {
267         ElementPSVInfosetImpl psvi =
268             (ElementPSVInfosetImpl) getCurrentInfoset();
269         int index = psvi.addAttribute(namespace, localName, attrDecl);
270         if (attrDecl == null) {
271             psvi.setField(
272                 index,
273                 PSVInfosetImpl.VALIDATION_ATTEMPTED,
274                 PSVInfoset.NONE);
275             psvi.setField(index, PSVInfosetImpl.VALIDITY, PSVInfoset.NOTKNOWN);
276             if (psvi.getValidationAttempted() != PSVInfoset.NONE)
277                 psvi.setField(
278                     -1,
279                     PSVInfosetImpl.VALIDATION_ATTEMPTED,
280                     PSVInfoset.PARTIAL);
281             if (strict)
282                 psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID);
283         } else {
284             psvi.setField(
285                 index,
286                 PSVInfosetImpl.VALIDATION_ATTEMPTED,
287                 PSVInfoset.FULL);
288             psvi.setField(index, PSVInfosetImpl.VALIDITY, PSVInfoset.VALID);
289             if (psvi.getValidationAttempted() != PSVInfoset.FULL)
290                 psvi.setField(
291                     -1,
292                     PSVInfosetImpl.VALIDATION_ATTEMPTED,
293                     PSVInfoset.PARTIAL);
294         }
295         return index;
296     }
297
298     void computeAttributeValidationInfo(int index) {
299         ElementPSVInfosetImpl psvi =
300             (ElementPSVInfosetImpl) getCurrentInfoset();
301         if (psvi.getField(index, PSVInfosetImpl.SCHEMA_ERROR_CODES) != null) {
302             psvi.setField(index, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID);
303             psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID);
304         }
305     }
306
307     void addErrorCodes(int attrIndex, SchemaException ex) {
308         ElementPSVInfosetImpl psvi =
309             (ElementPSVInfosetImpl) getCurrentInfoset();
310         psvi.addErrorCodes(attrIndex, ex);
311     }
312
313     public void setMemberType(int attrIndex, Type memberType) {
314         ((ElementPSVInfosetImpl) getCurrentInfoset()).setField(
315             attrIndex,
316             PSVInfosetImpl.MEMBER_TYPE,
317             memberType);
318     }
319
320     public void setNormalizedValue(int attrIndex, String JavaDoc normalizedValue) {
321         ((ElementPSVInfosetImpl) getCurrentInfoset()).setField(
322             attrIndex,
323             PSVInfosetImpl.SCHEMA_NORMALIZED_VALUE,
324             normalizedValue);
325     }
326
327     public void setActualValue(int attrIndex, Object JavaDoc actualValue) {
328         ((ElementPSVInfosetImpl) getCurrentInfoset()).setField(
329             attrIndex,
330             PSVInfosetImpl.SCHEMA_ACTUAL_VALUE,
331             actualValue);
332     }
333
334     void setNotation(NotationDeclaration notation) {
335         ((ElementPSVInfosetImpl) getCurrentInfoset()).setNotation(notation);
336     }
337
338     void setSchemaSpecified(int attrIndex, boolean schema) {
339         if (schema)
340             ((ElementPSVInfosetImpl) getCurrentInfoset()).setField(
341                 attrIndex,
342                 PSVInfosetImpl.SCHEMA_SPECIFIED,
343                 PSVInfoset.SCHEMA);
344         else
345             ((ElementPSVInfosetImpl) getCurrentInfoset()).setField(
346                 attrIndex,
347                 PSVInfosetImpl.SCHEMA_SPECIFIED,
348                 PSVInfoset.INFOSET);
349     }
350
351     void checkKeyValue(Object JavaDoc actualValue) throws SchemaException {
352         ElementPSVInfosetImpl psvi =
353             (ElementPSVInfosetImpl) getCurrentInfoset();
354         psvi.checkKeyValue(actualValue);
355         checkIDValue(psvi.getType(), actualValue);
356     }
357
358     void checkKeyValue(AttributeDeclaration decl, Object JavaDoc actualValue)
359         throws SchemaException {
360         ((ElementPSVInfosetImpl) getCurrentInfoset()).checkKeyValue(
361             decl,
362             actualValue);
363         checkIDValue(decl.getType(), actualValue);
364     }
365
366     // check IdentityConstraint
367
void checkIdentityConstraints() throws SchemaException {
368         ((ElementPSVInfosetImpl) getCurrentInfoset())
369             .checkIdentityConstraints();
370         checkPendingIDRefs();
371     }
372
373     private void checkIDValue(Type type, Object JavaDoc value) throws SchemaException {
374         if (type != null) {
375             if (type.isDerivedFrom(manager.getIDType())) {
376                 pendingRefs.remove(value);
377                 if (!IDSet.add(value)) {
378                     throw idException(
379                         new SchemaException("cvc-id.2", (Object JavaDoc) value));
380                 }
381             } else if (type.isDerivedFrom(manager.getIDREFType())) {
382                 if (!IDSet.contains(value))
383                     pendingRefs.add(value);
384             } else if (type.isDerivedFrom(manager.getIDREFSType())) {
385                 List refList = (List)value;
386                 for (int i = 0; i < refList.size(); i++) {
387                     Object JavaDoc ref = refList.get(i);
388                     if (!IDSet.contains(ref))
389                         pendingRefs.add(ref);
390                 }
391             }
392         }
393     }
394
395     private void checkPendingIDRefs() throws SchemaException {
396         if (level == validationContext && pendingRefs.size() > 0)
397             throw idException(new SchemaException("cvc-id.1", pendingRefs));
398     }
399
400     private SchemaException idException(SchemaException se) {
401         SchemaException result =
402             new SchemaException("cvc-elt.7", getValidationRoot(), se);
403         ElementPSVInfosetImpl rootPsvi =
404             (ElementPSVInfosetImpl) getInfoset(validationContext);
405         rootPsvi.addErrorCodes(-1, result);
406         return result;
407     }
408
409     private SchemaException idException(List exceptions) {
410         SchemaException result =
411             new SchemaException("cvc-elt.7", getValidationRoot(), exceptions);
412         ElementPSVInfosetImpl rootPsvi =
413             (ElementPSVInfosetImpl) getInfoset(validationContext);
414         rootPsvi.addErrorCodes(-1, result);
415         return result;
416     }
417
418     private ElementDeclaration getValidationRoot() {
419         if (validationContext == -1)
420             return null;
421         return (ElementDeclaration)
422             ((ElementPSVInfosetImpl) getInfoset(validationContext))
423             .getDeclaration();
424     }
425
426     public static abstract class PSVInfosetImpl implements PSVInfoset {
427         protected static final int NAMESPACE = 0;
428         protected static final int LOCAL_NAME = 1;
429         public static final int DECLARATION = 2;
430         protected static final int SCHEMA_ERROR_CODES = 3;
431         protected static final int SCHEMA_SPECIFIED = 4;
432         public static final int SCHEMA_NORMALIZED_VALUE = 5;
433         protected static final int MEMBER_TYPE = 6;
434         protected static final int VALIDITY = 7;
435         protected static final int VALIDATION_ATTEMPTED = 8;
436         public static final int SCHEMA_ACTUAL_VALUE = 9;
437         protected static final int NFIELDS = 10;
438         protected static final ArrayList EMPTY;
439         static {
440             EMPTY = new ArrayList(NFIELDS);
441             for (int i = 0; i < NFIELDS; i++)
442                 EMPTY.add(null);
443         }
444
445         public String JavaDoc getNamespaceURI() {
446             return (String JavaDoc) getField(NAMESPACE);
447         }
448
449         public String JavaDoc getLocalName() {
450             return (String JavaDoc) getField(LOCAL_NAME);
451         }
452
453         public Declaration getDeclaration() {
454             return (Declaration) getField(DECLARATION);
455         }
456
457         public Type getType() {
458             Declaration decl = getDeclaration();
459             if (decl == null)
460                 return null;
461             return decl.getType();
462         }
463
464         public String JavaDoc getNormalizedValue() {
465             return (String JavaDoc) getField(SCHEMA_NORMALIZED_VALUE);
466         }
467
468         public Object JavaDoc getActualValue() {
469             return getField(SCHEMA_ACTUAL_VALUE);
470         }
471
472         public List getErrorCodes() {
473             return (List) getField(SCHEMA_ERROR_CODES);
474         }
475
476         public String JavaDoc getSpecified() {
477             return (String JavaDoc) getField(SCHEMA_SPECIFIED);
478         }
479
480         public String JavaDoc getSchemaDefault() {
481             Declaration decl = getDeclaration();
482             if (decl == null)
483                 return null;
484             return decl.getDefaultValue();
485         }
486
487         public SimpleType getValidatingMemberType() {
488             return (SimpleType) getField(MEMBER_TYPE);
489         }
490
491         public String JavaDoc getValidity() {
492             return (String JavaDoc) getField(VALIDITY);
493         }
494
495         public String JavaDoc getValidationAttempted() {
496             return (String JavaDoc) getField(VALIDATION_ATTEMPTED);
497         }
498
499         public abstract ElementPSVInfoset getValidationContext();
500
501         abstract Object JavaDoc getField(int field);
502     }
503
504     public class ElementPSVInfosetImpl
505         extends PSVInfosetImpl
506         implements ElementPSVInfoset {
507         private static final String JavaDoc RCSRevision = "$Revision: 1.5 $";
508         private static final String JavaDoc RCSName = "$Name: $";
509         private Type elementType = null;
510         private boolean nilElement = false;
511         private NotationDeclaration notation = null;
512         private ArrayList fields;
513         private int process = SchemaConstants.STRICT;
514         private HashMap bindingsTable = null;
515         private List references = null;
516         private List filters = null;
517         private List selectors = null;
518
519         public ElementPSVInfosetImpl() {
520             fields = new ArrayList(5 * NFIELDS);
521             fields.addAll(EMPTY);
522         }
523
524         public Type getType() {
525             return elementType;
526         }
527
528         public boolean isNil() {
529             return nilElement;
530         }
531
532         public int getAttributeCount() {
533             return (fields.size() / NFIELDS) - 1;
534         }
535
536         public int getAttributeIndex(String JavaDoc namespace, String JavaDoc localName) {
537             if (namespace != null && namespace.length() == 0)
538                 namespace = null;
539             for (int i = 0; i < getAttributeCount(); i++) {
540                 String JavaDoc ns = (String JavaDoc) getField(i, NAMESPACE);
541                 String JavaDoc name = (String JavaDoc) getField(i, LOCAL_NAME);
542                 if (localName.equals(name)
543                     && ((namespace == null && ns == null)
544                         || (namespace != null && namespace.equals(ns))))
545                     return i;
546             }
547             return -1;
548         }
549
550         public ElementPSVInfoset getValidationContext() {
551             return getInfoset(validationContext);
552         }
553
554         public PSVInfoset getAttributePSVInfoset(int index) {
555             if (index < 0)
556                 return null;
557             return new ElementPSVInfosetImpl.AttributePSVInfosetImpl(index);
558         }
559
560         public Collection getIdentityConstraintBindings() {
561             return bindingsTable.values();
562         }
563
564         public NotationDeclaration getNotation() {
565             return notation;
566         }
567
568         public Collection getSchemas() {
569             ElementPSVInfoset root = getValidationContext();
570             if (this != root)
571                 return null;
572             return manager.getSchemas();
573         }
574
575         /* (non-Javadoc)
576          * @see org.xquark.xml.util.NamespaceContext#getNamespaceURI(java.lang.String)
577          */

578         public String JavaDoc getNamespaceURI(String JavaDoc prefix) {
579             return nsContext != null ? nsContext.getNamespaceURI(prefix) : null;
580         }
581
582         /* (non-Javadoc)
583          * @see org.xquark.xml.util.NamespaceContext#getNamespaceURI(java.lang.String)
584          */

585         public Collection getNamespaceURIs() {
586             return nsContext != null ? nsContext.getNamespaceURIs() : null;
587         }
588
589         /* (non-Javadoc)
590          * @see org.xquark.xml.util.NamespaceContext#getPrefix(java.lang.String)
591          */

592         public String JavaDoc getPrefix(String JavaDoc uri) {
593             return nsContext != null ? nsContext.getPrefix(uri) : null;
594         }
595
596         /* (non-Javadoc)
597          * @see org.xquark.xml.util.NamespaceContext#getPrefixes()
598          */

599         public Collection getPrefixes() {
600             return nsContext != null ? nsContext.getPrefixes() : null;
601         }
602
603         /* (non-Javadoc)
604          * @see org.xquark.xml.util.NamespaceContext#getPrefixes(java.lang.String)
605          */

606         public Collection getPrefixes(String JavaDoc uri) {
607             return nsContext != null ? nsContext.getPrefixes(uri) : null;
608         }
609
610         /* (non-Javadoc)
611          * @see org.xquark.xml.util.NamespaceContext#getDeclaredPrefixes()
612          */

613         public List getDeclaredPrefixes() {
614             return nsContext != null ? nsContext.getDeclaredPrefixes() : null;
615         }
616
617         Object JavaDoc getField(int field) {
618             return getField(-1, field);
619         }
620
621         public void initialize(String JavaDoc namespace, String JavaDoc localName) {
622             elementType = null;
623             nilElement = false;
624             fields.clear();
625             fields.addAll(EMPTY);
626             setField(-1, NAMESPACE, namespace);
627             setField(-1, LOCAL_NAME, localName);
628             HashMap prevBindings =
629                 ((ElementPSVInfosetImpl) getParentInfoset()).getBindingsTable();
630             if (prevBindings != null)
631                 bindingsTable = (HashMap) prevBindings.clone();
632             List prevFilters =
633                 ((ElementPSVInfosetImpl) getParentInfoset()).getFilters();
634             if (prevFilters != null) {
635                 Iterator it = prevFilters.iterator();
636                 while (it.hasNext()) {
637                     XPathFilter xf = (XPathFilter) it.next();
638                     if (xf.nextElement(namespace, localName)) {
639                         addFilter(xf);
640                         if (xf.isDone() && xf instanceof SelectorFilter) {
641                             IdentityConstraintBinding binding =
642                                 ((SelectorFilter) xf).getBinding();
643                             addSelector(
644                                 new ElementPSVInfosetImpl.Selector(binding));
645                         }
646                     }
647                 }
648             }
649         }
650
651         public void cleanup() {
652             if (filters != null) {
653                 Iterator it = filters.iterator();
654                 while (it.hasNext()) {
655                     XPathFilter xf = (XPathFilter) it.next();
656                     xf.decrementIndex();
657                 }
658             }
659             HashMap prevBindings =
660                 ((ElementPSVInfosetImpl) getParentInfoset()).getBindingsTable();
661             if (prevBindings != null) {
662                 Iterator it = bindingsTable.entrySet().iterator();
663                 while (it.hasNext()) {
664                     Map.Entry entry = (Map.Entry) it.next();
665                     IdentityConstraintBinding prev =
666                         (IdentityConstraintBinding) prevBindings.get(
667                             entry.getKey());
668                     if (prev != null && entry.getValue() != prev) {
669                         prev.propagateEntries(
670                             (IdentityConstraintBinding) entry.getValue());
671                     }
672                 }
673             }
674             filters = null;
675             selectors = null;
676             bindingsTable = null;
677             references = null;
678             fields.clear();
679         }
680
681         int addAttribute(
682             String JavaDoc namespace,
683             String JavaDoc localName,
684             AttributeDeclaration attrDecl) {
685             int index = getAttributeCount();
686             fields.addAll(EMPTY);
687             setField(index, NAMESPACE, namespace);
688             setField(index, LOCAL_NAME, localName);
689             setField(index, DECLARATION, attrDecl);
690             return index;
691         }
692
693         public void setType(Type type) {
694             elementType = type;
695         }
696
697         void setNil(boolean isNil) {
698             nilElement = isNil;
699         }
700
701         void setNotation(NotationDeclaration notation) {
702             this.notation = notation;
703         }
704
705         public void setField(int index, int field, Object JavaDoc value) {
706             int i = (index + 1) * NFIELDS + field;
707             try {
708                 fields.set(i, value);
709             } catch (IndexOutOfBoundsException JavaDoc e) {
710                 throw new IndexOutOfBoundsException JavaDoc("index = " + index);
711             }
712         }
713
714         Object JavaDoc getField(int index, int field) {
715             int i = (index + 1) * NFIELDS + field;
716             try {
717                 return fields.get(i);
718             } catch (IndexOutOfBoundsException JavaDoc e) {
719                 throw new IndexOutOfBoundsException JavaDoc("index = " + index);
720             }
721         }
722
723         int getProcess() {
724             return process;
725         }
726
727         void setProcess(int process) {
728             this.process = process;
729         }
730
731         List getSelectors() {
732             return selectors;
733         }
734
735         void addSelector(ElementPSVInfosetImpl.Selector selector) {
736             if (selectors == null)
737                 selectors = new ArrayList();
738             selectors.add(selector);
739             Iterator it = selector.getFields().iterator();
740             int index = 0;
741             while (it.hasNext()) {
742                 Iterator it2 = ((List) it.next()).iterator();
743                 while (it2.hasNext()) {
744                     XPathExpr xpath = (XPathExpr) it2.next();
745                     addFilter(new FieldFilter(xpath, selector, index));
746                 }
747                 index++;
748             }
749         }
750
751         List getFilters() {
752             return filters;
753         }
754
755         void addFilter(XPathFilter xi) {
756             if (filters == null)
757                 filters = new ArrayList();
758             filters.add(xi);
759         }
760
761         HashMap getBindingsTable() {
762             return bindingsTable;
763         }
764
765         void addIdentityConstraints(Collection constraints) {
766             Iterator it = constraints.iterator();
767             while (it.hasNext()) {
768                 IdentityConstraint constraint = (IdentityConstraint) it.next();
769                 if (constraint.getReferencedKey() == null) {
770                     IdentityConstraintBinding binding =
771                         addIdentityConstraintBinding(constraint);
772                     addBindingFilters(binding);
773                 }
774             }
775             it = constraints.iterator();
776             while (it.hasNext()) {
777                 IdentityConstraint constraint = (IdentityConstraint) it.next();
778                 IdentityConstraint ref = constraint.getReferencedKey();
779                 if (ref != null) {
780                     IdentityConstraintBinding binding =
781                         addReferenceBinding(constraint);
782                     addBindingFilters(binding);
783                     IdentityConstraintBinding refBinding =
784                         getIdentityConstraintBinding(ref);
785                     if (refBinding == null) {
786                         refBinding = addIdentityConstraintBinding(ref);
787                     }
788                     binding.setReference(refBinding);
789                 }
790             }
791         }
792
793         IdentityConstraintBinding addIdentityConstraintBinding(IdentityConstraint constraint) {
794             if (bindingsTable == null)
795                 bindingsTable = new HashMap();
796             IdentityConstraintBinding binding =
797                 new IdentityConstraintBinding(constraint);
798             bindingsTable.put(constraint, binding);
799             return binding;
800         }
801
802         IdentityConstraintBinding addReferenceBinding(IdentityConstraint constraint) {
803             if (references == null)
804                 references = new ArrayList();
805             IdentityConstraintBinding binding =
806                 new IdentityConstraintBinding(constraint);
807             references.add(binding);
808             return binding;
809         }
810
811         void addBindingFilters(IdentityConstraintBinding binding) {
812             IdentityConstraint constraint = binding.getDefinition();
813             List xpaths = constraint.getSelector();
814             Iterator it = xpaths.iterator();
815             while (it.hasNext()) {
816                 SelectorFilter xf =
817                     new SelectorFilter((XPathExpr) it.next(), binding);
818                 addFilter(xf);
819                 if (xf.isDone())
820                     addSelector(new ElementPSVInfosetImpl.Selector(binding));
821             }
822         }
823
824         IdentityConstraintBinding getIdentityConstraintBinding(IdentityConstraint constraint) {
825             if (bindingsTable == null)
826                 return null;
827             return (IdentityConstraintBinding) bindingsTable.get(constraint);
828         }
829
830         void checkKeyValue(Object JavaDoc value) throws SchemaException {
831             if (filters != null) {
832                 Iterator it = filters.iterator();
833                 ArrayList exceptions = null;
834                 while (it.hasNext()) {
835                     try {
836                         XPathFilter xf = (XPathFilter) it.next();
837                         if (xf.isDone())
838                             xf.setKeyValue(value);
839                     } catch (SchemaException ex) {
840                         if (exceptions == null)
841                             exceptions = new ArrayList();
842                         exceptions.add(ex);
843                     }
844                 }
845                 if (exceptions != null)
846                     throw new SchemaException(exceptions);
847             }
848         }
849
850         void checkKeyValue(AttributeDeclaration decl, Object JavaDoc value)
851             throws SchemaException {
852             if (filters != null) {
853                 Iterator it = filters.iterator();
854                 ArrayList exceptions = null;
855                 String JavaDoc ns = decl.getNamespace();
856                 String JavaDoc localName = decl.getName();
857                 while (it.hasNext()) {
858                     try {
859                         XPathFilter xf = (XPathFilter) it.next();
860                         if (xf.nextAttribute(ns, localName))
861                             xf.setKeyValue(value);
862                     } catch (SchemaException ex) {
863                         if (exceptions == null)
864                             exceptions = new ArrayList();
865                         exceptions.add(ex);
866                     }
867                 }
868                 if (exceptions != null)
869                     throw new SchemaException(exceptions);
870             }
871         }
872
873         void checkIdentityConstraints() throws SchemaException {
874             ArrayList exceptions = null;
875             // Check that element value used as field is of simple type and not nillable
876
boolean nillable =
877                 getDeclaration() != null
878                     && ((ElementDeclaration) getDeclaration()).isNillable();
879             boolean complex =
880                 getType() != null && getType().getValueType() == null;
881             if (filters != null && (nillable || complex)) {
882                 Iterator it = filters.iterator();
883                 while (it.hasNext()) {
884                     XPathFilter xf = (XPathFilter) it.next();
885                     if (xf.isDone() && xf instanceof FieldFilter) {
886                         IdentityConstraint constraint =
887                             ((FieldFilter) xf)
888                                 .getSelector()
889                                 .getIdentityConstraint();
890                         if (complex) {
891                             if (exceptions == null)
892                                 exceptions = new ArrayList();
893                             SchemaException se =
894                                 new SchemaException(
895                                     "cvc-identity-constraint.3",
896                                     constraint);
897                             exceptions.add(
898                                 identityConstraintException(constraint, se));
899                         }
900                         if (nillable
901                             && constraint.getCategory()
902                                 == IdentityConstraint.CATEGORY_KEY) {
903                             if (exceptions == null)
904                                 exceptions = new ArrayList();
905                             SchemaException se =
906                                 new SchemaException(
907                                     "cvc-identity-constraint.4.2.3",
908                                     constraint);
909                             exceptions.add(
910                                 identityConstraintException(constraint, se));
911                         }
912                     }
913                 }
914             }
915             // Check that key sequence is complete for key constraints
916
if (selectors != null) {
917                 Iterator it = selectors.iterator();
918                 while (it.hasNext()) {
919                     ElementPSVInfosetImpl.Selector s =
920                         (ElementPSVInfosetImpl.Selector) it.next();
921                     IdentityConstraint constraint = s.getIdentityConstraint();
922                     if (s.isSequenceComplete()) {
923                         // add new entry in identity constraint binding
924
try {
925                             s.getBinding().registerEntry(s.getSequence());
926                         } catch (SchemaException se) {
927                             if (exceptions == null)
928                                 exceptions = new ArrayList();
929                             exceptions.add(
930                                 identityConstraintException(constraint, se));
931                         }
932                     } else if (
933                         constraint.getCategory()
934                             == IdentityConstraint.CATEGORY_KEY) {
935                         // All selected nodes must have a key sequence for a key constraint
936
if (exceptions == null)
937                             exceptions = new ArrayList();
938                         SchemaException ke = null;
939                         if (s.isValid())
940                             ke =
941                                 new SchemaException(
942                                     null,
943                                     "key sequence: " + s.getSequence());
944                         SchemaException se =
945                             new SchemaException(
946                                 "cvc-identity-constraint.4.2.1",
947                                 constraint,
948                                 ke);
949                         exceptions.add(
950                             identityConstraintException(constraint, se));
951                     }
952                 }
953             }
954             if (references != null) {
955                 Iterator it = references.iterator();
956                 while (it.hasNext()) {
957                     IdentityConstraintBinding binding =
958                         (IdentityConstraintBinding) it.next();
959                     try {
960                         binding.checkPendingRefs();
961                     } catch (SchemaException se) {
962                         if (exceptions == null)
963                             exceptions = new ArrayList();
964                         exceptions.add(
965                             identityConstraintException(
966                                 binding.getDefinition(),
967                                 se));
968                     }
969                 }
970             }
971             if (exceptions != null)
972                 throw new SchemaException(exceptions);
973         }
974
975         void addErrorCodes(int attrIndex, SchemaException ex) {
976             ArrayList list =
977                 (ArrayList) getField(attrIndex, SCHEMA_ERROR_CODES);
978             if (list == null) {
979                 list = new ArrayList();
980                 setField(attrIndex, SCHEMA_ERROR_CODES, list);
981             }
982             addErrorCodes(list, ex);
983         }
984
985         private void addErrorCodes(ArrayList list, SchemaException ex) {
986             list.add(ex.getErrorCode());
987             List exceptions = ex.getExceptions();
988             if (exceptions != null) {
989                 Iterator it = exceptions.iterator();
990                 while (it.hasNext()) {
991                     Exception JavaDoc e = (Exception JavaDoc) it.next();
992                     if (e instanceof SchemaException)
993                         addErrorCodes(list, (SchemaException) e);
994                 }
995             }
996         }
997
998         SchemaException identityConstraintException(
999             IdentityConstraint constraint,
1000            SchemaException se) {
1001            ElementDeclaration context = constraint.getContextDeclaration();
1002            SchemaException result =
1003                new SchemaException("cvc-elt.6", context, se);
1004            ElementPSVInfosetImpl contextPsvi =
1005                (ElementPSVInfosetImpl) getInfoset(context);
1006            contextPsvi.addErrorCodes(-1, result);
1007            return result;
1008        }
1009
1010        SchemaException identityConstraintException(
1011            IdentityConstraint constraint,
1012            List exceptions) {
1013            ElementDeclaration context = constraint.getContextDeclaration();
1014            SchemaException result =
1015                new SchemaException("cvc-elt.6", context, exceptions);
1016            ElementPSVInfosetImpl contextPsvi =
1017                (ElementPSVInfosetImpl) getInfoset(context);
1018            contextPsvi.addErrorCodes(-1, result);
1019            return result;
1020        }
1021
1022        public PSVInfoset getAttributePSVInfoset(
1023            String JavaDoc namespace,
1024            String JavaDoc localName) {
1025            return getAttributePSVInfoset(
1026                getAttributeIndex(namespace, localName));
1027        }
1028
1029        class AttributePSVInfosetImpl extends PSVInfosetImpl {
1030            private static final String JavaDoc RCSRevision = "$Revision: 1.5 $";
1031            private static final String JavaDoc RCSName = "$Name: $";
1032
1033            private int index;
1034
1035            AttributePSVInfosetImpl(int index) {
1036                this.index = index;
1037            }
1038
1039            public ElementPSVInfoset getValidationContext() {
1040                return getInfoset(validationContext);
1041            }
1042
1043            Object JavaDoc getField(int field) {
1044                return ElementPSVInfosetImpl.this.getField(index, field);
1045            }
1046        }
1047
1048        class Selector {
1049            private static final String JavaDoc RCSRevision = "$Revision: 1.5 $";
1050            private static final String JavaDoc RCSName = "$Name: $";
1051            IdentityConstraintBinding binding;
1052            ArrayList keySequence = null;
1053            boolean valid = true;
1054
1055            Selector(IdentityConstraintBinding binding) {
1056                this.binding = binding;
1057            }
1058
1059            IdentityConstraintBinding getBinding() {
1060                return binding;
1061            }
1062
1063            IdentityConstraint getIdentityConstraint() {
1064                return binding.getDefinition();
1065            }
1066
1067            void setKeyValue(Object JavaDoc value, int index) throws SchemaException {
1068                if (keySequence == null) {
1069                    int size = getFields().size();
1070                    keySequence = new ArrayList(size);
1071                    for (int i = 0; i < size; i++)
1072                        keySequence.add(null);
1073                }
1074                if (keySequence.get(index) != null) {
1075                    valid = false;
1076                    SchemaException se =
1077                        new SchemaException(
1078                            "cvc-identity-constraint.3",
1079                            getIdentityConstraint(),
1080                            new SchemaException(
1081                                null,
1082                                "key sequence: " + keySequence));
1083                    throw identityConstraintException(
1084                        getIdentityConstraint(),
1085                        se);
1086                }
1087                keySequence.set(index, value);
1088            }
1089
1090            boolean isValid() {
1091                return valid;
1092            }
1093
1094            List getFields() {
1095                return getIdentityConstraint().getFields();
1096            }
1097
1098            boolean isSequenceComplete() {
1099                if (!valid)
1100                    return false;
1101                if (keySequence == null)
1102                    return false;
1103                return !keySequence.contains(null);
1104            }
1105
1106            List getSequence() {
1107                return keySequence;
1108            }
1109        }
1110    }
1111
1112    static class XPathFilter {
1113        private static final String JavaDoc RCSRevision = "$Revision: 1.5 $";
1114        private static final String JavaDoc RCSName = "$Name: $";
1115        int index = 0;
1116        XPathExpr xpath;
1117
1118        XPathFilter(XPathExpr xpath) {
1119            this.xpath = xpath;
1120        }
1121
1122        boolean isDone() {
1123            return index == xpath.getStepCount();
1124        }
1125
1126        boolean nextElement(String JavaDoc namespaceURI, String JavaDoc localName) {
1127            if (isDone())
1128                return false;
1129            if (xpath.matches(namespaceURI, localName, index, false)) {
1130                index++;
1131                return true;
1132            }
1133            if (index == 0 && xpath.isAnyLevel())
1134                return true;
1135            return false;
1136        }
1137
1138        boolean nextAttribute(String JavaDoc namespaceURI, String JavaDoc localName) {
1139            if (isDone())
1140                return false;
1141            if (xpath.matches(namespaceURI, localName, index, true)) {
1142                return true;
1143            }
1144            return false;
1145        }
1146
1147        void decrementIndex() {
1148            if (index > 0)
1149                index--;
1150        }
1151
1152        void setKeyValue(Object JavaDoc value) throws SchemaException {
1153        }
1154    }
1155
1156    static class SelectorFilter extends XPathFilter {
1157        private static final String JavaDoc RCSRevision = "$Revision: 1.5 $";
1158        private static final String JavaDoc RCSName = "$Name: $";
1159        IdentityConstraintBinding binding;
1160
1161        SelectorFilter(XPathExpr xpath, IdentityConstraintBinding binding) {
1162            super(xpath);
1163            this.binding = binding;
1164        }
1165
1166        IdentityConstraintBinding getBinding() {
1167            return binding;
1168        }
1169    }
1170
1171    static class FieldFilter extends XPathFilter {
1172        private static final String JavaDoc RCSRevision = "$Revision: 1.5 $";
1173        private static final String JavaDoc RCSName = "$Name: $";
1174        ElementPSVInfosetImpl.Selector selector;
1175        int index;
1176
1177        FieldFilter(
1178            XPathExpr xpath,
1179            ElementPSVInfosetImpl.Selector selector,
1180            int index) {
1181            super(xpath);
1182            this.selector = selector;
1183            this.index = index;
1184        }
1185
1186        ElementPSVInfosetImpl.Selector getSelector() {
1187            return selector;
1188        }
1189
1190        void setKeyValue(Object JavaDoc value) throws SchemaException {
1191            selector.setKeyValue(value, index);
1192        }
1193    }
1194
1195}
1196
Popular Tags