1 package org.clearsilver; 2 3 import java.io.FileNotFoundException; 4 import java.io.IOException; 5 6 import java.util.Calendar; 7 import java.util.Date; 8 import java.util.TimeZone; 9 10 /** This class is a wrapper around the HDF C API. Many features of the C API 11 * are not yet exposed through this wrapper. 12 */ 13 public class HDF { 14 long hdfptr; // stores the C HDF* pointer 15 HDF root; // If this is a child HDF node, points at the root node of 16 // the tree. For root nodes this is null. A child node needs 17 // to hold a reference on the root to prevent the root from 18 // being GC-ed. 19 static { JNI.loadLibrary()20 JNI.loadLibrary(); 21 } 22 23 /** Constructs an empty HDF dataset */ HDF()24 public HDF() { 25 hdfptr = _init(); 26 root = null; 27 } 28 29 /** Constructs an HDF child node. Used by other methods in this class when 30 * a child node needs to be constructed. 31 */ HDF(long hdfptr, HDF parent)32 private HDF(long hdfptr, HDF parent) { 33 this.hdfptr = hdfptr; 34 this.root = (parent.root != null) ? parent.root : parent; 35 } 36 37 /** Clean up allocated memory if neccesary. close() allows application 38 * to force clean up. 39 */ close()40 public void close() { 41 // Only root nodes have ownership of the C HDF pointer, so only a root 42 // node needs to dealloc hdfptr.dir 43 if ( root == null) { 44 if (hdfptr != 0) { 45 _dealloc(hdfptr); 46 hdfptr = 0; 47 } 48 } 49 } 50 51 /** Call close() just in case when deallocating Java object. 52 */ 53 // Should be protected access (like Object). finalize()54 protected void finalize() throws Throwable { 55 close(); 56 super.finalize(); 57 } 58 59 /** Loads the contents of the specified HDF file from disk into the current 60 * HDF object. The loaded contents are merged with the existing contents. 61 */ readFile(String filename)62 public boolean readFile(String filename) throws IOException, 63 FileNotFoundException { 64 if (hdfptr == 0) { 65 throw new NullPointerException("HDF is closed."); 66 } 67 return _readFile(hdfptr, filename, fileLoader != null); 68 } 69 fileLoad(String filename)70 protected String fileLoad(String filename) throws IOException, 71 FileNotFoundException { 72 if (hdfptr == 0) { 73 throw new NullPointerException("HDF is closed."); 74 } 75 CSFileLoader aFileLoader = fileLoader; 76 if (aFileLoader == null) { 77 throw new NullPointerException("No fileLoader specified."); 78 } else { 79 String result = aFileLoader.load(this, filename); 80 if (result == null) { 81 throw new NullPointerException("CSFileLoader.load() returned null"); 82 } 83 return result; 84 } 85 } 86 87 // The optional CS file loader to use to read in files 88 private CSFileLoader fileLoader = null; 89 90 /** 91 * Get the file loader in use, if any. 92 * @return the file loader in use. 93 */ getFileLoader()94 public CSFileLoader getFileLoader() { 95 return fileLoader; 96 } 97 98 /** 99 * Set the CS file loader to use 100 * @param fileLoader the file loader that should be used. 101 */ setFileLoader(CSFileLoader fileLoader)102 public void setFileLoader(CSFileLoader fileLoader) { 103 this.fileLoader = fileLoader; 104 } 105 106 /** Serializes HDF contents to a file (readable by readFile) 107 */ writeFile(String filename)108 public boolean writeFile(String filename) throws IOException { 109 if (hdfptr == 0) { 110 throw new NullPointerException("HDF is closed."); 111 } 112 return _writeFile(hdfptr, filename); 113 } 114 115 /** Serializes HDF contents to a file (readable by readFile), but 116 * writes the file atomically by writing to a temp file then doing a 117 * rename(2) on it. 118 */ writeFileAtomic(String filename)119 public boolean writeFileAtomic(String filename) throws IOException { 120 if (hdfptr == 0) { 121 throw new NullPointerException("HDF is closed."); 122 } 123 return _writeFileAtomic(hdfptr, filename); 124 } 125 126 /** Parses/loads the contents of the given string as HDF into the current 127 * HDF object. The loaded contents are merged with the existing contents. 128 */ readString(String data)129 public boolean readString(String data) { 130 if (hdfptr == 0) { 131 throw new NullPointerException("HDF is closed."); 132 } 133 return _readString(hdfptr, data); 134 } 135 136 /** Serializes HDF contents to a string (readable by readString) 137 */ writeString()138 public String writeString() { 139 if (hdfptr == 0) { 140 throw new NullPointerException("HDF is closed."); 141 } 142 return _writeString(hdfptr); 143 } 144 145 /** Retrieves the integer value at the specified path in this HDF node's 146 * subtree. If the value does not exist, or cannot be converted to an 147 * integer, default_value will be returned. */ getIntValue(String hdfname, int default_value)148 public int getIntValue(String hdfname, int default_value) { 149 if (hdfptr == 0) { 150 throw new NullPointerException("HDF is closed."); 151 } 152 return _getIntValue(hdfptr,hdfname,default_value); 153 } 154 155 /** Retrieves the value at the specified path in this HDF node's subtree. 156 */ getValue(String hdfname, String default_value)157 public String getValue(String hdfname, String default_value) { 158 if (hdfptr == 0) { 159 throw new NullPointerException("HDF is closed."); 160 } 161 return _getValue(hdfptr,hdfname,default_value); 162 } 163 164 /** Sets the value at the specified path in this HDF node's subtree. */ setValue(String hdfname, String value)165 public void setValue(String hdfname, String value) { 166 if (hdfptr == 0) { 167 throw new NullPointerException("HDF is closed."); 168 } 169 _setValue(hdfptr,hdfname,value); 170 } 171 172 /** Remove the specified subtree. */ removeTree(String hdfname)173 public void removeTree(String hdfname) { 174 if (hdfptr == 0) { 175 throw new NullPointerException("HDF is closed."); 176 } 177 _removeTree(hdfptr,hdfname); 178 } 179 180 /** Links the src hdf name to the dest. */ setSymLink(String hdf_name_src, String hdf_name_dest)181 public void setSymLink(String hdf_name_src, String hdf_name_dest) { 182 if (hdfptr == 0) { 183 throw new NullPointerException("HDF is closed."); 184 } 185 _setSymLink(hdfptr,hdf_name_src,hdf_name_dest); 186 } 187 188 /** Export a date to a clearsilver tree using a specified timezone */ exportDate(String hdfname, TimeZone timeZone, Date date)189 public void exportDate(String hdfname, TimeZone timeZone, Date date) { 190 if (hdfptr == 0) { 191 throw new NullPointerException("HDF is closed."); 192 } 193 194 Calendar cal = Calendar.getInstance(timeZone); 195 cal.setTime(date); 196 197 String sec = Integer.toString(cal.get(Calendar.SECOND)); 198 setValue(hdfname + ".sec", sec.length() == 1 ? "0" + sec : sec); 199 200 String min = Integer.toString(cal.get(Calendar.MINUTE)); 201 setValue(hdfname + ".min", min.length() == 1 ? "0" + min : min); 202 203 setValue(hdfname + ".24hour", 204 Integer.toString(cal.get(Calendar.HOUR_OF_DAY))); 205 // java.util.Calendar uses represents 12 o'clock as 0 206 setValue(hdfname + ".hour", 207 Integer.toString( 208 cal.get(Calendar.HOUR) == 0 ? 12 : cal.get(Calendar.HOUR))); 209 setValue(hdfname + ".am", 210 cal.get(Calendar.AM_PM) == Calendar.AM ? "1" : "0"); 211 setValue(hdfname + ".mday", 212 Integer.toString(cal.get(Calendar.DAY_OF_MONTH))); 213 setValue(hdfname + ".mon", 214 Integer.toString(cal.get(Calendar.MONTH)+1)); 215 setValue(hdfname + ".year", 216 Integer.toString(cal.get(Calendar.YEAR))); 217 setValue(hdfname + ".2yr", 218 Integer.toString(cal.get(Calendar.YEAR)).substring(2)); 219 setValue(hdfname + ".wday", 220 Integer.toString(cal.get(Calendar.DAY_OF_WEEK))); 221 222 boolean tzNegative = timeZone.getRawOffset() < 0; 223 int tzAbsolute = java.lang.Math.abs(timeZone.getRawOffset()/1000); 224 String tzHour = Integer.toString(tzAbsolute/3600); 225 String tzMin = Integer.toString(tzAbsolute/60 - (tzAbsolute/3600)*60); 226 String tzString = (tzNegative ? "-" : "+") 227 + (tzHour.length() == 1 ? "0" + tzHour : tzHour) 228 + (tzMin.length() == 1 ? "0" + tzMin : tzMin); 229 setValue(hdfname + ".tzoffset", tzString); 230 } 231 232 /** Export a date to a clearsilver tree using a specified timezone */ 233 public void exportDate(String hdfname, String tz, int tt) { 234 if (hdfptr == 0) { 235 throw new NullPointerException("HDF is closed."); 236 } 237 238 TimeZone timeZone = TimeZone.getTimeZone(tz); 239 240 if (timeZone == null) { 241 throw new RuntimeException("Unknown timezone: " + tz); 242 } 243 244 Date date = new Date((long)tt * 1000); 245 246 exportDate(hdfname, timeZone, date); 247 } 248 249 /** Retrieves the HDF object that is the root of the subtree at hdfpath, or 250 * null if no object exists at that path. */ 251 public HDF getObj(String hdfpath) { 252 if (hdfptr == 0) { 253 throw new NullPointerException("HDF is closed."); 254 } 255 long obj_ptr = _getObj(hdfptr, hdfpath); 256 if ( obj_ptr == 0 ) { 257 return null; 258 } 259 return new HDF(obj_ptr, this); 260 } 261 262 /** Retrieves the HDF for the first child of the root of the subtree 263 * at hdfpath, or null if no child exists of that path or if the 264 * path doesn't exist. */ 265 public HDF getChild(String hdfpath) { 266 if (hdfptr == 0) { 267 throw new NullPointerException("HDF is closed."); 268 } 269 long obj_ptr = _getChild(hdfptr, hdfpath); 270 if ( obj_ptr == 0 ) { 271 return null; 272 } 273 return new HDF(obj_ptr, this); 274 } 275 276 /** Return the root of the tree where the current node lies. If the 277 * current node is the root, return this. */ 278 public HDF getRootObj() { 279 return root != null ? root : this; 280 } 281 282 /** Retrieves the HDF object that is the root of the subtree at 283 * hdfpath, create the subtree if it doesn't exist */ 284 public HDF getOrCreateObj(String hdfpath) { 285 if (hdfptr == 0) { 286 throw new NullPointerException("HDF is closed."); 287 } 288 long obj_ptr = _getObj(hdfptr, hdfpath); 289 if ( obj_ptr == 0 ) { 290 // Create a node 291 _setValue(hdfptr, hdfpath, ""); 292 obj_ptr = _getObj( hdfptr, hdfpath ); 293 if ( obj_ptr == 0 ) { 294 return null; 295 } 296 } 297 return new HDF(obj_ptr, this); 298 } 299 300 /** Returns the name of this HDF node. The root node has no name, so 301 * calling this on the root node will return null. */ 302 public String objName() { 303 if (hdfptr == 0) { 304 throw new NullPointerException("HDF is closed."); 305 } 306 return _objName(hdfptr); 307 } 308 309 /** Returns the value of this HDF node, or null if this node has no value. 310 * Every node in the tree can have a value, a child, and a next peer. */ 311 public String objValue() { 312 if (hdfptr == 0) { 313 throw new NullPointerException("HDF is closed."); 314 } 315 return _objValue(hdfptr); 316 } 317 318 /** Returns the child of this HDF node, or null if there is no child. 319 * Use this in conjunction with objNext to walk the HDF tree. Every node 320 * in the tree can have a value, a child, and a next peer. */ 321 public HDF objChild() { 322 if (hdfptr == 0) { 323 throw new NullPointerException("HDF is closed."); 324 } 325 long child_ptr = _objChild(hdfptr); 326 if ( child_ptr == 0 ) { 327 return null; 328 } 329 return new HDF(child_ptr, this); 330 } 331 332 /** Returns the next sibling of this HDF node, or null if there is no next 333 * sibling. Use this in conjunction with objChild to walk the HDF tree. 334 * Every node in the tree can have a value, a child, and a next peer. */ 335 public HDF objNext() { 336 if (hdfptr == 0) { 337 throw new NullPointerException("HDF is closed."); 338 } 339 long next_ptr = _objNext(hdfptr); 340 if ( next_ptr == 0 ) { 341 return null; 342 } 343 return new HDF(next_ptr, this); 344 } 345 346 public void copy(String hdfpath, HDF src) { 347 if (hdfptr == 0 || src.hdfptr == 0) { 348 throw new NullPointerException("HDF is closed."); 349 } 350 _copy(hdfptr, hdfpath, src.hdfptr); 351 } 352 353 /** 354 * Generates a string representing the content of the HDF tree rooted at 355 * this node. 356 */ 357 public String dump() { 358 if (hdfptr == 0) { 359 throw new NullPointerException("HDF is closed."); 360 } 361 return _dump(hdfptr); 362 } 363 364 private static native long _init(); 365 private static native void _dealloc(long ptr); 366 private native boolean _readFile(long ptr, String filename, boolean use_cb); 367 private static native boolean _writeFile(long ptr, String filename); 368 private static native boolean _writeFileAtomic(long ptr, String filename); 369 private static native boolean _readString(long ptr, String data); 370 private static native String _writeString(long ptr); 371 private static native int _getIntValue(long ptr, String hdfname, 372 int default_value); 373 private static native String _getValue(long ptr, String hdfname, 374 String default_value); 375 private static native void _setValue(long ptr, String hdfname, 376 String hdf_value); 377 private static native void _removeTree(long ptr, String hdfname); 378 private static native void _setSymLink(long ptr, String hdf_name_src, 379 String hdf_name_dest); 380 private static native long _getObj(long ptr, String hdfpath); 381 private static native long _getChild(long ptr, String hdfpath); 382 private static native long _objChild(long ptr); 383 private static native long _objNext(long ptr); 384 private static native String _objName(long ptr); 385 private static native String _objValue(long ptr); 386 private static native void _copy(long destptr, String hdfpath, long srcptr); 387 388 private static native String _dump(long ptr); 389 } 390