001    /**
002     * 
003     */
004    package org.wdssii.ltgingest;
005    
006    import java.io.BufferedReader;
007    import java.io.File;
008    import java.io.FileReader;
009    import java.io.IOException;
010    import java.text.ParseException;
011    import java.text.SimpleDateFormat;
012    import java.util.Date;
013    
014    import org.apache.commons.logging.Log;
015    import org.apache.commons.logging.LogFactory;
016    import org.wdssii.core.DataEncoder;
017    import org.wdssii.core.DataTable;
018    import org.wdssii.core.Ingestor;
019    import org.wdssii.core.Location;
020    import org.wdssii.core.DataTable.Column;
021    
022    /**
023     * Base class of ingestors for ASCII lightning data
024     * 
025     * @author lakshman
026     *
027     */
028    public abstract class AbstractAsciiLightningIngest extends Ingestor {
029            private static Log log = LogFactory.getLog(AbstractAsciiLightningIngest.class);
030    
031            private String fieldSeparatorRegex  = ",?\\s+";
032            private int everyNseconds = 30;
033            private String subtype = "";
034            private String dateFormatInFileName = "yyyyMMdd-HHmmss";
035            private String dateFormatInData     = "yyyyMMdd HHmmss";
036            
037            public String getFieldSeparatorRegex() {
038                    return fieldSeparatorRegex;
039            }
040    
041            public void setFieldSeparatorRegex(String fieldSeparatorRegex) {
042                    this.fieldSeparatorRegex = fieldSeparatorRegex;
043            }
044    
045            public int getEveryNseconds() {
046                    return everyNseconds;
047            }
048    
049            public void setEveryNseconds(int everyNseconds) {
050                    this.everyNseconds = everyNseconds;
051            }
052    
053            public String getSubtype() {
054                    return subtype;
055            }
056    
057            public void setSubtype(String subtype) {
058                    this.subtype = subtype;
059            }
060    
061            public String getDateFormatInFileName() {
062                    return dateFormatInFileName;
063            }
064    
065            public void setDateFormatInFileName(String dateFormatInFileName) {
066                    this.dateFormatInFileName = dateFormatInFileName;
067                    fileNameTimeParser = new SimpleDateFormat(dateFormatInFileName);
068            }
069    
070            public String getDateFormatInData() {
071                    return dateFormatInData;
072            }
073    
074            public void setDateFormatInData(String dateFormatInData) {
075                    this.dateFormatInData = dateFormatInData;
076                    fileContentTimeParser = new SimpleDateFormat(dateFormatInData);
077            }
078    
079            private SimpleDateFormat fileNameTimeParser = new SimpleDateFormat(dateFormatInFileName);
080            private SimpleDateFormat fileContentTimeParser = new SimpleDateFormat(dateFormatInData);
081    
082            public AbstractAsciiLightningIngest(){
083                    setFilenamePatterns(".txt ltg");
084            }
085            
086            @Override
087            protected void doIngest(File f) {
088                    BufferedReader reader = null;
089                    try {
090                            log.info("Reading " + f);
091                            // Create DataTable for output
092                            DataTable table = newDataTable(getTimeFromFileName(f.getAbsolutePath()));
093                            reader = new BufferedReader(new FileReader(f));
094                            String line;
095                            
096                            while ( (line = reader.readLine()) != null){
097                                    String[] fields = line.split(fieldSeparatorRegex);
098    
099                                    // get the time from the line
100                                    Date ltgTime = fileContentTimeParser.parse(line.substring(0,dateFormatInData.length()));
101    
102                                    // if > allowable time ... write out XML
103                                    long elapsed;
104                                    while ( (elapsed = ltgTime.getTime() - table.getTime().getTime()) > (everyNseconds*1000) ){
105                                            // write current table
106                                            DataEncoder.writeDataAndNotify(table, getOutputDir(), subtype);
107                                            
108                                            // start new table at current time + 30s
109                                            Date newTime = new Date(table.getTime().getTime() + everyNseconds*1000 );
110                                            if (log.isInfoEnabled()){
111                                                    log.info("Starting new table at " + newTime + " elapsed=" + elapsed + " need to catch up to " + ltgTime);
112                                            }
113                                            table = newDataTable(newTime);
114                                    }
115                                    
116                                    // add record to table
117                                    addRow(table, ltgTime, fields);
118                                    
119                            }
120                            // write current table
121                            log.info("Writing table up to " + table.getTime() + " because input file ended");
122                            DataEncoder.writeDataAndNotify(table, getOutputDir(), subtype);
123                            
124                    } catch (Exception e){
125                            log.error("Unable to ingest " + f, e);
126                    } finally {
127                            if (reader != null){
128                                    try {
129                                            reader.close();
130                                    } catch (IOException e) {
131                                            // ok
132                                    }
133                            }
134                    }
135            }
136    
137            protected abstract void addRow(DataTable table, Date ltgTime, String[] fields);
138    
139            private DataTable newDataTable(Date time){
140                    Location loc = new Location(35,-97,0); // arbitrary anyway
141                    Column[] columns = new Column[]{
142                            new Column("RowName", "dimensionless"),
143                            new Column("Date", "dimensionless"),
144                            new Column("Latitude", "Degrees"),
145                            new Column("Longitude", "Degrees"),
146                            new Column("PeakCurrent", "kA"),
147                            new Column("Sign", "dimensionless"),
148                            new Column("Count", "dimensionless"),
149                            new Column("DischargeType", "dimensionless"),
150                            new Column("Rank", "dimensionless"),
151                    };
152                    DataTable table = new DataTable(loc, time, "Lightning", columns);
153                    if (subtype.length() > 0){
154                            table.setAttribute("SubType", subtype);
155                    }
156                    table.setAttribute("interval", Integer.toString(everyNseconds));
157                    return table;
158            }
159            
160            /** Assumes that the time is the last part of the file name with the exception of an optional filename extension */
161            private Date getTimeFromFileName(String fileName) throws ParseException {
162                    int startOfSuffix = fileName.lastIndexOf('.');
163                    if ( startOfSuffix == -1 ){
164                            startOfSuffix = fileName.length();
165                    }
166                    
167                    String digits = fileName.substring(startOfSuffix - dateFormatInFileName.length(), startOfSuffix);
168    
169                    return fileNameTimeParser.parse(digits);
170            }
171    
172    }