/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.bio.program.sax.blastxml; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import org.biojava.bio.BioException; import org.biojava.utils.stax.SAX2StAXAdaptor; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; /** * A facade class that wraps the NCBI Blast XML * parsing framework in a more user-friendly form. * It is identical to BlastlikeSAXParser in use. * * @author David Huen * @since 1.3 */ public class BlastXMLParserFacade implements XMLReader { // these are defined for the handlers // DOWNSTREAM of this one. private ContentHandler contentHandler; // these are internal handlers final BlastXMLParser blasthandler = new BlastXMLParser(); // this is the SAX parser XMLReader parser; // this is a default base URI so SAX does not complain // when user doesn't give an absolute URI. private String baseURI; private class Resolver implements EntityResolver { public InputSource resolveEntity(String publicID, String systemID) throws SAXException { // try { // resolve the NCBI URN // System.out.println("resolve " + publicID + ":" + systemID); String resourceName = "org/biojava/bio/program/sax/blastxml/"; if (publicID.equals("-//NCBI//NCBI BlastOutput/EN")) { resourceName = resourceName + "NCBI_BlastOutput.dtd"; } else if (publicID.equals("-//NCBI//NCBI Entity Module//EN")) { resourceName = resourceName + "NCBI_Entity.mod"; } else if (publicID.equals("-//NCBI//NCBI BlastOutput Module//EN")) { resourceName = resourceName + "NCBI_BlastOutput.mod"; } else return null; InputSource is = new InputSource(this.getClass().getClassLoader().getResourceAsStream(resourceName)); is.setSystemId(baseURI); return is; } } public BlastXMLParserFacade() throws BioException { // just initialise content handler // to avoid fubar if undefined DefaultHandler handler = new DefaultHandler(); contentHandler = handler; try { // create the parser parser = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); // assign the EntityResolver parser.setEntityResolver(new Resolver()); parser.setContentHandler(new SAX2StAXAdaptor(blasthandler)); // assign default sane settings // namespaces must be true if the SAX2StAX parser isn't to fubar. parser.setFeature("http://xml.org/sax/features/namespaces", true); parser.setFeature("http://xml.org/sax/features/validation", false); // make a base URI just in case the user doesn't baseURI = this.getClass().getClassLoader().getResource("org/biojava/bio/program/sax/blastxml/").toString(); } catch (SAXException se) { throw new BioException (se); } catch (ParserConfigurationException sce) { throw new BioException(sce); } } /** * correct this later */ public ContentHandler getContentHandler() { return contentHandler; } public DTDHandler getDTDHandler() { return parser.getDTDHandler(); } /** * This class has an EntityResolver that * resolves the public ID specifying the * NCBI DTDs to resource files within the * BioJava libraries. This call will return * that resolver. It you should set your * own resolver, ensure you resolve that * URN yourself or the parser will blow up * on you!. */ public EntityResolver getEntityResolver() { return parser.getEntityResolver(); } public ErrorHandler getErrorHandler() { return parser.getErrorHandler(); } public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException { return parser.getFeature(name); } public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { return parser.getProperty(name); } public void parse(InputSource is) throws IOException, SAXException { if (is.getSystemId() == null) is.setSystemId(baseURI); parser.parse(is); } public void parse(String systemId) throws IOException, SAXException { parser.parse(systemId); } /** * this sets the ContentHandler that receives * SAX events from the internal Blast XML parser which * is the actual ContentHandler. It will not * change the internal Blast XML parser. */ public void setContentHandler(ContentHandler handler) { contentHandler = handler; blasthandler.setContentHandler(handler); } public void setDTDHandler(DTDHandler handler) { parser.setDTDHandler(handler); } /** * This class has an EntityResolver that * resolves the public ID specifying the * NCBI DTDs to resource files within the * BioJava libraries. This call will return * that resolver. It you should set your * own resolver, ensure you resolve that * URN yourself or the parser will blow up * on you!. */ public void setEntityResolver(EntityResolver resolver) { parser.setEntityResolver(resolver); } public void setErrorHandler(ErrorHandler handler) { parser.setErrorHandler(handler); } /** * by default, we set the parser to non-validating. * change it if you wish/dare! The parser is * also set to be namespace aware. DO NOT * CHANGE THAT!!! */ public void setFeature(String key, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { parser.setFeature(key, value); } public void setProperty(String key, Object value) throws SAXNotRecognizedException, SAXNotSupportedException { parser.setProperty(key, value); } }