001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.parser;
020:
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.Reader;
024: import java.util.Locale;
025: import java.util.MissingResourceException;
026:
027: import org.apache.batik.i18n.LocalizableSupport;
028: import org.apache.batik.util.io.NormalizingReader;
029: import org.apache.batik.util.io.StreamNormalizingReader;
030: import org.apache.batik.util.io.StringNormalizingReader;
031:
032: /**
033: * This class is the superclass of all parsers. It provides localization
034: * and error handling methods.
035: *
036: * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
037: * @version $Id: AbstractParser.java 502167 2007-02-01 09:26:51Z dvholten $
038: */
039: public abstract class AbstractParser implements Parser {
040:
041: /**
042: * The default resource bundle base name.
043: */
044: public static final String BUNDLE_CLASSNAME = "org.apache.batik.parser.resources.Messages";
045:
046: /**
047: * The error handler.
048: */
049: protected ErrorHandler errorHandler = new DefaultErrorHandler();
050:
051: /**
052: * The localizable support.
053: */
054: protected LocalizableSupport localizableSupport = new LocalizableSupport(
055: BUNDLE_CLASSNAME, AbstractParser.class.getClassLoader());
056:
057: /**
058: * The normalizing reader.
059: */
060: protected NormalizingReader reader;
061:
062: /**
063: * The current character.
064: */
065: protected int current;
066:
067: /**
068: * Returns the current character value.
069: */
070: public int getCurrent() {
071: return current;
072: }
073:
074: /**
075: * Implements {@link org.apache.batik.i18n.Localizable#setLocale(Locale)}.
076: */
077: public void setLocale(Locale l) {
078: localizableSupport.setLocale(l);
079: }
080:
081: /**
082: * Implements {@link org.apache.batik.i18n.Localizable#getLocale()}.
083: */
084: public Locale getLocale() {
085: return localizableSupport.getLocale();
086: }
087:
088: /**
089: * Implements {@link
090: * org.apache.batik.i18n.Localizable#formatMessage(String,Object[])}.
091: */
092: public String formatMessage(String key, Object[] args)
093: throws MissingResourceException {
094: return localizableSupport.formatMessage(key, args);
095: }
096:
097: /**
098: * Allow an application to register an error event handler.
099: *
100: * <p>If the application does not register an error event handler,
101: * all error events reported by the parser will cause an exception
102: * to be thrown.
103: *
104: * <p>Applications may register a new or different handler in the
105: * middle of a parse, and the parser must begin using the new
106: * handler immediately.</p>
107: * @param handler The error handler.
108: */
109: public void setErrorHandler(ErrorHandler handler) {
110: errorHandler = handler;
111: }
112:
113: /**
114: * Parses the given reader
115: */
116: public void parse(Reader r) throws ParseException {
117: try {
118: reader = new StreamNormalizingReader(r);
119: doParse();
120: } catch (IOException e) {
121: errorHandler.error(new ParseException(createErrorMessage(
122: "io.exception", null), e));
123: }
124: }
125:
126: /**
127: * Parses the given input stream. If the encoding is null,
128: * ISO-8859-1 is used.
129: */
130: public void parse(InputStream is, String enc) throws ParseException {
131: try {
132: reader = new StreamNormalizingReader(is, enc);
133: doParse();
134: } catch (IOException e) {
135: errorHandler.error(new ParseException(createErrorMessage(
136: "io.exception", null), e));
137: }
138: }
139:
140: /**
141: * Parses the given string.
142: */
143: public void parse(String s) throws ParseException {
144: try {
145: reader = new StringNormalizingReader(s);
146: doParse();
147: } catch (IOException e) {
148: errorHandler.error(new ParseException(createErrorMessage(
149: "io.exception", null), e));
150: }
151: }
152:
153: /**
154: * Method responsible for actually parsing data after AbstractParser
155: * has initialized itself.
156: */
157: protected abstract void doParse() throws ParseException,
158: IOException;
159:
160: /**
161: * Signals an error to the error handler.
162: * @param key The message key in the resource bundle.
163: * @param args The message arguments.
164: */
165: protected void reportError(String key, Object[] args)
166: throws ParseException {
167: errorHandler.error(new ParseException(createErrorMessage(key,
168: args), reader.getLine(), reader.getColumn()));
169: }
170:
171: /**
172: * simple api to call often reported error.
173: * Just a wrapper for reportError().
174: *
175: * @param expectedChar what caller expected
176: * @param currentChar what caller found
177: */
178: protected void reportCharacterExpectedError(char expectedChar,
179: int currentChar) {
180: reportError("character.expected", new Object[] {
181: new Character(expectedChar), new Integer(currentChar) });
182:
183: }
184:
185: /**
186: * simple api to call often reported error.
187: * Just a wrapper for reportError().
188: *
189: * @param currentChar what the caller found and didnt expect
190: */
191: protected void reportUnexpectedCharacterError(int currentChar) {
192: reportError("character.unexpected", new Object[] { new Integer(
193: currentChar) });
194:
195: }
196:
197: /**
198: * Returns a localized error message.
199: * @param key The message key in the resource bundle.
200: * @param args The message arguments.
201: */
202: protected String createErrorMessage(String key, Object[] args) {
203: try {
204: return formatMessage(key, args);
205: } catch (MissingResourceException e) {
206: return key;
207: }
208: }
209:
210: /**
211: * Returns the resource bundle base name.
212: * @return BUNDLE_CLASSNAME.
213: */
214: protected String getBundleClassName() {
215: return BUNDLE_CLASSNAME;
216: }
217:
218: /**
219: * Skips the whitespaces in the current reader.
220: */
221: protected void skipSpaces() throws IOException {
222: for (;;) {
223: switch (current) {
224: default:
225: return;
226: case 0x20:
227: case 0x09:
228: case 0x0D:
229: case 0x0A:
230: }
231: current = reader.read();
232: }
233: }
234:
235: /**
236: * Skips the whitespaces and an optional comma.
237: */
238: protected void skipCommaSpaces() throws IOException {
239: wsp1: for (;;) {
240: switch (current) {
241: default:
242: break wsp1;
243: case 0x20:
244: case 0x9:
245: case 0xD:
246: case 0xA:
247: }
248: current = reader.read();
249: }
250: if (current == ',') {
251: wsp2: for (;;) {
252: switch (current = reader.read()) {
253: default:
254: break wsp2;
255: case 0x20:
256: case 0x9:
257: case 0xD:
258: case 0xA:
259: }
260: }
261: }
262: }
263: }
|