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 * FrontendDefaultHandler.java
029 * ------------
030 * (C) Copyright 2002-2005, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   -;
034 *
035 * $Id: FrontendDefaultHandler.java,v 1.9 2008/09/10 09:20:49 mungady Exp $
036 *
037 * Changes
038 * -------
039 * 02-Feb-2005 : Initial version.
040 *
041 */
042package org.jfree.xml;
043
044import java.net.MalformedURLException;
045import java.net.URL;
046import java.util.Iterator;
047import java.util.Enumeration;
048
049import org.jfree.util.Configuration;
050import org.jfree.util.DefaultConfiguration;
051import org.xml.sax.Locator;
052import org.xml.sax.SAXException;
053import org.xml.sax.helpers.DefaultHandler;
054
055/**
056 * The frontenddefault handler connects the SAX-backend with the handler implementations.
057 * It must be the base class for all parser implementations used by the ParserFrontEnd.
058 *
059 * @author Thomas Morgner
060 */
061public abstract class FrontendDefaultHandler extends DefaultHandler implements Configuration {
062    /**
063     * A key for the content base.
064     */
065    public static final String CONTENTBASE_KEY = "content-base";
066
067    /**
068     * Storage for the parser configuration.
069     */
070    private DefaultConfiguration parserConfiguration;
071
072    /**
073     * The DocumentLocator can be used to resolve the current parse position.
074     */
075    private Locator locator;
076
077    /**
078     * The current comment handler used to receive xml comments.
079     */
080    private final CommentHandler commentHandler;
081
082    /**
083     * Default constructor.
084     */
085    protected FrontendDefaultHandler() {
086        this.parserConfiguration = new DefaultConfiguration();
087        this.commentHandler = new CommentHandler();
088    }
089
090    /**
091     * Returns the comment handler that is used to collect comments.
092     *
093     * @return the comment handler.
094     */
095    public CommentHandler getCommentHandler() {
096        return this.commentHandler;
097    }
098
099    /**
100     * Receive an object for locating the origin of SAX document events.
101     * <p>
102     * The locator allows the application to determine the end position of
103     * any document-related event, even if the parser is not reporting an
104     * error. Typically, the application will use this information for
105     * reporting its own errors (such as character content that does not
106     * match an application's business rules). The information returned by
107     * the locator is probably not sufficient for use with a search engine.
108     * </p>
109     * 
110     * @param locator the locator.
111     */
112    public void setDocumentLocator(final Locator locator) {
113        this.locator = locator;
114    }
115
116    /**
117     * Returns the current locator.
118     *
119     * @return the locator.
120     */
121    public Locator getLocator() {
122        return this.locator;
123    }
124
125    /**
126     * Returns the configuration property with the specified key.
127     *
128     * @param key the property key.
129     * @return the property value.
130     */
131    public String getConfigProperty(final String key) {
132        return getConfigProperty(key, null);
133    }
134
135    /**
136     * Returns the configuration property with the specified key (or the specified default value
137     * if there is no such property).
138     * <p>
139     * If the property is not defined in this configuration, the code will lookup the property in
140     * the parent configuration.</p>
141     *
142     * @param key          the property key.
143     * @param defaultValue the default value.
144     * @return the property value.
145     */
146    public String getConfigProperty(final String key, final String defaultValue) {
147        return this.parserConfiguration.getConfigProperty(key, defaultValue);
148    }
149
150    /**
151     * Sets a parser configuration value.
152     *
153     * @param key   the key.
154     * @param value the value.
155     */
156    public void setConfigProperty(final String key, final String value) {
157        if (value == null) {
158            this.parserConfiguration.remove(key);
159        }
160        else {
161            this.parserConfiguration.setProperty(key, value);
162        }
163    }
164
165    /**
166     * Returns the configuration properties.
167     *
168     * @return An enumeration of the configuration properties.
169     */
170    public Enumeration getConfigProperties()
171    {
172      return this.parserConfiguration.getConfigProperties();
173    }
174
175  /**
176     * Returns a new instance of the parser.
177     *
178     * @return a new instance of the parser.
179     */
180    public abstract FrontendDefaultHandler newInstance();
181
182    /**
183     * Returns all keys with the given prefix.
184     *
185     * @param prefix the prefix
186     * @return the iterator containing all keys with that prefix
187     */
188    public Iterator findPropertyKeys(final String prefix) {
189        return this.parserConfiguration.findPropertyKeys(prefix);
190    }
191
192    /**
193     * Returns the parse result. This method is called at the end of the
194     * parsing process and expects the generated object.
195     *
196     * @return the object.
197     * @throws SAXException if something went wrong.
198     */
199    public abstract Object getResult() throws SAXException;
200
201    /**
202     * Gets the ContentBase used to resolve relative URLs.
203     *
204     * @return the current contentbase, or null if no contentBase is set.
205     */
206    public URL getContentBase() {
207        final String contentBase = getConfigProperty(Parser.CONTENTBASE_KEY);
208        if (contentBase == null) {
209            return null;
210        }
211        try {
212            return new URL(contentBase);
213        }
214        catch (MalformedURLException mfe) {
215            throw new IllegalStateException("Content Base is illegal." + contentBase);
216        }
217    }
218
219    /**
220     * Returns a clone of this instance.
221     *
222     * @return A clone.
223     *
224     * @throws CloneNotSupportedException if there is a problem cloning.
225     */
226    public Object clone () throws CloneNotSupportedException
227    {
228      final FrontendDefaultHandler o = (FrontendDefaultHandler) super.clone();
229      o.parserConfiguration = (DefaultConfiguration) this.parserConfiguration.clone();
230      return o;
231    }
232}