001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.bio.program.sax.blastxml; 022 023import java.io.IOException; 024 025import javax.xml.parsers.ParserConfigurationException; 026import javax.xml.parsers.SAXParserFactory; 027 028import org.biojava.bio.BioException; 029import org.biojava.utils.stax.SAX2StAXAdaptor; 030import org.xml.sax.ContentHandler; 031import org.xml.sax.DTDHandler; 032import org.xml.sax.EntityResolver; 033import org.xml.sax.ErrorHandler; 034import org.xml.sax.InputSource; 035import org.xml.sax.SAXException; 036import org.xml.sax.SAXNotRecognizedException; 037import org.xml.sax.SAXNotSupportedException; 038import org.xml.sax.XMLReader; 039import org.xml.sax.helpers.DefaultHandler; 040 041/** 042 * A facade class that wraps the NCBI Blast XML 043 * parsing framework in a more user-friendly form. 044 * It is identical to BlastlikeSAXParser in use. 045 * 046 * @author David Huen 047 * @since 1.3 048 */ 049public class BlastXMLParserFacade 050 implements XMLReader 051{ 052 // these are defined for the handlers 053 // DOWNSTREAM of this one. 054 private ContentHandler contentHandler; 055 056 // these are internal handlers 057 final BlastXMLParser blasthandler = new BlastXMLParser(); 058 059 // this is the SAX parser 060 XMLReader parser; 061 062 // this is a default base URI so SAX does not complain 063 // when user doesn't give an absolute URI. 064 private String baseURI; 065 066 private class Resolver 067 implements EntityResolver 068 { 069 public InputSource resolveEntity(String publicID, String systemID) 070 throws SAXException 071 { 072// try { 073 // resolve the NCBI URN 074// System.out.println("resolve " + publicID + ":" + systemID); 075 076 String resourceName = "org/biojava/bio/program/sax/blastxml/"; 077 078 if (publicID.equals("-//NCBI//NCBI BlastOutput/EN")) { 079 resourceName = resourceName + "NCBI_BlastOutput.dtd"; 080 } 081 else if (publicID.equals("-//NCBI//NCBI Entity Module//EN")) { 082 resourceName = resourceName + "NCBI_Entity.mod"; 083 } 084 else if (publicID.equals("-//NCBI//NCBI BlastOutput Module//EN")) { 085 resourceName = resourceName + "NCBI_BlastOutput.mod"; 086 } 087 else 088 return null; 089 090 InputSource is = new InputSource(this.getClass().getClassLoader().getResourceAsStream(resourceName)); 091 is.setSystemId(baseURI); 092 093 return is; 094 } 095 } 096 097 public BlastXMLParserFacade() 098 throws BioException 099 { 100 // just initialise content handler 101 // to avoid fubar if undefined 102 DefaultHandler handler = new DefaultHandler(); 103 contentHandler = handler; 104 105 try { 106 // create the parser 107 parser = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); 108 109 // assign the EntityResolver 110 parser.setEntityResolver(new Resolver()); 111 parser.setContentHandler(new SAX2StAXAdaptor(blasthandler)); 112 113 // assign default sane settings 114 // namespaces must be true if the SAX2StAX parser isn't to fubar. 115 parser.setFeature("http://xml.org/sax/features/namespaces", true); 116 parser.setFeature("http://xml.org/sax/features/validation", false); 117 118 // make a base URI just in case the user doesn't 119 baseURI = this.getClass().getClassLoader().getResource("org/biojava/bio/program/sax/blastxml/").toString(); 120 } 121 catch (SAXException se) { throw new BioException (se); } 122 catch (ParserConfigurationException sce) { throw new BioException(sce); } 123 } 124 125 /** 126 * correct this later 127 */ 128 public ContentHandler getContentHandler() 129 { 130 return contentHandler; 131 } 132 133 public DTDHandler getDTDHandler() 134 { 135 return parser.getDTDHandler(); 136 } 137 138 /** 139 * This class has an EntityResolver that 140 * resolves the public ID specifying the 141 * NCBI DTDs to resource files within the 142 * BioJava libraries. This call will return 143 * that resolver. It you should set your 144 * own resolver, ensure you resolve that 145 * URN yourself or the parser will blow up 146 * on you!. 147 */ 148 public EntityResolver getEntityResolver() 149 { 150 return parser.getEntityResolver(); 151 } 152 153 public ErrorHandler getErrorHandler() 154 { 155 return parser.getErrorHandler(); 156 } 157 158 public boolean getFeature(String name) 159 throws SAXNotRecognizedException, SAXNotSupportedException 160 { 161 return parser.getFeature(name); 162 } 163 164 public Object getProperty(String name) 165 throws SAXNotRecognizedException, SAXNotSupportedException 166 { 167 return parser.getProperty(name); 168 } 169 170 public void parse(InputSource is) 171 throws IOException, SAXException 172 { 173 if (is.getSystemId() == null) 174 is.setSystemId(baseURI); 175 parser.parse(is); 176 } 177 178 public void parse(String systemId) 179 throws IOException, SAXException 180 { 181 parser.parse(systemId); 182 } 183/** 184 * this sets the ContentHandler that receives 185 * SAX events from the internal Blast XML parser which 186 * is the actual ContentHandler. <b> It will not 187 * change the internal Blast XML parser. </b> 188 */ 189 public void setContentHandler(ContentHandler handler) 190 { 191 contentHandler = handler; 192 blasthandler.setContentHandler(handler); 193 } 194 195 public void setDTDHandler(DTDHandler handler) 196 { 197 parser.setDTDHandler(handler); 198 } 199 200 /** 201 * This class has an EntityResolver that 202 * resolves the public ID specifying the 203 * NCBI DTDs to resource files within the 204 * BioJava libraries. This call will return 205 * that resolver. It you should set your 206 * own resolver, ensure you resolve that 207 * URN yourself or the parser will blow up 208 * on you!. 209 */ 210 public void setEntityResolver(EntityResolver resolver) 211 { 212 parser.setEntityResolver(resolver); 213 } 214 215 public void setErrorHandler(ErrorHandler handler) 216 { 217 parser.setErrorHandler(handler); 218 } 219 220 /** 221 * by default, we set the parser to non-validating. 222 * change it if you wish/dare! The parser is 223 * also set to be namespace aware. <b>DO NOT 224 * CHANGE THAT!!!</b> 225 */ 226 public void setFeature(String key, boolean value) 227 throws SAXNotRecognizedException, SAXNotSupportedException 228 { 229 parser.setFeature(key, value); 230 } 231 232 public void setProperty(String key, Object value) 233 throws SAXNotRecognizedException, SAXNotSupportedException 234 { 235 parser.setProperty(key, value); 236 } 237} 238