2
* This program is free software; you can redistribute it and/or modify it under the
3
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
6
* You should have received a copy of the GNU Lesser General Public License along with this
7
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
8
* or from the Free Software Foundation, Inc.,
9
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
11
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
* See the GNU Lesser General Public License for more details.
15
* Copyright (c) 2006 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors. All rights reserved.
18
package org.pentaho.reporting.libraries.xmlns.parser;
20
import java.util.HashMap;
21
import java.util.Iterator;
23
import org.pentaho.reporting.libraries.base.config.Configuration;
24
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
27
* The AbstractReadHandlerFactory provides a base implementation for all
28
* read-handler factories. A read-handler factory decouples the tag-handlers
29
* of a SAX parser and allows to configure alternate parser configuations
30
* at runtime, resulting in a more flexible parsing process.
32
* @author Thomas Morgner
34
public abstract class AbstractReadHandlerFactory
37
* The TagDefinitionKey is a compund key to lookup handler implementations
38
* using a namespace and tagname.
40
private static class TagDefinitionKey
42
private String namespace;
43
private String tagName;
48
* @param namespace the namespace (can be null for undefined).
49
* @param tagName the tagname (can be null for undefined).
51
private TagDefinitionKey(final String namespace, final String tagName)
53
this.namespace = namespace;
54
this.tagName = tagName;
58
* Compares this key for equality with an other object.
60
* @param o the other object.
61
* @return true, if this key is the same as the given object, false otherwise.
63
public boolean equals(final Object o)
69
if (o == null || getClass() != o.getClass())
74
final TagDefinitionKey that = (TagDefinitionKey) o;
76
if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null)
80
if (tagName != null ? !tagName.equals(that.tagName) : that.tagName != null)
89
* Computes the hashcode for this key.
91
* @return the hashcode.
95
int result = (namespace != null ? namespace.hashCode() : 0);
96
result = 29 * result + (tagName != null ? tagName.hashCode() : 0);
101
private HashMap defaultDefinitions;
102
private HashMap tagData;
103
private String defaultNamespace;
106
* A default-constructor.
108
protected AbstractReadHandlerFactory()
110
defaultDefinitions = new HashMap();
111
tagData = new HashMap();
115
* Configures this factory from the given configuration using the speoified
118
* @param conf the configuration.
119
* @param prefix the key-prefix.
120
* @noinspection ObjectAllocationInLoop as this method configures the factory.
122
public void configure(final Configuration conf, final String prefix)
124
final HashMap knownNamespaces = new HashMap();
126
final String nsConfPrefix = prefix + "namespace.";
127
final Iterator namespaces = conf.findPropertyKeys(nsConfPrefix);
128
while (namespaces.hasNext())
130
final String key = (String) namespaces.next();
131
final String nsPrefix = key.substring(nsConfPrefix.length());
132
final String nsUri = conf.getConfigProperty(key);
133
knownNamespaces.put(nsPrefix, nsUri);
136
defaultNamespace = (String) knownNamespaces.get
137
(conf.getConfigProperty(prefix + "namespace"));
139
final String globalDefaultKey = prefix + "default";
140
final String globalValue = conf.getConfigProperty(globalDefaultKey);
141
if (isValidHandler(globalValue))
143
defaultDefinitions.put(null, globalValue);
147
// let the loading fail ..
148
if (defaultDefinitions.containsKey(null) == false)
150
defaultDefinitions.put(null, "");
154
final String nsDefaultPrefix = prefix + "default.";
155
final Iterator defaults = conf.findPropertyKeys(nsDefaultPrefix);
156
while (defaults.hasNext())
158
final String key = (String) defaults.next();
159
final String nsPrefix = key.substring(nsDefaultPrefix.length());
160
final String nsUri = (String) knownNamespaces.get(nsPrefix);
166
final String tagData = conf.getConfigProperty(key);
171
if (isValidHandler(tagData))
173
defaultDefinitions.put(nsUri, tagData);
177
// let the loading fail .. to indicate we want no parsing ..
178
defaultDefinitions.put(nsUri, "");
182
final String nsTagsPrefix = prefix + "tag.";
183
final Iterator tags = conf.findPropertyKeys(nsTagsPrefix);
184
while (tags.hasNext())
186
final String key = (String) tags.next();
187
final String tagDef = key.substring(nsTagsPrefix.length());
188
final String tagData = conf.getConfigProperty(key);
193
if (isValidHandler(tagData) == false)
198
final int delim = tagDef.indexOf('.');
201
this.tagData.put(new TagDefinitionKey(null, tagDef), tagData);
205
final String nsPrefix = tagDef.substring(0, delim);
206
final String nsUri = (String) knownNamespaces.get(nsPrefix);
212
final String tagName = tagDef.substring(delim + 1);
213
this.tagData.put(new TagDefinitionKey(nsUri, tagName), tagData);
219
* Checks, whether the given handler classname can be instantiated
220
* and is in fact an object of the required target-type.
222
* @param className the classname that should be checked.
223
* @return true, if the handler is valid, false otherwise.
225
private boolean isValidHandler(final String className)
227
if (className == null)
231
final Object o = ObjectUtilities.loadAndInstantiate
232
(className, getClass(), getTargetClass());
237
* Returns the implementation class for this read-handler factory.
239
* @return the implementation class.
241
protected abstract Class getTargetClass();
244
* The returned handler can be null, in case no handler is registered.
246
* @param namespace the namespace of the xml-tag for which a handler should be returned.
247
* @param tagname the tagname of the xml-tag.
248
* @return the instantiated read handler, or null if there is no handler registered.
250
public XmlReadHandler getHandler(String namespace, final String tagname)
252
if (namespace == null)
254
namespace = defaultNamespace;
257
final TagDefinitionKey key = new TagDefinitionKey(namespace, tagname);
258
final String tagVal = (String) tagData.get(key);
261
final Object o = ObjectUtilities.loadAndInstantiate
262
(tagVal, getClass(), getTargetClass());
263
return (XmlReadHandler) o;
266
final String className = (String) defaultDefinitions.get(namespace);
267
if (className != null)
269
final Object o = ObjectUtilities.loadAndInstantiate
270
(className, getClass(), getTargetClass());
271
return (XmlReadHandler) o;
274
final String fallbackName = (String) defaultDefinitions.get(null);
275
final Object fallbackValue = ObjectUtilities.loadAndInstantiate
276
(fallbackName, getClass(), getTargetClass());
277
if (fallbackValue != null)
279
return (XmlReadHandler) fallbackValue;