    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.h4;
    016
    017import java.io.File;
    018import java.lang.reflect.Array;
    019import java.util.Iterator;
    020import java.util.LinkedList;
    021import java.util.List;
    022import java.util.Queue;
    023import java.util.Vector;
    024
    025import hdf.hdflib.HDFConstants;
    026import hdf.hdflib.HDFException;
    027import hdf.hdflib.HDFLibrary;
    028import hdf.object.Attribute;
    029import hdf.object.Dataset;
    030import hdf.object.Datatype;
    031import hdf.object.FileFormat;
    032import hdf.object.Group;
    033import hdf.object.HObject;
    034
    035/**
    036 * This class provides file level APIs. File access APIs include retrieving the
    037 * file hierarchy, opening and closing file, and writing file content to disk.
    038 *
    039 * @version 2.4 9/4/2007
    040 * @author Peter X. Cao
    041 */
    042public class H4File extends FileFormat {
    043    private static final long serialVersionUID = 8985533001471224030L;
    044
    045    private final static org.slf4j.Logger   log = org.slf4j.LoggerFactory.getLogger(H4File.class);
    046
    047    /**
    048     * the file access flag.
    049     */
    050    private int                             flag;
    051
    052    /**
    053     * The root object of this file.
    054     */
    055    private HObject                         rootObject;
    056
    057    /**
    058     * The list of unique (tag, ref) pairs. It is used to avoid duplicate
    059     * objects in memory.
    060     */
    061    @SuppressWarnings("rawtypes")
    062    private List                            objList;
    063
    064    /**
    065     * The GR interface identifier. The identifier is returned by GRstart(fid),
    066     * which initializes the GR interface for the file specified by the
    067     * parameter. GRstart(fid) is an expensive call. It should be called only
    068     * once. Calling GRstart(fid) in a loop should be avoided.
    069     */
    070    private long                            grid;
    071
    072    private boolean                         isNetCDF = false;
    073
    074    /**
    075     * The SDS interface identifier. The identifier is returned by
    076     * SDstart(fname, flag), which initializes the SD interface for the file
    077     * specified by the parameter. SDstart(fname, flag) is an expensive call. It
    078     * should be called only once. Calling SDstart(fname, flag) in a loop should
    079     * be avoided.
    080     */
    081    private long                            sdid;
    082
    083    /**
    084     * secret flag: show CDF0.0, etc., to help debug
    085     */
    086    private boolean                         showAll = false;
    087
    088    /**
    089     * Creates an H4File with read only access.
    090     */
    091    public H4File() {
    092        this("", WRITE);
    093    }
    094
    095    /**
    096     * Creates an H4File with read only access.
    097     *
    098     * @param pathname
    099     *        The file path string.
    100     */
    101    public H4File(String pathname) {
    102        this(pathname, WRITE);
    103    }
    104
    105    /**
    106     * Creates an H4File instance with specified file name and access.
    107     * <p>
    108     * The access parameter values and corresponding behaviors:
    109     * <ul>
    110     * <li>READ: Read-only access; open() will fail if file doesn't exist.
    111     * <li>WRITE: Read/Write access; if file doesn't exist, open() will create
    112     * it; open() will fail if read/write access not allowed.
    113     * <li>CREATE: Read/Write access; create a new file or truncate an existing
    114     * one; open() will fail if file can't be created or if file exists but
    115     * can't be opened read/write.
    116     * </ul>
    117     * <p>
    118     * This constructor does not open the file for access, nor does it confirm
    119     * that the file can later be opened read/write or created.
    120     * <p>
    121     * The flag returned by {@link #isReadOnly()} is set to true if the access
    122     * parameter value is READ, even though the file isn't yet open.
    123     *
    124     * @param fileName
    125     *            A valid file name, with a relative or absolute path.
    126     * @param access
    127     *            The file access flag, which determines behavior when file is
    128     *            opened. Acceptable values are <code> READ, WRITE, </code> and
    129     *            <code>CREATE</code>.
    130     *
    131     * @throws NullPointerException
    132     *             If the <code>fileName</code> argument is <code>null</code>.
    133     */
    134    @SuppressWarnings("rawtypes")
    135    public H4File(String fileName, int access) {
    136        super(fileName);
    137        isReadOnly = (access == READ);
    138        objList = new Vector();
    139
    140        this.fid = -1;
    141
    142        if ((access & FILE_CREATE_OPEN) == FILE_CREATE_OPEN) {
    143            File f = new File(fileName);
    144            if (f.exists()) {
    145                access = WRITE;
    146            }
    147            else {
    148                access = CREATE;
    149            }
    150        }
    151
    152        if (access == READ) {
    153            flag = HDFConstants.DFACC_READ;
    154        }
    155        else if (access == WRITE) {
    156            flag = HDFConstants.DFACC_WRITE;
    157        }
    158        else if (access == CREATE) {
    159            flag = HDFConstants.DFACC_CREATE;
    160        }
    161        else {
    162            flag = access;
    163        }
    164
    165        if (log != null) log.trace("File: {} isReadOnly={} accessType={}", fileName, isReadOnly, flag);
    166
    167        String shwAll = System.getProperty("h4showall");
    168        if (shwAll != null) {
    169            showAll = true;
    170            if (log != null) log.debug("show all is on");
    171        }
    172        else {
    173            if (log != null) log.debug("show all is off");
    174        }
    175    }
    176
    177    /**
    178     * Checks if the given file format is an HDF4 file.
    179     *
    180     * @param fileformat
    181     *            the fileformat to be checked.
    182     *
    183     * @return true if the given file is an HDF4 file; otherwise returns false.
    184     */
    185    @Override
    186    public boolean isThisType(FileFormat fileformat) {
    187        return (fileformat instanceof H4File);
    188    }
    189
    190    /**
    191     * Checks if the given file is an HDF4 file or netCDF. HDF4 library supports
    192     * netCDF version 2.3.2. It only supports SDS APIs.
    193     *
    194     * @param filename
    195     *            the file to be checked.
    196     *
    197     * @return true if the given file is an HDF4 file; otherwise returns false.
    198     */
    199    @Override
    200    public boolean isThisType(String filename) {
    201        boolean isH4 = false;
    202
    203        try {
    204            isH4 = HDFLibrary.Hishdf(filename);
    205        }
    206        catch (HDFException ex) {
    207            isH4 = false;
    208        }
    209
    210        if (!isH4) {
    211            isH4 = isNetCDF(filename);
    212        }
    213
    214        log.trace("isThisType(): isH4={}", isH4);
    215        return isH4;
    216    }
    217
    218    /**
    219     * Creates an HDF4 file with the specified name and returns a new H4File
    220     * instance associated with the file.
    221     *
    222     * @throws HDFException
    223     *             If the file cannot be created or if createFlag has unexpected
    224     *             value.
    225     *
    226     * @see hdf.object.FileFormat#createFile(java.lang.String, int)
    227     * @see #H4File(String, int)
    228     */
    229    @Override
    230    public FileFormat createFile(String filename, int createFlag)
    231            throws Exception {
    232        log.trace("createFile(): start");
    233
    234        // Flag if we need to create or truncate the file.
    235        Boolean doCreateFile = true;
    236
    237        // Won't create or truncate if CREATE_OPEN specified and file exists
    238        if (createFlag == FILE_CREATE_OPEN) {
    239            File f = new File(filename);
    240            if (f.exists()) {
    241                doCreateFile = false;
    242            }
    243        }
    244
    245        log.trace("createFile(): doCreateFile={}", doCreateFile);
    246
    247        if (doCreateFile) {
    248            long fileid = HDFLibrary.Hopen(filename, HDFConstants.DFACC_CREATE);
    249            try {
    250                HDFLibrary.Hclose(fileid);
    251            }
    252            catch (HDFException ex) {
    253                log.debug("Hclose failure: ", ex);
    254            }
    255        }
    256
    257        log.trace("createFile(): finish");
    258        return new H4File(filename, WRITE);
    259    }
    260
    261    /**
    262     * Creates an H4File instance with specified file name and access.
    263     *
    264     * @see hdf.object.FileFormat#createInstance(java.lang.String, int)
    265     * @see #H4File(String, int)
    266     */
    267    @Override
    268    public FileFormat createInstance(String filename, int access)
    269            throws Exception {
    270        return new H4File(filename, access);
    271    }
    272
    273    // Implementing FileFormat
    274    @Override
    275    public long open() throws Exception {
    276        log.trace("open(): start");
    277
    278        if (fid >= 0) {
    279            log.trace("open(): File " + fid + " already open");
    280            log.trace("open(): finish");
    281            return fid; // file is opened already
    282        }
    283
    284        // check for valid file access permission
    285        if (flag < 0) { // invalid access id
    286            throw new HDFException("Invalid access identifer -- " + flag);
    287        }
    288        else if (flag == HDFConstants.DFACC_READ) {
    289            if (!exists()) {
    290                log.debug("File {} does not exist", fullFileName);
    291                log.trace("open(): finish");
    292                throw new HDFException("File does not exist -- " + fullFileName);
    293            }
    294            else if (exists() && !canRead()) {
    295                log.debug("Cannot read file {}", fullFileName);
    296                log.trace("open(): finish");
    297                throw new HDFException("Cannot read file -- " + fullFileName);
    298            }
    299        }
    300        else if ((flag == HDFConstants.DFACC_WRITE)
    301                || (flag == HDFConstants.DFACC_CREATE)) {
    302            if (exists() && !canWrite()) {
    303                log.debug("Cannot write file {}, try opening as read-only", fullFileName);
    304                log.trace("open(): finish");
    305                throw new HDFException(
    306                        "Cannot write file, try opening as read-only -- "
    307                                + fullFileName);
    308            }
    309        }
    310
    311        // Only check for NetCDF if the file exists, else isNetCDF() throws an exception
    312        if (exists()) isNetCDF = isNetCDF(fullFileName);
    313        if (isNetCDF) {
    314            isReadOnly = true; // read only for netCDF
    315        }
    316
    317        log.trace("open(): isNetCDF={}", isNetCDF);
    318
    319        // only support SDS APIs for netCDF
    320        if (isNetCDF) {
    321            fid = 0;
    322        }
    323        else {
    324            log.trace("HDFLibrary - open({},{})", fullFileName, flag);
    325            fid = HDFLibrary.Hopen(fullFileName, flag);
    326            HDFLibrary.Vstart(fid);
    327            grid = HDFLibrary.GRstart(fid);
    328            log.trace("open(): fid:{} grid:{}", fid, grid);
    329        }
    330
    331        try {
    332            sdid = HDFLibrary.SDstart(fullFileName, flag & ~HDFConstants.DFACC_CREATE);
    333
    334            if (sdid < 0) log.debug("open(): SDstart failed!");
    335        }
    336        catch (HDFException ex) {
    337            log.debug("open(): SDstart failure: ", ex);
    338        }
    339
    340        log.trace("open(): sdid:{}", sdid);
    341
    342        // load the file hierarchy
    343        loadIntoMemory();
    344
    345        log.trace("open(): finish");
    346        return fid;
    347    }
    348
    349    // Implementing FileFormat
    350    @Override
    351    public void close() throws HDFException {
    352        log.trace("close(): start");
    353
    354        // clean unused objects
    355        if (rootObject != null) {
    356            HObject theObj = null;
    357            Iterator<HObject> it = getMembersBreadthFirst(rootObject).iterator();
    358            while (it.hasNext()) {
    359                theObj = it.next();
    360
    361                if (theObj instanceof Dataset) {
    362                    ((Dataset) theObj).clearData();
    363                }
    364                else if (theObj instanceof Group) {
    365                    ((Group) theObj).clear();
    366                }
    367            }
    368        }
    369
    370        try {
    371            HDFLibrary.GRend(grid);
    372        }
    373        catch (HDFException ex) {
    374            log.debug("close(): GRend failure: ", ex);
    375        }
    376        try {
    377            HDFLibrary.SDend(sdid);
    378        }
    379        catch (HDFException ex) {
    380            log.debug("close(): SDend failure: ", ex);
    381        }
    382        try {
    383            HDFLibrary.Vend(fid);
    384        }
    385        catch (HDFException ex) {
    386            log.debug("close(): Vend failure: ", ex);
    387        }
    388
    389        HDFLibrary.Hclose(fid);
    390
    391        fid = -1;
    392        objList = null;
    393    }
    394
    395    // Implementing FileFormat
    396    @Override
    397    public HObject getRootObject() {
    398        return rootObject;
    399    }
    400
    401    @Override
    402    public Group createGroup(String name, Group pgroup) throws Exception {
    403        return H4Group.create(name, pgroup);
    404    }
    405
    406    @Override
    407    public Datatype createDatatype(int tclass, int tsize, int torder, int tsign)
    408            throws Exception {
    409        return new H4Datatype(tclass, tsize, torder, tsign);
    410    }
    411
    412    @Override
    413    public Datatype createDatatype(int tclass, int tsize, int torder,
    414            int tsign, Datatype tbase) throws Exception {
    415        return new H4Datatype(tclass, tsize, torder, tsign);
    416    }
    417
    418    @Override
    419    public Datatype createDatatype(int tclass, int tsize, int torder,
    420            int tsign, String name) throws Exception {
    421        throw new UnsupportedOperationException(
    422                "HDF4 does not support named datatype.");
    423    }
    424
    425    @Override
    426    public Datatype createDatatype(int tclass, int tsize, int torder,
    427            int tsign, Datatype tbase, String name) throws Exception {
    428        throw new UnsupportedOperationException(
    429                "HDF4 does not support named datatype.");
    430    }
    431
    432    @Override
    433    public Dataset createScalarDS(String name, Group pgroup, Datatype type,
    434            long[] dims, long[] maxdims, long[] chunks, int gzip,
    435            Object fillValue, Object data) throws Exception {
    436        return H4SDS.create(name, pgroup, type, dims, maxdims, chunks, gzip,
    437                fillValue, data);
    438    }
    439
    440    @Override
    441    public Dataset createImage(String name, Group pgroup, Datatype type,
    442            long[] dims, long[] maxdims, long[] chunks, int gzip, int ncomp,
    443            int interlace, Object data) throws Exception {
    444        H4GRImage dataset = H4GRImage.create(name, pgroup, type, dims, maxdims,
    445                chunks, gzip, ncomp, interlace, data);
    446
    447        return dataset;
    448    }
    449
    450    /**
    451     * Delete an object from the file.
    452     *
    453     * @param obj
    454     *            the data object to delete.
    455     *
    456     * @throws Exception if the object can not be deleted
    457     */
    458    @Override
    459    public void delete(HObject obj) throws Exception {
    460        throw (new UnsupportedOperationException("Cannot delete HDF4 object."));
    461    }
    462
    463    /**
    464     * Copy an object to a group.
    465     *
    466     * @param srcObj
    467     *            the object to copy.
    468     * @param dstGroup
    469     *            the destination group.
    470     *
    471     * @return the destination group, if the copy was successful, or
    472     *            null otherwise.
    473     *
    474     * @throws Exception if the object can not be copied
    475     */
    476    @Override
    477    public HObject copy(HObject srcObj, Group dstGroup, String dstName)
    478            throws Exception {
    479        log.trace("copy(): start: srcObj={} dstGroup={} dstName={}", srcObj, dstGroup, dstName);
    480
    481        if ((srcObj == null) || (dstGroup == null)) {
    482            log.debug("copy(): source or destination is null");
    483            log.trace("copy(): finish");
    484            return null;
    485        }
    486
    487        if (dstName == null) {
    488            dstName = srcObj.getName();
    489            log.trace("copy(): dstName is null, using dstName={}", dstName);
    490        }
    491
    492        HObject newObj = null;
    493        if (srcObj instanceof H4SDS) {
    494            log.trace("copy(): srcObj instanceof H4SDS");
    495            newObj = ((H4SDS) srcObj).copy(dstGroup, dstName, null, null);
    496        }
    497        else if (srcObj instanceof H4GRImage) {
    498            log.trace("copy(): srcObj instanceof H4GRImage");
    499            newObj = ((H4GRImage) srcObj).copy(dstGroup, dstName, null, null);
    500        }
    501        else if (srcObj instanceof H4Vdata) {
    502            log.trace("copy(): srcObj instanceof H4Vdata");
    503            newObj = ((H4Vdata) srcObj).copy(dstGroup, dstName, null, null);
    504        }
    505        else if (srcObj instanceof H4Group) {
    506            log.trace("copy(): srcObj instanceof H4Group");
    507            newObj = copyGroup((H4Group) srcObj, (H4Group) dstGroup);
    508        }
    509
    510        log.trace("copy(): finish");
    511        return newObj;
    512    }
    513
    514    /**
    515     * Creates a new attribute and attaches it to the object if the
    516     * attribute does not exist. Otherwise, just update the value of
    517     * the attribute.
    518     *
    519     * @param obj
    520     *            the object which the attribute is to be attached to.
    521     * @param attr
    522     *            the attribute to attach.
    523     * @param isSDglobalAttr
    524     *            The indicator if the given attribute exists.
    525     *
    526     * @throws HDFException if the attribute can not be written
    527     */
    528    @Override
    529    public void writeAttribute(HObject obj, Attribute attr,
    530            boolean isSDglobalAttr) throws HDFException {
    531        log.trace("writeAttribute(): start: obj={} attribute={} isSDglobalAttr={}", obj, attr, isSDglobalAttr);
    532
    533        String attrName = attr.getName();
    534        long attrType = attr.getDatatype().createNative();
    535        long[] dims = attr.getDims();
    536        int count = 1;
    537        if (dims != null) {
    538            for (int i = 0; i < dims.length; i++) {
    539                count *= (int) dims[i];
    540            }
    541        }
    542
    543        log.trace("writeAttribute(): count={}", count);
    544
    545        Object attrValue;
    546        try {
    547            attrValue = attr.getData();
    548        } catch (Exception ex) {
    549            attrValue = null;
    550            log.trace("writeAttribute(): getData() failure:", ex);
    551        }
    552
    553        if (Array.get(attrValue, 0) instanceof String) {
    554            String strValue = (String) Array.get(attrValue, 0);
    555
    556            if (strValue.length() > count) {
    557                // truncate the extra characters
    558                strValue = strValue.substring(0, count);
    559                Array.set(attrValue, 0, strValue);
    560            }
    561            else {
    562                // pad space to the unused space
    563                for (int i = strValue.length(); i < count; i++) {
    564                    strValue += " ";
    565                }
    566            }
    567
    568            byte[] bval = strValue.getBytes();
    569            // add null to the end to get rid of the junks
    570            bval[(strValue.length() - 1)] = 0;
    571            attrValue = bval;
    572        }
    573
    574        if ((obj instanceof H4Group) && ((H4Group) obj).isRoot()) {
    575            if (isSDglobalAttr) {
    576                HDFLibrary.SDsetattr(sdid, attrName, attrType, count, attrValue);
    577            }
    578            else {
    579                HDFLibrary.GRsetattr(grid, attrName, attrType, count, attrValue);
    580            }
    581            log.trace("writeAttribute(): wrote attribute to root H4Group");
    582            log.trace("writeAttribute(): finish");
    583            return;
    584        }
    585
    586        long id = obj.open();
    587
    588        if (id >= 0) {
    589            if (obj instanceof H4Group) {
    590                HDFLibrary.Vsetattr(id, attrName, attrType, count, attrValue);
    591                log.trace("writeAttribute(): wrote attribute to H4Group");
    592            }
    593            else if (obj instanceof H4SDS) {
    594                HDFLibrary.SDsetattr(id, attrName, attrType, count, attrValue);
    595                log.trace("writeAttribute(): wrote attribute to H4SDS");
    596            }
    597            else if (obj instanceof H4GRImage) {
    598                HDFLibrary.GRsetattr(id, attrName, attrType, count, attrValue);
    599                log.trace("writeAttribute(): wrote attribute to H4GRImage");
    600            }
    601            else if (obj instanceof H4Vdata) {
    602                HDFLibrary.VSsetattr(id, -1, attrName, attrType, count, attrValue);
    603                log.trace("writeAttribute(): wrote attribute to H4Vdata");
    604            }
    605
    606            obj.close(id);
    607        }
    608
    609        log.trace("writeAttribute(): finish");
    610    }
    611
    612    private HObject copyGroup(H4Group srcGroup, H4Group pgroup)
    613            throws Exception {
    614        log.trace("copyGroup(): start: srcGroup={} parentGroup={}", srcGroup, pgroup);
    615
    616        H4Group group = null;
    617        long srcgid, dstgid;
    618        String gname = null, path = null;
    619
    620        dstgid = HDFLibrary.Vattach(fid, -1, "w");
    621        if (dstgid < 0) {
    622            log.trace("copyGroup(): Invalid dst Group Id");
    623            log.trace("copyGroup(): finish");
    624            return null;
    625        }
    626
    627        gname = srcGroup.getName();
    628        srcgid = srcGroup.open();
    629
    630        HDFLibrary.Vsetname(dstgid, gname);
    631        int ref = HDFLibrary.VQueryref(dstgid);
    632        int tag = HDFLibrary.VQuerytag(dstgid);
    633
    634        if (pgroup.isRoot()) {
    635            path = HObject.separator;
    636        }
    637        else {
    638            // add the dataset to the parent group
    639            path = pgroup.getPath() + pgroup.getName() + HObject.separator;
    640            long pid = pgroup.open();
    641            HDFLibrary.Vinsert(pid, dstgid);
    642            pgroup.close(pid);
    643        }
    644
    645        // copy attributes
    646        int numberOfAttributes = 0;
    647        try {
    648            numberOfAttributes = HDFLibrary.Vnattrs(srcgid);
    649        }
    650        catch (Exception ex) {
    651            log.debug("copyGroup(): Vnattrs failure: ", ex);
    652            numberOfAttributes = 0;
    653        }
    654
    655        String[] attrName = new String[1];
    656        byte[] attrBuff = null;
    657        int[] attrInfo = new int[3]; // data_type, count, size
    658        for (int i = 0; i < numberOfAttributes; i++) {
    659            try {
    660                attrName[0] = "";
    661                HDFLibrary.Vattrinfo(srcgid, i, attrName, attrInfo);
    662                attrBuff = new byte[attrInfo[2]];
    663                HDFLibrary.Vgetattr(srcgid, i, attrBuff);
    664                HDFLibrary.Vsetattr(dstgid, attrName[0], attrInfo[0],
    665                        attrInfo[2], attrBuff);
    666            }
    667            catch (Exception ex) {
    668                log.trace("copyGroup(): failure: ", ex);
    669                continue;
    670            }
    671        }
    672
    673        long[] oid = { tag, ref };
    674        group = new H4Group(this, gname, path, pgroup, oid);
    675
    676        pgroup.addToMemberList(group);
    677
    678        // copy members of the source group to the new group
    679        List<HObject> members = srcGroup.getMemberList();
    680        if ((members != null) && (members.size() > 0)) {
    681            Iterator<HObject> iterator = members.iterator();
    682            while (iterator.hasNext()) {
    683                HObject mObj = iterator.next();
    684                try {
    685                    copy(mObj, group, mObj.getName());
    686                }
    687                catch (Exception ex) {
    688                    log.debug("copy(): failure: ", ex);
    689                }
    690            }
    691        }
    692
    693        srcGroup.close(srcgid);
    694
    695        if (dstgid >= 0) {
    696            try {
    697                HDFLibrary.Vdetach(dstgid);
    698            }
    699            catch (Exception ex) {
    700                log.debug("copyGroup(): Vdetach failure: ", ex);
    701            }
    702        }
    703
    704        log.trace("copyGroup(): finish");
    705        return group;
    706    }
    707
    708    /**
    709     * Retrieves the file structure from disk and returns the root object.
    710     * <p>
    711     * First gets the top level objects or objects that do not belong to any
    712     * groups. If a top level object is a group, call the depth_first() to
    713     * retrieve the sub-tree of that group, recursively.
    714     */
    715    private void loadIntoMemory() {
    716        log.trace("loadIntoMemory(): start");
    717
    718        if (fid < 0) {
    719            log.debug("loadIntoMemory(): Invalid File Id");
    720            log.trace("loadIntoMemory(): finish");
    721            return;
    722        }
    723
    724        int n = 0, ref = -1;
    725        int[] argv = null;
    726
    727        // get top level VGroup
    728        int[] tmpN = new int[1];
    729        int[] refs = null;
    730
    731        try {
    732            // first call to get the number of lone Vgroups
    733            log.trace("loadIntoMemory(): first call to Vlone: get number of lone Vgroups");
    734            n = HDFLibrary.Vlone(fid, tmpN, 0);
    735            log.trace("loadIntoMemory(): number of lone Vgroups={}", n);
    736            refs = new int[n];
    737
    738            // second call to get the references of all lone Vgroups
    739            log.trace("loadIntoMemory(): second call to Vlone: get references of lone Vgroups");
    740            n = HDFLibrary.Vlone(fid, refs, n);
    741        }
    742        catch (HDFException ex) {
    743            log.trace("loadIntoMemory(): get Vlone failure: ", ex);
    744            n = 0;
    745        }
    746
    747        /*
    748         * TODO: Root group's name should be changed to 'this.getName()' and all
    749         * previous accesses of this field should now use getPath() instead of getName()
    750         * to get the root group. The root group actually does have a path of "/". The
    751         * depth_first method will have to be changed to setup other object paths
    752         * appropriately, as it currently assumes the root path to be null.
    753         */
    754        long[] oid = { 0, 0 };
    755        rootObject = new H4Group(this, "/",
    756                null, // root object does not have a parent path
    757                null, // root object does not have a parent object
    758                oid);
    759
    760        int i0 = Math.max(0, getStartMembers());
    761        int i1 = getMaxMembers();
    762        if (i1 >= n) {
    763            i1 = n;
    764            i0 = 0; // load all members
    765        }
    766        i1 += i0;
    767        i1 = Math.min(i1, n);
    768
    769        // Iterate through the file to see members of the group
    770        log.trace("loadIntoMemory(): start={} to last={}", i0, i1);
    771        for (int i = i0; i < i1; i++) {
    772            ref = refs[i];
    773            log.trace("loadIntoMemory(): Iterate[{}] members of the group ref={}",i,ref);
    774            H4Group g = getVGroup(HDFConstants.DFTAG_VG, ref,
    775                    HObject.separator, (H4Group) rootObject, false);
    776
    777            if (g != null) {
    778                ((H4Group) rootObject).addToMemberList(g);
    779
    780                // recursively get the sub-tree
    781                depth_first(g);
    782            }
    783        } // for (int i=0; i<n; i++)
    784
    785        // get the top level GR images
    786        argv = new int[2];
    787        boolean b = false;
    788        try {
    789            b = HDFLibrary.GRfileinfo(grid, argv);
    790        }
    791        catch (HDFException ex) {
    792            log.debug("loadIntoMemory(): GRfileinfo failure: ",ex);
    793            b = false;
    794        }
    795
    796        if (b) {
    797            n = argv[0];
    798
    799            for (int i = 0; i < n; i++) {
    800                // no duplicate object at top level
    801                H4GRImage gr = getGRImage(HDFConstants.DFTAG_RIG, i,
    802                        HObject.separator, false);
    803                if (gr != null) {
    804                    ((H4Group) rootObject).addToMemberList(gr);
    805                }
    806            } // for (int i=0; i<n; i++)
    807        } // if ( grid!=HDFConstants.FAIL && HDFLibrary.GRfileinfo(grid,argv) )
    808
    809        // get top level SDS
    810        try {
    811            b = HDFLibrary.SDfileinfo(sdid, argv);
    812        }
    813        catch (HDFException ex) {
    814            log.debug("loadIntoMemory(): SDfileinfo failure: ",ex);
    815            b = false;
    816        }
    817
    818        if (b) {
    819            n = argv[0];
    820            for (int i = 0; i < n; i++) {
    821                // no duplicate object at top level
    822                H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, i,
    823                        HObject.separator, false);
    824                if (sds != null) {
    825                    ((H4Group) rootObject).addToMemberList(sds);
    826                }
    827            } // for (int i=0; i<n; i++)
    828        } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv))
    829
    830        // get top level VData
    831        try {
    832            n = HDFLibrary.VSlone(fid, tmpN, 0);
    833            log.trace("loadIntoMemory(): number of lone Vdatas={}", n);
    834            refs = new int[n];
    835            n = HDFLibrary.VSlone(fid, refs, n);
    836        }
    837        catch (HDFException ex) {
    838            log.debug("loadIntoMemory(): VSlone failure: ",ex);
    839            n = 0;
    840        }
    841
    842        for (int i = 0; i < n; i++) {
    843            ref = refs[i];
    844            log.trace("loadIntoMemory(): references of Vdata[{}]={}", i, ref);
    845
    846            // no duplicate object at top level
    847            H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref,
    848                    HObject.separator, false);
    849
    850            if (vdata != null) {
    851                ((H4Group) rootObject).addToMemberList(vdata);
    852            }
    853        } // for (int i=0; i<n; i++)
    854
    855        if (rootObject != null) {
    856            // retrieve file annotation, GR and SDS global attributes
    857            @SuppressWarnings("rawtypes")
    858            List attributeList = null;
    859            try {
    860                attributeList = ((H4Group) rootObject).getMetadata();
    861            }
    862            catch (HDFException ex) {
    863                log.debug("loadIntoMemory(): getMetadata failure: ", ex);
    864            }
    865
    866            try {
    867                getFileAnnotation(fid, attributeList);
    868            }
    869            catch (HDFException ex) {
    870                log.debug("loadIntoMemory(): getFileAnnotation failure: ", ex);
    871            }
    872            try {
    873                getGRglobalAttribute(grid, attributeList);
    874            }
    875            catch (HDFException ex) {
    876                log.debug("loadIntoMemory(): getGRglobalAttribute failure: ", ex);
    877            }
    878            try {
    879                getSDSglobalAttribute(sdid, attributeList);
    880            }
    881            catch (HDFException ex) {
    882                log.debug("loadIntoMemory(): getSDglobalAttribute failure: ", ex);
    883            }
    884        }
    885
    886        log.trace("loadIntoMemory(): finish");
    887    }
    888
    889    /**
    890     * Retrieves the tree structure of the file by depth-first order. The
    891     * current implementation only retrieves groups and datasets. It does not
    892     * include named datatypes and soft links.
    893     *
    894     * @param parentObject
    895     *            the parent object.
    896     */
    897    private void depth_first(HObject parentObj) {
    898        log.trace("depth_first(pobj = {})", parentObj);
    899
    900        if (parentObj == null) {
    901            log.debug("depth_first(): Parent object is null");
    902            log.trace("depth_first(): finish");
    903            return;
    904        }
    905
    906        int nelems = 0, ref = -1, tag = -1, index = -1;
    907        int[] tags = null;
    908        int[] refs = null;
    909
    910        H4Group parentGroup = (H4Group) parentObj;
    911
    912        String fullPath = parentGroup.getPath() + parentGroup.getName() + HObject.separator;
    913        long gid = parentGroup.open();
    914        if (gid == HDFConstants.FAIL) {
    915            log.debug("depth_first(): Invalid Parent group ID");
    916            log.trace("depth_first(): finish");
    917            return;
    918        }
    919
    920        try {
    921            nelems = HDFLibrary.Vntagrefs(gid);
    922            tags = new int[nelems];
    923            refs = new int[nelems];
    924            nelems = HDFLibrary.Vgettagrefs(gid, tags, refs, nelems);
    925        }
    926        catch (HDFException ex) {
    927            log.debug("depth_first(): failure: ", ex);
    928            nelems = 0;
    929        }
    930        finally {
    931            parentGroup.close(gid);
    932        }
    933
    934        int i0 = Math.max(0, getStartMembers());
    935        int i1 = getMaxMembers();
    936        if (i1 >= nelems) {
    937            i1 = nelems;
    938            i0 = 0; // load all members
    939        }
    940        i1 += i0;
    941        i1 = Math.min(i1, nelems);
    942
    943        // Iterate through the file to see members of the group
    944        for (int i = i0; i < i1; i++) {
    945            tag = tags[i];
    946            ref = refs[i];
    947
    948            switch (tag) {
    949                case HDFConstants.DFTAG_RIG:
    950                case HDFConstants.DFTAG_RI:
    951                case HDFConstants.DFTAG_RI8:
    952                    try {
    953                        index = HDFLibrary.GRreftoindex(grid, (short) ref);
    954                    }
    955                    catch (HDFException ex) {
    956                        index = HDFConstants.FAIL;
    957                    }
    958                    if (index != HDFConstants.FAIL) {
    959                        H4GRImage gr = getGRImage(tag, index, fullPath, true);
    960                        parentGroup.addToMemberList(gr);
    961                    }
    962                    break;
    963                case HDFConstants.DFTAG_SD:
    964                case HDFConstants.DFTAG_SDG:
    965                case HDFConstants.DFTAG_NDG:
    966                    try {
    967                        index = HDFLibrary.SDreftoindex(sdid, ref);
    968                    }
    969                    catch (HDFException ex) {
    970                        index = HDFConstants.FAIL;
    971                    }
    972                    if (index != HDFConstants.FAIL) {
    973                        H4SDS sds = getSDS(tag, index, fullPath, true);
    974                        parentGroup.addToMemberList(sds);
    975                    }
    976                    break;
    977                case HDFConstants.DFTAG_VH:
    978                case HDFConstants.DFTAG_VS:
    979                    H4Vdata vdata = getVdata(tag, ref, fullPath, true);
    980                    parentGroup.addToMemberList(vdata);
    981                    break;
    982                case HDFConstants.DFTAG_VG:
    983                    H4Group vgroup = getVGroup(tag, ref, fullPath, parentGroup, true);
    984                    parentGroup.addToMemberList(vgroup);
    985                    if ((vgroup != null) && (parentGroup != null)) {
    986                        // check for loops
    987                        boolean looped = false;
    988                        H4Group theGroup = parentGroup;
    989                        while ((theGroup != null) && !looped) {
    990                            long[] oid = { tag, ref };
    991                            if (theGroup.equalsOID(oid)) {
    992                                looped = true;
    993                            }
    994                            else {
    995                                theGroup = (H4Group) theGroup.getParent();
    996                            }
    997                        }
    998                        if (!looped) {
    999                            depth_first(vgroup);
    1000                        }
    1001                    }
    1002                    break;
    1003                default:
    1004                    break;
    1005            } // switch (tag)
    1006
    1007        } // for (int i=0; i<nelms; i++)
    1008
    1009        log.trace("depth_first(): finish");
    1010    } // private depth_first()
    1011
    1012    /**
    1013     * Returns a list of all the members of this H4File in a
    1014     * breadth-first ordering that are rooted at the specified
    1015     * object.
    1016     */
    1017    private static List<HObject> getMembersBreadthFirst(HObject obj) {
    1018        List<HObject> allMembers = new Vector<>();
    1019        Queue<HObject> queue = new LinkedList<>();
    1020        HObject currentObject = obj;
    1021
    1022        queue.add(currentObject);
    1023
    1024        while(!queue.isEmpty()) {
    1025            currentObject = queue.remove();
    1026            allMembers.add(currentObject);
    1027
    1028            if(currentObject instanceof Group) {
    1029                queue.addAll(((Group) currentObject).getMemberList());
    1030            } else {
    1031                continue;
    1032            }
    1033        }
    1034
    1035        return allMembers;
    1036    }
    1037
    1038    /**
    1039     * Retrieve a GR image for the given GR image identifier and index.
    1040     *
    1041     * @param tag
    1042     *            the reference tag of the GR image.
    1043     * @param index
    1044     *            the index of the image.
    1045     * @param path
    1046     *            the path of the image.
    1047     * @param copyAllowed
    1048     *            The indicator if multiple copies of an object is allowed.
    1049     *
    1050     * @return the new H5GRImage if successful; otherwise returns null.
    1051     */
    1052    @SuppressWarnings("unchecked")
    1053    private final H4GRImage getGRImage(int tag, int index, String path,
    1054            boolean copyAllowed) {
    1055        log.trace("getGRImage(): start: tag={} index={} path={} copyAllowed={}", tag, index, path, copyAllowed);
    1056
    1057        long id = -1;
    1058        int ref = -1;
    1059        H4GRImage gr = null;
    1060        String[] objName = { "" };
    1061        int[] imgInfo = new int[4];
    1062        int[] dim_sizes = { 0, 0 };
    1063        // int tag = HDFConstants.DFTAG_RIG;
    1064
    1065        try {
    1066            id = HDFLibrary.GRselect(grid, index);
    1067            ref = HDFLibrary.GRidtoref(id);
    1068            log.trace("getGRImage(): GRselect:{} GRidtoref:{}",id,ref);
    1069            HDFLibrary.GRgetiminfo(id, objName, imgInfo, dim_sizes);
    1070        }
    1071        catch (HDFException ex) {
    1072            log.debug("getGRImage(): failure: ", ex);
    1073            id = HDFConstants.FAIL;
    1074        }
    1075        finally {
    1076            if (id >= 0) {
    1077                try {
    1078                    HDFLibrary.GRendaccess(id);
    1079                }
    1080                catch (HDFException ex) {
    1081                    log.debug("getGRImage(): GRendaccess failure: ", ex);
    1082                }
    1083            }
    1084        }
    1085
    1086        if (id != HDFConstants.FAIL) {
    1087            long oid[] = { tag, ref };
    1088
    1089            if (copyAllowed) {
    1090                objList.add(oid);
    1091            }
    1092            else if (find(oid)) {
    1093                log.trace("getGRImage(): Image found in memory with OID:({}, {})", oid[0], oid[1]);
    1094                log.trace("getGRImage(): finish");
    1095                return null;
    1096            }
    1097
    1098            gr = new H4GRImage(this, objName[0], path, oid);
    1099        }
    1100
    1101        log.trace("getGRImage(): finish");
    1102        return gr;
    1103    }
    1104
    1105    /**
    1106     * Retrieve a SDS for the given sds identifier and index.
    1107     *
    1108     * @param tag
    1109     *            the reference tag of the group (DFTAG_SD, DFTAG_SDG, DFTAG_NDG).
    1110     * @param index
    1111     *            the index of the SDS.
    1112     * @param path
    1113     *            the path of the SDS.
    1114     * @param copyAllowed
    1115     *            The indicator if multiple copies of an object is allowed.
    1116     *
    1117     * @return the new H4SDS if successful; otherwise returns null.
    1118     */
    1119    @SuppressWarnings("unchecked")
    1120    private final H4SDS getSDS(int tag, int index, String path,
    1121            boolean copyAllowed) {
    1122        log.trace("getSDS(): start: tag={} index={} path={} copyAllowed={}", tag, index, path, copyAllowed);
    1123
    1124        long id = -1;
    1125        int ref = -1;
    1126        H4SDS sds = null;
    1127        String[] objName = { "" };
    1128        int[] tmpInfo = new int[HDFConstants.MAX_VAR_DIMS];
    1129        int[] sdInfo = { 0, 0, 0 };
    1130        // int tag = HDFConstants.DFTAG_NDG;
    1131
    1132        boolean isCoordvar = false;
    1133        try {
    1134            id = HDFLibrary.SDselect(sdid, index);
    1135            if (isNetCDF) {
    1136                ref = index; // HDFLibrary.SDidtoref(id) fails for netCDF
    1137                tag = H4SDS.DFTAG_NDG_NETCDF;
    1138            }
    1139            else {
    1140                ref = HDFLibrary.SDidtoref(id);
    1141            }
    1142            log.trace("getSDS(): SDselect id={} with ref={} isNetCDF={}", id, ref, isNetCDF);
    1143
    1144            HDFLibrary.SDgetinfo(id, objName, tmpInfo, sdInfo);
    1145            log.trace("getSDS(): SDselect id={} with objName={}: rank={}, numberType={}, nAttributes={}", id, objName, sdInfo[0], sdInfo[1], sdInfo[2]);
    1146
    1147            try {
    1148                isCoordvar = HDFLibrary.SDiscoordvar(id);
    1149            }
    1150            catch (Exception ex) {
    1151                log.debug("getSDS(): SDiscoordvar failure: ", ex);
    1152                isCoordvar = false;
    1153            }
    1154        }
    1155        catch (HDFException ex) {
    1156            log.debug("getSDS(): failure: ", ex);
    1157            id = HDFConstants.FAIL;
    1158        }
    1159        finally {
    1160            if (id >= 0) {
    1161                try {
    1162                    HDFLibrary.SDendaccess(id);
    1163                }
    1164                catch (HDFException ex) {
    1165                    log.debug("getSDS(): SDendaccess failure: ", ex);
    1166                }
    1167            }
    1168        }
    1169
    1170        // check if the given SDS has dimension metadata
    1171        // Coordinate variables are not displayed. They are created to store
    1172        // metadata associated with dimensions. To ensure compatibility with
    1173        // netCDF, coordinate variables are implemented as data sets
    1174
    1175        if (isCoordvar) {
    1176            objName[0] += " (dimension)";
    1177        }
    1178
    1179        if (id != HDFConstants.FAIL) { // && !isCoordvar)
    1180            long oid[] = { tag, ref };
    1181
    1182            if (copyAllowed) {
    1183                objList.add(oid);
    1184            }
    1185            else if (find(oid)) {
    1186                log.trace("getSDS(): SDS found in memory with OID:({}, {})", oid[0], oid[1]);
    1187                log.trace("getSDS(): finish");
    1188                return null;
    1189            }
    1190
    1191            sds = new H4SDS(this, objName[0], path, oid);
    1192        }
    1193
    1194        log.trace("getSDS(): finish");
    1195        return sds;
    1196    }
    1197
    1198    /**
    1199     * Retrieve a Vdata for the given Vdata identifier and index.
    1200     *
    1201     * @param tag
    1202     *            the reference tag of the Vdata.
    1203     * @param ref
    1204     *            the reference identifier of the Vdata.
    1205     * @param path
    1206     *            the path of the Vdata.
    1207     * @param copyAllowed
    1208     *            The indicator if multiple copies of an object is allowed.
    1209     *
    1210     * @return the new H4Vdata if successful; otherwise returns null.
    1211     */
    1212    @SuppressWarnings("unchecked")
    1213    private final H4Vdata getVdata(int tag, int ref, String path,
    1214            boolean copyAllowed) {
    1215        log.trace("getVdata(): start: tag={} ref={} path={} copyAllowed={}", tag, ref, path, copyAllowed);
    1216
    1217        long id = -1;
    1218        H4Vdata vdata = null;
    1219        String[] objName = { "" };
    1220        String[] vClass = { "" };
    1221        // int tag = HDFConstants.DFTAG_VS;
    1222        long oid[] = { tag, ref };
    1223
    1224        if (copyAllowed) {
    1225            objList.add(oid);
    1226        }
    1227        else if (find(oid)) {
    1228            log.trace("getVdata(): VData found in memory with OID:({}, {})", oid[0], oid[1]);
    1229            log.trace("getVdata(): finish");
    1230            return null;
    1231        }
    1232
    1233        try {
    1234            id = HDFLibrary.VSattach(fid, ref, "r");
    1235            HDFLibrary.VSgetclass(id, vClass);
    1236            vClass[0] = vClass[0].trim();
    1237            HDFLibrary.VSgetname(id, objName);
    1238        }
    1239        catch (HDFException ex) {
    1240            log.trace("getVData(): failure: ", ex);
    1241            id = HDFConstants.FAIL;
    1242        }
    1243        finally {
    1244            if (id >= 0) {
    1245                try {
    1246                    HDFLibrary.VSdetach(id);
    1247                }
    1248                catch (HDFException ex) {
    1249                    log.debug("getVData(): VSdetach failure: ", ex);
    1250                }
    1251            }
    1252        }
    1253
    1254        if (showAll ||
    1255                ((id != HDFConstants.FAIL)
    1256                        && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_ATTRIBUTE) // do not display Vdata named "Attr0.0" // commented out for bug 1737
    1257                        && !vClass[0].startsWith(HDFConstants.HDF_CHK_TBL)         // do not display internal Vdata, "_HDF_CHK_TBL_"
    1258                        && !vClass[0].startsWith(HDFConstants.HDF_SDSVAR)          // do not display attributes
    1259                        && !vClass[0].startsWith(HDFConstants.HDF_CRDVAR)
    1260                        && !vClass[0].startsWith(HDFConstants.DIM_VALS)
    1261                        && !vClass[0].startsWith(HDFConstants.DIM_VALS01)
    1262                        && !vClass[0].startsWith(HDFConstants.RIGATTRCLASS)
    1263                        && !vClass[0].startsWith(HDFConstants.RIGATTRNAME)
    1264                        && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_CDF)))     // do not display internal vdata for CDF, "CDF0.0"
    1265        {
    1266            vdata = new H4Vdata(this, objName[0], path, oid);
    1267        }
    1268
    1269        log.trace("getVdata(): finish");
    1270        return vdata;
    1271    }
    1272
    1273    /**
    1274     * Retrieve a VGroup for the given VGroup identifier and index.
    1275     *
    1276     * @param tag
    1277     *            the reference tag of the VGroup.
    1278     * @param ref
    1279     *            the reference identifier of the VGroup.
    1280     * @param path
    1281     *            the path of the VGroup.
    1282     * @param pgroup
    1283     *            the parent group.
    1284     * @param copyAllowed
    1285     *            The indicator if multiple copies of an object is allowed.
    1286     *
    1287     * @return the new H4VGroup if successful; otherwise returns null.
    1288     */
    1289    @SuppressWarnings("unchecked")
    1290    private final H4Group getVGroup(int tag, int ref, String path,
    1291            H4Group pgroup, boolean copyAllowed) {
    1292        log.trace("getVGroup(): start: tag={}, ref={} path={} pgroup={} copyAllowed={}", tag, ref, path, pgroup, copyAllowed);
    1293
    1294        long id = -1;
    1295        H4Group vgroup = null;
    1296        String[] objName = { "" };
    1297        String[] vClass = { "" };
    1298        // int tag = HDFConstants.DFTAG_VG;
    1299        long oid[] = { tag, ref };
    1300
    1301        if (ref <= 0) {
    1302            log.trace("getVGroup(): Skipping dummy root group with ref={}", ref);
    1303            log.trace("getVGroup(): finish");
    1304            return null;
    1305        }
    1306
    1307        if (copyAllowed) {
    1308            objList.add(oid);
    1309        }
    1310        else if (find(oid)) {
    1311            log.trace("getVGroup(): VGroup found in memory with OID:({}, {})", oid[0], oid[1]);
    1312            log.trace("getVGroup(): finish");
    1313            return null;
    1314        }
    1315
    1316        try {
    1317            id = HDFLibrary.Vattach(fid, ref, "r");
    1318            log.trace("getVGroup(): Vattach fid={} id={}", fid, id);
    1319            HDFLibrary.Vgetclass(id, vClass);
    1320            vClass[0] = vClass[0].trim();
    1321            HDFLibrary.Vgetname(id, objName);
    1322        }
    1323        catch (HDFException ex) {
    1324            log.debug("getVGroup(): failure: ",ex);
    1325            id = HDFConstants.FAIL;
    1326        }
    1327        finally {
    1328            if (id >= 0) {
    1329                try {
    1330                    HDFLibrary.Vdetach(id);
    1331                }
    1332                catch (HDFException ex) {
    1333                    log.debug("getVGroup(): Vdetach failure: ", ex);
    1334                }
    1335            }
    1336        }
    1337
    1338        // ignore the Vgroups created by the GR interface
    1339        if (showAll || ((id != HDFConstants.FAIL)
    1340                && !vClass[0].equalsIgnoreCase(HDFConstants.GR_NAME) // do not display Vdata named "Attr0.0"
    1341                && !vClass[0].equalsIgnoreCase(HDFConstants.RI_NAME)
    1342                && !vClass[0].equalsIgnoreCase(HDFConstants.RIGATTRNAME)
    1343                && !vClass[0].equalsIgnoreCase(HDFConstants.RIGATTRCLASS)
    1344                && !vClass[0].equalsIgnoreCase(HDFConstants.HDF_CDF)))
    1345        {
    1346            vgroup = new H4Group(this, objName[0], path, pgroup, oid);
    1347        }
    1348
    1349        log.trace("getVGroup(): finish");
    1350        return vgroup;
    1351    }
    1352
    1353    /**
    1354     * Check if object already exists in memory by matching the (tag, ref) pairs.
    1355     */
    1356    @SuppressWarnings("unchecked")
    1357    private final boolean find(long[] oid) {
    1358        log.trace("find(): start: oid({}, {})", oid[0], oid[1]);
    1359
    1360        boolean existed = false;
    1361
    1362        if (objList == null) {
    1363            log.debug("find(): objList is null");
    1364            log.trace("find(): finish");
    1365            return false;
    1366        }
    1367
    1368        int n = objList.size();
    1369        long[] theOID = null;
    1370
    1371        for (int i = 0; i < n; i++) {
    1372            theOID = (long[]) objList.get(i);
    1373            if ((theOID[0] == oid[0]) && (theOID[1] == oid[1])) {
    1374                log.trace("find(): matched object in objList");
    1375                existed = true;
    1376                break;
    1377            }
    1378        }
    1379
    1380        if (!existed) {
    1381            objList.add(oid);
    1382        }
    1383
    1384        log.trace("find(): finish");
    1385        return existed;
    1386    }
    1387
    1388    /**
    1389     * Returns the GR identifier, which is returned from GRstart(fid).
    1390     *
    1391     * @return the identifier.
    1392     */
    1393    long getGRAccessID() {
    1394        return grid;
    1395    }
    1396
    1397    /**
    1398     * Returns the SDS identifier, which is returned from SDstart(fname, flag).
    1399     *
    1400     * @return the identifier.
    1401     */
    1402    long getSDAccessID() {
    1403        return sdid;
    1404    }
    1405
    1406    /**
    1407     * Reads HDF file annotation (file labels and descriptions) into memory.
    1408     * The file annotation is stored as an attribute of the root group.
    1409     *
    1410     * @param fid
    1411     *            the file identifier.
    1412     * @param attrList
    1413     *            the list of attributes.
    1414     *
    1415     * @return the updated attribute list.
    1416     *
    1417     * @throws Exception if the annotation can not be read
    1418     */
    1419    @SuppressWarnings({"rawtypes", "unchecked"})
    1420    private List getFileAnnotation(long fid, List attrList) throws HDFException {
    1421        log.trace("getFileAnnotation(): start: FID={}", fid);
    1422
    1423        if (fid < 0) {
    1424            log.debug("getFileAnnotation(): Invalid FID");
    1425            log.trace("getFileAnnotation(): finish");
    1426            return attrList;
    1427        }
    1428
    1429        long anid = HDFConstants.FAIL;
    1430        try {
    1431            anid = HDFLibrary.ANstart(fid);
    1432            // fileInfo[0] = n_file_label, fileInfo[1] = n_file_desc,
    1433            // fileInfo[2] = n_data_label, fileInfo[3] = n_data_desc
    1434            int[] fileInfo = new int[4];
    1435            HDFLibrary.ANfileinfo(anid, fileInfo);
    1436
    1437            if (fileInfo[0] + fileInfo[1] <= 0) {
    1438                try {
    1439                    HDFLibrary.ANend(anid);
    1440                }
    1441                catch (HDFException ex) {
    1442                    log.debug("getFileAnnotation(): ANend failure: ", ex);
    1443                }
    1444
    1445                log.debug("getFileAnnotation(): n_file_labels + n_file_descriptions <= 0");
    1446                log.trace("getFileAnnotation(): finish");
    1447                return attrList;
    1448            }
    1449
    1450            if (attrList == null) {
    1451                attrList = new Vector(fileInfo[0] + fileInfo[1], 5);
    1452            }
    1453
    1454            // load file labels and descriptions
    1455            long id = -1;
    1456            int[] annTypes = { HDFConstants.AN_FILE_LABEL,
    1457                    HDFConstants.AN_FILE_DESC };
    1458            for (int j = 0; j < 2; j++) {
    1459                String annName = null;
    1460                if (j == 0) {
    1461                    annName = "File Label";
    1462                }
    1463                else {
    1464                    annName = "File Description";
    1465                }
    1466
    1467                for (int i = 0; i < fileInfo[j]; i++) {
    1468                    try {
    1469                        id = HDFLibrary.ANselect(anid, i, annTypes[j]);
    1470                    }
    1471                    catch (HDFException ex) {
    1472                        log.debug("getFileAnnotation(): ANselect failure: ", ex);
    1473                        id = HDFConstants.FAIL;
    1474                    }
    1475
    1476                    if (id == HDFConstants.FAIL) {
    1477                        log.trace("getFileAnnotation(): ANselect({}, {}, {}) failure", anid, i, annTypes[j]);
    1478                        try {
    1479                            HDFLibrary.ANendaccess(id);
    1480                        }
    1481                        catch (HDFException ex) {
    1482                            log.debug("getFileAnnotation(): ANendaccess failure: ", ex);
    1483                        }
    1484                        continue;
    1485                    }
    1486
    1487                    int length = 0;
    1488                    try {
    1489                        length = HDFLibrary.ANannlen(id) + 1;
    1490                    }
    1491                    catch (HDFException ex) {
    1492                        log.debug("getFileAnnotation(): ANannlen failure: ", ex);
    1493                        length = 0;
    1494                    }
    1495
    1496                    if (length > 0) {
    1497                        boolean b = false;
    1498                        String str[] = { "" };
    1499                        try {
    1500                            b = HDFLibrary.ANreadann(id, str, length);
    1501                        }
    1502                        catch (HDFException ex) {
    1503                            log.debug("getFileAnnotation(): ANreadann failure: ", ex);
    1504                            b = false;
    1505                        }
    1506
    1507                        if (b && (str[0].length() > 0)) {
    1508                            long attrDims[] = { str[0].length() };
    1509                            Attribute newAttr = new Attribute(getRootObject(), annName + " #" + i,
    1510                                    new H4Datatype(HDFConstants.DFNT_CHAR), attrDims);
    1511                            attrList.add(newAttr);
    1512                            newAttr.setData(str[0]);
    1513                        }
    1514                    }
    1515
    1516                    try {
    1517                        HDFLibrary.ANendaccess(id);
    1518                    }
    1519                    catch (HDFException ex) {
    1520                        log.debug("getFileAnnotation(): ANendaccess failure: ", ex);
    1521                    }
    1522                } // for (int i=0; i < fileInfo[annTYpe]; i++)
    1523            } // for (int annType=0; annType<2; annType++)
    1524        }
    1525        finally {
    1526            if (anid >= 0) {
    1527                try {
    1528                    HDFLibrary.ANend(anid);
    1529                }
    1530                catch (HDFException ex) {
    1531                    log.debug("getFileAnnotation(): ANend failure: ", ex);
    1532                }
    1533            }
    1534        }
    1535
    1536        log.trace("getFileAnnotation(): finish");
    1537        return attrList;
    1538    }
    1539
    1540    /**
    1541     * Reads GR global attributes into memory. The attributes are stored as
    1542     * attributes of the root group.
    1543     *
    1544     * @param grid
    1545     *            the GR identifier.
    1546     * @param attrList
    1547     *            the list of attributes.
    1548     *
    1549     * @return the updated attribute list.
    1550     *
    1551     * @throws HDFException if the GR attributes can not be read
    1552     */
    1553    @SuppressWarnings({"rawtypes", "unchecked"})
    1554    private List getGRglobalAttribute(long grid, List attrList)
    1555            throws HDFException {
    1556        log.trace("getGRglobalAttribute(): start: GRID={}", grid);
    1557
    1558        if (grid == HDFConstants.FAIL) {
    1559            log.debug("getGRglobalAttribute(): Invalid GRID");
    1560            log.trace("getGRglobalAttribute(): finish");
    1561            return attrList;
    1562        }
    1563
    1564        int[] attrInfo = { 0, 0 };
    1565        HDFLibrary.GRfileinfo(grid, attrInfo);
    1566        int numberOfAttributes = attrInfo[1];
    1567
    1568        if (numberOfAttributes > 0) {
    1569            if (attrList == null) {
    1570                attrList = new Vector(numberOfAttributes, 5);
    1571            }
    1572
    1573            String[] attrName = new String[1];
    1574            for (int i = 0; i < numberOfAttributes; i++) {
    1575                attrName[0] = "";
    1576                boolean b = false;
    1577                try {
    1578                    b = HDFLibrary.GRattrinfo(grid, i, attrName, attrInfo);
    1579                    // mask off the litend bit
    1580                    attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND);
    1581                }
    1582                catch (HDFException ex) {
    1583                    log.debug("getGRglobalAttribute(): GRattrinfo failure: ", ex);
    1584                    b = false;
    1585                }
    1586
    1587                if (!b) {
    1588                    continue;
    1589                }
    1590
    1591                long[] attrDims = { attrInfo[1] };
    1592                Attribute attr = new Attribute(getRootObject(), attrName[0], new H4Datatype(attrInfo[0]), attrDims);
    1593                attrList.add(attr);
    1594
    1595                Object buf = null;
    1596                try {
    1597                    buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]);
    1598                }
    1599                catch (OutOfMemoryError e) {
    1600                    log.debug("getGRglobalAttribute(): out of memory: ", e);
    1601                    buf = null;
    1602                }
    1603
    1604                try {
    1605                    HDFLibrary.GRgetattr(grid, i, buf);
    1606                }
    1607                catch (HDFException ex) {
    1608                    log.debug("getGRglobalAttribute(): GRgetattr failure: ", ex);
    1609                    buf = null;
    1610                }
    1611
    1612                if (buf != null) {
    1613                    if ((attrInfo[0] == HDFConstants.DFNT_CHAR)
    1614                            || (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) {
    1615                        buf = Dataset.byteToString((byte[]) buf, attrInfo[1]);
    1616                    }
    1617
    1618                    attr.setData(buf);
    1619                }
    1620
    1621            } // for (int i=0; i<numberOfAttributes; i++)
    1622        } // if (b && numberOfAttributes>0)
    1623
    1624        log.trace("getGRglobalAttribute(): finish");
    1625        return attrList;
    1626    }
    1627
    1628    /**
    1629     * Reads SDS global attributes into memory. The attributes are stored as
    1630     * attributes of the root group.
    1631     *
    1632     * @param sdid
    1633     *            the SD identifier.
    1634     * @param attrList
    1635     *            the list of attributes.
    1636     *
    1637     * @return the updated attribute list.
    1638     *
    1639     * @throws HDFException if the SDS attributes can not be read
    1640     */
    1641    @SuppressWarnings({"rawtypes", "unchecked"})
    1642    private List getSDSglobalAttribute(long sdid, List attrList)
    1643            throws HDFException {
    1644        log.trace("getSDSglobalAttribute(): start: SDID:{}", sdid);
    1645
    1646        if (sdid == HDFConstants.FAIL) {
    1647            log.debug("getSDSglobalAttribute(): Invalid SDID");
    1648            log.trace("getSDSglobalAttribute(): finish");
    1649            return attrList;
    1650        }
    1651
    1652        int[] attrInfo = { 0, 0 };
    1653        HDFLibrary.SDfileinfo(sdid, attrInfo);
    1654
    1655        int numberOfAttributes = attrInfo[1];
    1656        if (numberOfAttributes > 0) {
    1657            if (attrList == null) {
    1658                attrList = new Vector(numberOfAttributes, 5);
    1659            }
    1660
    1661            String[] attrName = new String[1];
    1662            for (int i = 0; i < numberOfAttributes; i++) {
    1663                attrName[0] = "";
    1664                boolean b = false;
    1665                try {
    1666                    b = HDFLibrary.SDattrinfo(sdid, i, attrName, attrInfo);
    1667                    // mask off the litend bit
    1668                    attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND);
    1669                }
    1670                catch (HDFException ex) {
    1671                    log.debug("getSDSglobalAttribute(): SDattrinfo failure: ", ex);
    1672                    b = false;
    1673                }
    1674
    1675                if (!b) {
    1676                    continue;
    1677                }
    1678
    1679                long[] attrDims = { attrInfo[1] };
    1680                Attribute attr = new Attribute(getRootObject(), attrName[0], new H4Datatype(attrInfo[0]), attrDims);
    1681                attrList.add(attr);
    1682
    1683                Object buf = null;
    1684                try {
    1685                    buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]);
    1686                }
    1687                catch (OutOfMemoryError e) {
    1688                    log.debug("getSDSglobalAttribute(): out of memory: ", e);
    1689                    buf = null;
    1690                }
    1691
    1692                try {
    1693                    HDFLibrary.SDreadattr(sdid, i, buf);
    1694                }
    1695                catch (HDFException ex) {
    1696                    log.debug("getSDSglobalAttribute(): SDreadattr failure: ", ex);
    1697                    buf = null;
    1698                }
    1699
    1700                if (buf != null) {
    1701                    if ((attrInfo[0] == HDFConstants.DFNT_CHAR)
    1702                            || (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) {
    1703                        buf = Dataset.byteToString((byte[]) buf, attrInfo[1]);
    1704                    }
    1705
    1706                    attr.setData(buf);
    1707                }
    1708
    1709            } // for (int i=0; i<numberOfAttributes; i++)
    1710        } // if (b && numberOfAttributes>0)
    1711
    1712        log.trace("getSDSglobalAttribute(): finish");
    1713        return attrList;
    1714    }
    1715
    1716    /**
    1717     * Returns the version of the HDF4 library.
    1718     */
    1719    @Override
    1720    public String getLibversion() {
    1721        int[] vers = new int[3];
    1722        String ver = "HDF ";
    1723        String[] verStr = { "" };
    1724
    1725        try {
    1726            HDFLibrary.Hgetlibversion(vers, verStr);
    1727        }
    1728        catch (HDFException ex) {
    1729            log.debug("getLibVersion(): Hgetlibversion failure: ", ex);
    1730        }
    1731
    1732        ver += vers[0] + "." + vers[1] + "." + vers[2];
    1733        log.debug("getLibversion(): libversion is {}", ver);
    1734
    1735        return ver;
    1736    }
    1737
    1738    /** HDF4 library supports netCDF version 2.3.2. It only supports SDS APIs. */
    1739    private boolean isNetCDF(String filename) {
    1740        log.trace("isNetCDF(): start: filename={}", filename);
    1741
    1742        boolean isnetcdf = false;
    1743        java.io.RandomAccessFile raf = null;
    1744
    1745        try {
    1746            raf = new java.io.RandomAccessFile(filename, "r");
    1747        }
    1748        catch (Exception ex) {
    1749            log.debug("RandomAccessFile {}", filename, ex);
    1750            try {
    1751                raf.close();
    1752            }
    1753            catch (Exception ex2) {
    1754                log.debug("RAF.close failure: ", ex2);
    1755            }
    1756            raf = null;
    1757        }
    1758
    1759        if (raf == null) {
    1760            log.debug("isNetCDF(): raf is null");
    1761            log.trace("isNetCDF(): finish");
    1762            return false;
    1763        }
    1764
    1765        byte[] header = new byte[4];
    1766        try {
    1767            raf.read(header);
    1768        }
    1769        catch (Exception ex) {
    1770            header = null;
    1771        }
    1772
    1773        if (header != null) {
    1774            if (
    1775                    // netCDF
    1776                    ((header[0] == 67) && (header[1] == 68) && (header[2] == 70) && (header[3] == 1))) {
    1777                isnetcdf = true;
    1778            }
    1779            else {
    1780                isnetcdf = false;
    1781            }
    1782        }
    1783
    1784        try {
    1785            raf.close();
    1786        }
    1787        catch (Exception ex) {
    1788            log.debug("RAF.close failure: ", ex);
    1789        }
    1790
    1791        log.trace("isNetCDF(): finish");
    1792        return isnetcdf;
    1793    }
    1794
    1795    /**
    1796     * Get an individual HObject with a given path. It does not load the whole
    1797     * file structure.
    1798     *
    1799     * @param path the path of the object
    1800     *
    1801     * @throws Exception if the object cannot be found
    1802     */
    1803    @Override
    1804    @SuppressWarnings("rawtypes")
    1805    public HObject get(String path) throws Exception {
    1806        log.trace("get(): start: path={}", path);
    1807
    1808        if (objList == null) {
    1809            objList = new Vector();
    1810        }
    1811
    1812        if ((path == null) || (path.length() <= 0)) {
    1813            log.debug("get(): path is null or invalid path length");
    1814            log.trace("get(): finish");
    1815            return null;
    1816        }
    1817
    1818        path = path.replace('\\', '/');
    1819        if (!path.startsWith("/")) {
    1820            path = "/" + path;
    1821        }
    1822
    1823        String name = null, pPath = null;
    1824        boolean isRoot = false;
    1825
    1826        if (path.equals("/")) {
    1827            name = "/"; // the root
    1828            isRoot = true;
    1829        }
    1830        else {
    1831            if (path.endsWith("/")) {
    1832                path = path.substring(0, path.length() - 2);
    1833            }
    1834            int idx = path.lastIndexOf('/');
    1835            name = path.substring(idx + 1);
    1836            if (idx == 0) {
    1837                pPath = "/";
    1838            }
    1839            else {
    1840                pPath = path.substring(0, idx);
    1841            }
    1842        }
    1843
    1844        log.trace("get(): isRoot={}", isRoot);
    1845
    1846        HObject obj = null;
    1847        isReadOnly = false;
    1848
    1849        if (fid < 0) {
    1850            fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_WRITE);
    1851            if (fid < 0) {
    1852                isReadOnly = true;
    1853                fid = HDFLibrary.Hopen(fullFileName, HDFConstants.DFACC_READ);
    1854            }
    1855            HDFLibrary.Vstart(fid);
    1856            grid = HDFLibrary.GRstart(fid);
    1857            sdid = HDFLibrary.SDstart(fullFileName, flag);
    1858        }
    1859
    1860        if (isRoot) {
    1861            obj = getRootGroup();
    1862        }
    1863        else {
    1864            obj = getAttachedObject(pPath, name);
    1865        }
    1866
    1867        log.trace("get(): finish");
    1868        return obj;
    1869    }
    1870
    1871    /** Get the root group and all the alone objects */
    1872    private H4Group getRootGroup() {
    1873        log.trace("getRootGroup(): start");
    1874
    1875        H4Group rootGroup = null;
    1876
    1877        long[] oid = { 0, 0 };
    1878        int n = 0, ref = -1;
    1879        int[] argv = null;
    1880
    1881        rootGroup = new H4Group(this, "/", null, null, oid);
    1882
    1883        // get top level VGroup
    1884        int[] tmpN = new int[1];
    1885        int[] refs = null;
    1886        try {
    1887            // first call to get the number of lone Vgroups
    1888            log.trace("getRootGroup(): first call to Vlone, get number of lone Vgroups");
    1889            n = HDFLibrary.Vlone(fid, tmpN, 0);
    1890            log.trace("getRootGroup(): number of lone Vgroups={}", n);
    1891            refs = new int[n];
    1892            // second call to get the references of all lone Vgroups
    1893            log.trace("getRootGroup(): second call to Vlone, get references of lone Vgroups");
    1894            n = HDFLibrary.Vlone(fid, refs, n);
    1895        }
    1896        catch (HDFException ex) {
    1897            log.debug("getRootGroup(): Vlone failure: ", ex);
    1898            n = 0;
    1899        }
    1900
    1901        // Iterate through the file to see members of the group
    1902        for (int i = 0; i < n; i++) {
    1903            ref = refs[i];
    1904            H4Group g = getVGroup(HDFConstants.DFTAG_VG, ref,
    1905                    HObject.separator, rootGroup, false);
    1906            if (g != null) {
    1907                rootGroup.addToMemberList(g);
    1908            }
    1909        } // for (int i=0; i<n; i++)
    1910
    1911        // get the top level GR images
    1912        argv = new int[2];
    1913        boolean b = false;
    1914        try {
    1915            b = HDFLibrary.GRfileinfo(grid, argv);
    1916        }
    1917        catch (HDFException ex) {
    1918            log.debug("getRootGroup(): GRfileinfo failure: ", ex);
    1919            b = false;
    1920        }
    1921
    1922        if (b) {
    1923            n = argv[0];
    1924            for (int i = 0; i < n; i++) {
    1925                // no duplicate object at top level
    1926                H4GRImage gr = getGRImage(HDFConstants.DFTAG_RIG, i,
    1927                        HObject.separator, false);
    1928                if (gr != null) {
    1929                    rootGroup.addToMemberList(gr);
    1930                }
    1931            } // for (int i=0; i<n; i++)
    1932        } // if ( grid!=HDFConstants.FAIL && HDFLibrary.GRfileinfo(grid,argv) )
    1933
    1934        // get top level SDS
    1935        try {
    1936            b = HDFLibrary.SDfileinfo(sdid, argv);
    1937        }
    1938        catch (HDFException ex) {
    1939            log.debug("getRootGroup(): SDfileinfo failure: ", ex);
    1940            b = false;
    1941        }
    1942
    1943        if (b) {
    1944            n = argv[0];
    1945
    1946            for (int i = 0; i < n; i++) {
    1947                // no duplicate object at top level
    1948                H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, i,
    1949                        HObject.separator, false);
    1950                if (sds != null) {
    1951                    rootGroup.addToMemberList(sds);
    1952                }
    1953            } // for (int i=0; i<n; i++)
    1954        } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv))
    1955
    1956        // get top level VData
    1957        try {
    1958            log.trace("getRootGroup(): first call to VSlone, get number of lone VDatas");
    1959            n = HDFLibrary.VSlone(fid, tmpN, 0);
    1960            log.trace("getRootGroup(): number of lone Vdatas={}", n);
    1961            refs = new int[n];
    1962            log.trace("getRootGroup(): second call to VSlone, get references of lone VDatas");
    1963            n = HDFLibrary.VSlone(fid, refs, n);
    1964        }
    1965        catch (HDFException ex) {
    1966            log.debug("getRootGroup(): VSlone failure: ex");
    1967            n = 0;
    1968        }
    1969
    1970        for (int i = 0; i < n; i++) {
    1971            ref = refs[i];
    1972
    1973            // no duplicate object at top level
    1974            H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref,
    1975                    HObject.separator, false);
    1976
    1977            if (vdata != null) {
    1978                rootGroup.addToMemberList(vdata);
    1979            }
    1980        } // for (int i=0; i<n; i++)
    1981
    1982        if (rootGroup != null) {
    1983            // retrieve file annotation, GR and SDS globle attributes
    1984            @SuppressWarnings("rawtypes")
    1985            List attributeList = null;
    1986            try {
    1987                attributeList = rootGroup.getMetadata();
    1988            }
    1989            catch (HDFException ex) {
    1990                log.debug("getRootGroup(): getMetadata() failure: ", ex);
    1991            }
    1992
    1993            if (attributeList != null) {
    1994                try {
    1995                    getFileAnnotation(fid, attributeList);
    1996                }
    1997                catch (HDFException ex) {
    1998                    log.debug("getRootGroup(): getFileAnnotation() failure: ", ex);
    1999                }
    2000                try {
    2001                    getGRglobalAttribute(grid, attributeList);
    2002                }
    2003                catch (HDFException ex) {
    2004                    log.debug("getRootGroup(): getGRglobalAttribute() failure: ", ex);
    2005                }
    2006                try {
    2007                    getSDSglobalAttribute(sdid, attributeList);
    2008                }
    2009                catch (HDFException ex) {
    2010                    log.debug("getRootGroup(): getSDSglobalAttribute() failure: ", ex);
    2011                }
    2012            }
    2013        }
    2014
    2015        log.trace("getRootGroup(): finish");
    2016        return rootGroup;
    2017    }
    2018
    2019    /** Get the object attached to a vgroup */
    2020    private HObject getAttachedObject(String path, String name) {
    2021        log.trace("getAttachedObject(): start");
    2022
    2023        if ((name == null) || (name.length() <= 0)) {
    2024            log.debug("getAttachedObject(): name is null or invalid name length");
    2025            log.trace("getAttachedObject(): finish");
    2026            return null;
    2027        }
    2028
    2029        // get top level VGroup
    2030        String[] objName = { "" };
    2031        // check if it is an image
    2032        int idx = -1;
    2033        try {
    2034            idx = HDFLibrary.GRnametoindex(grid, name);
    2035        }
    2036        catch (HDFException ex) {
    2037            log.debug("getAttachedObject(): GRnametoindex failure: ", ex);
    2038            idx = -1;
    2039        }
    2040
    2041        if (idx >= 0) {
    2042            H4GRImage img = getGRImage(HDFConstants.DFTAG_RIG, idx, HObject.separator, false);
    2043            log.trace("getAttachedObject(): finish");
    2044            return img;
    2045        }
    2046
    2047        // get top level SDS
    2048        try {
    2049            idx = HDFLibrary.SDnametoindex(sdid, name);
    2050        }
    2051        catch (HDFException ex) {
    2052            log.debug("getAttachedObject(): SDnametoindex failure: ", ex);
    2053            idx = -1;
    2054        }
    2055
    2056        if (idx >= 0) {
    2057            H4SDS sds = getSDS(HDFConstants.DFTAG_NDG, idx, HObject.separator, false);
    2058            log.trace("getAttachedObject(): finish");
    2059            return sds;
    2060        } // if (sdid != HDFConstants.FAIL && HDFLibrary.SDfileinfo(sdid, argv))
    2061
    2062        int ref = 0;
    2063        try {
    2064            ref = HDFLibrary.Vfind(fid, name);
    2065        }
    2066        catch (HDFException ex) {
    2067            log.debug("getAttachedObject(): Vfind failure: ", ex);
    2068            ref = -1;
    2069        }
    2070
    2071        if (ref > 0) {
    2072            long oid[] = { HDFConstants.DFTAG_VG, ref };
    2073            H4Group g = new H4Group(this, objName[0], path, null, oid);
    2074            depth_first(g);
    2075            log.trace("getAttachedObject(): finish");
    2076            return g;
    2077        }
    2078
    2079        // get top level VData
    2080        try {
    2081            ref = HDFLibrary.VSfind(fid, name);
    2082        }
    2083        catch (HDFException ex) {
    2084            log.debug("getAttachedObject(): VSfind failure: ", ex);
    2085            ref = -1;
    2086        }
    2087
    2088        if (ref > 0) {
    2089            H4Vdata vdata = getVdata(HDFConstants.DFTAG_VS, ref, HObject.separator, false);
    2090            log.trace("getAttachedObject(): finish");
    2091            return vdata;
    2092        } // for (int i=0; i<n; i++)
    2093
    2094        log.debug("getAttachedObject(): Object not found");
    2095        log.trace("getAttachedObject(): finish");
    2096        return null;
    2097    }
    2098
    2099    @Override
    2100    public void setNewLibBounds(String lowStr, String highStr) throws Exception {
    2101        return;
    2102    }
    2103
    2104}