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.8 2006/11/20 21:36:30 taqua 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    public Enumeration getConfigProperties()
165    {
166      return parserConfiguration.getConfigProperties();
167    }
168
169  /**
170     * Returns a new instance of the parser.
171     *
172     * @return a new instance of the parser.
173     */
174    public abstract FrontendDefaultHandler newInstance();
175
176    /**
177     * Returns all keys with the given prefix.
178     *
179     * @param prefix the prefix
180     * @return the iterator containing all keys with that prefix
181     */
182    public Iterator findPropertyKeys(final String prefix) {
183        return this.parserConfiguration.findPropertyKeys(prefix);
184    }
185
186    /**
187     * Returns the parse result. This method is called at the end of the
188     * parsing process and expects the generated object.
189     *
190     * @return the object.
191     * @throws SAXException if something went wrong.
192     */
193    public abstract Object getResult() throws SAXException;
194
195    /**
196     * Gets the ContentBase used to resolve relative URLs.
197     *
198     * @return the current contentbase, or null if no contentBase is set.
199     */
200    public URL getContentBase() {
201        final String contentBase = getConfigProperty(Parser.CONTENTBASE_KEY);
202        if (contentBase == null) {
203            return null;
204        }
205        try {
206            return new URL(contentBase);
207        }
208        catch (MalformedURLException mfe) {
209            throw new IllegalStateException("Content Base is illegal." + contentBase);
210        }
211    }
212
213    public Object clone () throws CloneNotSupportedException
214    {
215      final FrontendDefaultHandler o = (FrontendDefaultHandler) super.clone();
216      o.parserConfiguration = (DefaultConfiguration) parserConfiguration.clone();
217      return o;
218    }
219}