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     *
109     * @param locator the locator.
110     */
111    public void setDocumentLocator(final Locator locator) {
112        this.locator = locator;
113    }
114
115    /**
116     * Returns the current locator.
117     *
118     * @return the locator.
119     */
120    public Locator getLocator() {
121        return this.locator;
122    }
123
124    /**
125     * Returns the configuration property with the specified key.
126     *
127     * @param key the property key.
128     * @return the property value.
129     */
130    public String getConfigProperty(final String key) {
131        return getConfigProperty(key, null);
132    }
133
134    /**
135     * Returns the configuration property with the specified key (or the specified default value
136     * if there is no such property).
137     * <p/>
138     * If the property is not defined in this configuration, the code will lookup the property in
139     * the parent configuration.
140     *
141     * @param key          the property key.
142     * @param defaultValue the default value.
143     * @return the property value.
144     */
145    public String getConfigProperty(final String key, final String defaultValue) {
146        return this.parserConfiguration.getConfigProperty(key, defaultValue);
147    }
148
149    /**
150     * Sets a parser configuration value.
151     *
152     * @param key   the key.
153     * @param value the value.
154     */
155    public void setConfigProperty(final String key, final String value) {
156        if (value == null) {
157            this.parserConfiguration.remove(key);
158        }
159        else {
160            this.parserConfiguration.setProperty(key, value);
161        }
162    }
163
164    /**
165     * Returns the configuration properties.
166     *
167     * @return An enumeration of the configuration properties.
168     */
169    public Enumeration getConfigProperties()
170    {
171      return this.parserConfiguration.getConfigProperties();
172    }
173
174  /**
175     * Returns a new instance of the parser.
176     *
177     * @return a new instance of the parser.
178     */
179    public abstract FrontendDefaultHandler newInstance();
180
181    /**
182     * Returns all keys with the given prefix.
183     *
184     * @param prefix the prefix
185     * @return the iterator containing all keys with that prefix
186     */
187    public Iterator findPropertyKeys(final String prefix) {
188        return this.parserConfiguration.findPropertyKeys(prefix);
189    }
190
191    /**
192     * Returns the parse result. This method is called at the end of the
193     * parsing process and expects the generated object.
194     *
195     * @return the object.
196     * @throws SAXException if something went wrong.
197     */
198    public abstract Object getResult() throws SAXException;
199
200    /**
201     * Gets the ContentBase used to resolve relative URLs.
202     *
203     * @return the current contentbase, or null if no contentBase is set.
204     */
205    public URL getContentBase() {
206        final String contentBase = getConfigProperty(Parser.CONTENTBASE_KEY);
207        if (contentBase == null) {
208            return null;
209        }
210        try {
211            return new URL(contentBase);
212        }
213        catch (MalformedURLException mfe) {
214            throw new IllegalStateException("Content Base is illegal." + contentBase);
215        }
216    }
217
218    /**
219     * Returns a clone of this instance.
220     *
221     * @return A clone.
222     *
223     * @throws CloneNotSupportedException if there is a problem cloning.
224     */
225    public Object clone () throws CloneNotSupportedException
226    {
227      final FrontendDefaultHandler o = (FrontendDefaultHandler) super.clone();
228      o.parserConfiguration = (DefaultConfiguration) this.parserConfiguration.clone();
229      return o;
230    }
231}