/* BEGIN_HEADER                                              Java TreeView
*
* $Author: alokito $
* $RCSfile: FlatFileStreamLiner.java,v $
* $Revision: 1.7 $
* $Date: 2005-03-12 22:32:08 $
* $Name:  $
*
* This file is part of Java TreeView
* Copyright (C) 2001-2014 Alok Saldanha, All Rights Reserved. Modifications Copyright (C) Lawrence Berkeley Lab.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* END_HEADER
*/
package edu.stanford.genetics.treeview.model;

import java.io.*;
import java.util.Vector;


/**
 *  implements the "lexical structure" of flat files basically, calling
 *  nextToken returns a series of words, nulls and newlines, and finally an EOF.
 *  Note that numbers are not parsed by the tokenizer. Also, there is no enforcement
 * of the correct number of tokens per line.
 *
 * it will, however, filter out blank lines.
 * 
 * @author     Alok Saldanha <alok@genome.stanford.edu>
 * @version $Revision: 1.7 $ $Date: 2005-03-12 22:32:08 $
 */
public class FlatFileStreamLiner{

	private char sep;
	/**
	 * parse quoted strings?
	 */
	private boolean pqs = true;
	private StreamTokenizer st;
	private Vector line;

	/**
	 *  Constructor for the FlatFileStreamTokenizer object
	 *
	 * @param  reader  Reader of file to tokenize
	 * @param  ch      Separator character to split cols
	 */
	public FlatFileStreamLiner(Reader reader, char ch, boolean parseQuotedStrings) {
		sep = ch;
		pqs = parseQuotedStrings;
		st = new StreamTokenizer(reader);
		resetSyntax();
		line = new Vector();
	   }
	public void resetSyntax() {
		st.resetSyntax();
		st.wordChars(0, 3000);
		st.whitespaceChars('\r', '\r');
		st.whitespaceChars('\n', '\n');
		st.ordinaryChar(sep);
		if (pqs) {
			//make sure to add these chars to the nextLine() switch statement
			st.quoteChar('"');
		}
		st.eolIsSignificant(true);
		//st.parseNumbers(); do not uncomment.
	}

	public static void main(String astring[])
	{
		System.out.println("analysizing " + astring[0]);
	  	BufferedReader br;
		try {
			br = new BufferedReader(new FileReader(astring[0]));
			FlatFileStreamLiner st = new FlatFileStreamLiner(br, '\t', true);
			while(st.nextLine()) {
				String [] tok = st.getLineTokens();
				for (int i = 0; i < tok.length; i++) {
					System.out.print(tok[i]);
					System.out.print(":");
				}
				System.out.print("\n");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	 }
	
	public String[] getLineTokens(){
		int len = line.size();
		String[] string = new String[len];
		for (int i = 0; i < len; i++){
			string[i] = (String)line.get(i);
		}
		return string;
	}
	
	public boolean nextLine() throws IOException {
		line.removeAllElements();
		boolean lastsep = true; //in case first token is sep

		while(st.nextToken() != StreamTokenizer.TT_EOF){
			switch (st.ttype){
			case StreamTokenizer.TT_EOL:
				// line ends with tab char (indicating last value null)
				if (lastsep) line.add(null);
				return true;
			case StreamTokenizer.TT_NUMBER:
				System.out.println("parsed number");
				line.add("" + st.nval);
				lastsep = false;
				break;
			case '"':
				if (lastsep == false) {
					// account for stupid excel embedded quotes
					line.setElementAt(line.lastElement() + st.sval, line.size()-1);
					break;
				}
				// otherwise, fall through to new word.
			case StreamTokenizer.TT_WORD:
				line.add(st.sval);
				lastsep = false;
				break;
			default:
				// case statements must be constants, so can't use sep.
				if (st.ttype == sep) {
					if (lastsep){ //already one sep
						line.add(null);
					}else{ //normal sep, after real token
						lastsep = true;
					}
				}
				break;
			}
		}
		
		// indicates that last line lacks EOL token
		if (line.size() == 0) 
			return false;
		else
			return true;
	}
}

