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