KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > thaiopensource > validate > nrl > ValidatorImpl


1 package com.thaiopensource.validate.nrl;
2
3 import org.xml.sax.helpers.DefaultHandler JavaDoc;
4 import org.xml.sax.ErrorHandler JavaDoc;
5 import org.xml.sax.Attributes JavaDoc;
6 import org.xml.sax.SAXException JavaDoc;
7 import org.xml.sax.ContentHandler JavaDoc;
8 import org.xml.sax.Locator JavaDoc;
9 import org.xml.sax.SAXParseException JavaDoc;
10 import org.xml.sax.DTDHandler JavaDoc;
11 import com.thaiopensource.validate.Validator;
12 import com.thaiopensource.validate.Schema;
13 import com.thaiopensource.validate.ValidateProperty;
14 import com.thaiopensource.validate.nrl.ActionSet;
15 import com.thaiopensource.validate.nrl.AttributeActionSet;
16 import com.thaiopensource.validate.nrl.FilteredAttributes;
17 import com.thaiopensource.validate.nrl.Hashset;
18 import com.thaiopensource.validate.nrl.IntSet;
19 import com.thaiopensource.validate.nrl.Mode;
20 import com.thaiopensource.validate.nrl.ModeUsage;
21 import com.thaiopensource.validate.nrl.NoResultAction;
22 import com.thaiopensource.validate.nrl.ResultAction;
23 import com.thaiopensource.validate.nrl.SectionState;
24 import com.thaiopensource.util.Localizer;
25 import com.thaiopensource.util.PropertyMap;
26
27 import java.util.Vector JavaDoc;
28 import java.util.Stack JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Enumeration JavaDoc;
31
32 class ValidatorImpl extends DefaultHandler JavaDoc implements Validator {
33   private static final String JavaDoc BEARER_URI = "";
34   private static final String JavaDoc BEARER_LOCAL_NAME = "#bearer";
35   private static final String JavaDoc NO_NS = "\0";
36   private final ErrorHandler JavaDoc eh;
37   private final PropertyMap properties;
38   private Locator JavaDoc locator;
39   private Section currentSection;
40   private PrefixMapping prefixMapping = null;
41   private final Hashtable JavaDoc validatorHandlerCache = new Hashtable JavaDoc();
42   private final Localizer localizer = new Localizer(ValidatorImpl.class);
43   private final Hashset noResultActions = new Hashset();
44   private final Hashtable JavaDoc attributeNamespaceIndexSets = new Hashtable JavaDoc();
45   private final Vector JavaDoc activeHandlersAttributeIndexSets = new Vector JavaDoc();
46   private final Hashset attributeSchemas = new Hashset();
47   private boolean attributeNamespaceRejected;
48   private Attributes JavaDoc filteredAttributes;
49   private final Mode startMode;
50
51   static private class PrefixMapping {
52     final String JavaDoc prefix;
53     final String JavaDoc uri;
54     final PrefixMapping parent;
55
56     PrefixMapping(String JavaDoc prefix, String JavaDoc uri, PrefixMapping parent) {
57       this.prefix = prefix;
58       this.uri = uri;
59       this.parent = parent;
60     }
61   }
62
63   private class Section implements SectionState {
64     final Section parent;
65     /**
66      * Namespace of this section. Empty string for absent.
67      */

68     final String JavaDoc ns;
69     /**
70      * Number of open elements in this section.
71      */

72     int depth = 0;
73     /**
74      * List of the Validators rooted in this section
75      */

76     final Vector JavaDoc validators = new Vector JavaDoc();
77     final Vector JavaDoc schemas = new Vector JavaDoc();
78     /**
79      * List of the ContentHandlers that want to see the elements in this section
80      */

81     final Vector JavaDoc activeHandlers = new Vector JavaDoc();
82     final Vector JavaDoc activeHandlersAttributeModeUsage = new Vector JavaDoc();
83     final Vector JavaDoc attributeValidationModeUsages = new Vector JavaDoc();
84     /**
85      * List of Programs saying what to do with child sections
86      */

87     final Vector JavaDoc childPrograms = new Vector JavaDoc();
88     final Stack JavaDoc context = new Stack JavaDoc();
89     boolean contextDependent = false;
90     int attributeProcessing = Mode.ATTRIBUTE_PROCESSING_NONE;
91
92     Section(String JavaDoc ns, Section parent) {
93       this.ns = ns;
94       this.parent = parent;
95     }
96
97     public void addChildMode(ModeUsage modeUsage, ContentHandler JavaDoc handler) {
98       childPrograms.addElement(new Program(modeUsage, handler));
99       if (modeUsage.isContextDependent())
100         contextDependent = true;
101     }
102
103     public void addValidator(Schema schema, ModeUsage modeUsage) {
104       schemas.addElement(schema);
105       Validator validator = createValidator(schema);
106       validators.addElement(validator);
107       activeHandlers.addElement(validator.getContentHandler());
108       activeHandlersAttributeModeUsage.addElement(modeUsage);
109       attributeProcessing = Math.max(attributeProcessing,
110                                      modeUsage.getAttributeProcessing());
111       childPrograms.addElement(new Program(modeUsage, validator.getContentHandler()));
112       if (modeUsage.isContextDependent())
113         contextDependent = true;
114     }
115
116     public void addActiveHandler(ContentHandler JavaDoc handler, ModeUsage attributeModeUsage) {
117       activeHandlers.addElement(handler);
118       activeHandlersAttributeModeUsage.addElement(attributeModeUsage);
119       attributeProcessing = Math.max(attributeProcessing,
120                                      attributeModeUsage.getAttributeProcessing());
121       if (attributeModeUsage.isContextDependent())
122         contextDependent = true;
123     }
124
125     public void addAttributeValidationModeUsage(ModeUsage modeUsage) {
126       int ap = modeUsage.getAttributeProcessing();
127       if (ap != Mode.ATTRIBUTE_PROCESSING_NONE) {
128         attributeValidationModeUsages.addElement(modeUsage);
129         attributeProcessing = Math.max(ap, attributeProcessing);
130         if (modeUsage.isContextDependent())
131           contextDependent = true;
132       }
133     }
134
135     public void reject() throws SAXException JavaDoc {
136       if (eh != null)
137         eh.error(new SAXParseException JavaDoc(localizer.message("reject_element", ns),
138                                        locator));
139     }
140
141   }
142
143   static private class Program {
144     final ModeUsage modeUsage;
145     final ContentHandler JavaDoc handler;
146
147     Program(ModeUsage modeUsage, ContentHandler JavaDoc handler) {
148       this.modeUsage = modeUsage;
149       this.handler = handler;
150     }
151   }
152
153   ValidatorImpl(Mode mode, PropertyMap properties) {
154     this.properties = properties;
155     this.eh = ValidateProperty.ERROR_HANDLER.get(properties);
156     this.startMode = mode;
157     initCurrentSection();
158   }
159
160   private void initCurrentSection() {
161     currentSection = new Section(NO_NS, null);
162     currentSection.addChildMode(new ModeUsage(startMode, startMode), null);
163   }
164
165   public void setDocumentLocator(Locator JavaDoc locator) {
166     this.locator = locator;
167   }
168
169   public void characters(char ch[], int start, int length)
170           throws SAXException JavaDoc {
171     for (int i = 0, len = currentSection.activeHandlers.size(); i < len; i++)
172       ((ContentHandler JavaDoc)(currentSection.activeHandlers.elementAt(i))).characters(ch, start, length);
173
174   }
175
176   public void ignorableWhitespace(char ch[], int start, int length)
177           throws SAXException JavaDoc {
178     for (int i = 0, len = currentSection.activeHandlers.size(); i < len; i++)
179       ((ContentHandler JavaDoc)(currentSection.activeHandlers.elementAt(i))).ignorableWhitespace(ch, start, length);
180   }
181
182   public void startElement(String JavaDoc uri, String JavaDoc localName,
183                            String JavaDoc qName, Attributes JavaDoc attributes)
184           throws SAXException JavaDoc {
185     if (!uri.equals(currentSection.ns))
186       startSection(uri);
187     currentSection.depth++;
188     if (currentSection.contextDependent)
189       currentSection.context.push(localName);
190     boolean transformAttributes = processAttributes(attributes);
191     for (int i = 0, len = currentSection.activeHandlers.size(); i < len; i++) {
192       ContentHandler JavaDoc handler = (ContentHandler JavaDoc)(currentSection.activeHandlers.elementAt(i));
193       handler.startElement(uri, localName, qName,
194                            transformAttributes
195                            ? filterAttributes((IntSet)activeHandlersAttributeIndexSets.elementAt(i),
196                                               attributes)
197                            : attributes);
198     }
199   }
200
201   private static Attributes JavaDoc filterAttributes(IntSet indexSet, Attributes JavaDoc attributes) {
202     if (indexSet.size() == attributes.getLength())
203       return attributes;
204     return new FilteredAttributes(indexSet, attributes);
205   }
206
207   private boolean processAttributes(Attributes JavaDoc attributes) throws SAXException JavaDoc {
208     if (currentSection.attributeProcessing == Mode.ATTRIBUTE_PROCESSING_NONE
209         || attributes.getLength() == 0)
210       return false;
211     attributeNamespaceIndexSets.clear();
212     for (int i = 0, len = attributes.getLength(); i < len; i++) {
213       String JavaDoc ns = attributes.getURI(i);
214       IntSet indexSet = (IntSet)attributeNamespaceIndexSets.get(ns);
215       if (indexSet == null) {
216         indexSet = new IntSet();
217         attributeNamespaceIndexSets.put(ns, indexSet);
218       }
219       indexSet.add(i);
220     }
221     if (currentSection.attributeProcessing == Mode.ATTRIBUTE_PROCESSING_QUALIFIED
222         && attributeNamespaceIndexSets.size() == 1
223         && attributeNamespaceIndexSets.get("") != null)
224       return false;
225     Vector JavaDoc handlerModes = currentSection.activeHandlersAttributeModeUsage;
226     activeHandlersAttributeIndexSets.setSize(handlerModes.size());
227     for (int i = 0, len = handlerModes.size(); i < len; i++)
228       activeHandlersAttributeIndexSets.setElementAt(new IntSet(), i);
229     boolean transform = false;
230     Vector JavaDoc validationModes = currentSection.attributeValidationModeUsages;
231     for (Enumeration JavaDoc e = attributeNamespaceIndexSets.keys(); e.hasMoreElements();) {
232       String JavaDoc ns = (String JavaDoc)e.nextElement();
233       IntSet indexSet = (IntSet)attributeNamespaceIndexSets.get(ns);
234       attributeSchemas.clear();
235       filteredAttributes = null;
236       attributeNamespaceRejected = false;
237       for (int i = 0, len = handlerModes.size(); i < len; i++) {
238         ModeUsage modeUsage = (ModeUsage)handlerModes.elementAt(i);
239         AttributeActionSet actions = processAttributeSection(modeUsage, ns, indexSet, attributes);
240         if (actions.getAttach())
241           ((IntSet)activeHandlersAttributeIndexSets.get(i)).addAll(indexSet);
242         else
243           transform = true;
244       }
245       for (int i = 0, len = validationModes.size(); i < len; i++) {
246         ModeUsage modeUsage = (ModeUsage)validationModes.elementAt(i);
247         processAttributeSection(modeUsage, ns, indexSet, attributes);
248       }
249     }
250     return transform;
251   }
252
253   private AttributeActionSet processAttributeSection(ModeUsage modeUsage,
254                                                      String JavaDoc ns,
255                                                      IntSet indexSet,
256                                                      Attributes JavaDoc attributes)
257           throws SAXException JavaDoc {
258     Mode mode = modeUsage.getMode(currentSection.context);
259     AttributeActionSet actions = mode.getAttributeActions(ns);
260     if (actions.getReject() && !attributeNamespaceRejected) {
261       attributeNamespaceRejected = true;
262       if (eh != null)
263         eh.error(new SAXParseException JavaDoc(localizer.message("reject_attribute", ns),
264                                        locator));
265     }
266     Schema[] schemas = actions.getSchemas();
267     for (int j = 0; j < schemas.length; j++) {
268       if (attributeSchemas.contains(schemas[j]))
269         continue;
270       attributeSchemas.add(schemas[j]);
271       if (filteredAttributes == null)
272         filteredAttributes = filterAttributes(indexSet, attributes);
273       validateAttributes(schemas[j], filteredAttributes);
274     }
275     return actions;
276   }
277
278   private void validateAttributes(Schema schema, Attributes JavaDoc attributes) throws SAXException JavaDoc {
279     Validator validator = createValidator(schema);
280     ContentHandler JavaDoc ch = validator.getContentHandler();
281     initHandler(ch);
282     ch.startElement(BEARER_URI, BEARER_LOCAL_NAME, BEARER_LOCAL_NAME, attributes);
283     ch.endElement(BEARER_URI, BEARER_LOCAL_NAME, BEARER_LOCAL_NAME);
284     cleanupHandler(ch);
285     releaseValidator(schema, validator);
286   }
287
288   private void startSection(String JavaDoc uri) throws SAXException JavaDoc {
289     Section section = new Section(uri, currentSection);
290     Vector JavaDoc childPrograms = currentSection.childPrograms;
291     noResultActions.clear();
292     for (int i = 0, len = childPrograms.size(); i < len; i++) {
293       Program program = (Program)childPrograms.elementAt(i);
294       ActionSet actions = program.modeUsage.getMode(currentSection.context).getElementActions(uri);
295       ResultAction resultAction = actions.getResultAction();
296       if (resultAction != null)
297         resultAction.perform(program.handler, section);
298       NoResultAction[] nra = actions.getNoResultActions();
299       for (int j = 0; j < nra.length; j++) {
300         NoResultAction tem = nra[j];
301         if (!noResultActions.contains(tem)) {
302           nra[j].perform(section);
303           noResultActions.add(tem);
304         }
305       }
306     }
307     for (int i = 0, len = section.validators.size(); i < len; i++)
308       initHandler(((Validator)section.validators.elementAt(i)).getContentHandler());
309     currentSection = section;
310   }
311
312   private void initHandler(ContentHandler JavaDoc ch) throws SAXException JavaDoc {
313     if (locator != null)
314       ch.setDocumentLocator(locator);
315     ch.startDocument();
316     for (PrefixMapping pm = prefixMapping; pm != null; pm = pm.parent)
317       ch.startPrefixMapping(pm.prefix, pm.uri);
318   }
319
320   public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName)
321           throws SAXException JavaDoc {
322     for (int i = 0, len = currentSection.activeHandlers.size(); i < len; i++)
323       ((ContentHandler JavaDoc)(currentSection.activeHandlers.elementAt(i))).endElement(uri, localName, qName);
324     currentSection.depth--;
325     if (currentSection.contextDependent)
326       currentSection.context.pop();
327     if (currentSection.depth == 0)
328       endSection();
329   }
330
331   private void endSection() throws SAXException JavaDoc {
332     for (int i = 0, len = currentSection.validators.size(); i < len; i++) {
333       Validator validator = (Validator)currentSection.validators.elementAt(i);
334       cleanupHandler(validator.getContentHandler());
335       releaseValidator((Schema)currentSection.schemas.elementAt(i), validator);
336       // endDocument() on one of the validators may throw an exception
337
// in this case we don't want to release the validator twice
338
currentSection.validators.setElementAt(null, i);
339     }
340     currentSection = currentSection.parent;
341   }
342
343   private void cleanupHandler(ContentHandler JavaDoc vh) throws SAXException JavaDoc {
344     for (PrefixMapping pm = prefixMapping; pm != null; pm = pm.parent)
345       vh.endPrefixMapping(pm.prefix);
346     vh.endDocument();
347   }
348
349   public void endDocument()
350           throws SAXException JavaDoc {
351   }
352
353   public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri)
354           throws SAXException JavaDoc {
355     super.startPrefixMapping(prefix, uri);
356     prefixMapping = new PrefixMapping(prefix, uri, prefixMapping);
357   }
358
359   public void endPrefixMapping(String JavaDoc prefix)
360           throws SAXException JavaDoc {
361     super.endPrefixMapping(prefix);
362     prefixMapping = prefixMapping.parent;
363   }
364
365   private Validator createValidator(Schema schema) {
366     Stack JavaDoc stack = (Stack JavaDoc)validatorHandlerCache.get(schema);
367     if (stack == null) {
368       stack = new Stack JavaDoc();
369       validatorHandlerCache.put(schema, stack);
370     }
371     if (stack.empty())
372       return schema.createValidator(properties);
373     return (Validator)stack.pop();
374   }
375
376   private void releaseValidator(Schema schema, Validator vh) {
377     if (vh == null)
378       return;
379     vh.reset();
380     ((Stack JavaDoc)validatorHandlerCache.get(schema)).push(vh);
381   }
382
383   public void reset() {
384     for (; currentSection != null; currentSection = currentSection.parent) {
385       for (int i = 0, len = currentSection.validators.size(); i < len; i++)
386         releaseValidator((Schema)currentSection.schemas.elementAt(i),
387                          (Validator)currentSection.validators.elementAt(i));
388     }
389     initCurrentSection();
390   }
391
392   public ContentHandler JavaDoc getContentHandler() {
393     return this;
394   }
395
396   public DTDHandler JavaDoc getDTDHandler() {
397     return this;
398   }
399 }
400
Popular Tags