001 /* 002 * $Id: SuomiNPPProductProfile.java,v 1.2 2012/02/19 17:35:42 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031 package edu.wisc.ssec.mcidasv.data.hydra; 032 033 import java.io.BufferedReader; 034 import java.io.IOException; 035 import java.io.InputStream; 036 import java.io.InputStreamReader; 037 import java.io.StringReader; 038 import java.io.UnsupportedEncodingException; 039 import java.net.URLDecoder; 040 import java.util.ArrayList; 041 import java.util.Enumeration; 042 import java.util.HashMap; 043 import java.util.jar.JarEntry; 044 import java.util.jar.JarFile; 045 046 import javax.xml.parsers.DocumentBuilder; 047 import javax.xml.parsers.DocumentBuilderFactory; 048 import javax.xml.parsers.ParserConfigurationException; 049 050 import org.slf4j.Logger; 051 import org.slf4j.LoggerFactory; 052 053 import org.w3c.dom.Document; 054 import org.w3c.dom.Node; 055 import org.w3c.dom.NodeList; 056 057 import org.xml.sax.EntityResolver; 058 import org.xml.sax.InputSource; 059 import org.xml.sax.SAXException; 060 061 public class SuomiNPPProductProfile { 062 063 private static final Logger logger = LoggerFactory.getLogger(SuomiNPPProductProfile.class); 064 065 DocumentBuilder db = null; 066 // if we need to pull product profiles from the McV jar file 067 boolean readFromJar = false; 068 HashMap<String, String> rangeMin = new HashMap<String, String>(); 069 HashMap<String, String> rangeMax = new HashMap<String, String>(); 070 HashMap<String, String> scaleFactorName = new HashMap<String, String>(); 071 HashMap<String, ArrayList<Float>> fillValues = new HashMap<String, ArrayList<Float>>(); 072 073 public SuomiNPPProductProfile() throws ParserConfigurationException, SAXException, IOException { 074 075 logger.trace("SuomiNPPProductProfile init..."); 076 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 077 factory.setNamespaceAware(false); 078 db = factory.newDocumentBuilder(); 079 db.setEntityResolver(new EntityResolver() 080 { 081 public InputSource resolveEntity(String publicId, String systemId) 082 throws SAXException, IOException 083 { 084 return new InputSource(new StringReader("")); 085 } 086 }); 087 088 } 089 090 /** 091 * See if for a given N_Collection_Short_Name attribute, the profile is present 092 * @param pathStr the directory the XML Product Profiles reside 093 * @param attrName The attribute name our file should match 094 * @return the full file name for the XML Product Profile 095 */ 096 097 public String getProfileFileName(String attrName) { 098 // sanity check 099 if (attrName == null) return null; 100 101 // print top level classloader files 102 // this is how we will tell if we need to pull the profiles out of a jar file 103 104 readFromJar = false; 105 ClassLoader loader = getClass().getClassLoader(); 106 InputStream in = loader.getResourceAsStream("."); 107 BufferedReader rdr = new BufferedReader(new InputStreamReader(in)); 108 String l; 109 try { 110 while ((l = rdr.readLine()) != null) { 111 if (l.equals("mcidasv.jar")) { 112 readFromJar = true; 113 } 114 } 115 rdr.close(); 116 } catch (IOException e) { 117 e.printStackTrace(); 118 return null; 119 } 120 121 // we need to pull the XML Product Profiles out of mcidasv.jar 122 if (readFromJar) { 123 JarFile jar; 124 try { 125 jar = new JarFile(URLDecoder.decode("mcidasv.jar", "UTF-8")); 126 Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar 127 boolean found = false; 128 String name = null; 129 while (entries.hasMoreElements()) { 130 name = entries.nextElement().getName(); 131 if (name.contains("XML_Product_Profiles")) { // filter according to the profiles 132 logger.trace("looking at line: " + name); 133 if (name.contains(attrName + "-PP")) { 134 found = true; 135 break; 136 } 137 } 138 } 139 if (found == true) { 140 logger.trace("Found profile: " + name); 141 return name; 142 } 143 } catch (UnsupportedEncodingException e) { 144 e.printStackTrace(); 145 return null; 146 } catch (IOException e) { 147 e.printStackTrace(); 148 return null; 149 } 150 } else { 151 // read contents of XML Product Profile directory as stream 152 InputStream ios = getClass().getResourceAsStream("resources/NPP/XML_Product_Profiles/"); 153 BufferedReader dirReader = new BufferedReader(new InputStreamReader(ios)); 154 try { 155 String line = dirReader.readLine(); 156 boolean found = false; 157 while (line != null) { 158 logger.trace("looking at line: " + line); 159 if (line.contains(attrName + "-PP")) { 160 found = true; 161 break; 162 } 163 line = dirReader.readLine(); 164 } 165 ios.close(); 166 if (found == true) { 167 logger.trace("Found profile: " + attrName); 168 return line; 169 } 170 } catch (IOException ioe) { 171 ioe.printStackTrace(); 172 return null; 173 } 174 } 175 176 return null; 177 } 178 179 public void addMetaDataFromFile(String fileName) throws SAXException, IOException { 180 logger.trace("Attempting to parse XML Product Profile: " + fileName); 181 Document d = null; 182 InputStream ios = null; 183 if (readFromJar) { 184 JarFile jar = new JarFile(URLDecoder.decode("mcidasv.jar", "UTF-8")); 185 JarEntry je = jar.getJarEntry(fileName); 186 ios = jar.getInputStream(je); 187 d = db.parse(ios); 188 } else { 189 ios = getClass().getResourceAsStream("resources/NPP/XML_Product_Profiles/" + fileName); 190 d = db.parse(ios); 191 } 192 NodeList nl = d.getElementsByTagName("Field"); 193 for (int i = 0; i < nl.getLength(); i++) { 194 ArrayList<Float> fValAL = new ArrayList<Float>(); 195 Node n = nl.item(i); 196 NodeList children = n.getChildNodes(); 197 NodeList datum = null; 198 String name = null; 199 200 // cycle through once, finding name and datum node 201 for (int j = 0; j < children.getLength(); j++) { 202 Node child = children.item(j); 203 logger.trace("looking at node name: " + child.getNodeName()); 204 if (child.getNodeName().equals("Name")) { 205 name = child.getTextContent(); 206 logger.trace("Found Suomi NPP product name: " + name); 207 } 208 if (child.getNodeName().equals("Datum")) { 209 datum = child.getChildNodes(); 210 logger.trace("Found Datum node"); 211 } 212 } 213 214 String rMin = null; 215 String rMax = null; 216 String sFactorName = null; 217 218 if ((name != null) && (datum != null)) { 219 for (int j = 0; j < datum.getLength(); j++) { 220 Node child = datum.item(j); 221 if (child.getNodeName().equals("RangeMin")) { 222 rMin = child.getTextContent(); 223 } 224 if (child.getNodeName().equals("RangeMax")) { 225 rMax = child.getTextContent(); 226 } 227 if (child.getNodeName().equals("ScaleFactorName")) { 228 sFactorName = child.getTextContent(); 229 } 230 if (child.getNodeName().equals("FillValue")) { 231 // go one level further to child element Value 232 NodeList grandChildren = child.getChildNodes(); 233 for (int k = 0; k < grandChildren.getLength(); k++) { 234 Node grandChild = grandChildren.item(k); 235 if (grandChild.getNodeName().equals("Value")) { 236 String fillValueStr = grandChild.getTextContent(); 237 fValAL.add(new Float(Float.parseFloat(fillValueStr))); 238 } 239 } 240 } 241 } 242 } 243 244 if ((name != null) && (rMin != null)) { 245 logger.trace("Adding range min: " + rMin + " for product: " + name); 246 rangeMin.put(name, rMin); 247 } 248 249 if ((name != null) && (rMax != null)) { 250 logger.trace("Adding range max: " + rMax + " for product: " + name); 251 rangeMax.put(name, rMax); 252 } 253 254 if ((name != null) && (sFactorName != null)) { 255 logger.trace("Adding scale factor name: " + sFactorName + " for product: " + name); 256 scaleFactorName.put(name, sFactorName); 257 } 258 259 if ((name != null) && (! fValAL.isEmpty())) { 260 logger.trace("Adding fill value array for product: " + name); 261 fillValues.put(name, fValAL); 262 } 263 264 } 265 if (ios != null) { 266 try { 267 ios.close(); 268 } catch (IOException ioe) { 269 // do nothing 270 } 271 } 272 } 273 274 /** 275 * Check if this product profile has a product AND metadata 276 * Only need to check one of the possible fields 277 * @param product name 278 * @return true if both conditions met 279 */ 280 281 public boolean hasNameAndMetaData(String name) { 282 if (rangeMin.containsKey(name)) { 283 return true; 284 } else { 285 return false; 286 } 287 } 288 289 public String getRangeMin(String name) { 290 return rangeMin.get(name); 291 } 292 293 public String getRangeMax(String name) { 294 return rangeMax.get(name); 295 } 296 297 public String getScaleFactorName(String name) { 298 return scaleFactorName.get(name); 299 } 300 301 public ArrayList<Float> getFillValues(String name) { 302 return fillValues.get(name); 303 } 304 305 }