001    /**
002     * 
003     */
004    package org.wdssii.core;
005    
006    import java.io.File;
007    import java.io.FileWriter;
008    import java.io.IOException;
009    import java.io.PrintWriter;
010    import java.text.DecimalFormat;
011    import java.text.NumberFormat;
012    import java.text.SimpleDateFormat;
013    import java.util.Date;
014    
015    import org.apache.commons.logging.Log;
016    import org.apache.commons.logging.LogFactory;
017    
018    /**
019     * @author lakshman
020     *
021     */
022    public abstract class DataEncoder {
023            private static Log log = LogFactory.getLog(DataEncoder.class);
024            private float sparseGridThreshold = 0.75f;
025            private boolean compressionEnabled = false;
026    
027            protected DataEncoder(){
028            }
029            
030            public float getSparseGridThreshold() {
031                    return sparseGridThreshold;
032            }
033            public boolean isAlwaysSparseGrid(){
034                    return (sparseGridThreshold <= 0);
035            }
036            public boolean isNeverSparseGrid(){
037                    return (sparseGridThreshold >= 1);
038            }
039            public void setSparseGridThreshold(String sparseGridThreshold) {
040                    if ( sparseGridThreshold != null && sparseGridThreshold.length() > 0 ){
041                            if (sparseGridThreshold.equals("never")){
042                                    this.sparseGridThreshold =   2;
043                            } else if ( sparseGridThreshold.equals("always") ){
044                                    this.sparseGridThreshold =  -1;
045                            } else {
046                                    this.sparseGridThreshold = Float.parseFloat(sparseGridThreshold);
047                            }
048                    }
049                    if ( log.isInfoEnabled() ){
050                            log.info("Sparsegridthreshold=" + this.sparseGridThreshold);
051                    }
052            }
053            public boolean isCompressionEnabled() {
054                    return compressionEnabled;
055            }
056            public void setCompressionEnabled(boolean compression) {
057                    this.compressionEnabled = compression;
058            }
059            public void setCompressionEnabled(String compression) {
060                    if ( compression != null ){
061                            boolean c = compression.equals("yes") || compression.equals("true");
062                            this.compressionEnabled = c;
063                    }
064            }
065    
066            public static void writeDataAndNotify(DataType dt, String outputDir, String subtype){
067                    if (subtype == null || subtype.length() == 0){
068                            writeDataAndNotify(dt, outputDir); // use default subtype
069                    } else {
070                            writeDataAndNotify(dt, outputDir, new String[]{subtype} );
071                    }
072            }
073    
074            /** Uses default subtype for product */
075            public static void writeDataAndNotify(DataType dt, String outputDir){
076                    String subtype = (String) dt.getAttribute("SubType");
077                    if (subtype == null || subtype.length() == 0 ){
078                            if ( dt instanceof PolarGrid ){
079                                    PolarGrid grid = (PolarGrid) dt;
080                                    NumberFormat nf = new DecimalFormat("00.00");
081                                    subtype = nf.format( grid.getElevation() );
082                            } else {
083                                    NumberFormat nf = new DecimalFormat("00.000");
084                                    subtype = nf.format(dt.getLocation().getHeightKms());
085                            }
086                    }
087                    writeDataAndNotify(dt, outputDir, subtype);
088            }
089            
090            /** The method to use **/
091            public static void writeDataAndNotify(DataType dt, String outputDir, String[] subtypes){
092                    DataEncoder encoder = DataEncoderFactory.getInstance().getEncoder(dt);
093                    if ( dt instanceof PolarGrid ){
094                            encoder.writeAndNotify( (PolarGrid) dt, outputDir, subtypes);
095                    } else if ( dt instanceof LatLonGrid )  {
096                            encoder.writeAndNotify( (LatLonGrid) dt, outputDir, subtypes);
097                    } else if ( dt instanceof DataTable ){
098                            encoder.writeAndNotify( (DataTable) dt, outputDir, subtypes);
099                    } else {
100                            log.warn("No encoder implemented to write object of type " + dt.getClass());
101                    }
102            }
103    
104            /** Computes sparse grid ratio if necessary to decide whether to write sparse */
105            protected boolean shouldWriteSparse(float[][] values, float background) {
106                    if ( this.isAlwaysSparseGrid() ){
107                            return true;
108                    } else if ( this.isNeverSparseGrid() ){
109                            return false;
110                    } else {
111                            float ratio = NetcdfSparseGrid.computeSparseGridRatio(values,background);
112                            return (ratio > this.getSparseGridThreshold());
113                    }
114            }
115            
116            protected void notifyRecord(DataType dt, String outputDir,
117                            String[] subtypes, String formattedDate, String relativeFileName)
118                            throws IOException {
119                    PrintWriter writer = null;
120                    try {
121                            String famDir = outputDir + "/code_index.fam/";
122                            new File(famDir).mkdirs();
123                            String[] params = getParams(relativeFileName);
124                            for (String subtype : subtypes) {
125                                    String[] selections = new String[] { formattedDate,
126                                                    dt.getTypeName(), subtype };
127                                    IndexRecord rec = new IndexRecord(dt.getTime(), selections,
128                                                    params);
129                                    String notifyName = new StringBuilder(famDir).append(
130                                                    dt.getTypeName()).append('_').append(subtype).append(
131                                                    '_').append(formattedDate).toString();
132                                    writer = new PrintWriter(new FileWriter(notifyName));
133                                    writer.println(rec.toXMLString());
134                                    writer.close();
135                            }
136                    } finally {
137                            if (writer != null) {
138                                    writer.close();
139                            }
140                    }
141            }
142    
143            protected static String getFormattedDate(DataType dt) {
144                    return getFormattedDate(dt.getTime());
145            }
146    
147            public static String getFormattedDate(Date time) {
148                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
149                    String formatted = sdf.format(time);
150                    return formatted;
151            }
152            
153            
154            protected abstract String[] getParams(String relativeFileName);
155            protected abstract void writeAndNotify(PolarGrid dt, String outputDir, String[] subtypes);
156            protected abstract void writeAndNotify(LatLonGrid dt, String outputDir, String[] subtypes);
157            protected abstract void writeAndNotify(DataTable dt, String outputDir, String[] subtypes);
158    }