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 * Represents Nexus taxa blocks.
033 * 
034 * @author Richard Holland
035 * @author Tobias Thierer
036 * @author Jim Balhoff
037 * @since 1.6
038 */
039public class TaxaBlock extends NexusBlock.Abstract {
040
041        /**
042         * A constant representing the name of Taxa blocks.
043         */
044        public static final String TAXA_BLOCK = "TAXA";
045
046        private int dimensionsNTax = 0;
047
048        private List taxLabels = new ArrayList();
049
050        private List comments = new ArrayList();
051
052        /**
053         * Delegates to NexusBlock.Abstract constructor using TaxaBlock.TAXA_BLOCK
054         * as the name.
055         */
056        public TaxaBlock() {
057                super(TaxaBlock.TAXA_BLOCK);
058        }
059
060        /**
061         * Set the NTAX value.
062         * 
063         * @param dimensionsNTax
064         *            the NTAX value.
065         */
066        public void setDimensionsNTax(int dimensionsNTax) {
067                this.dimensionsNTax = dimensionsNTax;
068        }
069
070        /**
071         * Get the NTAX value.
072         * 
073         * @return the NTAX value.
074         */
075        public int getDimensionsNTax() {
076                return this.dimensionsNTax;
077        }
078
079        /**
080         * Add a TAXLABEL. If it already exists, or is a number that refers to an
081         * index position that already exists, an exception is thrown.
082         * 
083         * @param taxLabel
084         *            the label to add.
085         * @throws ParseException
086         *             if the label cannot be added.
087         */
088        public void addTaxLabel(final String taxLabel) throws ParseException {
089                if (this.taxLabels.contains(taxLabel))
090                        throw new ParseException("Duplicate taxa label: " + taxLabel);
091                else
092                        try {
093                                // Try it as a number to see if it refers to
094                                // position we already have.
095                                final int i = Integer.parseInt(taxLabel);
096                                if (i <= this.taxLabels.size())
097                                        throw new ParseException("Taxa label " + i
098                                                        + " refers to already extant taxa position");
099                        } catch (NumberFormatException e) {
100                                // It is not a number, so ignore.
101                        } catch (ParseException e) {
102                                // Throw it.
103                                throw e;
104                        }
105                this.taxLabels.add(taxLabel);
106        }
107
108        /**
109         * Removes the given TAXLABEL.
110         * 
111         * @param taxLabel
112         *            the label to remove.
113         */
114        public void removeTaxLabel(final String taxLabel) {
115                this.taxLabels.remove(taxLabel);
116        }
117
118        /**
119         * Checks to see if we contain the given TAXLABEL.
120         * 
121         * @param taxLabel
122         *            the label to check for.
123         * @return <tt>true</tt> if we already contain it.
124         */
125        public boolean containsTaxLabel(final String taxLabel) {
126                if (this.taxLabels.contains(taxLabel))
127                        return true;
128                else
129                        try {
130                                // Try it as a number to see if it refers to
131                                // position we already have.
132                                final int i = Integer.parseInt(taxLabel);
133                                if (i <= this.taxLabels.size() + 1)
134                                        return true;
135                        } catch (NumberFormatException e) {
136                                // It is not a number, so ignore.
137                        }
138                return false;
139        }
140
141        /**
142         * Get the TAXLABEL values added so far.
143         * 
144         * @return this labels so far.
145         */
146        public List getTaxLabels() {
147                return this.taxLabels;
148        }
149
150        /**
151         * Adds a comment.
152         * 
153         * @param comment
154         *            the comment to add.
155         */
156        public void addComment(final NexusComment comment) {
157                this.comments.add(comment);
158        }
159
160        /**
161         * Removes a comment.
162         * 
163         * @param comment
164         *            the comment to remove.
165         */
166        public void removeComment(final NexusComment comment) {
167                this.comments.remove(comment);
168        }
169
170        /**
171         * Returns all comments.
172         * 
173         * @return all the selected comments.
174         */
175        public List getComments() {
176                return this.comments;
177        }
178
179        protected void writeBlockContents(Writer writer) throws IOException {
180                for (final Iterator i = this.comments.iterator(); i.hasNext();) {
181                        ((NexusComment) i.next()).writeObject(writer);
182                        writer.write(NexusFileFormat.NEW_LINE);
183                }
184                writer.write(" DIMENSIONS NTAX=" + this.dimensionsNTax + ";"
185                                + NexusFileFormat.NEW_LINE);
186                writer.write(" TAXLABELS");
187                for (final Iterator i = this.taxLabels.iterator(); i.hasNext();) {
188                        writer.write(' ');
189                        this.writeToken(writer, (String) i.next());
190                }
191                writer.write(";" + NexusFileFormat.NEW_LINE);
192        }
193
194}