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 org.biojava.bio.seq.io.ParseException;
024
025/**
026 * Parses Nexus taxa blocks.
027 * 
028 * @author Richard Holland
029 * @author Tobias Thierer
030 * @author Jim Balhoff
031 * @since 1.6
032 */
033public class TaxaBlockParser extends NexusBlockParser.Abstract {
034
035        private boolean expectingDimension;
036
037        private boolean expectingNTax;
038
039        private boolean expectingNTaxEquals;
040
041        private boolean expectingNTaxValue;
042
043        private boolean expectingTaxLabel;
044
045        private boolean expectingTaxLabelValue;
046
047        /**
048         * Delegates to NexusBlockParser.Abstract.
049         * 
050         * @param blockListener
051         *            the listener to send parse events to.
052         */
053        public TaxaBlockParser(TaxaBlockListener blockListener) {
054                super(blockListener);
055        }
056
057        public void resetStatus() {
058                this.expectingDimension = true;
059                this.expectingNTax = false;
060                this.expectingNTaxEquals = false;
061                this.expectingNTaxValue = false;
062                this.expectingTaxLabel = false;
063                this.expectingTaxLabelValue = false;
064        }
065
066        public void parseToken(String token) throws ParseException {
067                if (token.trim().length() == 0)
068                        return;
069                else if (this.expectingDimension
070                                && "DIMENSIONS".equalsIgnoreCase(token)) {
071                        this.expectingDimension = false;
072                        this.expectingNTax = true;
073                } else if (this.expectingNTax && token.toUpperCase().startsWith("NTAX")) {
074                        this.expectingNTax = false;
075                        if (token.indexOf('=') >= 0) {
076                                final String[] parts = token.split("=");
077                                if (parts.length > 1) {
078                                        this.expectingTaxLabel = true;
079                                        try {
080                                                ((TaxaBlockListener) this.getBlockListener())
081                                                                .setDimensionsNTax(Integer.parseInt(parts[1]));
082                                        } catch (NumberFormatException e) {
083                                                throw new ParseException("Invalid NTAX value: "
084                                                                + parts[1]);
085                                        }
086                                } else
087                                        this.expectingNTaxValue = true;
088                        } else
089                                this.expectingNTaxEquals = true;
090                } else if (this.expectingNTaxEquals && token.startsWith("=")) {
091                        this.expectingNTaxEquals = false;
092                        final String[] parts = token.split("=");
093                        if (parts.length > 1) {
094                                this.expectingTaxLabel = true;
095                                try {
096                                        ((TaxaBlockListener) this.getBlockListener())
097                                                        .setDimensionsNTax(Integer.parseInt(parts[1]));
098                                } catch (NumberFormatException e) {
099                                        throw new ParseException("Invalid NTAX value: " + parts[1]);
100                                }
101                        } else
102                                this.expectingNTaxValue = true;
103                } else if (this.expectingNTaxValue) {
104                        this.expectingNTaxValue = false;
105                        try {
106                                ((TaxaBlockListener) this.getBlockListener())
107                                                .setDimensionsNTax(Integer.parseInt(token));
108                        } catch (NumberFormatException e) {
109                                throw new ParseException("Invalid NTAX value: " + token);
110                        }
111                        this.expectingTaxLabel = true;
112                } else if (this.expectingTaxLabel
113                                && "TAXLABELS".equalsIgnoreCase(token)) {
114                        this.expectingTaxLabel = false;
115                        this.expectingTaxLabelValue = true;
116                } else if (this.expectingTaxLabelValue)
117                        // Use untoken version to preserve spaces.
118                        ((TaxaBlockListener) this.getBlockListener()).addTaxLabel(token);
119                else
120                        throw new ParseException("Found unexpected token " + token
121                                        + " in TAXA block");
122        }
123
124}