001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2007, Geotools Project Managment Committee (PMC)
005: * (C) 2007, Geomatys
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.util;
018:
019: // J2SE dependencies
020: import java.text.AttributedCharacterIterator;
021: import java.text.FieldPosition;
022: import java.text.Format;
023: import java.text.ParseException;
024: import java.text.ParsePosition;
025: import java.util.Locale;
026: import java.util.logging.Level;
027: import java.util.logging.LogRecord;
028: import java.util.logging.Logger;
029:
030: // Geotools dependencies
031: import org.geotools.resources.Utilities;
032: import org.geotools.resources.i18n.ErrorKeys;
033: import org.geotools.resources.i18n.Errors;
034:
035: /**
036: * Wraps a {@link Format} object in order to either parse fully a string, or log a warning.
037: * This class provides a {@link #parse} method which performs the following tasks:
038: * <p>
039: * <ul>
040: * <li>Checks if the string was fully parsed and log a warning if it was not. This is
041: * different than the default {@link #parseObject(String)} behavior which check only
042: * if the <em>begining</em> of the string was parsed and ignore any remaining characters.</li>
043: * <li>Ensures that the parsed object is of some specific class specified at construction time.</li>
044: * <li>If the string can't be fully parsed or is not of the expected class, logs a warning.</li>
045: * </ul>
046: *
047: * @since 2.4
048: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/util/LoggedFormat.java $
049: * @version $Id: LoggedFormat.java 27848 2007-11-12 13:10:32Z desruisseaux $
050: * @author Martin Desruisseaux
051: *
052: * @deprecated Moved to the {@link org.geotools.util.logging} package.
053: */
054: public class LoggedFormat/*<T>*/extends Format {
055: /**
056: * For cross-version compatibility.
057: */
058: private static final long serialVersionUID = 4578880360344271325L;
059:
060: /**
061: * The wrapped format.
062: */
063: private final Format format;
064:
065: /**
066: * The expected type for the parsed values.
067: */
068: private final Class/*<T>*/type;
069:
070: /**
071: * The logger where to log warnings, or {@code null} if none.
072: *
073: * @see #setLogger
074: */
075: private String logger;
076:
077: /**
078: * The class to declare in as the warning emitter, or {@code null} if none.
079: *
080: * @see #setCaller
081: */
082: private String className;
083:
084: /**
085: * The method to declare in as the warning emitter, or {@code null} if none.
086: *
087: * @see #setCaller
088: */
089: private String methodName;
090:
091: /**
092: * Creates a new format wrapping the specified one.
093: *
094: * @param format The format to use for parsing and formatting.
095: * @param type The expected type of parsed values.
096: */
097: protected LoggedFormat(final Format format, final Class/*<T>*/type) {
098: this .format = format;
099: this .type = type;
100: }
101:
102: /**
103: * Creates a new format wrapping the specified one.
104: *
105: * @param format The format to use for parsing and formatting.
106: * @param type The expected type of parsed values.
107: */
108: public static/*<T>*/LoggedFormat getInstance(final Format format,
109: final Class/*<T>*/type) {
110: return new LoggedFormat/*<T>*/(format, type);
111: }
112:
113: /**
114: * Sets the logger where to send the warnings eventually emitted by the {@link #parse} method.
115: *
116: * @param logger The logger where to log warnings, or {@code null} if none.
117: */
118: public void setLogger(final String logger) {
119: this .logger = logger;
120: }
121:
122: /**
123: * Sets the {@linkplain LogRecord#setSourceClassName source class name} and
124: * {@linkplain LogRecord#setSourceMethodName source method name} for the warnings
125: * eventually emitted by the {@link #parse} method.
126: *
127: * @param caller The class to declare as the warning emitter, or {@code null} if none.
128: * @param method The method to declare as the warning emitter, or {@code null} if none.
129: *
130: * @todo Use Class.getSimpleName() or something like that when we will be allowed to compile
131: * for J2SE 1.5.
132: */
133: public void setCaller(final Class caller, final String method) {
134: this .className = (caller != null) ? caller.getName() : null;
135: this .methodName = method;
136: }
137:
138: /**
139: * Parses the specified string. If the string can't be parsed, then this method returns
140: * {@code null}. If it can be parsed at least partially and is of the kind specified at
141: * construction time, then it is returned. If the string has not been fully parsed, then
142: * a {@linkplain LogRecord log record} is prepared and logged.
143: *
144: * @param text The text to parse, or {@code null}.
145: * @return The parsed object, or {@code null} if {@code text} was null or can't be parsed.
146: */
147: public Object/*<T>*/parse(String text) {
148: if (text == null || (text = text.trim()).length() == 0) {
149: return null;
150: }
151: final ParsePosition position = new ParsePosition(0);
152: final Object value = parseObject(text, position);
153: int index = position.getIndex();
154: final int error = position.getErrorIndex();
155: if (error >= 0 && error < index) {
156: index = error;
157: }
158: if (index < text.length()) {
159: logWarning(ErrorKeys.UNPARSABLE_STRING_$2, text, text
160: .substring(index));
161: } else if (value != null && !type.isInstance(value)) {
162: logWarning(ErrorKeys.ILLEGAL_CLASS_$2, value.getClass(),
163: type);
164: return null;
165: }
166: return value; // Use Class.cast with J2SE 1.5.
167: }
168:
169: /**
170: * Parses text from a string to produce an object. This method delegates the work to the
171: * {@linkplain Format format} specified at construction time. This method to not perform
172: * any logging.
173: *
174: * @param text The text to parse.
175: * @return An object parsed from the string.
176: * @throws ParseException if parsing failed.
177: */
178: //@Override
179: public Object parseObject(final String text) throws ParseException {
180: return format.parseObject(text);
181: }
182:
183: /**
184: * Parses text from a string to produce an object. This method delegates the work to the
185: * {@linkplain Format format} specified at construction time. This method to not perform
186: * any logging.
187: *
188: * @param text The text to parse.
189: * @param position Index and error index information.
190: * @return An object parsed from the string, or {@code null} in case of error.
191: */
192: public Object parseObject(final String text,
193: final ParsePosition position) {
194: return format.parseObject(text, position);
195: }
196:
197: /**
198: * Formats the specified object. This method delegates the work to the
199: * {@linkplain Format format} specified at construction time.
200: *
201: * @param value The object to format.
202: * @param toAppendTo The buffer where the text is to be appended.
203: * @param position Identifies a field in the formatted text.
204: * @return The string buffer passed in with formatted text appended.
205: */
206: public StringBuffer format(final Object value,
207: final StringBuffer toAppendTo, final FieldPosition position) {
208: return format.format(value, toAppendTo, position);
209: }
210:
211: /**
212: * Formats the specified object. This method delegates the work to the
213: * {@linkplain Format format} specified at construction time.
214: *
215: * @param value The object to format.
216: * @return The character iterator describing the formatted value.
217: */
218: //@Override
219: public AttributedCharacterIterator formatToCharacterIterator(
220: final Object value) {
221: return format.formatToCharacterIterator(value);
222: }
223:
224: /**
225: * Logs a warning.
226: *
227: * @param key The resource key.
228: * @param arg1 First value to format in the message.
229: * @param arg1 Second value to format in the message.
230: */
231: private void logWarning(final int key, final Object arg1,
232: final Object arg2) {
233: final LogRecord warning = Errors.getResources(
234: getWarningLocale()).getLogRecord(Level.WARNING, key,
235: arg1, arg2);
236: if (className != null) {
237: warning.setSourceClassName(className);
238: }
239: if (methodName != null) {
240: warning.setSourceMethodName(methodName);
241: }
242: logWarning(warning);
243: }
244:
245: /**
246: * Logs a warning. This method is invoked automatically by the {@link #parse parse} method
247: * when a text can't be fully parsed. The default implementation logs the warning to the
248: * logger specified by the last call to the {@link #setLogger setLogger} method. Subclasses
249: * may override this method if they want to change the log record before the logging.
250: *
251: * @param warning The warning to log.
252: */
253: protected void logWarning(final LogRecord warning) {
254: if (logger != null) {
255: Logger.getLogger(logger).log(warning);
256: }
257: }
258:
259: /**
260: * Returns the locale to use for formatting warnings. The default implementation returns
261: * the {@linkplain Locale#getDefault() default locale}.
262: */
263: protected Locale getWarningLocale() {
264: return Locale.getDefault();
265: }
266:
267: /**
268: * Returns a string representation for debugging purpose.
269: */
270: public String toString() {
271: final StringBuffer buffer = new StringBuffer(Utilities
272: .getShortClassName(this )).append('[').append(
273: Utilities.getShortClassName(format));
274: if (logger != null) {
275: buffer.append(", logger=").append(logger);
276: }
277: return buffer.append(']').toString();
278: }
279: }
|