001    /**
002     * 
003     */
004    package org.wdssii.core;
005    
006    import java.io.File;
007    import java.io.IOException;
008    import java.util.Date;
009    import java.util.Map;
010    
011    import javax.xml.parsers.DocumentBuilder;
012    import javax.xml.parsers.DocumentBuilderFactory;
013    import javax.xml.parsers.ParserConfigurationException;
014    
015    import org.apache.commons.logging.Log;
016    import org.apache.commons.logging.LogFactory;
017    import org.w3c.dom.Document;
018    import org.w3c.dom.Element;
019    
020    /**
021     * @author lakshman
022     * 
023     */
024    public class XmlDataEncoder extends DataEncoder {
025            private static Log log = LogFactory.getLog(XmlDataEncoder.class);
026    
027            @Override
028            protected String[] getParams(String relativeFileName) {
029                    String reader = isCompressionEnabled() ? "GzippedFile" : "FlatFile";
030                    return new String[] { "W2ALGS", reader, "{indexlocation}", "xmldata",
031                                    relativeFileName };
032            }
033    
034            @Override
035            protected void writeAndNotify(PolarGrid dt, String outputDir,
036                            String[] subtypes) {
037                    throw new UnsupportedOperationException("Only datatable");
038            }
039    
040            @Override
041            protected void writeAndNotify(LatLonGrid dt, String outputDir,
042                            String[] subtypes) {
043                    throw new UnsupportedOperationException("Only datatable");
044            }
045    
046            @Override
047            protected void writeAndNotify(DataTable dt, String outputDir,
048                            String[] subtypes) {
049                    try {
050                            // create XML document
051                            Document doc = createXMLDocument(dt);
052                            
053                            // where to write
054                            String formattedDate = getFormattedDate(dt);
055                            String relativeFileName = getRelativeFileName(dt, outputDir,
056                                            formattedDate, subtypes);
057                            String fileName = outputDir + '/' + relativeFileName;
058                            
059                            // write XML document
060                            XMLUtil.writeXmlFile(doc, fileName, isCompressionEnabled());
061                            
062                            // notify
063                            notifyRecord(dt, outputDir, subtypes, formattedDate,
064                                            relativeFileName);
065                    } catch (Exception e) {
066                            log.error("Writing failed: ", e);
067                    } finally {
068    
069                    }
070            }
071    
072            private static Document createXMLDocument(DataTable dt) throws ParserConfigurationException {
073                    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
074                    Document doc = builder.newDocument();
075                    
076                    Element root = doc.createElement("datatable");
077                    doc.appendChild(root);
078                    
079                    root.appendChild( createDataTypeElement(doc, dt) );
080    
081                    Element data = doc.createElement("data");
082                    root.appendChild(data);
083                    
084                    for (DataTable.Column column : dt.getColumns()){
085                            Element col = doc.createElement("datacolumn");
086                            data.appendChild(col);
087                            col.setAttribute("name", column.getName());
088                            col.setAttribute("units", column.getUnit());
089                            for (String value : column.getValues()){
090                                    Element item = doc.createElement("item");
091                                    item.setAttribute("value", value);
092                                    col.appendChild(item);
093                            }
094                    }
095                    
096                    return doc;
097            }
098    
099            private static Element createDataTypeElement(Document doc, DataTable dt) {
100                    Element datatype = doc.createElement("datatype");
101                    datatype.setAttribute("name", dt.getTypeName());
102                    datatype.appendChild( createStrefElement(doc, dt.getLocation(), dt.getTime()));
103                    // append attributes
104                    for (Map.Entry<String, String> entry : dt.getAttributes().entrySet()){
105                            Element attr = doc.createElement("attr");
106                            attr.setAttribute("name", entry.getKey());
107                        Element dc = doc.createElement("datacolumn");
108                        dc.setAttribute("name", entry.getKey());
109                        dc.setAttribute("units", "dimensionless");
110                        Element value = doc.createElement("item");
111                        value.setAttribute("value", entry.getValue());
112                        dc.appendChild(value);
113                        attr.appendChild(dc);
114                        datatype.appendChild(attr);
115                    }
116                    return datatype;
117            }
118    
119            private static Element createStrefElement(Document doc, Location location, Date time) {
120                    Element stref = doc.createElement("stref");
121                    Element loc = doc.createElement("location");
122                    stref.appendChild(loc);
123                    
124                    Element lat = doc.createElement("lat");
125                    loc.appendChild(lat);
126                    Element angle = doc.createElement("angle");
127                    lat.appendChild(angle);
128                    angle.setAttribute("units", "Degrees");
129                    angle.setAttribute("value", Double.toString(location.getLatitude()));
130                    Element lon = doc.createElement("lon");
131                    loc.appendChild(lon);
132                    angle = doc.createElement("angle");
133                    lon.appendChild(angle);
134                    angle.setAttribute("units", "Degrees");
135                    angle.setAttribute("value", Double.toString(location.getLongitude()));
136                    Element ht  = doc.createElement("ht");
137                    Element htval = doc.createElement("length");
138                    ht.appendChild(htval);
139                    htval.setAttribute("units", "Meters");
140                    htval.setAttribute("value", Double.toString(location.getHeightKms()*1000));
141                    loc.appendChild(ht);
142                    
143                    Element t = doc.createElement("time");
144                    stref.appendChild(t);
145                    t.setAttribute("units", "secondsSinceEpoch");
146                    t.setAttribute("value", Long.toString(time.getTime()));
147                    return stref;
148            }
149    
150            private String getRelativeFileName(DataType dt, String outputDir,
151                            String formattedDate, String[] subtypes) throws IOException {
152                    String subtype = (subtypes.length > 0) ? subtypes[0] : "";
153    
154                    StringBuilder dirName = new StringBuilder();
155                    dirName.append(dt.getTypeName()).append("/");
156                    dirName.append(subtype).append("/");
157    
158                    new File(outputDir + '/' + dirName.toString()).mkdirs();
159    
160                    String extension = isCompressionEnabled()? ".xml.gz" : ".xml";
161                    
162                    String fileName = dirName.append(formattedDate).append(extension).toString();
163                    return fileName;
164            }
165    }