package at.ac.tuwien.dsg.scaledom;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.HashMap;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import at.ac.tuwien.dsg.scaledom.io.ReaderFactory;
import at.ac.tuwien.dsg.scaledom.lazy.LazyLoadingStrategy;
import at.ac.tuwien.dsg.scaledom.parser.XmlParser;
import at.ac.tuwien.dsg.scaledom.util.ComponentFactory;
/**
* ScaleDOM implementation of the <code>DocumentBuilderFactory</code>. Utilizes the <code>attributes</code> map for
* configuration, see {@link ScaleDom} for possible configuration options.<br/>
* Warnings:
* <ul>
* <li>DocumentBuilderFactory.isXIncludeAware is not supported</li>
* <li>DocumentBuilderFactory.schema is not supported</li>
* <li>http://javax.xml.XMLConstants/feature/secure-processing feature has no impact</li>
* </ul>
*
* @author Dominik Rauch
* @see DocumentBuilderFactory
* @see ScaleDom
*/
public class ScaleDomDocumentBuilderFactory extends DocumentBuilderFactory {
private final Map<String, Object> attributes;
private final Map<String, Boolean> features;
/**
* Default constructor.
*/
public ScaleDomDocumentBuilderFactory() {
attributes = new HashMap<String, Object>();
features = new HashMap<String, Boolean>();
// Add features which are required to be supported
features.put(XMLConstants.FEATURE_SECURE_PROCESSING, false);
// Add all configuration options using defaults as initial values
attributes.put(ScaleDom.ATTRIBUTE_XMLPARSER_IMPLEMENTATION, ScaleDom.DEFAULT_XMLPARSER_IMPLEMENTATION);
attributes.put(ScaleDom.ATTRIBUTE_READERFACTORY_IMPLEMENTATION, ScaleDom.DEFAULT_READERFACTORY_IMPLEMENTATION);
attributes.put(ScaleDom.ATTRIBUTE_LAZYLOADINGSTRATEGY_IMPLEMENTATION,
ScaleDom.DEFAULT_LAZYLOADINGSTRATEGY_IMPLEMENTATION);
attributes.put(ScaleDom.ATTRIBUTE_DEFAULTENCODING, ScaleDom.DEFAULT_DEFAULTENCODING);
}
@Override
@SuppressWarnings("unchecked")
public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
try {
final ComponentFactory componentFactory = new ComponentFactory();
// Bind XmlParser instance
componentFactory.bind(XmlParser.class,
(Class<? extends XmlParser>) attributes.get(ScaleDom.ATTRIBUTE_XMLPARSER_IMPLEMENTATION), this);
// Bind ReaderFactory implementation type
componentFactory.bind(ReaderFactory.class,
(Class<? extends ReaderFactory>) attributes.get(ScaleDom.ATTRIBUTE_READERFACTORY_IMPLEMENTATION));
// Bind LazyLoadingStrategy implementation type
componentFactory.bind(LazyLoadingStrategy.class, (Class<? extends LazyLoadingStrategy>) attributes
.get(ScaleDom.ATTRIBUTE_LAZYLOADINGSTRATEGY_IMPLEMENTATION));
final String defaultEncoding = (String) attributes.get(ScaleDom.ATTRIBUTE_DEFAULTENCODING);
return new ScaleDomDocumentBuilder(componentFactory, defaultEncoding);
} catch (final InstantiationException ex) {
throw new ParserConfigurationException("Component 'XmlParser' could not be instantiated.");
}
}
@Override
public Object getAttribute(final String name) throws IllegalArgumentException {
checkNotNull(name, "Argument name must not be null.");
checkArgument(attributes.containsKey(name), "Attribute '%s' is not recognized.", name);
return attributes.get(name);
}
@Override
public void setAttribute(final String name, final Object value) throws IllegalArgumentException {
checkNotNull(name, "Argument name must not be null.");
checkArgument(attributes.containsKey(name), "Attribute '%s' is not recognized.", name);
checkNotNull(value, "Argument value must not be null.");
attributes.put(name, value);
}
@Override
public boolean getFeature(final String name) throws ParserConfigurationException {
checkNotNull(name, "Argument name must not be null.");
if (!features.containsKey(name)) {
throw new ParserConfigurationException("Feature '" + name + "' is not supported.");
}
return features.get(name);
}
@Override
public void setFeature(final String name, final boolean value) throws ParserConfigurationException {
checkNotNull(name, "Argument name must not be null.");
if (!features.containsKey(name)) {
throw new ParserConfigurationException("Feature '" + name + "' is not supported.");
}
checkNotNull(value, "Argument value must not be null.");
features.put(name, value);
}
}