
package jp.riken.brain.ni.samuraigraph.application;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jp.riken.brain.ni.samuraigraph.base.SGCSVTokenizer;
import jp.riken.brain.ni.samuraigraph.base.SGData;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;
import jp.riken.brain.ni.samuraigraph.data.SGDataTypeConstants;
import jp.riken.brain.ni.samuraigraph.data.SGISXYTypeData;
import jp.riken.brain.ni.samuraigraph.data.SGIVXYTypeData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYDateData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYMultipleData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYSamplingData;
import jp.riken.brain.ni.samuraigraph.data.SGVXYData;


/**
 * A class to create data objects.
 */
public class SGDataCreator
{

	/**
	 * The default constructor.
	 *
	 */
	public SGDataCreator()
	{
		super();
	}


	/**
	 * Creates a data object.
	 * @param path - the path name of the file
	 * @param infoList - information of data. [0]: dataType, [1]: data specific info.
	 * @return created data
	 * @throws FileNotFoundException
	 */
	public SGData create( final String path, final ArrayList infoList )
		throws FileNotFoundException
	{
		if( path==null || infoList==null )
		{
			throw new NullPointerException("path==null || infoList==null");
		}

		// when information is empty, returns null
		if( infoList.size()==0 )
		{
			return null;
		}

		SGData data = null;
		final String dataType = (String)infoList.get(0);
		if( dataType.equals( SGDataTypeConstants.SXY_DATA ) )
		{
			data = (SGData)this.createSXYData(path);
		}
		else if( dataType.equals( SGDataTypeConstants.SXY_DATE_DATA ) )
		{
			data = (SGData)this.createSXYDateData(path);
		}
		else if( dataType.equals( SGDataTypeConstants.VXY_DATA ) )
		{
			if( infoList.size()<=1 )
			{
				return null;
			}

			// get polar flag
			Object obj = infoList.get(1);
			if( ( obj instanceof Boolean ) == false )
			{
				return null;
			}
			Boolean b = (Boolean)obj;
			data = (SGData)this.createVXYData(path, b.booleanValue() );
		}
		else if( dataType.equals( SGDataTypeConstants.SXY_MULTIPLE_DATA ) )
		{
			data = this.createSXYMultipleData(path);
		}
		else if( dataType.equals( SGDataTypeConstants.SXY_SAMPLING_DATA ) )
		{
			if( infoList.size()<=1 )
			{
				return null;
			}

			// get sampling rate
			Object obj = infoList.get(1);
			if( ( obj instanceof Number ) == false )
			{
				return null;
			}
			Number num = (Number)obj;
			data = this.createSXYSamplingData( path, num.doubleValue() );
		}

		return data;
	}



	private static ArrayList getSXYTextColumnIndexList( final int columnNum )
	{
		ArrayList list = new ArrayList();
		// column == 1 : number
		// column == 2 : number, number
		// column == 3 : number, number, string
		// column == 4 : number, number, number, number
		// column == 5 : number, number, number, number, string
		// column >= 6 : ?
		for(int ii = 0; ii<columnNum; ii++){
			if((columnNum == 3 && ii == 2) || (columnNum == 5 && ii == 4))
				list.add( new Integer(0) );
			else
				list.add( new Integer(1) );
		}
		return list;
	}

	private static ArrayList getVXYTextColumnIndexList( final int columnNum )
	{
		ArrayList list = new ArrayList();
		// all culumns integer required 
		for(int ii = 0; ii<columnNum; ii++)
			list.add( new Integer(1) );
		return list;
	}

	private static ArrayList getSXYMultipleTextColumnIndexList( final int columnNum )
	{
		ArrayList list = new ArrayList();
		// all culumns integer required 
		for(int ii = 0; ii<columnNum; ii++)
			list.add( new Integer(1) );
		return list;
	}


	private static ArrayList getSXYDateTextColumnIndexList( final int columnNum )
	{
		ArrayList list = new ArrayList();
		// column == 1 : ?
		// column == 2 : string, number
		// column == 3 : string, number, string
		// column == 4 : string, number, number, number
		// column == 5 : string, number, number, number, string
		// column >= 6 : ?
		for(int ii=0; ii<columnNum; ii++){
			if(ii==0 || (columnNum==3 && ii==2) || (columnNum==5 && ii==4)){
				list.add( new Integer(0) );
			}else{
				list.add( new Integer(1) );				
			}
		}
		
		return list;
	}


	/**
	 * 
	 * @return
	 */
	private SGISXYTypeData createSXYData( final String path )
		throws FileNotFoundException
	{

		// get the number of columns
		final int num = this.getColumnNumber(path);
		if( num==-1 )
		{
			return null;
		}
		if( num<2 )
		{
			return null;
		}

		ArrayList columnIndexList = getSXYTextColumnIndexList(num);


		// リストの配列を作成
		ArrayList titleList = new ArrayList();
		ArrayList[] listArray
			= this.createListArray( path, num, titleList, columnIndexList );
		if( listArray==null )
		{
			return null;
		}


		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}


		//
		ArrayList cList = new ArrayList();
		if( this.getFileTypeCandidateList( path, cList ) == false )
		{
			return null;
		}


		//
		// create data object
		//

		SGISXYTypeData data = null;
		String str = null;
		Double d = null;
		{
			double[] xArray = new double[dataLength];
			double[] yArray = new double[dataLength];
			for( int ii=0; ii<dataLength; ii++ )
			{
				str = (String)listArray[0].get(ii);
				d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				xArray[ii] = d.doubleValue();

				str = (String)listArray[1].get(ii);
				d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				yArray[ii] = d.doubleValue();
			}

			double[] lArray = null;
			double[] uArray = null;
			String[] strArray = null;
			switch( num )
			{
				case 2 :
				{
					break;
				}
				case 4 :
				{
					lArray = new double[dataLength];
					uArray = new double[dataLength];
					for( int ii=0; ii<dataLength; ii++ )
					{
						str = (String)listArray[2].get(ii);
						d = SGUtilityText.getDouble(str);
						if( d==null )
						{
							return null;
						}
						lArray[ii] = d.doubleValue();

						str = (String)listArray[3].get(ii);
						d = SGUtilityText.getDouble(str);
						if( d==null )
						{
							return null;
						}
						uArray[ii] = d.doubleValue();
					}
					break;
				}
				case 3 :
				{
					strArray = new String[dataLength];
					for( int ii=0; ii<dataLength; ii++ )
					{
						strArray[ii] = (String)listArray[2].get(ii);
					}
					break;
				}
				case 5 :
				{
					lArray = new double[dataLength];
					uArray = new double[dataLength];
					strArray = new String[dataLength];
					for( int ii=0; ii<dataLength; ii++ )
					{
						str = (String)listArray[2].get(ii);
						d = SGUtilityText.getDouble(str);
						if( d==null )
						{
							return null;
						}
						lArray[ii] = d.doubleValue();

						str = (String)listArray[3].get(ii);
						d = SGUtilityText.getDouble(str);
						if( d==null )
						{
							return null;
						}
						uArray[ii] = d.doubleValue();

						strArray[ii] = (String)listArray[4].get(ii);
					}
					break;
				}
			
			}
			
			String[]  tArray = null;
			if ( titleList.size() != 0 ) {
				tArray = new String[num];
				for ( int ii=0; ii < titleList.size(); ii++ )
					tArray[ii] = (String)titleList.get(ii);
			}
			data = new SGSXYData(tArray, xArray, yArray, lArray, uArray, strArray );
		}

		return data;
	}




	/**
	 * 
	 * @return
	 */
	private SGISXYTypeData createSXYDateData( final String path )
		throws FileNotFoundException
	{
		// get the number of columns
		final int num = this.getColumnNumber(path);
		if( num==-1 )
		{
			return null;
		}
		if( num<2 )
		{
			return null;
		}


		ArrayList columnIndexList = getSXYDateTextColumnIndexList(num);

		// リストの配列を作成
		ArrayList titleList = new ArrayList();
		ArrayList[] listArray = this.createListArray( path, num, titleList, columnIndexList );
		if( listArray==null )
		{
			return null;
		}
		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}


		//
		ArrayList cList = new ArrayList();
		if( this.getFileTypeCandidateList( path, cList ) == false )
		{
			return null;
		}

		//
		// create data object
		//

		SGISXYTypeData data = null;
		String str = null;
		Double d = null;
		{
			String[] strArray = new String[dataLength];
			for( int ii=0; ii<dataLength; ii++ )
			{
				strArray[ii] = (String)listArray[0].get(ii);
			}

			double[] yArray = new double[dataLength];
			for( int ii=0; ii<dataLength; ii++ )
			{
				str = (String)listArray[1].get(ii);
				d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				yArray[ii] = d.doubleValue();
			}

			double[] lArray = null;
			double[] uArray = null;
			if( num==4 | num==5 )
			{
				lArray = new double[dataLength];
				uArray = new double[dataLength];
				for( int ii=0; ii<dataLength; ii++ )
				{
					str = (String)listArray[2].get(ii);
					d = SGUtilityText.getDouble(str);
					if( d==null )
					{
						return null;
					}
					lArray[ii] = d.doubleValue();

					str = (String)listArray[3].get(ii);
					d = SGUtilityText.getDouble(str);
					if( d==null )
					{
						return null;
					}
					uArray[ii] = d.doubleValue();
				}
			}
			
			String[] sArray = null;
			int strIndex = -1;
			if( num==3 )
			{
				strIndex = 2;
			}
			else if( num==5 )
			{
				strIndex = 4;
			}
			if( strIndex!=-1 )
			{
				sArray = new String[dataLength];
				for( int ii=0; ii<dataLength; ii++ )
				{
					str = (String)listArray[strIndex].get(ii);
					sArray[ii] = new String(str);
				}
			}
			
			String[]  tArray = null;
			if ( titleList.size() != 0 ) {
				tArray = new String[num];
				for ( int ii=0; ii < titleList.size(); ii++ )
					tArray[ii] = (String)titleList.get(ii);
			}
			try
			{
				data = new SGSXYDateData( tArray, strArray, yArray, lArray, uArray, sArray );
			}
			catch( ParseException ex )
			{
				
			}
		}

		return data;
	}



	/**
	 * 
	 * @return
	 */
	private SGSXYMultipleData createSXYMultipleData( final String path )
		throws FileNotFoundException
	{

		// ファイルからデータ列数を取得
		final int num = this.getColumnNumber(path);
		if( num==-1 )
		{
			return null;
		}
		if( num < 2 )
		{
			return null;
		}

		ArrayList columnIndexList = getSXYMultipleTextColumnIndexList(num);


		// リストの配列を作成
		ArrayList titleList = new ArrayList();
		ArrayList[] listArray = this.createListArray( path, num, titleList, columnIndexList );
		if( listArray==null )
		{
			return null;
		}

		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}


		//
		// create data object
		//

		SGSXYMultipleData data = null;
		{
			double[] xArray = new double[dataLength];
			for( int ii=0; ii<dataLength; ii++ )
			{
				String str = (String)listArray[0].get(ii);
				Double d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				xArray[ii] = d.doubleValue();
			}

			double[][] yArray = new double[num-1][];
			for( int ii=0; ii<num-1; ii++ )
			{
				yArray[ii] = new double[dataLength];
				for( int jj=0; jj<dataLength; jj++ )
				{
					String str = (String)listArray[ii+1].get(jj);
					Double d = SGUtilityText.getDouble(str);
					if( d==null )
					{
						return null;
					}
					yArray[ii][jj] = d.doubleValue();
				}
			}
			String[]  tArray = null;
			if ( titleList.size() != 0 ) {
				tArray = new String[num];
				for ( int ii=0; ii < titleList.size(); ii++ )
					tArray[ii] = (String)titleList.get(ii);
			}
			data = new SGSXYMultipleData( tArray, xArray, yArray );
		}

		return data;
	}



	/**
	 * 
	 * @return
	 */
	private SGSXYMultipleData createSXYSamplingData(
		final String path, final double sRate )
			throws FileNotFoundException
	{

		// ファイルからデータ列数を取得
		final int num = this.getColumnNumber(path);
		if( num==-1 )
		{
			return null;
		}
		if( num < 1 )
		{
			return null;
		}

		ArrayList columnIndexList = getSXYMultipleTextColumnIndexList(num);

		// リストの配列を作成
		ArrayList titleList = new ArrayList();
		ArrayList[] listArray = this.createListArray( path, num, titleList, columnIndexList );
		if( listArray==null )
		{
			return null;
		}

		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}


		//
		// create data object
		//

		SGSXYSamplingData data = null;

		Double d = null;
		String str = null;
		{
			double[][] yArray = new double[num][];
			for( int ii=0; ii<num; ii++ )
			{
				yArray[ii] = new double[dataLength];
				for( int jj=0; jj<dataLength; jj++ )
				{
					str = (String)listArray[ii].get(jj);
					d = SGUtilityText.getDouble(str);
					if( d==null )
					{
						return null;
					}
					yArray[ii][jj] = d.doubleValue();
				}
			}
			String[]  tArray = null;
			if ( titleList.size() != 0 ) {
				tArray = new String[num];
				for ( int ii=0; ii < titleList.size(); ii++ )
					tArray[ii] = (String)titleList.get(ii);
			}
			data = new SGSXYSamplingData( tArray, sRate, yArray );
		}

		return data;
	}



	/**
	 * 
	 * @return
	 */
	private SGIVXYTypeData createVXYData( final String path, final boolean isPolar )
		throws FileNotFoundException
	{
		// get the number of columns
		final int num = this.getColumnNumber(path);
		if( num==-1 )
		{
			return null;
		}
		if( num<4 )
		{
			return null;
		}


		ArrayList columnIndexList = getVXYTextColumnIndexList(num);


		// リストの配列を作成
		ArrayList titleList = new ArrayList();
		ArrayList[] listArray = this.createListArray( path, num, titleList, columnIndexList );
		if( listArray==null )
		{
			return null;
		}


		// check
		final int dataLength = listArray[0].size();
		for( int ii=1; ii<listArray.length; ii++ )
		{
			if( listArray[ii].size()!=dataLength )
			{
				return null;
			}
		}


		//
		ArrayList cList = new ArrayList();
		if( this.getFileTypeCandidateList( path, cList ) == false )
		{
			return null;
		}


		//
		// create data object
		//

		SGIVXYTypeData data = null;
		String str = null;
		Double d = null;
		{
			double[] xArray = new double[dataLength];
			double[] yArray = new double[dataLength];
			double[] cArray1 = new double[dataLength];
			double[] cArray2 = new double[dataLength];
			for( int ii=0; ii<dataLength; ii++ )
			{
				str = (String)listArray[0].get(ii);
				d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				xArray[ii] = d.doubleValue();

				str = (String)listArray[1].get(ii);
				d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				yArray[ii] = d.doubleValue();
			}

			for( int ii=0; ii<dataLength; ii++ )
			{
				str = (String)listArray[2].get(ii);
				d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				if( isPolar )
				{
					if( d.doubleValue() < 0.0 )
					{
						return null;
					}
				}
				cArray1[ii] = d.doubleValue();

				str = (String)listArray[3].get(ii);
				d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return null;
				}
				cArray2[ii] = d.doubleValue();
			}
			String[]  tArray = null;
			if ( titleList.size() != 0 ) {
				tArray = new String[num];
				for ( int ii=0; ii < titleList.size(); ii++ )
					tArray[ii] = (String)titleList.get(ii);
			}
			data = new SGVXYData( tArray, xArray, yArray, cArray1, cArray2, isPolar );
		}

		return data;
	}



	// Reads the first line and returns the number of token
	private int getColumnNumber( final String path )
		throws FileNotFoundException
	{
		int num = -1;

		BufferedReader br = null;
		try
		{
			br = new BufferedReader( new FileReader(path) );
			ArrayList tokenList = this.getFirstTokenList(br);
			num = tokenList.size();
		}
		catch( FileNotFoundException ex )
		{
			throw ex;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}

		return num;
	}



	/**
	 * Creates an array of the list.
	 * @param path
	 * @param num
	 * @return
	 * @throws FileNotFoundException
	 */
	private ArrayList[] createListArray(
		final String path,
		final int num, 
		final ArrayList titleList,
		final ArrayList columnIndexList )
		throws FileNotFoundException
	{

		// create an array of list
		ArrayList[] listArray = new ArrayList[num];
		for( int ii=0; ii<listArray.length; ii++ )
		{
			listArray[ii] = new ArrayList();
		}

		// read the file
		BufferedReader br = null;
		try
		{
			br = new BufferedReader( new FileReader(path) );
			boolean isFirstLine = true;

			while( true )
			{
				// read a line
				final String line = SGUtilityText.readLine(br);
				if( line==null )
				{
					break;
				}

				// break the string into tokens
				final ArrayList tokenList = new ArrayList();
				// line is read from data file
				if( SGUtilityText.tokenize( line, tokenList, true ) == false )
				{
					return null;
				}

				// check the tokens
				if( tokenList.size()!=num )
				{
					if( tokenList.size()!=0 )
					{
						// format error
						return null;
					}
					// only contains spaces and tabs
					continue;
				}

				// format check
				ArrayList indexList = getColumnIndexListOfNumber(tokenList);

				if ( isFirstLine ) {
					if( this.evaluteTitleList( indexList ) ) {
						titleList.addAll(tokenList);
						isFirstLine = false;
						continue;
					}
				}
				
				if(machesNumberColumnIndex(columnIndexList, indexList) == false)
					return null;
				
				// array of the tokens
				final String[] array = new String[num];
				for( int ii=0; ii<num; ii++ )
				{
					String str = (String)tokenList.get(ii);
					listArray[ii].add( str );
				}
			}
		}
		catch( FileNotFoundException ex )
		{
			throw ex;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}

		return listArray;
	}
	
	// check index list : can token index convert column index ? 
	private boolean machesNumberColumnIndex(final ArrayList columnList, final ArrayList tokenIndexList){
		Integer column;
		Integer token;
		if(columnList.size() != tokenIndexList.size())
			return false;
		for(int ii=0; ii<columnList.size(); ii++){
			column = (Integer)columnList.get(ii);
			token  = (Integer)tokenIndexList.get(ii);
			if(column.intValue() == 1 && token.intValue() == 0)
				return false;
		}
		return true;
	}
	
//	public static void main( String[] args ) throws Exception
//	{
//System.out.println("start");
//
//		String path = "D:\\Tmp\\test.txt";
//		
//		ArrayList list = new ArrayList();
//		list.add( SGDataTypeConstants.VXY_DATA );
//		list.add( Boolean.FALSE );
//
//		SGDataCreator c = new SGDataCreator();
//		SGData data = c.create( path, list );
//
//		System.out.println(data);
//
//System.out.println("end");
//	}
	
	// returns a list of number convertable column index
	private static ArrayList getColumnIndexListOfNumber( final ArrayList tokenlist )
	{
		final String NUM_PATTERN = "^[+-]?[0-9]+(\\.[0-9]*)?([eE][+-]?[0-9]+)?$";
		Pattern pattern;
		Matcher matcher;
		ArrayList list = new ArrayList();
		pattern = Pattern.compile(NUM_PATTERN);
		for(int ii = 0; ii < tokenlist.size(); ii++){
			String token = (String)tokenlist.get(ii);
			matcher = pattern.matcher(token);			
			if(matcher.matches())
				list.add(new Integer(1));
			else
				list.add(new Integer(0));
		}
		return list;
	}
	
	// check title list
	private boolean evaluteTitleList( final ArrayList indexList )
	{
		boolean ret = true;
		if( indexList.size() == 0 )
			return false;
		for ( int ii=0; ii<indexList.size(); ii++) {
			Integer val = (Integer)indexList.get(ii);
			if (val.intValue() != 0)
				ret = false;
		}
		return ret;
	}
	
	/**
	 * Determine the data-type from the first line.
	 */
	public boolean getFileTypeCandidateList(
		final String path,
		final ArrayList cList
		) throws FileNotFoundException
	{
		BufferedReader br = null;
		try
		{
			br = new BufferedReader( new FileReader( path ) );

			ArrayList tokenList = this.getFirstTokenList(br);
			int tokenNum = tokenList.size();
			HashSet cSet = new HashSet();

			// get number convertable culumns
			ArrayList indexList = getColumnIndexListOfNumber(tokenList);
			
			// get titles
			if( this.evaluteTitleList(indexList) )
			{
				// this is title. read next line for indexList
				tokenList = this.getFirstTokenList(br);
				indexList = getColumnIndexListOfNumber(tokenList);
			}
			
			// SXY
			if( this.evaluateDataTypeSXY(tokenList) )
			{
				ArrayList columnIndexList = getSXYTextColumnIndexList(tokenNum);
				if( machesNumberColumnIndex( columnIndexList, indexList ) )
				{
					cSet.add(SGDataTypeConstants.SXY_DATA);
				}
			}

			// VXY
			if( this.evaluateDataTypeVXY(tokenList) )
			{
				ArrayList columnIndexList = getVXYTextColumnIndexList(tokenNum);
				if( machesNumberColumnIndex( columnIndexList, indexList ) )
				{
					cSet.add(SGDataTypeConstants.VXY_DATA);
				}
			}

			// SXY Multiple
			if( this.evaluateDataTypeSXYMultiple(tokenList) )
			{
				ArrayList columnIndexList = getSXYMultipleTextColumnIndexList(tokenNum);
				if( machesNumberColumnIndex( columnIndexList, indexList ) )
				{
					if( tokenNum>=3 )
					{
						cSet.add(SGDataTypeConstants.SXY_MULTIPLE_DATA);
					}

					if( tokenNum>=1 )
					{
						cSet.add(SGDataTypeConstants.SXY_SAMPLING_DATA);
					}
				}
			}

			// SXY Date
			if( this.evaluateDataTypeSXYDate( tokenList ) )
			{
				ArrayList columnIndexList = getSXYDateTextColumnIndexList(tokenNum);
				if( machesNumberColumnIndex( columnIndexList, indexList ) )
				{
					cSet.add(SGDataTypeConstants.SXY_DATE_DATA);
				}
			}

			cList.addAll( cSet );
		}
		catch( FileNotFoundException ex )
		{
			throw ex;
		}
		finally
		{
			if( br!=null )
			{
				try
				{
					br.close();
				}
				catch( IOException ex )
				{
					
				}
			}
		}

		return true;
	}



	/**
	 * 
	 */
	private boolean evaluateDataTypeSXY( final ArrayList tokenList )
	{
		final int size = tokenList.size();

		ArrayList numberIndexList = new ArrayList();
		if( size==2 | size==4 )
		{
			for( int ii=0; ii<size; ii++ )
			{
				numberIndexList.add( new Integer(ii) );
			}
		}
		else if( size==3 )
		{
			numberIndexList.add( new Integer(0) );
			numberIndexList.add( new Integer(1) );
		}
		else if( size==5 )
		{
			for( int ii=0; ii<4; ii++ )
			{
				numberIndexList.add( new Integer(ii) );
			}
		}
		else
		{
			return false;
		}


		boolean b = true;
		for( int ii=0; ii<numberIndexList.size(); ii++ )
		{
			final int index = ((Integer)numberIndexList.get(ii)).intValue();
			String str = (String)tokenList.get(index);
			Double d = SGUtilityText.getDouble(str);
			if( d==null )
			{
				b = false;
				break;
			}
		}

		return b;
	}


	/**
	 * 
	 */
	private boolean evaluateDataTypeVXY( final ArrayList tokenList )
	{
		boolean b = true;
		final int size = tokenList.size();
		if( size!=4 )
		{
			return false;
		}

		for( int ii=0; ii<size; ii++ )
		{
			String str = (String)tokenList.get(ii);
			Double d = SGUtilityText.getDouble(str);
			if( d==null )
			{
				b = false;
				break;
			}
		}

		return b;
	}



	/**
	 * 
	 */
	private boolean evaluateDataTypeSXYMultiple( final ArrayList tokenList )
	{
		boolean b = true;
		final int size = tokenList.size();
		for( int ii=0; ii<size; ii++ )
		{
			String str = (String)tokenList.get(ii);
			Double d = SGUtilityText.getDouble(str);
			if( d==null )
			{
				b = false;
				break;
			}
		}

		return b;
	}


	//
	private boolean evaluateDataTypeSXYDate( final ArrayList tokenList )
	{
		final int num = tokenList.size();
		if( num!=2 & num!=3 & num!=4 & num!=5 )
		{
			return false;
		}

		// date
		final ArrayList dList = new ArrayList();
		dList.add( tokenList.get(0) );

		final DateFormat df = DateFormat.getDateInstance();
		for( int ii=0; ii<dList.size(); ii++ )
		{
			final String str = (String)dList.get(ii);
			final Date d = SGUtilityText.getDate(str);
			if( d==null )
			{
				return false;
			}
		}


		// number
		final ArrayList nList = new ArrayList();
		nList.add( tokenList.get(1) );
		if( num==4 | num==5  )
		{
			nList.add( tokenList.get(1) );
			nList.add( tokenList.get(2) );
			nList.add( tokenList.get(3) );
		}

		for( int ii=0; ii<nList.size(); ii++ )
		{
			final String str = (String)nList.get(ii);
			final Double d = SGUtilityText.getDouble(str);
			if( d==null )
			{
				return false;
			}
		}

		return true;
	}


	/**
	 * Returns a list of tokens of the first line.
	 * @param br - a buffered reader
	 * @return a list of tokens
	 */
	private ArrayList getFirstTokenList( BufferedReader br )
	{
		ArrayList tokenList = new ArrayList();
		while( true )
		{
			String line = SGUtilityText.readLine(br);
			if( line == null )
			{
				break;
			}

			// tokenize the line
			tokenList.clear();
			SGCSVTokenizer csvt = new SGCSVTokenizer(line, true); // from data file
			while (csvt.hasMoreTokens()) {
				try {
					String result = csvt.nextToken();
					tokenList.add(result);
				} catch (NoSuchElementException e) {
				}
			}
			final int size = tokenList.size();	// the number of tokens
			if( size!=0 )
			{
				break;
			}
		}

		return tokenList;
	}


}

