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.io.IOException; 024import java.io.Writer; 025import java.util.ArrayList; 026import java.util.Iterator; 027import java.util.List; 028 029import org.biojava.bio.seq.io.ParseException; 030 031/** 032 * Builds a Nexus file by listening to events. 033 * 034 * @author Richard Holland 035 * @author Tobias Thierer 036 * @author Jim Balhoff 037 * @since 1.6 038 */ 039public class NexusFileBuilder extends NexusFileListener.Abstract { 040 041 private NexusFile file; 042 043 private NexusComment comment; 044 045 public void setDefaultBlockParsers() { 046 this.setBlockParser(NexusBlockParser.UNKNOWN_BLOCK, 047 new UnknownBlockParser()); 048 this.setBlockParser(TaxaBlock.TAXA_BLOCK, new TaxaBlockParser( 049 new TaxaBlockBuilder())); 050 this.setBlockParser(TreesBlock.TREES_BLOCK, new TreesBlockParser( 051 new TreesBlockBuilder())); 052 this.setBlockParser(CharactersBlock.CHARACTERS_BLOCK, 053 new CharactersBlockParser(new CharactersBlockBuilder())); 054 this.setBlockParser(DataBlock.DATA_BLOCK, new DataBlockParser( 055 new DataBlockBuilder())); 056 this.setBlockParser(DistancesBlock.DISTANCES_BLOCK, 057 new DistancesBlockParser(new DistancesBlockBuilder())); 058 } 059 060 protected void blockEnded(final NexusBlockParser blockParser) { 061 final NexusBlockListener listener = blockParser.getBlockListener(); 062 if (listener instanceof NexusBlockBuilder) 063 file.addObject(((NexusBlockBuilder) listener).getNexusBlock()); 064 } 065 066 public void startFile() { 067 this.file = new NexusFile(); 068 } 069 070 public void endFile() { 071 // We don't care. 072 } 073 074 /** 075 * Obtain the constructed file. 076 * 077 * @return the constructed file. 078 */ 079 public NexusFile getNexusFile() { 080 return this.file; 081 } 082 083 public void beginFileComment() { 084 if (this.comment != null) 085 this.comment.openSubComment(); 086 else 087 this.comment = new NexusComment(); 088 } 089 090 public void fileCommentText(String comment) { 091 this.comment.addCommentText(comment); 092 } 093 094 public void endFileComment() { 095 if (this.comment != null && this.comment.hasOpenSubComment()) 096 this.comment.closeSubComment(); 097 else { 098 this.file.addObject(this.comment); 099 this.comment = null; 100 } 101 } 102 103 // This class builds unknown blocks by remembering all tokens and 104 // comments in the order they were received, and writing them out 105 // again in that order when requested. 106 private static class UnknownBlockParser extends NexusBlockParser.Abstract { 107 private UnknownBlockParser() { 108 super(new UnknownBlockBuilder()); 109 } 110 111 public void resetStatus() { 112 // Ignore. 113 } 114 115 public boolean wantsBracketsAndBraces() { 116 return false; 117 } 118 119 public void parseToken(final String token) throws ParseException { 120 ((UnknownBlockBuilder) this.getBlockListener()).getComponents() 121 .add(token); 122 } 123 124 private static class UnknownBlockBuilder extends 125 NexusBlockBuilder.Abstract { 126 127 private UnknownBlock block; 128 129 private List getComponents() { 130 return this.block.getComponents(); 131 } 132 133 public void endTokenGroup() { 134 // Only write not-first, as we also receive the one 135 // from after the BEGIN statement. 136 if (this.getComponents().size() > 0) 137 this.getComponents().add(";"); 138 } 139 140 public boolean wantsBracketsAndBraces() { 141 return false; 142 } 143 144 public void endBlock() { 145 // We don't care. 146 } 147 148 public void addComment(NexusComment comment) { 149 this.getComponents().add(comment); 150 } 151 152 public NexusBlock startBlockObject() { 153 this.block = new UnknownBlock(this.getBlockName()); 154 return this.block; 155 } 156 157 // Holds unknown block data. 158 private static class UnknownBlock extends NexusBlock.Abstract { 159 160 private List components = new ArrayList(); 161 162 private UnknownBlock(String blockName) { 163 super(blockName); 164 } 165 166 private List getComponents() { 167 return this.components; 168 } 169 170 public void writeBlockContents(final Writer writer) 171 throws IOException { 172 for (final Iterator i = this.components.iterator(); i 173 .hasNext();) { 174 final Object obj = (Object) i.next(); 175 if (obj instanceof NexusComment) 176 ((NexusComment) obj).writeObject(writer); 177 else 178 this.writeToken(writer, (String) obj); 179 } 180 } 181 } 182 } 183 } 184}