001    package edu.nrao.sss.model.source.parser;
002    
003    import java.io.IOException;
004    import java.io.LineNumberReader;
005    import java.io.Reader;
006    
007    import edu.nrao.sss.model.source.SourceCatalog;
008    
009    /**
010     * A parser of source catalog text files in the VLBA's format.
011     * Lines that start with "#" are comments.  Data lines conform
012     * to this format:
013     * <pre>
014     * J2000 name IVS name  Right ascension  Declination     Pos_err X-band flux S-band flux C-Cat
015     *                                                               Total Unres Total Unres
016     *                      hr mn seconds    deg mn seconds    mas   Jy    Jy    Jy    Jy   
017     * </pre>
018     * Whitespace is used as the delimiter.  This parser does not count columns in
019     * order to find the next field, it just uses the whitespace.  This means you
020     * may put any number of spaces between data items.  Here is an example from
021     * the VLBA catalog:
022     * <pre>
023     * J1254+4536  1252+458  12h54m28.828654s +45d36'04.32606"  1.02  0.12  0.10  0.21  0.20  C-VCS1
024     * </pre>
025     * For more detailed information about this format, see the
026     * <a href="http://www.vlba.nrao.edu/astro/calib/vlbaCalib.txt">
027     * VLBA Calibrator List</a>.
028     * <p>
029     * <b>Version Info:</b>
030     * <table style="margin-left:2em">
031     *   <tr><td>$Revision: 830 $</td></tr>
032     *   <tr><td>$Date: 2007-08-20 10:43:04 -0600 (Mon, 20 Aug 2007) $</td></tr>
033     *   <tr><td>$Author: dharland $</td></tr>
034     * </table></p>
035     * 
036     * @author David M. Harland
037     * @since 2007-03-14
038     */
039    public class OldVlbaSourceCatalogReader
040      extends AbstractSourceCatalogReader
041    {
042      private OldVlbaSourceReader sourceReader;
043      private LineNumberReader dataReader;
044      
045      /** Creates a new instance. */
046      public OldVlbaSourceCatalogReader()
047      {
048        sourceReader = new OldVlbaSourceReader();
049      }
050      
051      /** Prepares this instance to read from a new source. */
052      private void reset(Reader in, SourceCatalog destination)
053      {
054        catalog = (destination == null) ? new SourceCatalog() : destination;
055    
056        readWasSuccessful = false;
057        errors.clear();
058    
059        dataReader = new LineNumberReader(in);
060      }
061    
062      /**
063             * NOTE: This method closes the incoming Reader!
064             *
065       * @see AbstractSourceCatalogReader#read(java.io.Reader,
066       *      edu.nrao.sss.model.source.SourceCatalog)
067       */
068      public boolean read(Reader in, SourceCatalog destination)
069      {
070        reset(in, destination);
071        
072        String line = getNextLine();
073    
074        while (line != null)
075        {
076          if (sourceReader.textCouldBeData(line))
077          {
078            if (!sourceReader.read(line, dataReader.getLineNumber(), histRecPrefix))
079              errors.addAll(sourceReader.errors);
080            
081            if (sourceReader.source != null)
082            {
083              if (sourceInfoOrigin != null)
084                sourceReader.source.setOriginOfInformation(sourceInfoOrigin);
085    
086              catalog.addItem(sourceReader.source);
087            }
088          }
089          
090          line = getNextLine();
091        }
092        
093                    try
094                    {
095                            this.dataReader.close();
096                    }
097    
098                    catch(IOException ioe)
099                    {
100                            putError(0, "Error closing Reader: " + ioe.getMessage());
101                    }
102    
103        readWasSuccessful = getErrorCount() == 0;
104        
105        return readWasSuccessful;
106      }
107      
108      //============================================================================
109      // 
110      //============================================================================
111      
112      /** Reads lines, returning first one that does not cause an error. */
113      private String getNextLine()
114      {
115        int attempt = 0;
116        
117        while (++attempt <= 100)
118        {
119          try {
120            return dataReader.readLine();
121          }
122          catch (IOException ex) {
123            putError("I/O Exception: " + ex.getMessage());
124          }
125        }
126        
127        throw new RuntimeException("Failed " + attempt +
128                                   " times while attempting to read a line.");
129      }
130      
131      /** Adds a new parsing error to our list. */
132      private void putError(String message)
133      {
134        putError(dataReader.getLineNumber(), message);
135      }
136    }