1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
33 import org.xml.sax.Attributes;
34 import org.xml.sax.ContentHandler;
35 import org.xml.sax.Locator;
36 import org.xml.sax.SAXException;
37 import org.xml.sax.SAXParseException;
38
39 /**
40 * Runtime Engine for RELAXNGCC execution.
41 *
42 * This class has the following functionalities:
43 *
44 * <ol>
45 * <li>Managing a stack of NGCCHandler objects and
46 * switching between them appropriately.
47 *
48 * <li>Keep track of all Attributes.
49 *
50 * <li>manage mapping between namespace URIs and prefixes.
51 *
52 * <li>TODO: provide support for interleaving.
53 *
54 * @version $Id: NGCCRuntime.java,v 1.15 2002/09/29 02:55:48 okajima Exp $
55 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
56 */
57 public class NGCCRuntime implements ContentHandler, NGCCEventSource {
58
59 public NGCCRuntime() {
60 reset();
61 }
62
63 /**
64 * Sets the root handler, which will be used to parse the
65 * root element.
66 * <p>
67 * This method can be called right after the object is created
68 * or the reset method is called. You can't replace the root
69 * handler while parsing is in progress.
70 * <p>
71 * Usually a generated class that corresponds to the <start>
72 * pattern will be used as the root handler, but any NGCCHandler
73 * can be a root handler.
74 *
75 * @exception IllegalStateException
76 * If this method is called but it doesn't satisfy the
77 * pre-condition stated above.
78 */
79 public void setRootHandler( NGCCHandler rootHandler ) {
80 if(currentHandler!=null)
81 throw new IllegalStateException();
82 currentHandler = rootHandler;
83 }
84
85
86 /**
87 * Cleans up all the data structure so that the object can be reused later.
88 * Normally, applications do not need to call this method directly,
89 *
90 * as the runtime resets itself after the endDocument method.
91 */
161 *
162 * <p>
163 * Whitespace handling is a tricky business. Consider the following
164 * schema fragment:
165 *
166 * <pre>{@code
167 * <element name="foo">
168 * <choice>
169 * <element name="bar"><empty/></element>
170 * <text/>
171 * </choice>
172 * </element>
173 * }</pre>
174 *
175 * Assume we hit the following instance:
176 * <pre>{@code
177 * <foo> <bar/></foo>
178 * }</pre>
179 *
180 * Then this first space needs to be ignored (for otherwise, we will
181 * end up treating this space as the match to <text/> and won't
182 * be able to process <bar>.)
183 *
184 * Now assume the following instance:
185 * <pre>{@code
186 * <foo/>
187 * }</pre>
188 *
189 * This time, we need to treat this empty string as a text, for
190 * otherwise we won't be able to accept this instance.
191 *
192 * <p>
193 * This is very difficult to solve in general, but one seemingly
194 * easy solution is to use the type of next event. If a text is
195 * followed by a start tag, it follows from the constraint on
196 * RELAX NG that that text must be either whitespaces or a match
197 * to <text/>.
198 *
199 * <p>
200 * On the contrary, if a text is followed by a end tag, then it
201 * cannot be whitespace unless the content model can accept empty,
202 * in which case sending a text event will be harmlessly ignored
203 * by the NGCCHandler.
204 *
205 * <p>
206 * Thus this method take one parameter, which controls the
207 * behavior of this method.
208 *
209 * <p>
210 * TODO: according to the constraint of RELAX NG, if characters
211 * follow an end tag, then they must be either whitespaces or
212 * must match to <text/>.
213 *
214 * @param possiblyWhitespace
215 * True if the buffered character can be ignorabale. False if
216 * it needs to be consumed.
217 */
218 private void processPendingText(boolean ignorable) throws SAXException {
219 if(ignorable && text.toString().trim().length()==0)
220 ; // ignore. See the above javadoc comment for the description
221 else
222 currentHandler.text(text.toString()); // otherwise consume this token
223
224 // truncate StringBuffer, but avoid excessive allocation.
225 if(text.length()>1024) text = new StringBuffer();
226 else text.setLength(0);
227 }
228
229 public void processList( String str ) throws SAXException {
230 StringTokenizer t = new StringTokenizer(str, " \t\r\n");
231 while(t.hasMoreTokens())
232 currentHandler.text(t.nextToken());
233 }
234
498 private int nsEffectivePtr=0;
499
500 /**
501 * Stack to preserve old nsEffectivePtr values.
502 */
503 private final Stack nsEffectiveStack = new Stack();
504
505 public String resolveNamespacePrefix( String prefix ) {
506 for( int i = nsEffectivePtr-2; i>=0; i-=2 )
507 if( namespaces.get(i).equals(prefix) )
508 return (String)namespaces.get(i+1);
509
510 // no binding was found.
511 if(prefix.equals("")) return ""; // return the default no-namespace
512 if(prefix.equals("xml")) // pre-defined xml prefix
513 return "http://www.w3.org/XML/1998/namespace";
514 else return null; // prefix undefined
515 }
516
517
518 // error reporting
519 protected void unexpectedX(String token) throws SAXException {
520 throw new SAXParseException(MessageFormat.format(
521 "Unexpected {0} appears at line {1} column {2}",
522 new Object[]{
523 token,
524 new Integer(getLocator().getLineNumber()),
525 new Integer(getLocator().getColumnNumber()) }),
526 getLocator());
527 }
528
529
530
531
532 //
533 //
534 // trace functions
535 //
536 //
537 private int indent=0;
538 private boolean needIndent=true;
539 private void printIndent() {
540 for( int i=0; i<indent; i++ )
541 System.out.print(" ");
542 }
543 public void trace( String s ) {
544 if(needIndent) {
545 needIndent=false;
546 printIndent();
547 }
548 System.out.print(s);
549 }
550 public void traceln( String s ) {
551 trace(s);
552 trace("\n");
|
1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
33 import org.xml.sax.Attributes;
34 import org.xml.sax.ContentHandler;
35 import org.xml.sax.Locator;
36 import org.xml.sax.SAXException;
37 import org.xml.sax.SAXParseException;
38
39 /**
40 * Runtime Engine for RELAXNGCC execution.
41 *
42 * This class has the following functionalities:
43 *
44 * <ol>
45 * <li>Managing a stack of NGCCHandler objects and
46 * switching between them appropriately.
47 *
48 * <li>Keep track of all Attributes.
49 *
50 * <li>manage mapping between namespace URIs and prefixes.
51 *
52 * <li>TODO: provide support for interleaving.
53 * </ol>
54 *
55 * <p><b>
56 * Auto-generated, do not edit.
57 * </b></p>
58 * @version $Id: NGCCRuntime.java,v 1.15 2002/09/29 02:55:48 okajima Exp $
59 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
60 */
61 public class NGCCRuntime implements ContentHandler, NGCCEventSource {
62
63 public NGCCRuntime() {
64 reset();
65 }
66
67 /**
68 * Sets the root handler, which will be used to parse the
69 * root element.
70 * <p>
71 * This method can be called right after the object is created
72 * or the reset method is called. You can't replace the root
73 * handler while parsing is in progress.
74 * <p>
75 * Usually a generated class that corresponds to the {@code <start>}
76 * pattern will be used as the root handler, but any NGCCHandler
77 * can be a root handler.
78 *
79 * @exception IllegalStateException
80 * If this method is called but it doesn't satisfy the
81 * pre-condition stated above.
82 */
83 public void setRootHandler( NGCCHandler rootHandler ) {
84 if(currentHandler!=null)
85 throw new IllegalStateException();
86 currentHandler = rootHandler;
87 }
88
89
90 /**
91 * Cleans up all the data structure so that the object can be reused later.
92 * Normally, applications do not need to call this method directly,
93 *
94 * as the runtime resets itself after the endDocument method.
95 */
165 *
166 * <p>
167 * Whitespace handling is a tricky business. Consider the following
168 * schema fragment:
169 *
170 * <pre>{@code
171 * <element name="foo">
172 * <choice>
173 * <element name="bar"><empty/></element>
174 * <text/>
175 * </choice>
176 * </element>
177 * }</pre>
178 *
179 * Assume we hit the following instance:
180 * <pre>{@code
181 * <foo> <bar/></foo>
182 * }</pre>
183 *
184 * Then this first space needs to be ignored (for otherwise, we will
185 * end up treating this space as the match to {@code <text/>} and won't
186 * be able to process {@code <bar>}.)
187 *
188 * Now assume the following instance:
189 * <pre>{@code
190 * <foo/>
191 * }</pre>
192 *
193 * This time, we need to treat this empty string as a text, for
194 * otherwise we won't be able to accept this instance.
195 *
196 * <p>
197 * This is very difficult to solve in general, but one seemingly
198 * easy solution is to use the type of next event. If a text is
199 * followed by a start tag, it follows from the constraint on
200 * RELAX NG that that text must be either whitespaces or a match
201 * to {@code <text/>}.
202 *
203 * <p>
204 * On the contrary, if a text is followed by a end tag, then it
205 * cannot be whitespace unless the content model can accept empty,
206 * in which case sending a text event will be harmlessly ignored
207 * by the NGCCHandler.
208 *
209 * <p>
210 * Thus this method take one parameter, which controls the
211 * behavior of this method.
212 *
213 * <p>
214 * TODO: according to the constraint of RELAX NG, if characters
215 * follow an end tag, then they must be either whitespaces or
216 * must match to {@code <text/>}.
217 *
218 * @param ignorable
219 * True if the buffered character can be ignorabale. False if
220 * it needs to be consumed.
221 */
222 private void processPendingText(boolean ignorable) throws SAXException {
223 if(ignorable && text.toString().trim().length()==0)
224 ; // ignore. See the above javadoc comment for the description
225 else
226 currentHandler.text(text.toString()); // otherwise consume this token
227
228 // truncate StringBuffer, but avoid excessive allocation.
229 if(text.length()>1024) text = new StringBuffer();
230 else text.setLength(0);
231 }
232
233 public void processList( String str ) throws SAXException {
234 StringTokenizer t = new StringTokenizer(str, " \t\r\n");
235 while(t.hasMoreTokens())
236 currentHandler.text(t.nextToken());
237 }
238
502 private int nsEffectivePtr=0;
503
504 /**
505 * Stack to preserve old nsEffectivePtr values.
506 */
507 private final Stack nsEffectiveStack = new Stack();
508
509 public String resolveNamespacePrefix( String prefix ) {
510 for( int i = nsEffectivePtr-2; i>=0; i-=2 )
511 if( namespaces.get(i).equals(prefix) )
512 return (String)namespaces.get(i+1);
513
514 // no binding was found.
515 if(prefix.equals("")) return ""; // return the default no-namespace
516 if(prefix.equals("xml")) // pre-defined xml prefix
517 return "http://www.w3.org/XML/1998/namespace";
518 else return null; // prefix undefined
519 }
520
521
522 // error reporting
523 protected void unexpectedX(String token) throws SAXException {
524 throw new SAXParseException(MessageFormat.format(
525 "Unexpected {0} appears at line {1} column {2}",
526 new Object[]{
527 token,
528 new Integer(getLocator().getLineNumber()),
529 new Integer(getLocator().getColumnNumber()) }),
530 getLocator());
531 }
532
533
534
535
536 //
537 //
538 // trace functions
539 //
540 //
541 private int indent=0;
542 private boolean needIndent=true;
543 private void printIndent() {
544 for( int i=0; i<indent; i++ )
545 System.out.print(" ");
546 }
547 public void trace( String s ) {
548 if(needIndent) {
549 needIndent=false;
550 printIndent();
551 }
552 System.out.print(s);
553 }
554 public void traceln( String s ) {
555 trace(s);
556 trace("\n");
|