    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 COPYING file, which can be found  *
    009 * at the root of the source code distribution tree,                         *
    010 * or in https://www.hdfgroup.org/licenses.                                  *
    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.nc2;
    016
    017import java.util.Arrays;
    018import java.util.List;
    019import java.util.Vector;
    020
    021import org.slf4j.Logger;
    022import org.slf4j.LoggerFactory;
    023
    024import hdf.object.FileFormat;
    025import hdf.object.Group;
    026
    027import ucar.nc2.NetcdfFile;
    028
    029/**
    030 * An NC2Group represents NetCDF3 group, inheriting from Group. Every NetCDF3 object
    031 * has at least one name. An NetCDF3 group is used to store a set of the names
    032 * together in one place, i.e. a group. The general structure of a group is
    033 * similar to that of the UNIX file system in that the group may contain
    034 * references to other groups or data objects just as the UNIX directory may
    035 * contain subdirectories or files.
    036 *
    037 * @version 1.1 9/4/2007
    038 * @author Peter X. Cao
    039 */
    040public class NC2Group extends Group
    041{
    042    private static final long serialVersionUID = -1261533010442193447L;
    043
    044    private static final Logger log = LoggerFactory.getLogger(NC2Group.class);
    045
    046    /**
    047     * The corresponding netcdf Group for this group.
    048     */
    049    protected ucar.nc2.Group netCDFGroup;
    050
    051    /**
    052     * @return the corresponding netcdf Group for this group.
    053     */
    054    public ucar.nc2.Group getNetCDFGroup() {
    055        return netCDFGroup;
    056    }
    057
    058    /**
    059     * Set the corresponding netcdf Group for this group.
    060     *
    061     * @param netCDFGroup
    062     *        the ucar.nc2.Group to associate to this group
    063     */
    064    public void setNetCDFGroup(ucar.nc2.Group netCDFGroup) {
    065        this.netCDFGroup = netCDFGroup;
    066    }
    067
    068    /**
    069     * The list of attributes of this data object. Members of the list are
    070     * instance of NC2Attribute.
    071     */
    072    private List attributeList;
    073
    074    /** The list of netcdf typedefs of this data object. Members of the list are instance of ucar.nc2.*. */
    075    private List netcdfTypedefList;
    076    /** The list of netcdf dimensions of this data object. Members of the list are instance of ucar.nc2.*. */
    077    private List netcdfDimensionList;
    078    /** The list of netcdf attributes of this data object. Members of the list are * instance of ucar.nc2.*. */
    079    private List netcdfAttributeList;
    080
    081    /** The default object ID for NC2 objects */
    082    private static final long[] DEFAULT_OID = { 0 };
    083
    084    /**
    085     * Constructs an NC2 group with specific name, path, and parent.
    086     *
    087     * @param fileFormat
    088     *            the file which containing the group.
    089     * @param name
    090     *            the name of this group.
    091     * @param path
    092     *            the full path of this group.
    093     * @param parent
    094     *            the parent of this group.
    095     * @param theID
    096     *            the unique identifier of this data object.
    097     */
    098    public NC2Group(FileFormat fileFormat, String name, String path, Group parent, long[] theID) {
    099        super(fileFormat, name, path, parent, ((theID == null) ? DEFAULT_OID : theID));
    100        ucar.nc2.Group parentGroup = null;
    101        if (parent != null)
    102            parentGroup = ((NC2Group)parent).getNetCDFGroup();
    103        netCDFGroup = new ucar.nc2.Group(((NC2File)fileFormat).getNetcdfFile(), parentGroup, name);
    104        log.trace("NC2Group:{}", name);
    105    }
    106
    107    /**
    108     * Check if the object has any attributes attached.
    109     *
    110     * @return true if it has any attributes, false otherwise.
    111     */
    112    public boolean hasAttribute() {
    113        return false;
    114    }
    115
    116    /**
    117     * @return true if this group has an attached dimension.
    118     */
    119    public boolean hasDimension() {
    120        return false;
    121    }
    122
    123    // Implementing DataFormat
    124    /**
    125     * Retrieves the object's metadata, such as attributes, from the file.
    126     *
    127     * Metadata, such as attributes, is stored in a List.
    128     *
    129     * @return the list of metadata objects.
    130     *
    131     * @throws Exception
    132     *             if the metadata can not be retrieved
    133     */
    134    @SuppressWarnings("rawtypes")
    135    public List getMetadata() throws Exception {
    136        if (attributeList != null)
    137            return attributeList;
    138
    139        NC2File theFile = (NC2File)getFileFormat();
    140        NetcdfFile ncFile = theFile.getNetcdfFile();
    141        if (!isRoot() && (netCDFGroup !=null)) {
    142            netcdfDimensionList = netCDFGroup.getDimensions();
    143
    144            netcdfTypedefList = netCDFGroup.getEnumTypedefs();
    145
    146            netcdfAttributeList = netCDFGroup.getAttributes();
    147        }
    148        else {
    149            netcdfDimensionList = ncFile.getDimensions();
    150
    151            netcdfAttributeList = ncFile.getGlobalAttributes();
    152        }
    153        if (netcdfAttributeList == null) {
    154            attributeList = null;
    155        }
    156        else {
    157            int n = netcdfAttributeList.size();
    158            log.trace("Attribute size:{}", n);
    159            attributeList = new Vector(n);
    160
    161            ucar.nc2.Attribute netcdfAttr = null;
    162            for (int i = 0; i < n; i++) {
    163                netcdfAttr = (ucar.nc2.Attribute) netcdfAttributeList.get(i);
    164                log.trace("getMetadata(): Attribute[{}]:{}", i, netcdfAttr.toString());
    165                attributeList.add(NC2File.convertAttribute(this, netcdfAttr));
    166            }
    167        }
    168        return attributeList;
    169    }
    170
    171    /**
    172     * Creates a new attribute and attached to this dataset if attribute does
    173     * not exist. Otherwise, just update the value of the attribute.
    174     *
    175     * @param info
    176     *            the attribute to attach
    177     *
    178     * @throws Exception
    179     *            if there is an error
    180     */
    181    public void writeMetadata(Object info) throws Exception {
    182        // not supported
    183        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
    184    }
    185
    186    /**
    187     * Deletes an attribute from this dataset.
    188     *
    189     * @param info
    190     *            the attribute to delete.
    191     *
    192     * @throws Exception
    193     *            if there is an error
    194     */
    195    public void removeMetadata(Object info) throws Exception {
    196        // not supported
    197        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
    198    }
    199
    200    // implementing DataFormat
    201    /**
    202     * Updates an attribute from this dataset.
    203     *
    204     * @param info
    205     *            the attribute to update.
    206     *
    207     * @throws Exception
    208     *            if there is an error
    209     */
    210    public void updateMetadata(Object info) throws Exception {
    211        // not supported
    212        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
    213    }
    214
    215    // Implementing DataFormat
    216    /**
    217     * open a group.
    218     *
    219     * @return the group identifier if successful.
    220     */
    221    @Override
    222    public long open() {
    223        // not supported
    224        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
    225    }
    226
    227    /**
    228     * Close a group.
    229     *
    230     * @param gid
    231     *            the identifier of the group to close.
    232     */
    233    @Override
    234    public void close(long gid) {
    235        // not supported
    236        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
    237    }
    238
    239    /**
    240     * Creates a new group.
    241     *
    242     * @param name
    243     *            the name of the group to create.
    244     * @param pgroup
    245     *            the parent group of the new group.
    246     *
    247     * @return the new group if successful. Otherwise returns null.
    248     *
    249     * @throws Exception
    250     *            if there is an error
    251     */
    252    public static NC2Group create(String name, Group pgroup) throws Exception {
    253        // not supported
    254        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
    255    }
    256
    257    /**
    258     * Retrieves the object's metadata, such as attributes, from the file.
    259     *
    260     * Metadata, such as attributes, is stored in a List.
    261     *
    262     * @param attrPropList
    263     *             the list of properties to get
    264     *
    265     * @return the list of metadata objects.
    266     *
    267     * @throws Exception
    268     *             if the metadata can not be retrieved
    269     */
    270    @SuppressWarnings("rawtypes")
    271    public List getMetadata(int... attrPropList) throws Exception {
    272        int hdfType = 0;
    273        int attrType = 0;
    274        int dimType = 0;
    275        int enumType = 0;
    276        List returnList = null;
    277
    278        // use 0 to skip or 1 select in attrPropList to get the list
    279        // hdf attributes first netcdf attributes second, dimensions third, enumTypes fourth
    280        log.trace("getMetadata(...): attrPropList={}", attrPropList.length);
    281        if (attrPropList.length > 0)
    282            hdfType = attrPropList[0];
    283        if (attrPropList.length > 1)
    284            attrType = attrPropList[1];
    285        if (attrPropList.length > 2)
    286            dimType = attrPropList[2];
    287        if (attrPropList.length > 3)
    288            enumType = attrPropList[3];
    289        if ((hdfType != 0) && (attributeList != null))
    290            returnList = attributeList;
    291        else if ((attrType != 0) && (netcdfAttributeList != null))
    292            returnList = netcdfAttributeList;
    293        else if ((dimType != 0) && (netcdfDimensionList != null))
    294            returnList = netcdfDimensionList;
    295        else if ((enumType != 0) && (netcdfTypedefList != null))
    296            returnList = netcdfTypedefList;
    297
    298        return returnList;
    299    }
    300
    301    /**
    302     * Retrieves the attribute name.
    303     *
    304     * @param index
    305     *             the index of the attribute to get
    306     *
    307     * @return the attribute string.
    308     */
    309    public String netcdfAttributeString(int index) {
    310        ucar.nc2.Attribute netcdfAttr = (ucar.nc2.Attribute) netcdfAttributeList.get(index);
    311        log.trace("netcdfAttributeString(): netcdfAttribute[{}]:{}", index, netcdfAttr.toString());
    312        String returnStr = netcdfAttr.toString();
    313        return returnStr;
    314    }
    315
    316    /**
    317     * Retrieves the Dimension name.
    318     *
    319     * @param index
    320     *             the index of the Dimension to get
    321     *
    322     * @return the Dimension string.
    323     */
    324    public String netcdfDimensionString(int index) {
    325        ucar.nc2.Dimension netcdfDim = (ucar.nc2.Dimension) netcdfDimensionList.get(index);
    326        log.trace("netcdfDimensionString(): netcdfDimension[{}]:{}", index, netcdfDim.toString());
    327        StringBuilder objDimensionStr = new StringBuilder(netcdfDim.getShortName());
    328        if (netcdfDim.isShared())
    329            objDimensionStr.append("[SHARED]");
    330        if (netcdfDim.isUnlimited())
    331            objDimensionStr.append(" = UNLIMITED");
    332          else if (netcdfDim.isVariableLength())
    333              objDimensionStr.append(" = UNKNOWN");
    334          else
    335              objDimensionStr.append(" = " + netcdfDim.getLength());
    336        return objDimensionStr.toString();
    337    }
    338
    339    /**
    340     * Retrieves the EnumTypedef name.
    341     *
    342     * @param index
    343     *             the index of the EnumTypedef to get
    344     *
    345     * @return the EnumTypedef string.
    346     */
    347    public String netcdfTypedefString(int index) {
    348        ucar.nc2.EnumTypedef netcdfType = (ucar.nc2.EnumTypedef) netcdfTypedefList.get(index);
    349        log.trace("netcdfEnumTypedefString(): netcdfTypedef[{}]:{}", index, netcdfType.toString());
    350        StringBuilder objEnumTypedefStr = new StringBuilder(netcdfType.getShortName() + " {");
    351        int count = 0;
    352        List<Object> keyset = Arrays.asList(netcdfType.getMap().keySet().toArray());
    353        for (Object key : keyset) {
    354          String s = netcdfType.getMap().get(key);
    355          if (0 < count++)
    356              objEnumTypedefStr.append(", ");
    357          objEnumTypedefStr.append("'" + s + "' = " + key);
    358        }
    359        objEnumTypedefStr.append(" }");
    360        return objEnumTypedefStr.toString();
    361    }
    362
    363}