001    package edu.nrao.sss.model.source.parser;
002    
003    import java.io.FileNotFoundException;
004    import java.io.Reader;
005    import java.io.File;
006    import java.io.FileReader;
007    import java.io.InputStreamReader;
008    import java.io.InputStream;
009    import java.io.IOException;
010    
011    import java.util.zip.ZipInputStream;
012    import java.util.zip.GZIPInputStream;
013    import java.util.List;
014    import java.util.ArrayList;
015    
016    import edu.nrao.sss.model.source.SourceCatalog;
017    import edu.nrao.sss.util.FileCompressionFormat;
018    
019    /**
020     * An abstract implementation of the common methods in the SourceCatalogReader interface.
021     * <p>
022     * <b>CVS Info:</b>
023     * <table style="margin-left:2em">
024     *   <tr><td>$Revision: 630 $</td></tr>
025     *   <tr><td>$Date: 2007-05-18 14:12:55 -0600 (Fri, 18 May 2007) $</td></tr>
026     *   <tr><td>$Author: dharland $</td></tr>
027     * </table></p>
028     */
029    public abstract class AbstractSourceCatalogReader
030            implements SourceCatalogReader
031    {
032      protected SourceCatalog    catalog;
033      protected boolean          readWasSuccessful;
034      protected List<ParseError> errors;
035      
036      protected String sourceInfoOrigin;
037      protected String histRecPrefix;
038      
039            public AbstractSourceCatalogReader()
040            {
041        errors       = new ArrayList<ParseError>();
042        readWasSuccessful = false;
043        
044        sourceInfoOrigin = null;
045        histRecPrefix    = "";
046            }
047    
048      /**
049             * A default implementation of {@link SourceCatalogReader#read(String)}. This
050             * calls {@link #read(String, SourceCatalog)} with a null catalog.
051       */
052      public boolean read(String fileName)
053                    throws FileNotFoundException
054            {
055                    return read(fileName, null);
056            }
057    
058      /**
059             * A default implementation of {@link SourceCatalogReader#read(String, SourceCatalog)}. This
060             * calls {@link #read(Reader, SourceCatalog)}, wrapping <code>fileName</code> with a FileReader.
061       */
062      public boolean read(String fileName, SourceCatalog destination)
063        throws FileNotFoundException
064            {
065                    return read(new FileReader(new File(fileName)), destination);
066            }
067      
068      /**
069             * A default implementation of {@link SourceCatalogReader#read(Reader)}. This
070             * calls {@link #read(Reader, SourceCatalog)} with a null catalog.
071       */
072      public boolean read(Reader in)
073            {
074                    return read (in, null);
075            }
076      
077      /**
078             * A default implementation of {@link SourceCatalogReader#read(InputStream)}.
079             * This calls {@link #read(InputStream, SourceCatalog, FileCompressionFormat)}
080             * with a null catalog and a UNCOMPRESSED format.
081       */
082            public boolean read(InputStream in)
083            {
084                    return read(in, null, FileCompressionFormat.UNCOMPRESSED);
085            }
086    
087      /**
088             * A default implementation of {@link SourceCatalogReader#read(InputStream, SourceCatalog)}.
089             * This calls {@link #read(InputStream, SourceCatalog, FileCompressionFormat)}
090             * with a UNCOMPRESSED format.
091       */
092            public boolean read(InputStream in, SourceCatalog destination)
093            {
094                    return read(in, destination, FileCompressionFormat.UNCOMPRESSED);
095            }
096    
097      /**
098             * A default implementation of {@link SourceCatalogReader#read(InputStream, FileCompressionFormat)}.
099             * This calls {@link #read(InputStream, SourceCatalog, FileCompressionFormat)}
100             * with a null catalog.
101       */
102            public boolean read(InputStream in, FileCompressionFormat format)
103            {
104                    return read(in, null, format);
105            }
106    
107            /**
108             * This method prepares the input stream {@code in} to be passed as an
109             * InputStreamReader to {@link #read(Reader, SourceCatalog)}. If {@code
110             * format} is ZIP or GZ, the InputStream is wrapped in a ZipInputStream or
111             * GZIPInputStream respectively before being wrapped in an InputStreamReader.
112             * This allows the primary read method (which is abstract in this class) to
113             * be unaware that the input was compressed. If {@code format} is null or
114             * UNCOMPRESSED, {@code in} is passed directly into the InputStreamReader
115             * constructor.
116             */
117            public boolean read(InputStream in, SourceCatalog destination, FileCompressionFormat format)
118            {
119                    InputStream wrappedIn = in;
120    
121                    //Wrap "in" in an appropriate compression filter if necessary, then wrap
122                    //that in an InputStreamReader and call read(reader, destination);
123                    if (format != null)
124                    {
125                            switch(format)
126                            {
127                                    case ZIP:
128                                            try
129                                            {
130                                                    wrappedIn = new ZipInputStream(in);
131    
132                                                    //Prepare the ZipInputStream to be reading the next (and hopefully
133                                                    //only) file.
134                                                    ((ZipInputStream)wrappedIn).getNextEntry();
135                                            }
136    
137                                            catch(IOException ioe)
138                                            {
139                                                    putError(0, "Error reading catalog. Invalid ZIP format.");
140                                                    return false;
141                                            }
142                                            break;
143    
144                                    case GZ:
145                                            try
146                                            {
147                                                    wrappedIn = new GZIPInputStream(in);
148                                            }
149    
150                                            catch(IOException ioe)
151                                            {
152                                                    putError(0, "Error reading catalog. Invalid GZIP format.");
153                                                    return false;
154                                            }
155                                            break;
156    
157                                    //These cases will just use the default value of wrappedIn (i.e. in
158                                    //itself)
159                                    //case UNCOMPRESSED:
160                                    //default:
161                            }
162                    }
163    
164                    boolean success = read(new InputStreamReader(wrappedIn), destination);
165                    //wrappedIn.close();
166    
167                    return success;
168            }
169    
170            /**
171             * An abstract method that must be implemented by subclasses. All other read
172             * methods delegate to this one.
173             *
174       * @see #read(Reader, SourceCatalog)
175             */
176      public abstract boolean read(Reader in, SourceCatalog destination);
177    
178      /**
179       * @see SourceCatalogReader#getErrors()
180       */
181      public StringBuilder getErrors()
182      {
183        StringBuilder errorMsg = new StringBuilder();
184        
185        for (ParseError error : errors)
186          error.appendTo(errorMsg);
187        
188        return errorMsg;
189      }
190      
191      /**
192       * @see SourceCatalogReader#getError(int)
193       */
194      public String getError(int index)
195      {
196        return errors.get(index).toString();
197      }
198    
199      /**
200       * @see SourceCatalogReader#getErrorCount()
201       */
202      public int getErrorCount()
203      {
204        return errors.size();
205      }
206    
207      /**
208       * @see SourceCatalogReader#getCatalog()
209       */
210      public SourceCatalog getCatalog()
211      {
212        if (catalog == null)
213          catalog = new SourceCatalog();
214        
215        return catalog;
216      }
217      
218      /**
219       * @see SourceCatalogReader#getSuccess()
220       */
221      public boolean getSuccess()
222      {
223        return readWasSuccessful;
224      }
225    
226      /**
227       * @see SourceCatalogReader#setOriginOfSourceInformation(String)
228       */
229      public void setOriginOfSourceInformation(String origin)
230      {
231        sourceInfoOrigin = origin;
232      }
233    
234      public String getOriginOfSourceInformation()
235            {
236                    return sourceInfoOrigin;
237            }
238    
239      /**
240       * @see SourceCatalogReader#setPrefixForHistoricalRecords(String)
241       */
242      public void setPrefixForHistoricalRecords(String prefix)
243      {
244        histRecPrefix = (prefix == null) ? "" : prefix;
245      }
246    
247      public String getPrefixForHistoricalRecords()
248      {
249                    return histRecPrefix;
250            }
251      
252      /** Adds a new parsing error to our list. */
253      protected void putError(int lineNum, String message)
254      {
255        errors.add(new ParseError(lineNum, message));
256      }
257    }