    001/*****************************************************************************
    002 * Copyright by The HDF Group.                                               *
    003 * Copyright by the Board of Trustees of the University of Illinois.         *
    004 * All rights reserved.                                                      *
    005 *                                                                           *
    006 * This file is part of the HDF Java Products distribution.                  *
    007 * The full copyright notice, including terms governing use, modification,   *
    008 * and redistribution, is contained in the files COPYING and Copyright.html. *
    009 * COPYING can be found at the root of the source code distribution tree.    *
    010 * Or, see https://support.hdfgroup.org/products/licenses.html               *
    011 * If you do not have access to either file, you may request a copy from     *
    012 * help@hdfgroup.org.                                                        *
    013 ****************************************************************************/
    014
    015package hdf.object;
    016
    017import java.io.File;
    018import java.util.Enumeration;
    019import java.util.Hashtable;
    020import java.util.Iterator;
    021import java.util.Map;
    022import java.util.StringTokenizer;
    023import java.util.Vector;
    024
    025
    026/**
    027 * FileFormat defines general interfaces for working with files whose data is
    028 * organized according to a supported format.
    029 * <p>
    030 * FileFormat is a pluggable component. New implementing classes of FileFormat
    031 * can be added to the list of supported file formats. Current implementing
    032 * classes include H5File and H4File. By default, H5File and H4File are added to
    033 * the list of supported file formats maintained by the static FileFormat
    034 * instance.
    035 *
    036 * <pre>
    037 *                                    FileFormat
    038 *                       _________________|_________________
    039 *                       |                |                |
    040 *                     H5File          H4File           Other...
    041 * </pre>
    042 * <p>
    043 * A FileFormat instance may exist without being associated with a given file. A
    044 * FileFormat instance may be associated with a file that is not open for
    045 * access. Most typically, a FileFormat instance is used to open the associated
    046 * file and perform operations such as retrieval and manipulation (if the file
    047 * access is read-write) of the file structure and objects.
    048 *
    049 * @author Peter X. Cao
    050 * @version 2.4 9/4/2007
    051 */
    052public abstract class FileFormat extends File {
    053    private static final long                    serialVersionUID   = -4700692313888420796L;
    054
    055    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FileFormat.class);
    056
    057    /***************************************************************************
    058     * File access flags used in calls to createInstance( String, flag );
    059     **************************************************************************/
    060
    061    /**
    062     * File first time access flag for open file. With this access flag, added
    063     * to the regular value, indicates this file has no existing state.
    064     *
    065     */
    066    public static final int                      OPEN_NEW           = 1;
    067
    068    /**
    069     * File access flag for read-only permission. With this access flag,
    070     * modifications to the file will not be allowed.
    071     *
    072     * @see #createInstance(String, int )
    073     */
    074    public static final int                      READ               = 2;
    075
    076    /**
    077     * File access flag for read/write permission. With this access flag,
    078     * modifications to the file will be allowed. Behavior if the file does not
    079     * exist or cannot be opened for read/write access depends on the
    080     * implementing class.
    081     *
    082     * @see #createInstance(String, int)
    083     */
    084    public static final int                      WRITE              = 4;
    085
    086    /**
    087     * File access flag for creating/truncating with read-write permission. If
    088     * the file already exists, it will be truncated when opened. With this
    089     * access flag, modifications to the file will be allowed. Behavior if file
    090     * can't be created, or if it exists but can't be opened for read/write
    091     * access, depends on the implementing class.
    092     *
    093     * @see #createInstance(String, int )
    094     */
    095    public static final int                      CREATE             = 8;
    096
    097    /***************************************************************************
    098     * File creation flags used in calls to createFile( String, flag );
    099     **************************************************************************/
    100
    101    /**
    102     * Flag for creating/truncating a file. If the file already exists, it will
    103     * be truncated when opened. If the file does not exist, it will be created.
    104     * Modifications to the file will be allowed.
    105     *
    106     * @see #createFile(String, int )
    107     */
    108    public static final int                      FILE_CREATE_DELETE = 10;
    109
    110    /**
    111     * Flag for creating/opening a file. If the file already exists, it will be
    112     * opened without changing the existing contents. If the file does not
    113     * exist, it will be created. Modifications to the file will be allowed.
    114     *
    115     * @see #createFile(String, int )
    116     */
    117    public static final int                      FILE_CREATE_OPEN   = 20;
    118
    119    /**
    120     * Flag to indicate if the earliest version of library is used when creating
    121     * a new file.
    122     *
    123     * @see #createFile(String, int )
    124     */
    125    public static final int                      FILE_CREATE_EARLY_LIB   = 40;
    126
    127
    128    /***************************************************************************
    129     * Keys and fields related to supported file formats.
    130     **************************************************************************/
    131
    132    /** Key for HDF4 file format. */
    133    public static final String                   FILE_TYPE_HDF4     = "HDF4";
    134
    135    /** Key for HDF5 file format. */
    136    public static final String                   FILE_TYPE_HDF5     = "HDF5";
    137
    138    /**
    139     * A separator that separates file name and object name.
    140     *
    141     * @see hdf.object.FileFormat#getHObject(String)
    142     */
    143    public static final String                   FILE_OBJ_SEP       = "://";
    144
    145    /**
    146     * FileList keeps a list of supported FileFormats. This list can be updated
    147     * and queried at runtime.
    148     *
    149     * @see #addFileFormat(String,FileFormat)
    150     * @see #getFileFormat(String)
    151     * @see #getFileFormatKeys()
    152     * @see #getFileFormats()
    153     * @see #removeFileFormat(String)
    154     */
    155    private static final Map<String, FileFormat> FileList = new Hashtable<>(10);
    156
    157    /**
    158     * A list of file extensions for the supported file formats. This list of
    159     * file extensions is not integrated with the supported file formats kept in
    160     * FileList, but is provided as a convenience for applications who may
    161     * choose to process only those files with recognized extensions.
    162     */
    163    private static String extensions         = "hdf, h4, hdf5, h5, nc, fits";
    164
    165    /***************************************************************************
    166     * Sizing information and class metadata
    167     **************************************************************************/
    168
    169    /**
    170     * Current Java applications, such as HDFView, cannot handle files with
    171     * large numbers of objects due to JVM memory limitations. For example,
    172     * 1,000,000 objects is too many. max_members is defined so that
    173     * applications such as HDFView will load up to <i>max_members</i> objects
    174     * starting with the <i>start_members</i> -th object. The implementing class
    175     * has freedom in its interpretation of how to "count" objects in the file.
    176     */
    177    private int                                  max_members        = 10000;      // 10,000 by default
    178    private int                                  start_members      = 0;          // 0 by default
    179
    180    /**
    181     * File identifier. -1 indicates the file is not open.
    182     */
    183    protected long                                fid                = -1;
    184
    185    /**
    186     * The absolute pathname (path+name) of the file.
    187     */
    188    protected String                             fullFileName       = null;
    189
    190    /**
    191     * Flag indicating if the file access is read-only.
    192     */
    193    protected boolean                            isReadOnly         = false;
    194
    195    /***************************************************************************
    196     * Class initialization method
    197     **************************************************************************/
    198
    199    /**
    200     * By default, HDF4 and HDF5 file formats are added to the supported formats
    201     * list.
    202     */
    203    static {
    204        // add HDF4 to default modules
    205        if (FileFormat.getFileFormat(FILE_TYPE_HDF4) == null) {
    206            try {
    207                @SuppressWarnings("rawtypes")
    208                Class fileclass = Class.forName("hdf.object.h4.H4File");
    209                FileFormat fileformat = (FileFormat) fileclass.newInstance();
    210                if (fileformat != null) {
    211                    FileFormat.addFileFormat(FILE_TYPE_HDF4, fileformat);
    212                    log.debug("FILE_TYPE_HDF4 file format added");
    213                }
    214            }
    215            catch (Throwable err) {
    216                log.debug("FILE_TYPE_HDF4 instance failure: ", err);
    217            }
    218        }
    219
    220        // add HDF5 to default modules
    221        if (FileFormat.getFileFormat(FILE_TYPE_HDF5) == null) {
    222            try {
    223                @SuppressWarnings("rawtypes")
    224                Class fileclass = Class.forName("hdf.object.h5.H5File");
    225                FileFormat fileformat = (FileFormat) fileclass.newInstance();
    226                if (fileformat != null) {
    227                    FileFormat.addFileFormat(FILE_TYPE_HDF5, fileformat);
    228                    log.debug("FILE_TYPE_HDF5 file format added");
    229                }
    230            }
    231            catch (Throwable err) {
    232                log.debug("FILE_TYPE_HDF5 instance failure: ", err);
    233            }
    234        }
    235
    236        // add NetCDF to default modules
    237        if (FileFormat.getFileFormat("NetCDF") == null) {
    238            try {
    239                @SuppressWarnings("rawtypes")
    240                Class fileclass = Class.forName("hdf.object.nc2.NC2File");
    241                FileFormat fileformat = (FileFormat) fileclass.newInstance();
    242                if (fileformat != null) {
    243                    FileFormat.addFileFormat("NetCDF", fileformat);
    244                    log.debug("NetCDF file format added");
    245                }
    246            }
    247            catch (Throwable err) {
    248                log.debug("NetCDF instance failure: ", err);
    249            }
    250        }
    251
    252        // add FITS to default modules
    253        if (FileFormat.getFileFormat("FITS") == null) {
    254            try {
    255                @SuppressWarnings("rawtypes")
    256                Class fileclass = Class.forName("hdf.object.fits.FitsFile");
    257                FileFormat fileformat = (FileFormat) fileclass.newInstance();
    258                if (fileformat != null) {
    259                    FileFormat.addFileFormat("FITS", fileformat);
    260                    log.debug("Fits file format added");
    261                }
    262            }
    263            catch (Throwable err) {
    264                log.debug("FITS instance failure: ", err);
    265            }
    266        }
    267
    268    }
    269
    270    /***************************************************************************
    271     * Constructor
    272     **************************************************************************/
    273
    274    /**
    275     * Creates a new FileFormat instance with the given filename.
    276     * <p>
    277     * The filename in this method call is equivalent to the pathname in the
    278     * java.io.File class. The filename is converted into an abstract pathname
    279     * by the File class.
    280     * <p>
    281     * Typically this constructor is not called directly, but is called by a
    282     * constructor of an implementing class. Applications most frequently use
    283     * the <i>createFile()</i>, <i>createInstance()</i>, or <i>getInstance()</i>
    284     * methods to generate a FileFormat instance with an associated filename.
    285     * <p>
    286     * The file is not opened by this call. The read-only flag is set to false
    287     * by this call.
    288     *
    289     * @param filename
    290     *            The filename; a pathname string.
    291     * @throws NullPointerException
    292     *             If the <code>filename</code> argument is <code>null</code>.
    293     * @see java.io.File#File(String)
    294     * @see #createFile(String, int)
    295     * @see #createInstance(String, int)
    296     * @see #getInstance(String)
    297     */
    298    public FileFormat(String filename) {
    299        super(filename);
    300
    301        fullFileName = filename;
    302
    303        if ((filename != null) && (filename.length() > 0)) {
    304            try {
    305                fullFileName = this.getAbsolutePath();
    306            }
    307            catch (Exception ex) {
    308                log.debug("File {} getAbsolutePath failure: ", filename, ex);
    309            }
    310        }
    311        isReadOnly = false;
    312        log.trace("fullFileName={} isReadOnly={}", fullFileName, isReadOnly);
    313    }
    314
    315    /***************************************************************************
    316     * Class methods
    317     **************************************************************************/
    318
    319    /**
    320     * Adds a FileFormat with specified key to the list of supported formats.
    321     * <p>
    322     * This method allows a new FileFormat, tagged with an identifying key, to
    323     * be added dynamically to the list of supported File Formats. Using it,
    324     * applications can add new File Formats at runtime.
    325     * <p>
    326     * For example, to add a new File Format with the key "xyz" that is
    327     * implemented by the class xyzFile in the package companyC.files, an
    328     * application would make the following calls:
    329     *
    330     * <pre>
    331     *    Class fileClass = Class.forName( "companyC.files.xyzFile" );
    332     *    FileFormat ff = (FileFormat) fileClass.newInstance();
    333     *    if ( ff != null ) {
    334     *       ff.addFileFormat ("xyz", ff )
    335     *    }
    336     * </pre>
    337     * <p>
    338     * If either <code>key</code> or <code>fileformat</code> are
    339     * <code>null</code>, or if <code>key</code> is already in use, the method
    340     * returns without updating the list of supported File Formats.
    341     *
    342     * @param key
    343     *            A string that identifies the FileFormat.
    344     * @param fileformat
    345     *            An instance of the FileFormat to be added.
    346     * @see #getFileFormat(String)
    347     * @see #getFileFormatKeys()
    348     * @see #getFileFormats()
    349     * @see #removeFileFormat(String)
    350     */
    351    public static final void addFileFormat(String key, FileFormat fileformat) {
    352        if ((fileformat == null) || (key == null)) {
    353            return;
    354        }
    355
    356        key = key.trim();
    357
    358        if (!FileList.containsKey(key)) {
    359            FileList.put(key, fileformat);
    360        }
    361    }
    362
    363    /**
    364     * Returns the FileFormat with specified key from the list of supported
    365     * formats.
    366     * <p>
    367     * This method returns a FileFormat instance, as identified by an
    368     * identifying key, from the list of supported File Formats.
    369     * <p>
    370     * If the specified key is in the list of supported formats, the instance of
    371     * the associated FileFormat object is returned. If the specified key is not
    372     * in the list of supported formats, <code>null</code> is returned.
    373     *
    374     * @param key
    375     *            A string that identifies the FileFormat.
    376     * @return The FileFormat that matches the given key, or <code>null</code>
    377     *         if the key is not found in the list of supported File Formats.
    378     * @see #addFileFormat(String,FileFormat)
    379     * @see #getFileFormatKeys()
    380     * @see #getFileFormats()
    381     * @see #removeFileFormat(String)
    382     */
    383    public static final FileFormat getFileFormat(String key) {
    384        return FileList.get(key);
    385    }
    386
    387    /**
    388     * Returns an Enumeration of keys for all supported formats.
    389     * <p>
    390     * This method returns an Enumeration containing the unique keys (Strings)
    391     * for the all File Formats in the list of supported File Formats.
    392     *
    393     * @return An Enumeration of keys that are in the list of supported formats.
    394     * @see #addFileFormat(String,FileFormat)
    395     * @see #getFileFormat(String)
    396     * @see #getFileFormats()
    397     * @see #removeFileFormat(String)
    398     */
    399    @SuppressWarnings("rawtypes")
    400    public static final Enumeration getFileFormatKeys() {
    401        return ((Hashtable) FileList).keys();
    402    }
    403
    404    /**
    405     * Returns an array of supported FileFormat instances.
    406     * <p>
    407     * This method returns an array of FileFormat instances that appear in the
    408     * list of supported File Formats.
    409     * <p>
    410     * If the list of supported formats is empty, <code>null</code> is returned.
    411     *
    412     * @return An array of all FileFormat instances in the list of supported
    413     *         File Formats, or <code>null</code> if the list is empty.
    414     * @see #addFileFormat(String,FileFormat)
    415     * @see #getFileFormat(String)
    416     * @see #getFileFormatKeys()
    417     * @see #removeFileFormat(String)
    418     */
    419    @SuppressWarnings("rawtypes")
    420    public static final FileFormat[] getFileFormats() {
    421        int n = FileList.size();
    422        if (n <= 0) {
    423            return null;
    424        }
    425
    426        int i = 0;
    427        FileFormat[] fileformats = new FileFormat[n];
    428        Enumeration<?> local_enum = ((Hashtable) FileList).elements();
    429        while (local_enum.hasMoreElements()) {
    430            fileformats[i++] = (FileFormat) local_enum.nextElement();
    431        }
    432
    433        return fileformats;
    434    }
    435
    436    /**
    437     * Removes a FileFormat from the list of supported formats.
    438     * <p>
    439     * This method removes a FileFormat, as identified by the specified key,
    440     * from the list of supported File Formats.
    441     * <p>
    442     * If the specified key is in the list of supported formats, the instance of
    443     * the FileFormat object that is being removed from the list is returned. If
    444     * the key is not in the list of supported formats, <code>null</code> is
    445     * returned.
    446     *
    447     * @param key
    448     *            A string that identifies the FileFormat to be removed.
    449     * @return The FileFormat that is removed, or <code>null</code> if the key
    450     *         is not found in the list of supported File Formats.
    451     * @see #addFileFormat(String,FileFormat)
    452     * @see #getFileFormat(String)
    453     * @see #getFileFormatKeys()
    454     * @see #getFileFormats()
    455     */
    456    public static final FileFormat removeFileFormat(String key) {
    457        return FileList.remove(key);
    458    }
    459
    460    /**
    461     * Adds file extension(s) to the list of file extensions for supported file
    462     * formats.
    463     * <p>
    464     * Multiple extensions can be included in the single parameter if they are
    465     * separated by commas.
    466     * <p>
    467     * The list of file extensions updated by this call is not linked with
    468     * supported formats that implement FileFormat objects. The file extension
    469     * list is maintained for the benefit of applications that may choose to
    470     * recognize only those files with extensions that appear in the list of
    471     * file extensions for supported file formats.
    472     * <p>
    473     * By default, the file extensions list includes: "hdf, h4, hdf5, h5"
    474     *
    475     * @param extension
    476     *            The file extension(s) to add.
    477     * @see #addFileFormat(String,FileFormat)
    478     * @see #getFileExtensions()
    479     */
    480    public static final void addFileExtension(String extension) {
    481        if ((extensions == null) || (extensions.length() <= 0)) {
    482            extensions = extension;
    483        }
    484
    485        StringTokenizer currentExt = new StringTokenizer(extensions, ",");
    486        Vector<String> tokens = new Vector<>(currentExt.countTokens() + 5);
    487
    488        while (currentExt.hasMoreTokens()) {
    489            tokens.add(currentExt.nextToken().trim().toLowerCase());
    490        }
    491
    492        currentExt = new StringTokenizer(extension, ",");
    493        String ext = null;
    494        while (currentExt.hasMoreTokens()) {
    495            ext = currentExt.nextToken().trim().toLowerCase();
    496            if (tokens.contains(ext)) {
    497                continue;
    498            }
    499
    500            extensions = extensions + ", " + ext;
    501        }
    502
    503        tokens.setSize(0);
    504    }
    505
    506    /**
    507     * Returns a list of file extensions for all supported file formats.
    508     * <p>
    509     * The extensions in the returned String are separates by commas:
    510     * "hdf, h4, hdf5, h5"
    511     * <p>
    512     * It is the responsibility of the application to update the file extension
    513     * list using {@link #addFileExtension(String)} when new FileFormat
    514     * implementations are added.
    515     *
    516     * @return A list of file extensions for all supported file formats.
    517     * @see #addFileExtension(String)
    518     */
    519    public static final String getFileExtensions() {
    520        return extensions;
    521    }
    522
    523    /**
    524     * Creates a FileFormat instance for the specified file.
    525     * <p>
    526     * This method checks the list of supported file formats to find one that
    527     * matches the format of the specified file. If a match is found, the method
    528     * returns an instance of the associated FileFormat object. If no match is
    529     * found, <code>null</code> is returned.
    530     * <p>
    531     * For example, if "test_hdf5.h5" is an HDF5 file,
    532     * FileFormat.getInstance("test_hdf5.h5") will return an instance of H5File.
    533     * <p>
    534     * The file is not opened as part of this call. Read/write file access is
    535     * associated with the FileFormat instance if the matching file format
    536     * supports read/write access. Some file formats only support read access.
    537     *
    538     * @param filename
    539     *            A valid file name, with a relative or absolute path.
    540     * @return An instance of the matched FileFormat; <code>null</code> if no
    541     *         match.
    542     * @throws IllegalArgumentException
    543     *             If the <code>filename</code> argument is <code>null</code> or
    544     *             does not specify an existing file.
    545     * @throws Exception
    546     *             If there are problems creating the new instance.
    547     * @see #createFile(String, int)
    548     * @see #createInstance(String, int)
    549     * @see #getFileFormats()
    550     */
    551    @SuppressWarnings("rawtypes")
    552    public static final FileFormat getInstance(String filename) throws Exception {
    553        if ((filename == null) || (filename.length() <= 0)) {
    554            throw new IllegalArgumentException("Invalid file name: " + filename);
    555        }
    556
    557        if (!(new File(filename)).exists()) {
    558            throw new IllegalArgumentException("File " + filename + " does not exist.");
    559        }
    560
    561        FileFormat fileFormat = null;
    562        FileFormat knownFormat = null;
    563        Enumeration<?> elms = ((Hashtable) FileList).elements();
    564
    565        while (elms.hasMoreElements()) {
    566            knownFormat = (FileFormat) elms.nextElement();
    567            if (knownFormat.isThisType(filename)) {
    568                try {
    569                    fileFormat = knownFormat.createInstance(filename, WRITE);
    570                }
    571                catch (Exception ex) {
    572                    log.debug("File {} createInstance failure: ", filename, ex);
    573                }
    574                break;
    575            }
    576        }
    577
    578        return fileFormat;
    579    }
    580
    581    /***************************************************************************
    582     * Implementation Class methods. These methods are related to the
    583     * implementing FileFormat class, but not to a particular instance of that
    584     * class. Since we can't override class methods (they can only be shadowed
    585     * in Java), these are instance methods.
    586     *
    587     * The non-abstract methods just throw an exception indicating that the
    588     * implementing class doesn't support the functionality.
    589     **************************************************************************/
    590
    591    /**
    592     * Returns the version of the library for the implementing FileFormat class.
    593     * <p>
    594     * The implementing FileFormat classes have freedom in how they obtain or
    595     * generate the version number that is returned by this method. The H5File
    596     * and H4File implementations query the underlying HDF libraries and return
    597     * the reported version numbers. Other implementing classes may generate the
    598     * version string directly within the called method.
    599     *
    600     * @return The library version.
    601     */
    602    public abstract String getLibversion();
    603
    604    /**
    605     * Checks if the class implements the specified FileFormat.
    606     * <p>
    607     * The Java "instanceof" operation is unable to check if an object is an
    608     * instance of a FileFormat that is loaded at runtime. This method provides
    609     * the "instanceof" functionality, and works for implementing classes that
    610     * are loaded at runtime.
    611     * <p>
    612     * This method lets applications that only access the abstract object layer
    613     * determine the format of a given instance of the abstract class.
    614     * <p>
    615     * For example, HDFView uses the following code to determine if a file is an
    616     * HDF5 file:
    617     *
    618     * <pre>
    619     * FileFormat h5F = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
    620     * HObject hObject = viewer.getTreeView().getCurrentObject();
    621     * FileFormat thisF = hObject.getFileFormat();
    622     * boolean isH5 = h5F.isThisType(thisF);
    623     * </pre>
    624     *
    625     * @param fileFormat
    626     *            The FileFormat to be checked.
    627     * @return True if this instance implements the specified FileFormat;
    628     *         otherwise returns false.
    629     * @see #isThisType(String)
    630     */
    631    public abstract boolean isThisType(FileFormat fileFormat);
    632
    633    /**
    634     * Checks if the implementing FileFormat class matches the format of the
    635     * specified file.
    636     * <p>
    637     * For example, if "test.h5" is an HDF5 file, the first call to isThisType()
    638     * in the code fragment shown will return <code>false</code>, and the second
    639     * call will return <code>true</code>.
    640     *
    641     * <pre>
    642     * FileFormat h4F = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4);
    643     * FileFormat h5F = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
    644     * boolean isH4 = h4F.isThisType(&quot;test.h5&quot;); // false
    645     *                                                                                                                                                                                   boolean isH5 = h5F.isThisType(&quot;test.h5&quot;); // true
    646     * </pre>
    647     *
    648     * @param filename
    649     *            The name of the file to be checked.
    650     * @return True if the format of the file matches the format of this
    651     *         instance; otherwise returns false.
    652     * @see #isThisType(FileFormat)
    653     */
    654    public abstract boolean isThisType(String filename);
    655
    656    /**
    657     * Creates a file with the specified name and returns a new FileFormat
    658     * implementation instance associated with the file.
    659     * <p>
    660     * This method creates a file whose format is the same as that of the
    661     * implementing class. An instance of the FileFormat implementing class is
    662     * created and associated with the file. That instance is returned by the
    663     * method.
    664     * <p>
    665     * The filename in this method call is equivalent to the pathname in the
    666     * java.io.File class. The filename is converted into an abstract pathname
    667     * by the File class.
    668     * <p>
    669     * A flag controls the behavior if the named file already exists. The flag
    670     * values and corresponding behaviors are:
    671     * <ul>
    672     * <li>FILE_CREATE_DELETE: Create a new file or truncate an existing one.
    673     * <li>FILE_CREATE_OPEN: Create a new file or open an existing one.
    674     * </ul>
    675     * <p>
    676     * If the flag is FILE_CREATE_DELETE, the method will create a new file or
    677     * truncate an existing file. If the flag is FILE_CREATE_OPEN and the file
    678     * does not exist, the method will create a new file.
    679     * <p>
    680     * This method does not open the file for access, nor does it confirm that
    681     * the file can later be opened read/write. The file open is carried out by
    682     * the <i>open()</i> call.
    683     *
    684     * @param filename
    685     *            The filename; a pathname string.
    686     * @param createFlag
    687     *            The creation flag, which determines behavior when the file
    688     *            already exists. Acceptable values are
    689     *            <code>FILE_CREATE_DELETE</code> and
    690     *            <code>FILE_CREATE_OPEN</code>.
    691     * @throws NullPointerException
    692     *             If the <code>filename</code> argument is <code>null</code>.
    693     * @throws UnsupportedOperationException
    694     *             If the implementing class does not support the file creation
    695     *             operation.
    696     * @throws Exception
    697     *             If the file cannot be created or if the creation flag has an
    698     *             unexpected value. The exceptions thrown vary depending on the
    699     *             implementing class.
    700     * @see #createInstance(String, int)
    701     * @see #getInstance(String)
    702     * @see #open()
    703     *
    704     * @return the FileFormat instance.
    705     */
    706    public FileFormat createFile(String filename, int createFlag) throws Exception {
    707        // If the implementing subclass doesn't have this method then that
    708        // format doesn't support File Creation and we throw an exception.
    709        throw new UnsupportedOperationException("FileFormat FileFormat.createFile(...) is not implemented.");
    710    }
    711
    712    /**
    713     * Creates a FileFormat implementation instance with specified filename and
    714     * access.
    715     * <p>
    716     * This method creates an instance of the FileFormat implementing class and
    717     * sets the filename and file access parameters.
    718     * <p>
    719     * The filename in this method call is equivalent to the pathname in the
    720     * java.io.File class. The filename is converted into an abstract pathname
    721     * by the File class.
    722     * <p>
    723     * The access parameter values and corresponding behaviors at file open:
    724     * <ul>
    725     * <li>READ: Read-only access. Fail if file doesn't exist.
    726     * <li>WRITE: Read/Write access. Behavior if file doesn't exist or can't be
    727     * opened for read/write access depends on the implementing class.
    728     * <li>CREATE: Read/Write access. Create a new file or truncate an existing
    729     * one. Behavior if file can't be created, or if it exists but can't be
    730     * opened read/write depends on the implementing class.
    731     * </ul>
    732     * <p>
    733     * Some FileFormat implementing classes may only support READ access and
    734     * will use READ regardless of the value specified in the call. Refer to the
    735     * implementing class documentation for details.
    736     * <p>
    737     * This method does not open the file for access, nor does it confirm that
    738     * the file can later be opened read/write or created. The file open is
    739     * carried out by the <i>open()</i> call.
    740     * <p>
    741     * Example (without exception handling):
    742     *
    743     * <pre>
    744     * // Request the implementing class of FileFormat: H5File
    745     * FileFormat h5file = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
    746     *
    747     * // Create an instance of H5File object with read/write access
    748     * H5File test1 = (H5File) h5file.createInstance(&quot;test_hdf5.h5&quot;,
    749     *                                               FileFormat.WRITE);
    750     *
    751     * // Open the file and load the file structure; file id is returned.
    752     * int fid = test1.open();
    753     * </pre>
    754     *
    755     * @param filename
    756     *            The filename; a pathname string.
    757     * @param access
    758     *            The file access flag, which determines behavior when file is
    759     *            opened. Acceptable values are <code> READ, WRITE, </code> and
    760     *            <code>CREATE</code>.
    761     * @throws NullPointerException
    762     *             If the <code>filename</code> argument is <code>null</code>.
    763     * @throws Exception
    764     *             If the instance cannot be created or if the access flag has
    765     *             an unexpected value. The exceptions thrown vary depending on
    766     *             the implementing class.
    767     * @see #createFile(String, int)
    768     * @see #getInstance(String)
    769     * @see #open()
    770     *
    771     * @return the FileFormat instance.
    772     */
    773    public abstract FileFormat createInstance(String filename, int access) throws Exception;
    774
    775    // REVIEW DOCS for createInstance()
    776    // What if READ ONLY in implementation? What if file already open?
    777    // Can we doc exceptions better or in implementation methods?
    778
    779    /***************************************************************************
    780     * Final instance methods
    781     *
    782     * Related to a given instance of the class, but at the FileFormat level,
    783     * not at the implementing class level.
    784     **************************************************************************/
    785
    786    /**
    787     * Returns the absolute path for the file.
    788     * <p>
    789     * For example, "/samples/hdf5_test.h5". If there is no file associated with
    790     * this FileFormat instance, <code>null</code> is returned.
    791     *
    792     * @return The full path (file path + file name) of the associated file, or
    793     *         <code>null</code> if there is no associated file.
    794     */
    795    public final String getFilePath() {
    796        return fullFileName;
    797    }
    798
    799    /**
    800     * Returns file identifier of open file associated with this instance.
    801     *
    802     * @return The file identifer, or -1 if there is no file open.
    803     */
    804    public final long getFID() {
    805        return fid;
    806    }
    807
    808    /**
    809     * Returns true if the file access is read-only.
    810     * <p>
    811     * This method returns true if the file access is read-only. If the file
    812     * access is read-write, or if there is no file associated with the
    813     * FileFormat instance, false will be returned.
    814     * <p>
    815     * Note that this method may return true even if the file is not open for
    816     * access when the method is called. The file access is set by the
    817     * <i>createFile()</i>, <i>createInstance()</i>, or <i>getInstance()</i>
    818     * call, and the file is opened for access by the <i>open()</i> call.
    819     *
    820     * @return True if the file access is read-only, otherwise returns false.
    821     * @see #createFile(String, int)
    822     * @see #createInstance(String, int)
    823     * @see #getInstance(String)
    824     * @see #open()
    825     */
    826    public final boolean isReadOnly() {
    827        return isReadOnly;
    828    }
    829
    830    /**
    831     * Sets the maximum number of objects to be loaded into memory.
    832     * <p>
    833     * Current Java applications, such as HDFView, cannot handle files with
    834     * large numbers of objects due to JVM memory limitations. The maximum
    835     * number limits the number of objects that will be loaded for a given
    836     * FileFormat instance.
    837     * <p>
    838     * The implementing FileFormat class has freedom in how it interprets the
    839     * maximum number. H5File, for example, will load the maximum number of
    840     * objects for each group in the file.
    841     *
    842     * @param n
    843     *            The maximum number of objects to be loaded into memory.
    844     * @see #getMaxMembers()
    845     * @see #setStartMembers(int)
    846     */
    847    public final void setMaxMembers(int n) {
    848        max_members = n;
    849    }
    850
    851    /**
    852     * Returns the maximum number of objects that can be loaded into memory.
    853     *
    854     * @return The maximum number of objects that can be loaded into memory.
    855     * @see #setMaxMembers(int)
    856     */
    857    public final int getMaxMembers() {
    858        if (max_members<0)
    859            return Integer.MAX_VALUE; // load the whole file
    860
    861        return max_members;
    862    }
    863
    864    /**
    865     * Sets the starting index of objects to be loaded into memory.
    866     * <p>
    867     * The implementing FileFormat class has freedom in how it indexes objects
    868     * in the file.
    869     *
    870     * @param idx
    871     *            The starting index of the object to be loaded into memory
    872     * @see #getStartMembers()
    873     * @see #setMaxMembers(int)
    874     */
    875    public final void setStartMembers(int idx) {
    876        start_members = idx;
    877    }
    878
    879    /**
    880     * Returns the index of the starting object to be loaded into memory.
    881     *
    882     * @return The index of the starting object to be loaded into memory.
    883     * @see #setStartMembers(int)
    884     */
    885    public final int getStartMembers() {
    886        return start_members;
    887    }
    888
    889    /**
    890     * Returns the number of objects in memory.
    891     * <p>
    892     * This method returns the total number of objects loaded into memory for
    893     * this FileFormat instance. The method counts the objects that are loaded,
    894     * which can take some time for a large number of objects.
    895     * <p>
    896     * It is worth noting that the total number of objects in memory may be
    897     * different than the total number of objects in the file.
    898     * <p>
    899     * Since implementing classes have freedom in how they interpret and use the
    900     * maximum number of members value, there may be differing numbers of
    901     * objects in memory in different implementation instances, even with the
    902     * same "use case".
    903     * <p>
    904     * For example, say the use case is a file that contains 20,000 objects, the
    905     * maximum number of members for an instance is 10,000, and the start member
    906     * index is 1. There are 2 groups in the file. The root group contains
    907     * 10,500 objects and the group "/g1" contains 9,500 objects.
    908     * <p>
    909     * In an implementation that limits the total number of objects loaded to
    910     * the maximum number of members, this method will return 10,000.
    911     * <p>
    912     * In contrast, the H5File implementation loads up to the maximum number of
    913     * members objects for each group in the file. So, with our use case 10,000
    914     * objects will be loaded in the root group and 9,500 objects will be loaded
    915     * into group "/g1". This method will return the value 19,500, which exceeds
    916     * the maximum number of members value.
    917     *
    918     * @return The number of objects in memory.
    919     * @see #getMaxMembers()
    920     * @see #setMaxMembers(int)
    921     * @see #getStartMembers()
    922     * @see #setStartMembers(int)
    923     */
    924    public final int getNumberOfMembers() {
    925        HObject rootObject = getRootObject();
    926
    927        // Account for root object
    928        if (rootObject != null) return ((Group) rootObject).depthFirstMemberList().size() + 1;
    929
    930        return 0;
    931    }
    932
    933    /***************************************************************************
    934     * Abstract Instance methods
    935     *
    936     * These methods are related to the Implementing FileFormat class and to
    937     * particular instances of objects with those classes.
    938     **************************************************************************/
    939
    940    /**
    941     * Opens file and returns a file identifier.
    942     * <p>
    943     * This method uses the <code>filename</code> and <code>access</code>
    944     * parameters specified in the <i>createFile()</i>, <i>createInstance()</i>,
    945     * or <i>getInstance()</i> call to open the file. It returns the file
    946     * identifier if successful, or a negative value in case of failure.
    947     * <p>
    948     * The method also loads the file structure and basic information (name,
    949     * type) for data objects in the file into the FileFormat instance. It does
    950     * not load the contents of any data object.
    951     * <p>
    952     * The structure of the file is stored in a tree starting from the root
    953     * object.
    954     *
    955     * @return File identifier if successful; otherwise -1.
    956     * @throws Exception
    957     *             If the file cannot be opened. The exceptions thrown vary
    958     *             depending on the implementing class.
    959     * @see #createFile(String, int)
    960     * @see #createInstance(String, int)
    961     * @see #getInstance(String)
    962     * @see #getRootObject()
    963     */
    964    public abstract long open() throws Exception;
    965
    966    /**
    967     * Closes file associated with this instance.
    968     * <p>
    969     * This method closes the file associated with this FileFormat instance, as
    970     * well as all objects associated with the file.
    971     *
    972     * @throws Exception
    973     *             If the file or associated objects cannot be closed. The
    974     *             exceptions thrown vary depending on the implementing class.
    975     * @see #open()
    976     */
    977    public abstract void close() throws Exception;
    978
    979    // REVIEW DOCS for close()
    980    // What if we try to close a file whose fid is -1? Does this set fid to -1?
    981    // What if it's not open? What if no file? are structures & root object
    982    // still loaded?
    983    // Can we doc exceptions better or in implementation methods?
    984
    985    /**
    986     * Returns the root object for the file associated with this instance.
    987     * <p>
    988     * The root object is an HObject that represents the root group of a
    989     * file. If the file has not yet been opened, or if there is no file
    990     * associated with this instance, <code>null</code> will be returned.
    991     * <p>
    992     * Starting from the root, applications can descend through the tree
    993     * structure and navigate among the file's objects. In the tree structure,
    994     * internal items represent non-empty groups. Leaf items represent datasets,
    995     * named datatypes, or empty groups.
    996     *
    997     * @return The root object of the file, or <code>null</code> if there is no
    998     *         associated file or if the associated file has not yet been
    999     *         opened.
    1000     * @see #open()
    1001     */
    1002    public abstract HObject getRootObject();
    1003
    1004    /**
    1005     * Gets the HObject with the specified path from the file.
    1006     * <p>
    1007     * This method returns the specified object from the file associated with
    1008     * this FileFormat instance.
    1009     * <p>
    1010     * If the specified object is a group, groups and datasets that are members
    1011     * of the group will be accessible via the returned HObject instance. The
    1012     * exact contents of the returned HObject instance depends on whether or not
    1013     * {@link #open()} was called previously for this file.
    1014     * <ul>
    1015     * <li>If the file was opened prior to this method call, the complete tree
    1016     * of objects under the group will be accessible via the returned HObject
    1017     * instance.
    1018     * <li>If the file was not opened prior to this method call, only the
    1019     * members immediately under the group will be accessible via the returned
    1020     * HOBject instance.
    1021     * </ul>
    1022     * <p>
    1023     * The decision to have different behaviors was made to give users some
    1024     * control over the "cost" of the method. In many cases, a user wants only
    1025     * one level of a tree, and the performance penalty for loading the entire
    1026     * hierarchy of objects in a large and complex file can be significant. In
    1027     * the case where <i>open()</i> has already been called, the HObject
    1028     * instances have already been created in memory and can be returned
    1029     * quickly. If <i>open()</i> has not been called, this method creates the
    1030     * HObject instances before returning the requested HObject.
    1031     * <p>
    1032     * For example, say we have the following structure in our file:
    1033     *
    1034     * <pre>
    1035     *        /g0                      Group
    1036     *        /g0/dataset_comp         Dataset {50, 10}
    1037     *        /g0/dataset_int          Dataset {50, 10}
    1038     *        /g0/g00                  Group
    1039     *        /g0/g00/dataset_float    Dataset {50, 10}
    1040     *        /g0/g01                  Group
    1041     *        /g0/g01/dataset_string   Dataset {50, 10}
    1042     * </pre>
    1043     *
    1044     * <ul>
    1045     * <li>If <i>open()</i> is called before <i>get()</i>, the full structure of
    1046     * file is loaded into memory. The call <code>get("/g0")</code> returns the
    1047     * instance for /g0 with the information necessary to access
    1048     * /g0/dataset_comp, /g0/dataset_int, /g0/g00, /g0/g00/dataset_float,
    1049     * /g0/g01, and /g0/g01/dataset_string.
    1050     * <li>If <i>open()</i> is not called before <i>get()</i>, only the objects
    1051     * immediately under the specified group are accessible via the returned
    1052     * HObject instance. In this example, the call <code>get("/go")</code>
    1053     * returns the instance for /g0 with the information necessary to access
    1054     * /g0/dataset_comp, /g0/dataset_int, /g0/g00, and /g0/g01.
    1055     * </ul>
    1056     *
    1057     * @param path
    1058     *            Full path of the data object to be returned.
    1059     * @return The object if it exists in the file; otherwise <code>null</code>.
    1060     * @throws Exception
    1061     *             If there are unexpected problems in trying to retrieve the
    1062     *             object. The exceptions thrown vary depending on the
    1063     *             implementing class.
    1064     */
    1065    public abstract HObject get(String path) throws Exception;
    1066
    1067    // REVIEW DOCS for get(); What if no file associated w/ instance?
    1068    // Look at exceptions. Confirm example. Make sure perf tradeoffs
    1069    // documented properly.
    1070
    1071    /**
    1072     * Creates a named datatype in a file.
    1073     * <p>
    1074     * The following code creates a named datatype in a file.
    1075     *
    1076     * <pre>
    1077     * H5File file = (H5File) h5file.createInstance(&quot;test_hdf5.h5&quot;, FileFormat.WRITE);
    1078     * H5Datatype dtype = file.createDatatype(
    1079     *                             Datatype.CLASS_INTEGER,
    1080     *                             4,
    1081     *                             Datatype.NATIVE,
    1082     *                             Datatype.NATIVE,
    1083     *                             &quot;Native Integer&quot;);
    1084     * </pre>
    1085     *
    1086     * @param tclass
    1087     *            class of datatype, e.g. Datatype.CLASS_INTEGER
    1088     * @param tsize
    1089     *            size of the datatype in bytes, e.g. 4 for 32-bit integer.
    1090     * @param torder
    1091     *            order of the byte endianing, e.g. Datatype.ORDER_LE.
    1092     * @param tsign
    1093     *            signed or unsigned of an integer, e.g. Datatype.SIGN_NONE.
    1094     * @param name
    1095     *            name of the datatype to create, e.g. "Native Integer".
    1096     * @return The new datatype if successful; otherwise returns null.
    1097     * @throws Exception
    1098     *             The exceptions thrown vary depending on the implementing
    1099     *             class.
    1100     */
    1101    public abstract Datatype createDatatype(int tclass, int tsize, int torder, int tsign, String name) throws Exception;
    1102
    1103    /**
    1104     * Creates a named datatype in a file.
    1105     * <p>
    1106     * The following code creates a named datatype in a file.
    1107     *
    1108     * <pre>
    1109     * H5File file = (H5File) h5file.createInstance(&quot;test_hdf5.h5&quot;, FileFormat.WRITE);
    1110     * H5Datatype dtype = file.createDatatype(
    1111     *                             Datatype.CLASS_INTEGER,
    1112     *                             4,
    1113     *                             Datatype.NATIVE,
    1114     *                             Datatype.NATIVE,
    1115     *                             basetype,
    1116     *                             &quot;Native Integer&quot;);
    1117     * </pre>
    1118     *
    1119     * @param tclass
    1120     *            class of datatype, e.g. Datatype.CLASS_INTEGER
    1121     * @param tsize
    1122     *            size of the datatype in bytes, e.g. 4 for 32-bit integer.
    1123     * @param torder
    1124     *            order of the byte endianing, e.g. Datatype.ORDER_LE.
    1125     * @param tsign
    1126     *            signed or unsigned of an integer, e.g. Datatype.SIGN_NONE.
    1127     * @param tbase
    1128     *            the base datatype of the new datatype
    1129     * @param name
    1130     *            name of the datatype to create, e.g. "Native Integer".
    1131     * @return The new datatype if successful; otherwise returns null.
    1132     * @throws Exception
    1133     *             The exceptions thrown vary depending on the implementing
    1134     *             class.
    1135     */
    1136    public Datatype createDatatype(int tclass, int tsize, int torder, int tsign, Datatype tbase, String name) throws Exception
    1137    {
    1138        // Derived classes must override this function to use base type option
    1139        return createDatatype(tclass, tsize, torder, tsign, name);
    1140    }
    1141
    1142    // REVIEW DOCS for createDatatype(). Check and document exceptions.
    1143
    1144    /***************************************************************************
    1145     * Methods related to Datatypes and HObjects in the implementing FileFormat.
    1146     *
    1147     * Strictly speaking, these methods aren't related to FileFormat and the
    1148     * actions could be carried out through the HObject and Datatype classes.
    1149     * But, in some cases they allow a null input and expect the generated
    1150     * object to be of a type that has particular FileFormat. Therefore, we put
    1151     * them in the implementing FileFormat class so that we create the proper
    1152     * type of HObject... H5Group or H4Group for example.
    1153     *
    1154     * Here again, if there could be Implementation Class methods we'd use
    1155     * those. But, since we can't override class methods (they can only be
    1156     * shadowed in Java), these are instance methods.
    1157     *
    1158     * The non-abstract methods just throw an exception indicating that the
    1159     * implementing class doesn't support the functionality.
    1160     **************************************************************************/
    1161
    1162    /**
    1163     * Creates a new datatype in memory.
    1164     * <p>
    1165     * The following code creates an instance of H5Datatype in memory.
    1166     *
    1167     * <pre>
    1168     * H5File file = (H5File) h5file.createInstance(&quot;test_hdf5.h5&quot;, FileFormat.WRITE);
    1169     * H5Datatype dtype = file.createDatatype(
    1170     *                             Datatype.CLASS_INTEGER,
    1171     *                             4,
    1172     *                             Datatype.NATIVE,
    1173     *                             Datatype.NATIVE);
    1174     * </pre>
    1175     *
    1176     * @param tclass
    1177     *            class of datatype, e.g. Datatype.CLASS_INTEGER
    1178     * @param tsize
    1179     *            size of the datatype in bytes, e.g. 4 for 32-bit integer.
    1180     * @param torder
    1181     *            order of the byte endian, e.g. Datatype.ORDER_LE.
    1182     * @param tsign
    1183     *            signed or unsigned of an integer, e.g. Datatype.SIGN_NONE.
    1184     * @return The new datatype object if successful; otherwise returns null.
    1185     * @throws Exception
    1186     *             The exceptions thrown vary depending on the implementing
    1187     *             class.
    1188     */
    1189    public abstract Datatype createDatatype(int tclass, int tsize, int torder, int tsign) throws Exception;
    1190
    1191    /**
    1192     * Creates a new datatype in memory.
    1193     * <p>
    1194     * The following code creates an instance of H5Datatype in memory.
    1195     *
    1196     * <pre>
    1197     * H5File file = (H5File) h5file.createInstance(&quot;test_hdf5.h5&quot;, FileFormat.WRITE);
    1198     * H5Datatype dtype = file.createDatatype(
    1199     *                             Datatype.CLASS_INTEGER,
    1200     *                             4,
    1201     *                             Datatype.NATIVE,
    1202     *                             Datatype.NATIVE,
    1203     *                             basetype);
    1204     * </pre>
    1205     *
    1206     * @param tclass
    1207     *            class of datatype, e.g. Datatype.CLASS_INTEGER
    1208     * @param tsize
    1209     *            size of the datatype in bytes, e.g. 4 for 32-bit integer.
    1210     * @param torder
    1211     *            order of the byte endian, e.g. Datatype.ORDER_LE.
    1212     * @param tsign
    1213     *            signed or unsigned of an integer, e.g. Datatype.SIGN_NONE.
    1214     * @param tbase
    1215     *            the base datatype of the new datatype
    1216     * @return The new datatype object if successful; otherwise returns null.
    1217     * @throws Exception
    1218     *             The exceptions thrown vary depending on the implementing
    1219     *             class.
    1220     */
    1221    public Datatype createDatatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) throws Exception
    1222    {
    1223        // Derived classes must override this function to use base type option
    1224        return createDatatype(tclass, tsize, torder, tsign);
    1225    }
    1226
    1227    // REVIEW DOCS for createDatatype(). Check and document exceptions.
    1228
    1229    /**
    1230     * Creates a new dataset in a file with/without chunking/compression.
    1231     * <p>
    1232     * The following example creates a 2D integer dataset of size 100X50 at the
    1233     * root group in an HDF5 file.
    1234     *
    1235     * <pre>
    1236     * String name = &quot;2D integer&quot;;
    1237     * Group pgroup = (Group) getRootObject();
    1238     * Datatype dtype = new H5Datatype(
    1239     *                          Datatype.CLASS_INTEGER, // class
    1240     *                          4, // size in bytes
    1241     *                          Datatype.ORDER_LE, // byte order
    1242     *                          Datatype.SIGN_NONE); // signed or unsigned
    1243     * long[] dims = {100, 50};
    1244     * long[] maxdims = dims;
    1245     * long[] chunks = null; // no
    1246     * // chunking
    1247     * int gzip = 0; // no compression
    1248     * Object data = null; // no initial data values
    1249     * Dataset d = (H5File) file.createScalarDS(name, pgroup, dtype, dims, maxdims, chunks, gzip, data);
    1250     * </pre>
    1251     *
    1252     * @param name
    1253     *            name of the new dataset, e.g. "2D integer"
    1254     * @param pgroup
    1255     *            parent group where the new dataset is created.
    1256     * @param type
    1257     *            datatype of the new dataset.
    1258     * @param dims
    1259     *            dimension sizes of the new dataset, e.g. long[] dims = {100,
    1260     *            50}.
    1261     * @param maxdims
    1262     *            maximum dimension sizes of the new dataset, null if maxdims is
    1263     *            the same as dims.
    1264     * @param chunks
    1265     *            chunk sizes of the new dataset, null if no chunking.
    1266     * @param gzip
    1267     *            GZIP compression level (1 to 9), 0 or negative values if no
    1268     *            compression.
    1269     * @param fillValue
    1270     *            default value.
    1271     * @param data
    1272     *            data written to the new dataset, null if no data is written to
    1273     *            the new dataset.
    1274     *
    1275     * @return The new dataset if successful; otherwise returns null
    1276     * @throws Exception
    1277     *             The exceptions thrown vary depending on the implementing
    1278     *             class.
    1279     */
    1280    public abstract Dataset createScalarDS(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims,
    1281            long[] chunks, int gzip, Object fillValue, Object data) throws Exception;
    1282
    1283    public Dataset createScalarDS(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, long[] chunks,
    1284            int gzip, Object data) throws Exception {
    1285        return createScalarDS(name, pgroup, type, dims, maxdims, chunks, gzip, null, data);
    1286    }
    1287
    1288    // REVIEW DOCS for createScalarDS(). Check and document exceptions.
    1289
    1290    /**
    1291     * Creates a new compound dataset in a file with/without chunking and
    1292     * compression.
    1293     * <p>
    1294     * The following example creates a compressed 2D compound dataset with size
    1295     * of 100X50 in a root group. The compound dataset has two members, x and y.
    1296     * Member x is an interger, member y is an 1-D float array of size 10.
    1297     *
    1298     * <pre>
    1299     * String name = "2D compound";
    1300     * Group pgroup = (Group) getRootObject();
    1301     * long[] dims = {100, 50};
    1302     * long[] chunks = {1, 50};
    1303     * int gzip = 9;
    1304     * String[] memberNames = {"x", "y"};
    1305     *
    1306     * Datatype[] memberDatatypes = {
    1307     *     new H5Datatype(Datatype.CLASS_INTEGER, Datatype.NATIVE,
    1308     *                    Datatype.NATIVE, Datatype.NATIVE)
    1309     *     new H5Datatype(Datatype.CLASS_FLOAT, Datatype.NATIVE,
    1310     *                    Datatype.NATIVE, Datatype.NATIVE));
    1311     *
    1312     * int[] memberSizes = {1, 10};
    1313     * Object data = null; // no initial data values
    1314     * Dataset d = (H5File)file.createCompoundDS(name, pgroup, dims, null,
    1315     *           chunks, gzip, memberNames, memberDatatypes, memberSizes, null);
    1316     * </pre>
    1317     *
    1318     * @param name
    1319     *            name of the new dataset
    1320     * @param pgroup
    1321     *            parent group where the new dataset is created.
    1322     * @param dims
    1323     *            dimension sizes of the new dataset.
    1324     * @param maxdims
    1325     *            maximum dimension sizes of the new dataset, null if maxdims is
    1326     *            the same as dims.
    1327     * @param chunks
    1328     *            chunk sizes of the new dataset, null if no chunking.
    1329     * @param gzip
    1330     *            GZIP compression level (1 to 9), 0 or negative values if no
    1331     *            compression.
    1332     * @param memberNames
    1333     *            names of the members.
    1334     * @param memberDatatypes
    1335     *            datatypes of the members.
    1336     * @param memberSizes
    1337     *            array sizes of the members.
    1338     * @param data
    1339     *            data written to the new dataset, null if no data is written to
    1340     *            the new dataset.
    1341     *
    1342     * @return new dataset object if successful; otherwise returns null
    1343     * @throws UnsupportedOperationException
    1344     *             If the implementing class does not support compound datasets.
    1345     * @throws Exception
    1346     *             The exceptions thrown vary depending on the implementing
    1347     *             class.
    1348     */
    1349    public Dataset createCompoundDS(String name, Group pgroup, long[] dims, long[] maxdims, long[] chunks, int gzip,
    1350            String[] memberNames, Datatype[] memberDatatypes, int[] memberSizes, Object data) throws Exception
    1351    // REVIEW DOCS for createCompoundDS(). Check and document exceptions.
    1352    {
    1353        // If the implementing subclass doesn't have this method then that
    1354        // format doesn't support Compound DataSets and we throw an
    1355        // exception.
    1356        throw new UnsupportedOperationException("Dataset FileFormat.createCompoundDS(...) is not implemented.");
    1357    }
    1358
    1359    /**
    1360     * Creates a new image in a file.
    1361     * <p>
    1362     * The following example creates a 2D image of size 100X50 in a root group.
    1363     *
    1364     * <pre>
    1365     * String name = &quot;2D image&quot;;
    1366     * Group pgroup = (Group) getRootObject();
    1367     * Datatype dtype = new H5Datatype(Datatype.CLASS_INTEGER, 1, Datatype.NATIVE, Datatype.SIGN_NONE);
    1368     * long[] dims = {100, 50};
    1369     * long[] maxdims = dims;
    1370     * long[] chunks = null; // no chunking
    1371     * int gzip = 0; // no compression
    1372     * int ncomp = 3; // RGB true color image
    1373     * int interlace = ScalarDS.INTERLACE_PIXEL;
    1374     * Object data = null; // no initial data values
    1375     * Dataset d = (H5File) file.createScalarDS(name, pgroup, dtype, dims, maxdims, chunks, gzip, ncomp, interlace, data);
    1376     * </pre>
    1377     *
    1378     * @param name
    1379     *            name of the new image, "2D image".
    1380     * @param pgroup
    1381     *            parent group where the new image is created.
    1382     * @param type
    1383     *            datatype of the new image.
    1384     * @param dims
    1385     *            dimension sizes of the new dataset, e.g. long[] dims = {100,
    1386     *            50}.
    1387     * @param maxdims
    1388     *            maximum dimension sizes of the new dataset, null if maxdims is
    1389     *            the same as dims.
    1390     * @param chunks
    1391     *            chunk sizes of the new dataset, null if no chunking.
    1392     * @param gzip
    1393     *            GZIP compression level (1 to 9), 0 or negative values if no
    1394     *            compression.
    1395     * @param ncomp
    1396     *            number of components of the new image, e.g. int ncomp = 3; //
    1397     *            RGB true color image.
    1398     * @param interlace
    1399     *            interlace mode of the image. Valid values are
    1400     *            ScalarDS.INTERLACE_PIXEL, ScalarDS.INTERLACE_PLANEL and
    1401     *            ScalarDS.INTERLACE_LINE.
    1402     * @param data
    1403     *            data value of the image, null if no data.
    1404     *
    1405     * @return The new image object if successful; otherwise returns null
    1406     *
    1407     * @throws Exception
    1408     *             The exceptions thrown vary depending on the implementing
    1409     *             class.
    1410     */
    1411    public abstract Dataset createImage(
    1412            String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, long[] chunks, int gzip, int ncomp,
    1413            int interlace, Object data) throws Exception;
    1414
    1415    // REVIEW DOCS for createImage(). Check and document exceptions.
    1416
    1417    /**
    1418     * Creates a new group with specified name in existing group.
    1419     * <p>
    1420     * If the parent group is null, the new group will be created in the root
    1421     * group.
    1422     *
    1423     * @param name
    1424     *            The name of the new group.
    1425     * @param parentGroup
    1426     *            The parent group, or null.
    1427     *
    1428     * @return The new group if successful; otherwise returns null.
    1429     *
    1430     * @throws Exception
    1431     *             The exceptions thrown vary depending on the implementing
    1432     *             class.
    1433     */
    1434    public abstract Group createGroup(String name, Group parentGroup) throws Exception;
    1435
    1436    // REVIEW DOCS for createLink().
    1437    // Verify Implementing classes document these and also
    1438    // 'do the right thing' if fid is -1, currentObj is non-null, if
    1439    // object is null, or the root group then what? document & verify!
    1440
    1441    /**
    1442     * Creates a soft, hard or external link to an existing object in the open
    1443     * file.
    1444     * <p>
    1445     * If parentGroup is null, the new link is created in the root group.
    1446     *
    1447     * @param parentGroup
    1448     *            The group where the link is created.
    1449     * @param name
    1450     *            The name of the link.
    1451     * @param currentObj
    1452     *            The existing object the new link will reference.
    1453     * @param type
    1454     *            The type of link to be created. It can be a hard link, a soft
    1455     *            link or an external link.
    1456     *
    1457     * @return The object pointed to by the new link if successful; otherwise
    1458     *         returns null.
    1459     *
    1460     * @throws Exception
    1461     *             The exceptions thrown vary depending on the implementing
    1462     *             class.
    1463     */
    1464    public HObject createLink(Group parentGroup, String name, HObject currentObj, int type) throws Exception {
    1465        return createLink(parentGroup, name, currentObj);
    1466    }
    1467
    1468    /**
    1469     * Creates a soft or external link to an object in a file that does not exist
    1470     * at the time the link is created.
    1471     *
    1472     * @param parentGroup
    1473     *            The group where the link is created.
    1474     * @param name
    1475     *            The name of the link.
    1476     * @param currentObj
    1477     *            The name of the object the new link will reference. The object
    1478     *            doesn't have to exist.
    1479     * @param type
    1480     *            The type of link to be created.
    1481     *
    1482     * @return The H5Link object pointed to by the new link if successful;
    1483     *         otherwise returns null.
    1484     *
    1485     * @throws Exception
    1486     *             The exceptions thrown vary depending on the implementing
    1487     *             class.
    1488     */
    1489    public HObject createLink(Group parentGroup, String name, String currentObj, int type) throws Exception {
    1490        return createLink(parentGroup, name, currentObj);
    1491    }
    1492
    1493    /**
    1494     * Copies the source object to a new destination.
    1495     * <p>
    1496     * This method copies the source object to a destination group, and assigns
    1497     * the specified name to the new object.
    1498     * <p>
    1499     * The copy may take place within a single file or across files. If the source
    1500     * object and destination group are in different files, the files must have
    1501     * the same file format (both HDF5 for example).
    1502     * <p>
    1503     * The source object can be a group, a dataset, or a named datatype. This
    1504     * method copies the object along with all of its attributes and other
    1505     * properties. If the source object is a group, this method also copies all
    1506     * objects and sub-groups below the group.
    1507     * <p>
    1508     * The following example shows how to use the copy method to create two
    1509     * copies of an existing HDF5 file structure in a new HDF5 file. One copy
    1510     * will be under /copy1 and the other under /copy2 in the new file.
    1511     *
    1512     * <pre>
    1513     * // Open the existing file with the source object.
    1514     * H5File existingFile = new H5File(&quot;existingFile.h5&quot;, FileFormat.READ);
    1515     * existingFile.open();
    1516     * // Our source object will be the root group.
    1517     * HObject srcObj = existingFile.get(&quot;/&quot;);
    1518     * // Create a new file.
    1519     * H5File newFile = new H5File(&quot;newFile.h5&quot;, FileFormat.CREATE);
    1520     * newFile.open();
    1521     * // Both copies in the new file will have the root group as their
    1522     * // destination group.
    1523     * Group dstGroup = (Group) newFile.get(&quot;/&quot;);
    1524     * // First copy goes to &quot;/copy1&quot; and second goes to &quot;/copy2&quot;.
    1525     * // Notice that we can use either H5File instance to perform the copy.
    1526     * HObject copy1 = existingFile.copy(srcObj, dstGroup, &quot;copy1&quot;);
    1527     * HObject copy2 = newFile.copy(srcObj, dstGroup, &quot;copy2&quot;);
    1528     * // Close both the files.
    1529     * file.close();
    1530     * newFile.close();
    1531     * </pre>
    1532     *
    1533     * @param srcObj
    1534     *            The object to copy.
    1535     * @param dstGroup
    1536     *            The destination group for the new object.
    1537     * @param dstName
    1538     *            The name of the new object. If dstName is null, the name of
    1539     *            srcObj will be used.
    1540     *
    1541     * @return The new object, or null if the copy fails.
    1542     *
    1543     * @throws Exception
    1544     *             are specific to the implementing class.
    1545     */
    1546    public abstract HObject copy(HObject srcObj, Group dstGroup, String dstName) throws Exception;
    1547
    1548    /**
    1549     * Deletes an object from a file.
    1550     *
    1551     * @param obj
    1552     *            The object to delete.
    1553     * @throws Exception
    1554     *             The exceptions thrown vary depending on the implementing
    1555     *             class.
    1556     */
    1557    public abstract void delete(HObject obj) throws Exception;
    1558
    1559    // REVIEW DOCS for delete(). Check and document exceptions.
    1560
    1561    /**
    1562     * Attaches a given attribute to an object.
    1563     * <p>
    1564     * If an HDF(4&amp;5) attribute exists in file, the method updates its value. If
    1565     * the attribute does not exist in file, it creates the attribute in file
    1566     * and attaches it to the object. It will fail to write a new attribute to
    1567     * the object where an attribute with the same name already exists. To
    1568     * update the value of an existing attribute in file, one needs to get the
    1569     * instance of the attribute by getMetadata(), change its values, and use
    1570     * writeAttribute() to write the value.
    1571     *
    1572     * @param obj
    1573     *            The object to which the attribute is attached to.
    1574     * @param attr
    1575     *            The atribute to attach.
    1576     * @param attrExisted
    1577     *            The indicator if the given attribute exists.
    1578     *
    1579     * @throws Exception
    1580     *             The exceptions thrown vary depending on the implementing class.
    1581     */
    1582    public abstract void writeAttribute(HObject obj, Attribute attr, boolean attrExisted) throws Exception;
    1583
    1584    // REVIEW DOCS for writeAttribute(). Check and document exceptions.
    1585
    1586    /***************************************************************************
    1587     * Deprecated methods.
    1588     **************************************************************************/
    1589
    1590    /**
    1591     * @deprecated As of 2.4, replaced by {@link #createFile(String, int)}
    1592     *             <p>
    1593     *             The replacement method has an additional parameter that
    1594     *             controls the behavior if the file already exists. Use
    1595     *             <code>FileFormat.FILE_CREATE_DELETE</code> as the second
    1596     *             argument in the replacement method to mimic the behavior
    1597     *             originally provided by this method.
    1598     *
    1599     * @param fileName
    1600     *            The filename; a pathname string.
    1601     *
    1602     * @return the created file object
    1603     *
    1604     * @throws Exception if file cannot be created
    1605     */
    1606    @Deprecated
    1607    public final FileFormat create(String fileName) throws Exception {
    1608        return createFile(fileName, FileFormat.FILE_CREATE_DELETE);
    1609    }
    1610
    1611    /**
    1612     * @deprecated As of 2.4, replaced by {@link #createInstance(String, int)}
    1613     *
    1614     *             The replacement method has identical functionality and a more
    1615     *             descriptive name. Since <i>open</i> is used elsewhere to
    1616     *             perform a different function this method has been deprecated.
    1617     *
    1618     * @param pathname
    1619     *            The pathname string.
    1620     * @param access
    1621     *            The file access properties
    1622     *
    1623     * @return the opened file object
    1624     *
    1625     * @throws Exception if the file cannot be opened
    1626     */
    1627    @Deprecated
    1628    public final FileFormat open(String pathname, int access) throws Exception {
    1629        return createInstance(pathname, access);
    1630    }
    1631
    1632    /**
    1633     * @deprecated As of 2.4, replaced by
    1634     *             {@link #createCompoundDS(String, Group, long[], long[], long[], int, String[], Datatype[], int[], Object)}
    1635     *             <p>
    1636     *             The replacement method has additional parameters:
    1637     *             <code>maxdims, chunks,</code> and <code>gzip</code>. To mimic
    1638     *             the behavior originally provided by this method, call the
    1639     *             replacement method with the following parameter list:
    1640     *             <code> ( name, pgroup, dims, null, null, -1,
    1641     * memberNames, memberDatatypes, memberSizes, data ); </code>
    1642     *
    1643     * @param name
    1644     *            The dataset name.
    1645     * @param pgroup
    1646     *            The dataset parent.
    1647     * @param dims
    1648     *            The dataset dimensions.
    1649     * @param memberNames
    1650     *            The dataset compound member names.
    1651     * @param memberDatatypes
    1652     *            The dataset compound member datatypes.
    1653     * @param memberSizes
    1654     *            The dataset compound member sizes.
    1655     * @param data
    1656     *            The dataset data.
    1657     *
    1658     * @return
    1659     *            The dataset created.
    1660     *
    1661     * @throws Exception if the dataset cannot be created
    1662     */
    1663    @Deprecated
    1664    public final Dataset createCompoundDS(String name, Group pgroup, long[] dims, String[] memberNames,
    1665            Datatype[] memberDatatypes, int[] memberSizes, Object data) throws Exception {
    1666        return createCompoundDS(name, pgroup, dims, null, null, -1, memberNames, memberDatatypes, memberSizes, data);
    1667    }
    1668
    1669    /**
    1670     * @deprecated As of 2.4, replaced by {@link #copy(HObject, Group, String)}
    1671     *             <p>
    1672     *             To mimic the behavior originally provided by this method,
    1673     *             call the replacement method with <code>null</code> as the 3rd
    1674     *             parameter.
    1675     *
    1676     * @param srcObj
    1677     *             The object to be copied
    1678     * @param dstGroup
    1679     *             The group to contain the copied object
    1680     *
    1681     * @return the copied object
    1682     *
    1683     * @throws Exception if object can not be copied
    1684     */
    1685    @Deprecated
    1686    public final HObject copy(HObject srcObj, Group dstGroup) throws Exception {
    1687        return copy(srcObj, dstGroup, null);
    1688    }
    1689
    1690    /**
    1691     * @deprecated As of 2.4, replaced by {@link #get(String)}
    1692     *             <p>
    1693     *             This static method, which as been deprecated, causes two
    1694     *             problems:
    1695     *             <ul>
    1696     *             <li>It can be very expensive if it is called many times or in
    1697     *             a loop because each call to the method creates an instance of
    1698     *             a file.
    1699     *             <li>Since the method does not return the instance of the
    1700     *             file, the file cannot be closed directly and may be left open
    1701     *             (memory leak). The only way to close the file is through the
    1702     *             object returned by this method.
    1703     *             </ul>
    1704     *
    1705     * @param fullPath
    1706     *            The file path string.
    1707     *
    1708     * @return the object that has the given full path
    1709     *
    1710     * @throws Exception if the object can not be found
    1711     */
    1712    @Deprecated
    1713    public static final HObject getHObject(String fullPath) throws Exception {
    1714        if ((fullPath == null) || (fullPath.length() <= 0)) {
    1715            return null;
    1716        }
    1717
    1718        String filename = null, path = null;
    1719        int idx = fullPath.indexOf(FILE_OBJ_SEP);
    1720
    1721        if (idx > 0) {
    1722            filename = fullPath.substring(0, idx);
    1723            path = fullPath.substring(idx + FILE_OBJ_SEP.length());
    1724            if ((path == null) || (path.length() == 0)) {
    1725                path = "/";
    1726            }
    1727        }
    1728        else {
    1729            filename = fullPath;
    1730            path = "/";
    1731        }
    1732
    1733        return FileFormat.getHObject(filename, path);
    1734    };
    1735
    1736    /**
    1737     * @deprecated As of 2.4, replaced by {@link #get(String)}
    1738     *             <p>
    1739     *             This static method, which as been deprecated, causes two
    1740     *             problems:
    1741     *             <ul>
    1742     *             <li>It can be very expensive if it is called many times or in
    1743     *             a loop because each call to the method creates an instance of
    1744     *             a file.
    1745     *             <li>Since the method does not return the instance of the
    1746     *             file, the file cannot be closed directly and may be left open
    1747     *             (memory leak). The only way to close the file is through the
    1748     *             object returned by this method, for example:
    1749     *             <pre>
    1750     * Dataset dset = H5File.getObject("hdf5_test.h5", "/images/iceburg");
    1751     * ...
    1752     * // close the file through dset
    1753     * dset.getFileFormat().close();
    1754     * </pre>
    1755     *
    1756     *             </li>
    1757     *             </ul>
    1758     *
    1759     * @param filename
    1760     *            The filename string.
    1761     * @param path
    1762     *            The path of the file
    1763     *
    1764     * @return the object that has the given filename and path returns null
    1765     *
    1766     * @throws Exception if the object can not be found
    1767     */
    1768    @Deprecated
    1769    public static final HObject getHObject(String filename, String path) throws Exception {
    1770        if ((filename == null) || (filename.length() <= 0)) {
    1771            throw new IllegalArgumentException("Invalid file name. " + filename);
    1772        }
    1773
    1774        if (!(new File(filename)).exists()) {
    1775            throw new IllegalArgumentException("File does not exists");
    1776        }
    1777
    1778        HObject obj = null;
    1779        FileFormat file = FileFormat.getInstance(filename);
    1780
    1781        if (file != null) {
    1782            obj = file.get(path);
    1783            if (obj == null) {
    1784                file.close();
    1785            }
    1786        }
    1787
    1788        return obj;
    1789    }
    1790
    1791    /**
    1792     * Finds an object by its object ID
    1793     *
    1794     * @param file
    1795     *            the file containing the object
    1796     * @param oid
    1797     *            the oid to search for
    1798     *
    1799     * @return the object that has the given OID; otherwise returns null
    1800     */
    1801    public final static HObject findObject(FileFormat file, long[] oid) {
    1802        log.trace("findObject(): start");
    1803
    1804        if ((file == null) || (oid == null)) {
    1805            log.debug("findObject(): file is null or oid is null");
    1806            log.trace("findObject(): finish");
    1807            return null;
    1808        }
    1809
    1810        HObject theObj = null;
    1811
    1812        HObject theRoot = file.getRootObject();
    1813        if (theRoot == null) {
    1814            log.debug("findObject(): rootObject is null");
    1815            log.trace("findObject(): finish");
    1816            return null;
    1817        }
    1818
    1819        Iterator<HObject> member_it = ((Group) theRoot).breadthFirstMemberList().iterator();
    1820        while (member_it.hasNext()) {
    1821            theObj = member_it.next();
    1822            if (theObj.equalsOID(oid)) break;
    1823        }
    1824
    1825        return theObj;
    1826    }
    1827
    1828    /**
    1829     * Finds an object by the full path of the object (path+name)
    1830     *
    1831     * @param file
    1832     *            the file containing the object
    1833     * @param path
    1834     *            the full path of the object to search for
    1835     *
    1836     * @return the object that has the given path; otherwise returns null
    1837     */
    1838    public final static HObject findObject(FileFormat file, String path) {
    1839        log.trace("findObject({}): start", path);
    1840
    1841        if ((file == null) || (path == null)) {
    1842            log.debug("findObject(): file is null or path is null");
    1843            log.trace("findObject(): finish");
    1844            return null;
    1845        }
    1846
    1847        if (!path.endsWith("/")) {
    1848            path = path + "/";
    1849        }
    1850
    1851        HObject theRoot = file.getRootObject();
    1852
    1853        if (theRoot == null) {
    1854            log.debug("findObject(): rootObject is null");
    1855            log.trace("findObject(): finish");
    1856            return null;
    1857        }
    1858        else if (path.equals("/")) {
    1859            log.debug("findObject() path is rootObject");
    1860            log.trace("findObject(): finish");
    1861            return theRoot;
    1862        }
    1863
    1864        Iterator<HObject> member_it = ((Group) theRoot).breadthFirstMemberList().iterator();
    1865        HObject theObj = null;
    1866        while (member_it.hasNext()) {
    1867            theObj = member_it.next();
    1868            String fullPath = theObj.getFullName() + "/";
    1869
    1870            if (path.equals(fullPath) && theObj.getPath() != null) {
    1871                break;
    1872            }
    1873            else {
    1874                theObj = null;
    1875            }
    1876        }
    1877
    1878        log.trace("findObject(): finish");
    1879        return theObj;
    1880    }
    1881
    1882    // ////////////////////////////////////////////////////////////////////////////////////
    1883    // Added to support HDF5 1.8 features //
    1884    // ////////////////////////////////////////////////////////////////////////////////////
    1885
    1886    /**
    1887     * Opens file and returns a file identifier.
    1888     *
    1889     * @param indexList
    1890     *            The property list is the list of parameters, like index type
    1891     *            and the index order. The index type can be alphabetical or
    1892     *            creation. The index order can be increasing order or
    1893     *            decreasing order.
    1894     *
    1895     * @return File identifier if successful; otherwise -1.
    1896     *
    1897     * @throws Exception
    1898     *             The exceptions thrown vary depending on the implementing class.
    1899     */
    1900    public long open(int... indexList) throws Exception {
    1901        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:open.");
    1902    }
    1903
    1904    /**
    1905     * Creates a new group with specified name in existing group.
    1906     * <p>
    1907     * If the parent group is null, the new group will be created in the root
    1908     * group.
    1909     *
    1910     * @param name
    1911     *            The name of a new group.
    1912     * @param pgroup
    1913     *            The parent group object.
    1914     * @param gplist
    1915     *            The group creation properties, in which the order of the
    1916     *            properties conforms the HDF5 library API, H5Gcreate(), i.e.
    1917     *            lcpl, gcpl and gapl, where
    1918     *            <ul>
    1919     *            <li>lcpl : Property list for link creation <li>gcpl : Property
    1920     *            list for group creation <li>gapl : Property list for group
    1921     *            access
    1922     *            </ul>
    1923     *
    1924     * @return The new group if successful; otherwise returns null.
    1925     *
    1926     * @throws Exception
    1927     *             The exceptions thrown vary depending on the implementing class.
    1928     */
    1929    public Group createGroup(String name, Group pgroup, long... gplist) throws Exception {
    1930        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:createGroup.");
    1931    }
    1932
    1933    /***
    1934     * Creates the group creation property list identifier, gcpl. This
    1935     * identifier is used when creating Groups.
    1936     *
    1937     * @param creationorder
    1938     *            The order in which the objects in a group should be created.
    1939     *            It can be Tracked or Indexed.
    1940     * @param maxcompact
    1941     *            The maximum number of links to store in the group in a compact
    1942     *            format.
    1943     * @param mindense
    1944     *            The minimum number of links to store in the indexed
    1945     *            format.Groups which are in indexed format and in which the
    1946     *            number of links falls below this threshold are automatically
    1947     *            converted to compact format.
    1948     *
    1949     * @return The gcpl identifier.
    1950     *
    1951     * @throws Exception
    1952     *             The exceptions thrown vary depending on the implementing class.
    1953     */
    1954    public long createGcpl(int creationorder, int maxcompact, int mindense) throws Exception {
    1955        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:createGcpl.");
    1956    }
    1957
    1958    /**
    1959     * Creates a link to an existing object in the open file.
    1960     * <p>
    1961     * If linkGroup is null, the new link is created in the root group.
    1962     *
    1963     * @param linkGroup
    1964     *            The group where the link is created.
    1965     * @param name
    1966     *            The name of the link.
    1967     * @param currentObj
    1968     *            The existing object the new link will reference.
    1969     *
    1970     * @return The object pointed to by the new link if successful; otherwise
    1971     *         returns null.
    1972     *
    1973     * @throws Exception
    1974     *             The exceptions thrown vary depending on the implementing class.
    1975     */
    1976    public HObject createLink(Group linkGroup, String name, Object currentObj) throws Exception {
    1977        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:createLink.");
    1978    }
    1979
    1980    /**
    1981     * Export dataset.
    1982     *
    1983     * @param file_export_name
    1984     *            The file name to export data into.
    1985     * @param file_name
    1986     *            The name of the HDF5 file containing the dataset.
    1987     * @param object_path
    1988     *            The full path of the dataset to be exported.
    1989     * @param binary_order
    1990     *            The data byte order
    1991     *
    1992     * @throws Exception
    1993     *             The exceptions thrown vary depending on the implementing class.
    1994     */
    1995    public void exportDataset(String file_export_name, String file_name, String object_path, int binary_order) throws Exception {
    1996        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:exportDataset.");
    1997    }
    1998
    1999    /**
    2000     * Renames an attribute.
    2001     *
    2002     * @param obj
    2003     *            The object whose attribute is to be renamed.
    2004     * @param oldAttrName
    2005     *            The current name of the attribute.
    2006     * @param newAttrName
    2007     *            The new name of the attribute.
    2008     *
    2009     * @throws Exception
    2010     *             The exceptions thrown vary depending on the implementing class.
    2011     */
    2012    public void renameAttribute(HObject obj, String oldAttrName, String newAttrName) throws Exception {
    2013        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:renameAttribute.");
    2014    }
    2015
    2016    /**
    2017     * Sets the bounds of new library versions.
    2018     *
    2019     * @param lowStr
    2020     *            The earliest version of the library.
    2021     * @param highStr
    2022     *            The latest version of the library.
    2023     *
    2024     * @throws Exception
    2025     *             The exceptions thrown vary depending on the implementing class.
    2026     */
    2027    public void setNewLibBounds(String lowStr, String highStr) throws Exception {
    2028        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:setNewLibBounds.");
    2029    }
    2030
    2031    /**
    2032     * Sets the bounds of library versions.
    2033     *
    2034     * @param lowStr
    2035     *            The earliest version of the library.
    2036     * @param highStr
    2037     *            The latest version of the library.
    2038     *
    2039     * @throws Exception
    2040     *             The exceptions thrown vary depending on the implementing class.
    2041     */
    2042    public void setLibBounds(String lowStr, String highStr) throws Exception {
    2043        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:setLibBounds.");
    2044    }
    2045
    2046    /**
    2047     * Gets the bounds of library versions
    2048     *
    2049     * @return The earliest and latest library versions in an int array.
    2050     *
    2051     * @throws Exception
    2052     *             The exceptions thrown vary depending on the implementing class.
    2053     */
    2054    public int[] getLibBounds() throws Exception {
    2055        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:getLibBounds.");
    2056    }
    2057
    2058    public String getLibBoundsDescription() {
    2059        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:getLibBoundsDescription.");
    2060    }
    2061
    2062    public static int getIndexTypeValue(String strtype) {
    2063        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:getIndexTypeValue.");
    2064    }
    2065
    2066    public int getIndexType(String strtype) {
    2067        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:getIndexType.");
    2068    }
    2069
    2070    public void setIndexType(int indexType) {
    2071        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:setIndexType.");
    2072    }
    2073
    2074    public static int getIndexOrderValue(String strorder) {
    2075        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:getIndexOrderValue.");
    2076    }
    2077
    2078    public int getIndexOrder(String strorder) {
    2079        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:getIndexOrder.");
    2080    }
    2081
    2082    public void setIndexOrder(int indexOrder) {
    2083        throw new UnsupportedOperationException("Unsupported operation. Subclasses must implement FileFormat:setIndexOrder.");
    2084    }
    2085}