1 /*
2 
3    Licensed to the Apache Software Foundation (ASF) under one or more
4    contributor license agreements.  See the NOTICE file distributed with
5    this work for additional information regarding copyright ownership.
6    The ASF licenses this file to You under the Apache License, Version 2.0
7    (the "License"); you may not use this file except in compliance with
8    the License.  You may obtain a copy of the License at
9 
10        http://www.apache.org/licenses/LICENSE-2.0
11 
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 
18  */
19 package com.mxgraph.util.svg;
20 
21 import java.io.IOException;
22 import java.util.MissingResourceException;
23 
24 /**
25  * This class is the superclass of all parsers. It provides localization
26  * and error handling methods.
27  *
28  * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
29  */
30 public abstract class AbstractParser implements Parser
31 {
32 
33 	/**
34 	 * The default resource bundle base name.
35 	 */
36 	public static final String BUNDLE_CLASSNAME = "org.apache.batik.parser.resources.Messages";
37 
38 	/**
39 	 * The error handler.
40 	 */
41 	protected ErrorHandler errorHandler = new DefaultErrorHandler();
42 
43 	/**
44 	 * The normalizing reader.
45 	 */
46 	protected NormalizingReader reader;
47 
48 	/**
49 	 * The current character.
50 	 */
51 	protected int current;
52 
53 	/**
54 	 * Returns the current character value.
55 	 */
getCurrent()56 	public int getCurrent()
57 	{
58 		return current;
59 	}
60 
61 	/**
62 	 * Allow an application to register an error event handler.
63 	 *
64 	 * <p>If the application does not register an error event handler,
65 	 * all error events reported by the parser will cause an exception
66 	 * to be thrown.
67 	 *
68 	 * <p>Applications may register a new or different handler in the
69 	 * middle of a parse, and the parser must begin using the new
70 	 * handler immediately.</p>
71 	 * @param handler The error handler.
72 	 */
setErrorHandler(ErrorHandler handler)73 	public void setErrorHandler(ErrorHandler handler)
74 	{
75 		errorHandler = handler;
76 	}
77 
78 	/**
79 	 * Parses the given string.
80 	 */
parse(String s)81 	public void parse(String s) throws ParseException
82 	{
83 		try
84 		{
85 			reader = new StringNormalizingReader(s);
86 			doParse();
87 		}
88 		catch (IOException e)
89 		{
90 			errorHandler.error(new ParseException(createErrorMessage(
91 					"io.exception", null), e));
92 		}
93 	}
94 
95 	/**
96 	 * Method responsible for actually parsing data after AbstractParser
97 	 * has initialized itself.
98 	 */
doParse()99 	protected abstract void doParse() throws ParseException, IOException;
100 
101 	/**
102 	 * Signals an error to the error handler.
103 	 * @param key The message key in the resource bundle.
104 	 * @param args The message arguments.
105 	 */
reportError(String key, Object[] args)106 	protected void reportError(String key, Object[] args) throws ParseException
107 	{
108 		errorHandler.error(new ParseException(createErrorMessage(key, args),
109 				reader.getLine(), reader.getColumn()));
110 	}
111 
112 	/**
113 	 * simple api to call often reported error.
114 	 * Just a wrapper for reportError().
115 	 *
116 	 * @param expectedChar what caller expected
117 	 * @param currentChar what caller found
118 	 */
reportCharacterExpectedError(char expectedChar, int currentChar)119 	protected void reportCharacterExpectedError(char expectedChar,
120 			int currentChar)
121 	{
122 		reportError("character.expected", new Object[] {
123 				new Character(expectedChar), new Integer(currentChar) });
124 
125 	}
126 
127 	/**
128 	 * simple api to call often reported error.
129 	 * Just a wrapper for reportError().
130 	 *
131 	 * @param currentChar what the caller found and didnt expect
132 	 */
reportUnexpectedCharacterError(int currentChar)133 	protected void reportUnexpectedCharacterError(int currentChar)
134 	{
135 		reportError("character.unexpected", new Object[] { new Integer(
136 				currentChar) });
137 
138 	}
139 
140 	/**
141 	 * Returns a localized error message.
142 	 * @param key The message key in the resource bundle.
143 	 * @param args The message arguments.
144 	 */
createErrorMessage(String key, Object[] args)145 	protected String createErrorMessage(String key, Object[] args)
146 	{
147 		try
148 		{
149 			// TODO Replace with mx localisation
150 			// return formatMessage(key, args);
151 			return "";
152 		}
153 		catch (MissingResourceException e)
154 		{
155 			return key;
156 		}
157 	}
158 
159 	/**
160 	 * Returns the resource bundle base name.
161 	 * @return BUNDLE_CLASSNAME.
162 	 */
getBundleClassName()163 	protected String getBundleClassName()
164 	{
165 		return BUNDLE_CLASSNAME;
166 	}
167 
168 	/**
169 	 * Skips the whitespaces in the current reader.
170 	 */
skipSpaces()171 	protected void skipSpaces() throws IOException
172 	{
173 		for (;;)
174 		{
175 			switch (current)
176 			{
177 				default:
178 					return;
179 				case 0x20:
180 				case 0x09:
181 				case 0x0D:
182 				case 0x0A:
183 			}
184 			current = reader.read();
185 		}
186 	}
187 
188 	/**
189 	 * Skips the whitespaces and an optional comma.
190 	 */
skipCommaSpaces()191 	protected void skipCommaSpaces() throws IOException
192 	{
193 		wsp1: for (;;)
194 		{
195 			switch (current)
196 			{
197 				default:
198 					break wsp1;
199 				case 0x20:
200 				case 0x9:
201 				case 0xD:
202 				case 0xA:
203 			}
204 			current = reader.read();
205 		}
206 		if (current == ',')
207 		{
208 			wsp2: for (;;)
209 			{
210 				switch (current = reader.read())
211 				{
212 					default:
213 						break wsp2;
214 					case 0x20:
215 					case 0x9:
216 					case 0xD:
217 					case 0xA:
218 				}
219 			}
220 		}
221 	}
222 }
223