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.biojavax.bio.phylo.io.nexus; 022 023import java.util.HashMap; 024import java.util.Map; 025 026import org.biojava.bio.seq.io.ParseException; 027 028/** 029 * Listens to events fired by the Nexus parser. Use these events to handle data 030 * directly or construct objects. 031 * 032 * @author Richard Holland 033 * @author Tobias Thierer 034 * @author Jim Balhoff 035 * @since 1.6 036 */ 037public interface NexusFileListener { 038 039 /** 040 * About to start a new file. 041 */ 042 public void startFile(); 043 044 /** 045 * Finished reading a file. 046 */ 047 public void endFile(); 048 049 /** 050 * Opening a comment tag. 051 */ 052 public void beginComment(); 053 054 /** 055 * Receiving free text inside a comment tag. 056 * 057 * @param comment 058 * the text of the comment. 059 */ 060 public void commentText(String comment) throws ParseException; 061 062 /** 063 * Closing a comment tag. 064 */ 065 public void endComment(); 066 067 /** 068 * Closing a line (semi-colon encountered). This indicates that anything 069 * received after it is on the next logical line of the file. 070 */ 071 public void endTokenGroup(); 072 073 /** 074 * Causes the default block parsers to be assigned. This is called by the 075 * constructor of the abstract implementation. If it is not called, then at 076 * least the unknown block parser must be set by other means. 077 */ 078 public void setDefaultBlockParsers(); 079 080 /** 081 * Sets the parser to use for a given block. 082 * 083 * @param blockName 084 * the name of the block. 085 * @param parser 086 * the parser to use. Use <tt>null</tt> to unset an existing 087 * one and use the default one for that block instead. 088 */ 089 public void setBlockParser(String blockName, NexusBlockParser parser); 090 091 /** 092 * Gets the parser to use for a given block. 093 * 094 * @param blockName 095 * the name of the block. return parser the parser to use. Is 096 * never null. 097 */ 098 public NexusBlockParser getBlockParser(String blockName); 099 100 /** 101 * About to start a new block. 102 * 103 * @param blockName 104 * the name of the new block. 105 */ 106 public void startBlock(String blockName); 107 108 /** 109 * Finished reading a block. 110 */ 111 public void endBlock(); 112 113 /** 114 * Encountered a token. 115 * 116 * @param token 117 * the token. 118 * @throws ParseException 119 * if the token is invalid. 120 */ 121 public void parseToken(String token) throws ParseException; 122 123 /** 124 * Does the listener want to know about brackets and braces as separate 125 * tokens? 126 * 127 * @return <tt>true</tt> if it does. 128 */ 129 public boolean wantsBracketsAndBraces(); 130 131 /** 132 * Example abstract implementation which all others should extend. 133 */ 134 public abstract class Abstract implements NexusFileListener { 135 136 private static final NexusBlockParser ignoreUnknownBlocks = new NexusBlockParser.Abstract( 137 new NexusBlockListener() { 138 public void beginComment() { 139 } 140 141 public void commentText(String comment) 142 throws ParseException { 143 } 144 145 public void endBlock() { 146 } 147 148 public void endComment() { 149 } 150 151 public void endTokenGroup() { 152 } 153 154 public void startBlock(final String blockName) { 155 } 156 }) { 157 public void resetStatus() { 158 } 159 160 public void parseToken(final String token) throws ParseException { 161 } 162 }; 163 164 private Map blockParsers = new HashMap(); 165 166 private NexusBlockParser blockParser; 167 168 public Abstract() { 169 this.setDefaultBlockParsers(); 170 } 171 172 public void beginComment() { 173 if (this.blockParser != null) 174 this.blockParser.beginComment(); 175 else 176 this.beginFileComment(); 177 } 178 179 /** 180 * This method will get called when a comment is started on the file, 181 * and not any block within it. 182 */ 183 protected abstract void beginFileComment(); 184 185 public void commentText(String comment) throws ParseException { 186 if (this.blockParser != null) 187 this.blockParser.commentText(comment); 188 else 189 this.fileCommentText(comment); 190 } 191 192 /** 193 * This method will get called when comment text is found on the file, 194 * and not any block within it. 195 * 196 * @param comment 197 * the comment text. 198 */ 199 protected abstract void fileCommentText(String comment); 200 201 public void endComment() { 202 if (this.blockParser != null) 203 this.blockParser.endComment(); 204 else 205 this.endFileComment(); 206 } 207 208 /** 209 * This method will get called when a comment is ended on the file, and 210 * not any block within it. 211 */ 212 protected abstract void endFileComment(); 213 214 public void endBlock() { 215 this.blockParser.endBlock(); 216 this.blockEnded(this.blockParser); 217 this.blockParser = null; 218 } 219 220 /** 221 * This method gets called when the block parser is expected to have 222 * finished parsing a block. 223 * 224 * @param blockParser 225 * the parser that has finished. 226 */ 227 protected abstract void blockEnded(NexusBlockParser blockParser); 228 229 public boolean wantsBracketsAndBraces() { 230 return this.blockParser != null 231 && this.blockParser.wantsBracketsAndBraces(); 232 } 233 234 public void setDefaultBlockParsers() { 235 this.setBlockParser(NexusBlockParser.UNKNOWN_BLOCK, 236 NexusFileListener.Abstract.ignoreUnknownBlocks); 237 } 238 239 public NexusBlockParser getBlockParser(String blockName) { 240 blockName = blockName.toUpperCase(); 241 return blockParser = this.blockParsers.containsKey(blockName) ? (NexusBlockParser) this.blockParsers 242 .get(blockName) 243 : (NexusBlockParser) this.blockParsers 244 .get(NexusBlockParser.UNKNOWN_BLOCK); 245 } 246 247 public void endTokenGroup() { 248 // Only blocks care about semi-colons. 249 if (this.blockParser != null) 250 this.blockParser.endTokenGroup(); 251 } 252 253 public void parseToken(String token) throws ParseException { 254 // Only blocks can parse tokens. 255 if (this.blockParser != null) 256 this.blockParser.parseToken(token); 257 } 258 259 public void setBlockParser(String blockName, NexusBlockParser parser) { 260 this.blockParsers.put(blockName.toUpperCase(), parser); 261 } 262 263 public void startBlock(String blockName) { 264 this.blockParser = this.getBlockParser(blockName); 265 this.blockParser.startBlock(blockName); 266 } 267 268 } 269}