JEphem Informatic Trail build classes source code BuildELP82.java
//*********************************************************************************
// class BuildELP82 // default package
// Software released under the General Public License (version 2 or later), available at 
// http://www.gnu.org/copyleft/gpl.html
//*********************************************************************************

import java.io.*;
import jephem.astro.planets.elp82.ELP82;
/******************************************************************
Contains methods used to build jephem.astro.planets.elp82.ELP82.java.
<BR>This class is NOT part of 'jephem' package, and can be useful to developpers who want to transform
BDL ELP files.

@author Thierry Graff
@history Aug 18 2001 : Creation
*****************************************************************/
public class BuildELP82{

  private final static String ls = System.getProperty("line.separator");

  /** Number of coordinates; */
  private final static int NB_COORD = 3;
  /** Number of data files; */
  private final static int NB_FILES = 36;

  /** String containing one blank character. */
  private final static String BLANK = " ";
  /** String containing one minus sign. */
  private final static String MINUS = "-";
  /** String containing one point. */
  private final static String POINT = ".";

  /** Prefix of data file names. */
  private final static String INPUTFILENAME_PREFIX = "ELP";
  /** Suffix of data file names (original files don't have, I added '.txt' during dvpt for 
  convenience under windows */
  private final static String INPUTFILENAME_SUFFIX = ".txt";

  /** Prefix of result file names. */
  private final static String OUTPUTFILENAME_PREFIX = "dataELP";
  /** Suffix of result file names (original files don't have, I added '.txt' during dvpt for 
  convenience under windows */
  private final static String OUTPUTFILENAME_SUFFIX = ".txt";

  /** Name of temp file containing integer terms. */
  private final static String TEMP_INT_FILENAME = "res/fosTmpInt";
  /** Name of temp file containing double terms. */
  private final static String TEMP_DOUBLE_FILENAME = "res/fosTmpDouble";

  /** Number of terms contained in the files.
  <BR><CODE>nbTerms[i][j]</CODE> contains terms of file ELPXX where XX = i*NB_COORD + j. 
  <BR><B>WARNING</B> : the indication 'Records' in README specifies the nb of <B>lines</B> of
  a file, which is nbTerms + 1 for data files.
  <BR>Thi array was built putting 'records' - 1
  */
	private static final int[][] nbTerms = {
    {1023, 918, 704},       // nb terms in ELP1, ELP2, ELP3
    {347, 316, 237},        // nb terms in ELP4, ELP5, ELP6
    {14, 11, 8},
    {14328, 5233, 6631}, 
    {4384, 833, 1715}, 
    {170, 150, 114}, 
    {226, 188, 169},        // etc ...
    {3, 2, 2}, 
    {6, 4, 5}, 
    {20, 12, 14}, 
    {11, 4, 10},
    {28, 13, 19}            // nb terms in ELP34, ELP35, ELP36
  }; // total 37872
  
  /** The 36 data files can files can be grouped ; each group share the same format and the summation
  done on terms of a file of a group uses the same formula. 
  <BR>Fisrt group contains ELP1, ELP2, ELP3 ; second group contains ELP4 ... ELP9 etc...
  */
	private static final int[] fileGroups = {4, 10, 16, 22, 37};
  
  
  /** Array to indicate how many columns files contain.
  <BR><CODE>nbColInfileGroups[][0]</CODE> represent the nb of columns of integers ;
  <BR><CODE>nbColInfileGroups[][1]</CODE> represent the nb of columns of doubles ;
  <BR>For example, files ELP1, 2 and 3 (first group) contain 4 columns of integers and 1 of double
  (this example is particular : files contain 7 cols of doubles, but only 1 is used in the formulae).
  */
	private static final int[][] nbColInfileGroups = { {4, 6},
                                                     {5, 2},
                                                     {11, 2},
                                                     {11, 2},
                                                     {5, 2}
                                                   };

  /** Array to indicate limits of interesting parts of parsed files.
  (index based on 0 - correspond to groups as defined in 'fileGroups'. */
	private static final int[][] interestingParts = { {0, 87},
                                                    {0, 35},
                                                    {0, 53},
                                                    {0, 53},
                                                    {0, 35}
                                                  };

	//************************* main ********************************
  public static void main(String[] args){
    transformELP82(args);
    //testClass();
    //testGetFirstNumber();
    //countTerms();
  }// end main

	//**************** transformELP82() ************************
	/** Method to build java-formatted arrays from ELP82 original files.
  <BR>Original BDL files must be in a subdirectory called 'data'
  <BR>Results are stored in a subdirectory called 'res'.
  <BR>3 ways to use it :
  <LI><B>Without argument</B> : file ELP1 to 36 must be in /data ; all files are parsed.</LI>
  <LI><B>One numeric argument</B> (between 1 and 36) : only the corresponding file is parsed.</LI>
  <LI><B>One argument of type x[x]-y[y]</B> (where x and y represent numerical digits and [] means 'optionnaly' - 
  example : "8-15")</LI> : files between the two numbers are parsed - they must be in data/.
  @param args array containing 0 or 1 element.
  */
  public static void transformELP82(String[] args){
		try{
    
      // *** Get which files to parse. ***
      // parameter parsing not bullet-proof : "1r-21" will throw a FormatNumberException
      int iBegin, iEnd;
      if (args.length == 0){
        iBegin = 1; 
        iEnd = NB_FILES + 1;
      }
      else if (args.length == 1){
        String str = args[0];
        try{
          iBegin = Integer.parseInt(str);
          iEnd = iBegin + 1;
        }
        catch (NumberFormatException nfe){
          // format should be : x[x]-y[y]
          int i = str.indexOf("-");
          if (i == -1)
            throw new Exception("Bad syntax in parameter " + str);
          else{
            iBegin = Integer.parseInt(str.substring(0, i));
            iEnd = Integer.parseInt(str.substring(i+1)) + 1;
          }
        }
      }
      else
        throw new Exception("Only one parameter possible.");
      System.out.println("Parsing files ELP" + iBegin + " to ELP" + iEnd);

      // Declaration of variables
      String line = new String(); // current line read

      String strRes; // result Strings.

      File curFile; // current file parsed (input file)
      int iCurFile; // index of the current file parsed.
      String strCurFileIndex; // String representation of iCurFile.
      String curFileZ; // addZero done on iCurFile
      String inputFileName, outputFileName;

      int curFileGroup; // file group of the current file parsed.
      int a, b; // to retrieve indexes of nbTerms from iCurFile.

      int i, j; // to loop on the input files.
      
      LineNumberReader lnr;
  		FileOutputStream fos;

      // ***** Loop on the files to parse
      for (iCurFile = iBegin; iCurFile < iEnd; iCurFile++){ // MAIN LOOP

        strCurFileIndex = String.valueOf(iCurFile);
        curFileZ = addZero(iCurFile);
        curFileGroup = findFileGroup(iCurFile);
        //System.out.println("File : " + iCurFile + " - group : " + curFileGroup + " - " + curNbIntCol + " " + curNbDoubleCol);
        
        inputFileName = "data/" + INPUTFILENAME_PREFIX + strCurFileIndex + INPUTFILENAME_SUFFIX;
        outputFileName = "res/" + OUTPUTFILENAME_PREFIX + curFileZ + OUTPUTFILENAME_SUFFIX;
        System.out.println("Parsing file " + inputFileName);

        curFile = new File(inputFileName);
        lnr = new LineNumberReader(new FileReader(curFile));
    		fos = new FileOutputStream(new File(outputFileName));

        // Find out how many lines current file contains.
        a = (int)Math.floor((iCurFile - 1)/NB_COORD);
        b = (iCurFile - 1)%NB_COORD;
        //System.out.println("nbTerms[" + a + "][" + b + "] = " + nbTerms[a][b]);

        // ***** 1 - Write general header (copy first line of the file)
        line = lnr.readLine().trim() + ls; // skip first line (header present in all data files).
        fos.write(line.getBytes());
        
        // ***** 2 - Parse line after line of input file.
        for(i = 0; i < nbTerms[a][b]; i++){
          line = lnr.readLine();
          strRes = line.substring(interestingParts[findFileGroup(iCurFile)][0], 
                                  interestingParts[findFileGroup(iCurFile)][1]) + ls;
          fos.write(strRes.getBytes());

          if (i%50 == 0) System.out.println(INPUTFILENAME_PREFIX + strCurFileIndex + " - line nb " + i); // log


        }// end for(i = 0; i < nbTerms[a][b]; i++)
          
   			fos.close();

      } // end for (int iCurFile = iBegin; iCurFile < iEnd) // MAIN LOOP ON INPUT FILES
		}
		catch(Exception e){
			//System.out.println("Exception : " + e.toString());
      e.printStackTrace();
		}

  }// end transformELP82()

	//**************** findFileGroup ************************
	/** Auxiliary method used by <CODE>transformELP82</CODE>.
  @param fileIndex The index characterizing a file (1 - 36)
  @returns the groupFile of <CODE>fileIndex</CODE>.
  */
  private static int findFileGroup(int fileIndex){
    for (int i = 0; i < fileGroups.length; i++){
      if (fileIndex < fileGroups[i]){
        return i;
      }
    }
    return -1; // should not happen
  }// end findFileGroup

	//**************** getFirstNumber ************************
	/** Returns a String representation of the first number found in a String.
  <BR>Auxiliary method used by <CODE>transformELP82</CODE>.
  Two successive integers are not necessarily separated by a blank.
  So usual method with substring(BLANK) can't be applied.
  @param line The String to parse.
  */
  private static String getFirstNumber(String line){
    String strRes = "";
    int i = 0;

    // get rid of first charcters not belonging to a number
    while(i < line.length() && !Character.isDigit(line.charAt(i)) && !line.substring(i, i+1).equals(MINUS)){    while(i < line.length() && !Character.isDigit(line.charAt(i)) && !line.substring(i, i+1).equals(MINUS)){
      i++;
    }
    // handle minus sign
    if (i < line.length() && line.substring(i, i+1).equals(MINUS)){    if (i < line.length() && line.substring(i, i+1).equals(MINUS)){
      strRes += MINUS;
      i++;
    }
    // get the number (digits or point).
    while(i < line.length() && (Character.isDigit(line.charAt(i)) || line.substring(i, i+1).equals(POINT))){    while(i < line.length() && (Character.isDigit(line.charAt(i)) || line.substring(i, i+1).equals(POINT))){
      strRes += line.substring(i, i+1);
      i++;
    }
    return strRes;
  }// end getFirstNumber

	//**************** testGetFirstNumber() ************************
	/** Just test before use... */
  public static void testGetFirstNumber(){
    //String line = "  0  0  0  0  0  0  0  0  0  0  1 179.93197   0.00068     0.075".trim();
    String line = "  0  0  5-12  0  0  0  0 -2  0  3  49.96695   0.00003     0.071".trim();

    int NB_NUMBERS = 14;
    String strNumber;
    for(int i = 0; i < NB_NUMBERS; i++){
      strNumber = getFirstNumber(line);
      System.out.println("strNumber : " + strNumber);
      line = line.trim();
      line = line.substring(strNumber.length());
    }
  }// end testGetFirstNumber
  
  //***************************** addZero ***************************************
  // Taken from reference implementation in tig.util.Formats.java
  /** Formats a integer to a 2 character long String. Useful for date formatting.
  @param nb integer number to format.
  @return A String representation of <CODE>nb</CODE> :
  <LI>if <CODE>0 <= nb <= 9</CODE>, "0" followed by the digit ;</LI>
  <LI>if <CODE>10 <= nb <= 99</CODE>, the two digits ;</LI>
  <LI>if <CODE>nb < 0 or nb > 100</CODE>, the String "xx".</LI>
  */
  private static String addZero(int nb){
    if (nb<0 || nb>99) return "xx";
    if (nb<10) return "0" + String.valueOf(nb);
    else return String.valueOf(nb);
  }// end addZero

  //**************** countTerms() ************************
  /** Counts the number of total terms. */
  public static void countTerms(){
    int res = 0;
    for(int i = 0; i < NB_FILES/NB_COORD; i++)
      for(int j = 0; j < NB_COORD; j++)
        res += nbTerms[i][j];
    System.out.println("Total nb terms in ELP82 : " + res);
 }// end countTerms

}//end class BuildELP82