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