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     */
042    package org.jfree.xml;
043    
044    import java.net.MalformedURLException;
045    import java.net.URL;
046    import java.util.Iterator;
047    import java.util.Enumeration;
048    
049    import org.jfree.util.Configuration;
050    import org.jfree.util.DefaultConfiguration;
051    import org.xml.sax.Locator;
052    import org.xml.sax.SAXException;
053    import 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     */
061    public 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    }