    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}