001 /* ========================================================================
002 * JCommon : a free general purpose class library for the Java(tm) platform
003 * ========================================================================
004 *
005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jcommon/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * ---------------
028 * ParserUtil.java
029 * ---------------
030 * (C)opyright 2002-2005, by Thomas Morgner and Contributors.
031 *
032 * Original Author: Thomas Morgner (taquera@sherito.org);
033 * Contributor(s): David Gilbert (for Object Refinery Limited);
034 *
035 * $Id: ParserUtil.java,v 1.3 2005/10/18 13:25:44 mungady Exp $
036 *
037 * Changes
038 * -------
039 * 21-May-2002 : Contains utility functions to make parsing easier.
040 * 10-Dec-2002 : Fixed issues reported by Checkstyle (DG);
041 * 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon;
042 * 23-Sep-2003 : Minor Javadoc updates (DG);
043 *
044 */
045 package org.jfree.xml;
046
047 import java.awt.BasicStroke;
048 import java.awt.Color;
049 import java.awt.Stroke;
050 import java.awt.geom.Rectangle2D;
051 import java.lang.reflect.Field;
052
053 import org.xml.sax.Attributes;
054 import org.xml.sax.SAXException;
055
056 /**
057 * Basic helper functions to ease up the process of parsing.
058 *
059 * @author Thomas Morgner
060 */
061 public class ParserUtil {
062
063 /**
064 * Parses the string <code>text</code> into an int. If text is null or does not
065 * contain a parsable value, the message given in <code>message</code> is used to
066 * throw a SAXException.
067 *
068 * @param text the text to parse.
069 * @param message the error message if parsing fails.
070 *
071 * @return the int value.
072 *
073 * @throws SAXException if there is a problem with the parsing.
074 */
075 public static int parseInt(final String text, final String message) throws SAXException {
076 if (text == null) {
077 throw new SAXException(message);
078 }
079
080 try {
081 return Integer.parseInt(text);
082 }
083 catch (NumberFormatException nfe) {
084 throw new SAXException("NumberFormatError: " + message);
085 }
086 }
087
088 /**
089 * Parses an integer.
090 *
091 * @param text the text to parse.
092 * @param defaultVal the default value.
093 *
094 * @return the integer.
095 */
096 public static int parseInt(final String text, final int defaultVal) {
097 if (text == null) {
098 return defaultVal;
099 }
100
101 try {
102 return Integer.parseInt(text);
103 }
104 catch (NumberFormatException nfe) {
105 return defaultVal;
106 }
107 }
108
109 /**
110 * Parses the string <code>text</code> into an float. If text is null or does not
111 * contain a parsable value, the message given in <code>message</code> is used to
112 * throw a SAXException.
113 *
114 * @param text the text to parse.
115 * @param message the error message if parsing fails.
116 *
117 * @return the float value.
118 *
119 * @throws SAXException if there is a problem with the parsing.
120 */
121 public static float parseFloat(final String text, final String message) throws SAXException {
122 if (text == null) {
123 throw new SAXException(message);
124 }
125 try {
126 return Float.parseFloat(text);
127 }
128 catch (NumberFormatException nfe) {
129 throw new SAXException("NumberFormatError: " + message);
130 }
131 }
132
133 /**
134 * Parses the string <code>text</code> into an float. If text is null or does not
135 * contain a parsable value, the message given in <code>message</code> is used to
136 * throw a SAXException.
137 *
138 * @param text the text to parse.
139 * @param defaultVal the defaultValue returned if parsing fails.
140 *
141 * @return the float value.
142 */
143 public static float parseFloat(final String text, final float defaultVal) {
144 if (text == null) {
145 return defaultVal;
146 }
147 try {
148 return Float.parseFloat(text);
149 }
150 catch (NumberFormatException nfe) {
151 return defaultVal;
152 }
153 }
154
155 /**
156 * Parses a boolean. If the string <code>text</code> contains the value of "true", the
157 * true value is returned, else false is returned.
158 *
159 * @param text the text to parse.
160 * @param defaultVal the default value.
161 *
162 * @return a boolean.
163 */
164 public static boolean parseBoolean(final String text, final boolean defaultVal) {
165 if (text == null) {
166 return defaultVal;
167 }
168 return text.equalsIgnoreCase("true");
169 }
170
171 /**
172 * Parses a string. If the <code>text</code> is null, defaultval is returned.
173 *
174 * @param text the text to parse.
175 * @param defaultVal the default value.
176 *
177 * @return a string.
178 */
179 public static String parseString(final String text, final String defaultVal) {
180 if (text == null) {
181 return defaultVal;
182 }
183 return text;
184 }
185
186 /**
187 * Creates a basic stroke given the width contained as float in the given string.
188 * If the string could not be parsed into a float, a basic stroke with the width of
189 * 1 is returned.
190 *
191 * @param weight a string containing a number (the stroke weight).
192 *
193 * @return the stroke.
194 */
195 public static Stroke parseStroke(final String weight) {
196 try {
197 if (weight != null) {
198 final Float w = new Float(weight);
199 return new BasicStroke(w.floatValue());
200 }
201 }
202 catch (NumberFormatException nfe) {
203 //Log.warn("Invalid weight for stroke", nfe);
204 }
205 return new BasicStroke(1);
206 }
207
208 /**
209 * Parses a color entry. If the entry is in hexadecimal or ocal notation, the color is
210 * created using Color.decode(). If the string denotes a constant name of on of the color
211 * constants defined in java.awt.Color, this constant is used.
212 * <p>
213 * As fallback the color black is returned if no color can be parsed.
214 *
215 * @param color the color (as a string).
216 *
217 * @return the paint.
218 */
219 public static Color parseColor(final String color) {
220 return parseColor(color, Color.black);
221 }
222
223 /**
224 * Parses a color entry. If the entry is in hexadecimal or octal notation, the color is
225 * created using Color.decode(). If the string denotes a constant name of one of the color
226 * constants defined in java.awt.Color, this constant is used.
227 * <p>
228 * As fallback the supplied default value is returned if no color can be parsed.
229 *
230 * @param color the color (as a string).
231 * @param defaultValue the default value (returned if no color can be parsed).
232 *
233 * @return the paint.
234 */
235 public static Color parseColor(final String color, final Color defaultValue) {
236 if (color == null) {
237 return defaultValue;
238 }
239 try {
240 // get color by hex or octal value
241 return Color.decode(color);
242 }
243 catch (NumberFormatException nfe) {
244 // if we can't decode lets try to get it by name
245 try {
246 // try to get a color by name using reflection
247 // black is used for an instance and not for the color itselfs
248 final Field f = Color.class.getField(color);
249
250 return (Color) f.get(null);
251 }
252 catch (Exception ce) {
253 //Log.warn("No such Color : " + color);
254 // if we can't get any color return black
255 return defaultValue;
256 }
257 }
258 }
259
260
261 /**
262 * Parses a position of an element. If a relative postion is given, the returnvalue
263 * is a negative number between 0 and -100.
264 *
265 * @param value the value.
266 * @param exceptionMessage the exception message.
267 *
268 * @return the float value.
269 *
270 * @throws SAXException if there is a problem parsing the string.
271 */
272 public static float parseRelativeFloat(final String value, final String exceptionMessage)
273 throws SAXException {
274 if (value == null) {
275 throw new SAXException(exceptionMessage);
276 }
277 final String tvalue = value.trim();
278 if (tvalue.endsWith("%")) {
279 final String number = tvalue.substring(0, tvalue.indexOf("%"));
280 final float f = parseFloat(number, exceptionMessage) * -1.0f;
281 return f;
282 }
283 else {
284 return parseFloat(tvalue, exceptionMessage);
285 }
286 }
287
288 /**
289 * Parses an element position. The position is stored in the attributes "x", "y", "width" and
290 * "height". The attributes are allowed to have relative notion.
291 *
292 * @param atts the attributes.
293 *
294 * @return the element position.
295 *
296 * @throws SAXException if there is a problem getting the element position.
297 */
298 public static Rectangle2D getElementPosition(final Attributes atts) throws SAXException {
299 final float x = ParserUtil.parseRelativeFloat(atts.getValue("x"),
300 "Element x not specified");
301 final float y = ParserUtil.parseRelativeFloat(atts.getValue("y"),
302 "Element y not specified");
303 final float w = ParserUtil.parseRelativeFloat(atts.getValue("width"),
304 "Element width not specified");
305 final float h = ParserUtil.parseRelativeFloat(atts.getValue("height"),
306 "Element height not specified");
307 final Rectangle2D.Float retval = new Rectangle2D.Float(x, y, w, h);
308 return retval;
309 }
310
311 }