KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > thaiopensource > relaxng > impl > PatternValidator


1 package com.thaiopensource.relaxng.impl;
2
3 import com.thaiopensource.validate.Validator;
4 import com.thaiopensource.relaxng.parse.sax.DtdContext;
5 import com.thaiopensource.xml.util.WellKnownNamespaces;
6 import com.thaiopensource.xml.util.Name;
7 import org.xml.sax.Attributes JavaDoc;
8 import org.xml.sax.ErrorHandler JavaDoc;
9 import org.xml.sax.Locator JavaDoc;
10 import org.xml.sax.SAXException JavaDoc;
11 import org.xml.sax.SAXParseException JavaDoc;
12 import org.xml.sax.DTDHandler JavaDoc;
13 import org.xml.sax.ContentHandler JavaDoc;
14
15 import java.util.Hashtable JavaDoc;
16
17 public class PatternValidator extends DtdContext implements Validator, ContentHandler JavaDoc, DTDHandler JavaDoc {
18   private final ValidatorPatternBuilder builder;
19   private final Pattern start;
20   private final ErrorHandler JavaDoc eh;
21   private Hashtable JavaDoc recoverPatternTable;
22   private PatternMemo memo;
23   private boolean hadError;
24   private boolean collectingCharacters;
25   private final StringBuffer JavaDoc charBuf = new StringBuffer JavaDoc();
26   private PrefixMapping prefixMapping = new PrefixMapping("xml", WellKnownNamespaces.XML, null);
27   private Locator JavaDoc locator;
28
29   private static final class PrefixMapping {
30     private final String JavaDoc prefix;
31     private final String JavaDoc namespaceURI;
32     private final PrefixMapping previous;
33
34     PrefixMapping(String JavaDoc prefix, String JavaDoc namespaceURI, PrefixMapping prev) {
35       this.prefix = prefix;
36       this.namespaceURI = namespaceURI;
37       this.previous = prev;
38     }
39
40     PrefixMapping getPrevious() {
41       return previous;
42     }
43   }
44
45   private void startCollectingCharacters() {
46     if (!collectingCharacters) {
47       collectingCharacters = true;
48       charBuf.setLength(0);
49     }
50   }
51
52   private void flushCharacters() throws SAXException JavaDoc {
53     collectingCharacters = false;
54     int len = charBuf.length();
55     for (int i = 0; i < len; i++) {
56       switch (charBuf.charAt(i)) {
57       case ' ':
58       case '\r':
59       case '\t':
60       case '\n':
61     break;
62       default:
63     text();
64     return;
65       }
66     }
67   }
68
69   public void startElement(String JavaDoc namespaceURI,
70                String JavaDoc localName,
71                String JavaDoc qName,
72                Attributes JavaDoc atts) throws SAXException JavaDoc {
73     if (collectingCharacters)
74       flushCharacters();
75
76     Name name = new Name(namespaceURI, localName);
77     if (!setMemo(memo.startTagOpenDeriv(name))) {
78       PatternMemo next = memo.startTagOpenRecoverDeriv(name);
79       if (!next.isNotAllowed())
80         error("required_elements_missing");
81       else {
82         next = builder.getPatternMemo(builder.makeAfter(findElement(name), memo.getPattern()));
83         error(next.isNotAllowed() ? "unknown_element" : "out_of_context_element", name);
84       }
85       memo = next;
86     }
87     int len = atts.getLength();
88     for (int i = 0; i < len; i++) {
89       Name attName = new Name(atts.getURI(i), atts.getLocalName(i));
90
91       if (!setMemo(memo.startAttributeDeriv(attName)))
92     error("impossible_attribute_ignored", attName);
93       else if (!setMemo(memo.dataDeriv(atts.getValue(i), this))) {
94         error("bad_attribute_value", attName);
95         memo = memo.recoverAfter();
96       }
97     }
98     if (!setMemo(memo.endAttributes())) {
99       // XXX should specify which attributes
100
error("required_attributes_missing");
101       memo = memo.ignoreMissingAttributes();
102     }
103     if (memo.getPattern().getContentType() == Pattern.DATA_CONTENT_TYPE)
104       startCollectingCharacters();
105   }
106
107   private PatternMemo fixAfter(PatternMemo p) {
108     return builder.getPatternMemo(p.getPattern().applyForPattern(new ApplyAfterFunction(builder) {
109       Pattern apply(Pattern p) {
110         return builder.makeEmpty();
111       }
112     }));
113   }
114
115   public void endElement(String JavaDoc namespaceURI,
116              String JavaDoc localName,
117              String JavaDoc qName) throws SAXException JavaDoc {
118     // The tricky thing here is that the derivative that we compute may be notAllowed simply because the parent
119
// is notAllowed; we don't want to give an error in this case.
120
if (collectingCharacters) {
121       collectingCharacters = false;
122       if (!setMemo(memo.textOnly())) {
123     error("only_text_not_allowed");
124     memo = memo.recoverAfter();
125     return;
126       }
127       final String JavaDoc data = charBuf.toString();
128       if (!setMemo(memo.dataDeriv(data, this))) {
129         PatternMemo next = memo.recoverAfter();
130         if (!memo.isNotAllowed()) {
131           if (!next.isNotAllowed()
132               || fixAfter(memo).dataDeriv(data, this).isNotAllowed())
133             error("string_not_allowed");
134         }
135         memo = next;
136       }
137     }
138     else if (!setMemo(memo.endTagDeriv())) {
139       PatternMemo next = memo.recoverAfter();
140       if (!memo.isNotAllowed()) {
141         if (!next.isNotAllowed()
142             || fixAfter(memo).endTagDeriv().isNotAllowed())
143           error("unfinished_element");
144       }
145       memo = next;
146     }
147   }
148
149   public void characters(char ch[], int start, int length) throws SAXException JavaDoc {
150     if (collectingCharacters) {
151       charBuf.append(ch, start, length);
152       return;
153     }
154     for (int i = 0; i < length; i++) {
155       switch (ch[start + i]) {
156       case ' ':
157       case '\r':
158       case '\t':
159       case '\n':
160     break;
161       default:
162     text();
163     return;
164       }
165     }
166   }
167
168   private void text() throws SAXException JavaDoc {
169     if (!setMemo(memo.mixedTextDeriv()))
170       error("text_not_allowed");
171   }
172
173   public void endDocument() {
174     // XXX maybe check that memo.isNullable if !hadError
175
}
176
177   public void setDocumentLocator(Locator JavaDoc loc) {
178     locator = loc;
179   }
180
181   public void startDocument() throws SAXException JavaDoc {
182     if (memo.isNotAllowed())
183       error("schema_allows_nothing");
184   }
185   public void processingInstruction(String JavaDoc target, String JavaDoc date) { }
186   public void skippedEntity(String JavaDoc name) { }
187   public void ignorableWhitespace(char[] ch, int start, int len) { }
188   public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) {
189     prefixMapping = new PrefixMapping(prefix, uri, prefixMapping);
190   }
191   public void endPrefixMapping(String JavaDoc prefix) {
192     prefixMapping = prefixMapping.getPrevious();
193   }
194
195   public PatternValidator(Pattern pattern, ValidatorPatternBuilder builder, ErrorHandler JavaDoc eh) {
196     this.start = pattern;
197     this.builder = builder;
198     this.eh = eh;
199     reset();
200   }
201
202   public void reset() {
203     hadError = false;
204     collectingCharacters = false;
205     locator = null;
206     memo = builder.getPatternMemo(start);
207     prefixMapping = new PrefixMapping("xml", WellKnownNamespaces.XML, null);
208     clearDtdContext();
209   }
210
211   public ContentHandler JavaDoc getContentHandler() {
212     return this;
213   }
214
215   public DTDHandler JavaDoc getDTDHandler() {
216     return this;
217   }
218
219   private void error(String JavaDoc key) throws SAXException JavaDoc {
220     if (hadError && memo.isNotAllowed())
221       return;
222     hadError = true;
223     eh.error(new SAXParseException JavaDoc(SchemaBuilderImpl.localizer.message(key), locator));
224   }
225
226   private void error(String JavaDoc key, Name arg) throws SAXException JavaDoc {
227     error(key, NameFormatter.format(arg));
228   }
229
230   private void error(String JavaDoc key, String JavaDoc arg) throws SAXException JavaDoc {
231     if (hadError && memo.isNotAllowed())
232       return;
233     hadError = true;
234     eh.error(new SAXParseException JavaDoc(SchemaBuilderImpl.localizer.message(key, arg), locator));
235   }
236
237   /* Return false if m is notAllowed. */
238   private boolean setMemo(PatternMemo m) {
239     if (m.isNotAllowed())
240       return false;
241     else {
242       memo = m;
243       return true;
244     }
245   }
246
247   private Pattern findElement(Name name) {
248     if (recoverPatternTable == null)
249      recoverPatternTable = new Hashtable JavaDoc();
250     Pattern p = (Pattern)recoverPatternTable.get(name);
251     if (p == null) {
252       p = FindElementFunction.findElement(builder, name, start);
253       recoverPatternTable.put(name, p);
254     }
255     return p;
256   }
257
258   public String JavaDoc resolveNamespacePrefix(String JavaDoc prefix) {
259     PrefixMapping tem = prefixMapping;
260     do {
261       if (tem.prefix.equals(prefix))
262         return tem.namespaceURI;
263       tem = tem.previous;
264     } while (tem != null);
265     return null;
266   }
267
268   public String JavaDoc getBaseUri() {
269     return null;
270   }
271 }
272
Popular Tags