package at.ac.tuwien.dsg.scaledom;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.xml.parsers.DocumentBuilder;
import org.apache.xerces.dom.CoreDOMImplementationImpl;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import at.ac.tuwien.dsg.scaledom.dom.ScaleDomDocument;
import at.ac.tuwien.dsg.scaledom.parser.XmlParser;
import at.ac.tuwien.dsg.scaledom.util.ComponentFactory;
import at.ac.tuwien.dsg.scaledom.util.InputSourceUtils;
/**
* The <code>ScaleDomDocumentBuilder</code> constructs DOM documents (<code>ScaleDomDocument</code>) based upon the
* Apache Xerces DOM implementation.
*
* @author Dominik Rauch
* @see DocumentBuilder
*/
public class ScaleDomDocumentBuilder extends DocumentBuilder {
private final XmlParser parser;
private final ComponentFactory componentFactory;
private final String defaultEncoding;
/**
* Default constructor.
*
* @param componentFactory a factory to obtain required sub components.
* @param defaultEncoding the default encoding to be used.
*/
ScaleDomDocumentBuilder(final ComponentFactory componentFactory, final String defaultEncoding) {
checkNotNull(componentFactory, "Argument componentFactory must not be null.");
checkNotNull(defaultEncoding, "Argument defaultEncoding must not be null.");
checkArgument(Charset.isSupported(defaultEncoding), "Default encoding '%s' is not supported.", defaultEncoding);
this.parser = componentFactory.getInstance(XmlParser.class);
this.componentFactory = componentFactory;
this.defaultEncoding = defaultEncoding;
}
@Override
public Document parse(final InputSource is) throws SAXException, IOException {
checkNotNull(is, "Argument is must not be null.");
if (is.getCharacterStream() != null || is.getByteStream() != null) {
throw new IOException("ScaleDOM supports only file-based input sources.");
}
try {
final ScaleDomDocumentSource source = InputSourceUtils.inputSourceToDocumentSource(is, defaultEncoding);
return new ScaleDomDocument(source, parser, componentFactory);
} catch (final InstantiationException ex) {
throw new SAXException(ex);
}
}
/**
* Use this non-JAXP method if you want to parse a non-File source. Make sure you have a <code>ReaderFactory</code>
* configured, which is able to work with the given implementation of <code>ScaleDomDocumentSource</code>.
*
* @param source the XML source.
* @return a new DOM Document object.
* @throws SAXException If any parse errors occur.
* @throws IOException If any I/O errors occur.
*/
public Document parse(final ScaleDomDocumentSource source) throws SAXException, IOException {
checkNotNull(source, "Argument source must not be null.");
try {
return new ScaleDomDocument(source, parser, componentFactory);
} catch (final InstantiationException ex) {
throw new SAXException(ex);
}
}
@Override
public DOMImplementation getDOMImplementation() {
// ScaleDOM is based upon Apache Xerces
return new ScaleDomDOMImplementation(new CoreDOMImplementationImpl());
}
@Override
public boolean isNamespaceAware() {
return parser.isNamespaceAware();
}
@Override
public boolean isValidating() {
return parser.isValidating();
}
@Override
public Document newDocument() {
// No lazy loading possible if DOM is constructed from scratch => makes no sense
throw new UnsupportedOperationException("ScaleDOM does not support DOM construction from scratch.");
}
@Override
public void setEntityResolver(final EntityResolver er) {
parser.setEntityResolver(er);
}
@Override
public void setErrorHandler(final ErrorHandler eh) {
parser.setErrorHandler(eh);
}
}