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 blocks. Each instance should parse tokens into events that can
027 * be fired at some kind of NexusBlockListener. An Abstract parser is provided
028 * from which all implementations should derive.
029 * 
030 * @author Richard Holland
031 * @author Tobias Thierer
032 * @author Jim Balhoff
033 * @since 1.6
034 */
035public interface NexusBlockParser {
036
037        /**
038         * The name for an unknown block parser.
039         */
040        public static final String UNKNOWN_BLOCK = "__UNKNOWN";
041
042        /**
043         * Notifies the parser that a new block is starting.
044         * 
045         * @param blockName
046         *            the name of the block.
047         */
048        public void startBlock(String blockName);
049
050        /**
051         * Notifies the parser that a block is ending.
052         */
053        public void endBlock();
054
055        /**
056         * Notifies the parser of the next token. Comment tokens will already have
057         * been parsed out and sent separately to the text() method of the listener.
058         * Quoted strings will have been parsed and underscores converted. What this
059         * token contains is the full string, after removal of quotes if necessary.
060         * The token will never be only whitespace.
061         * 
062         * @param token
063         *            the token to parse.
064         * @throws ParseException
065         *             if the token is unparseable.
066         */
067        public void parseToken(String token) throws ParseException;
068
069        /**
070         * Opening a comment tag.
071         */
072        public void beginComment();
073
074        /**
075         * Closing a comment tag.
076         */
077        public void endComment();
078
079        /**
080         * Closing a line (semi-colon encountered). This indicates that anything
081         * received after it is on the next logical line of the block.
082         */
083        public void endTokenGroup();
084
085        /**
086         * Receiving free text inside a comment tag.
087         * 
088         * @param comment
089         *            the text of the comment.
090         */
091        public void commentText(String comment) throws ParseException;
092
093        /**
094         * Obtain the listener for this parser.
095         * 
096         * @return the listener.
097         */
098        public NexusBlockListener getBlockListener();
099
100        /**
101         * Does the listener want to know about brackets and braces as separate
102         * tokens?
103         * 
104         * @return <tt>true</tt> if it does.
105         */
106        public boolean wantsBracketsAndBraces();
107
108        /**
109         * All block parsers should derive from this abstract parser.
110         */
111        public abstract class Abstract implements NexusBlockParser {
112                private NexusBlockListener blockListener;
113
114                private String blockName;
115
116                public Abstract(final NexusBlockListener blockListener) {
117                        this.blockListener = blockListener;
118                        this.blockName = null;
119                }
120
121                public NexusBlockListener getBlockListener() {
122                        return this.blockListener;
123                }
124
125                public void startBlock(final String blockName) {
126                        this.resetStatus();
127                        this.blockName = blockName;
128                        this.blockListener.startBlock(blockName);
129                }
130
131                /**
132                 * This function is called when the parser is reset before starting a
133                 * new block.
134                 */
135                protected abstract void resetStatus();
136
137                protected String getBlockName() {
138                        return this.blockName;
139                }
140
141                public void endBlock() {
142                        this.blockName = null;
143                        this.blockListener.endBlock();
144                }
145
146                public void beginComment() {
147                        this.blockListener.beginComment();
148                }
149
150                public void endComment() {
151                        this.blockListener.endComment();
152                }
153
154                public void endTokenGroup() {
155                        this.blockListener.endTokenGroup();
156                }
157
158                public void commentText(final String comment) throws ParseException {
159                        this.blockListener.commentText(comment);
160                }
161
162                public abstract void parseToken(final String token)
163                                throws ParseException;
164
165                public boolean wantsBracketsAndBraces() {
166                        return false;
167                }
168        }
169}