Home | History | Annotate | Download | only in java-jni
      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 {
     20     JNI.loadLibrary();
     21   }
     22 
     23   /** Constructs an empty HDF dataset */
     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    */
     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    */
     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).
     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    */
     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 
     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    */
     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    */
    102   public void setFileLoader(CSFileLoader fileLoader) {
    103     this.fileLoader = fileLoader;
    104   }
    105 
    106   /** Serializes HDF contents to a file (readable by readFile)
    107    */
    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    */
    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    */
    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    */
    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. */
    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   */
    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. */
    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. */
    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. */
    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 */
    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