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    private static final long serialVersionUID = -1261533010442193447L;
038
039    private static final org.slf4j.Logger   log = org.slf4j.LoggerFactory.getLogger(NC2Group.class);
040
041    /**
042     * The corresponding netcdf Group for this group.
043     */
044    protected ucar.nc2.Group netCDFGroup;
045
046    public ucar.nc2.Group getNetCDFGroup() {
047        return netCDFGroup;
048    }
049
050    public void setNetCDFGroup(ucar.nc2.Group netCDFGroup) {
051        this.netCDFGroup = netCDFGroup;
052    }
053
054    /**
055     * The list of attributes of this data object. Members of the list are
056     * instance of Attribute.
057     */
058    private List attributeList;
059
060    /**
061     * The list of netcdf typedefs, dimensions and attributes of this data object. Members of the list are
062     * instance of ucar.nc2.*.
063     */
064    private List netcdfTypedefList;
065    private List netcdfDimensionList;
066    private List netcdfAttributeList;
067
068    /** The default object ID for NC2 objects */
069    private static final long[] DEFAULT_OID = { 0 };
070
071    /**
072     * Constructs an NC2 group with specific name, path, and parent.
073     *
074     * @param fileFormat
075     *            the file which containing the group.
076     * @param name
077     *            the name of this group.
078     * @param path
079     *            the full path of this group.
080     * @param parent
081     *            the parent of this group.
082     * @param theID
083     *            the unique identifier of this data object.
084     */
085    public NC2Group(FileFormat fileFormat, String name, String path, Group parent, long[] theID) {
086        super(fileFormat, name, path, parent, ((theID == null) ? DEFAULT_OID : theID));
087        ucar.nc2.Group parentGroup = null;
088        if (parent != null)
089            parentGroup = ((NC2Group)parent).getNetCDFGroup();
090        netCDFGroup = new ucar.nc2.Group(((NC2File)fileFormat).getNetcdfFile(), parentGroup, name);
091        log.trace("NC2Group:{}", name);
092    }
093
094    /*
095     * (non-Javadoc)
096     *
097     * @see hdf.object.DataFormat#hasAttribute()
098     */
099    public boolean hasAttribute() {
100        return false;
101    }
102
103    public boolean hasDimension() {
104        return false;
105    }
106
107    // Implementing DataFormat
108    @SuppressWarnings("rawtypes")
109    public List getMetadata() throws Exception {
110        if (attributeList != null) {
111            return attributeList;
112        }
113
114        NC2File theFile = (NC2File)getFileFormat();
115        NetcdfFile ncFile = theFile.getNetcdfFile();
116        if (!isRoot() && (netCDFGroup !=null)) {
117            netcdfDimensionList = netCDFGroup.getDimensions();
118
119            netcdfTypedefList = netCDFGroup.getEnumTypedefs();
120
121            netcdfAttributeList = netCDFGroup.getAttributes();
122        }
123        else {
124            netcdfDimensionList = ncFile.getDimensions();
125
126            netcdfAttributeList = ncFile.getGlobalAttributes();
127        }
128        if (netcdfAttributeList == null) {
129            attributeList = null;
130        }
131        else {
132            int n = netcdfAttributeList.size();
133            log.trace("Attribute size:{}", n);
134            attributeList = new Vector(n);
135
136            ucar.nc2.Attribute netcdfAttr = null;
137            for (int i = 0; i < n; i++) {
138                netcdfAttr = (ucar.nc2.Attribute) netcdfAttributeList.get(i);
139                log.trace("getMetadata(): Attribute[{}]:{}", i, netcdfAttr.toString());
140                attributeList.add(NC2File.convertAttribute(this, netcdfAttr));
141            }
142        }
143        return attributeList;
144    }
145
146    /**
147     * Creates a new attribute and attached to this dataset if attribute does
148     * not exist. Otherwise, just update the value of the attribute.
149     *
150     * @param info
151     *            the atribute to attach
152     *
153     * @throws Exception
154     *            if there is an error
155     */
156    public void writeMetadata(Object info) throws Exception {
157        // not supported
158        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
159    }
160
161    /**
162     * Deletes an attribute from this dataset.
163     *
164     * @param info
165     *            the attribute to delete.
166     *
167     * @throws Exception
168     *            if there is an error
169     */
170    public void removeMetadata(Object info) throws Exception {
171        // not supported
172        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
173    }
174
175    // implementing DataFormat
176    public void updateMetadata(Object info) throws Exception {
177        // not supported
178        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
179    }
180
181    // Implementing DataFormat
182    @Override
183    public long open() {
184        // not supported
185        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
186    }
187
188    /* close group access */
189    @Override
190    public void close(long gid) {
191        // not supported
192        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
193    }
194
195    /**
196     * Creates a new group.
197     *
198     * @param name
199     *            the name of the group to create.
200     * @param pgroup
201     *            the parent group of the new group.
202     *
203     * @return the new group if successful. Otherwise returns null.
204     *
205     * @throws Exception
206     *            if there is an error
207     */
208    public static NC2Group create(String name, Group pgroup) throws Exception {
209        // not supported
210        throw new UnsupportedOperationException("Unsupported operation for NetCDF.");
211    }
212
213    // overload to get different lists
214    @SuppressWarnings("rawtypes")
215    public List getMetadata(int... attrPropList) throws Exception {
216        int hdfType = 0;
217        int attrType = 0;
218        int dimType = 0;
219        int enumType = 0;
220        List returnList = null;
221
222        // use 0 to skip or 1 select in attrPropList to get the list
223        // hdf attributes first netcdf attributes second, dimensions third, enumTypes fourth
224        log.trace("getMetadata(...): attrPropList={}", attrPropList.length);
225        if (attrPropList.length > 0) {
226            hdfType = attrPropList[0];
227        }
228        if (attrPropList.length > 1) {
229            attrType = attrPropList[1];
230        }
231        if (attrPropList.length > 2) {
232            dimType = attrPropList[2];
233        }
234        if (attrPropList.length > 3) {
235            enumType = attrPropList[3];
236        }
237        if ((hdfType != 0) && (attributeList != null)) {
238            returnList = attributeList;
239        }
240        else if ((attrType != 0) && (netcdfAttributeList != null)) {
241            returnList = netcdfAttributeList;
242        }
243        else if ((dimType != 0) && (netcdfDimensionList != null)) {
244            returnList = netcdfDimensionList;
245        }
246        else if ((enumType != 0) && (netcdfTypedefList != null)) {
247            returnList = netcdfTypedefList;
248        }
249
250        return returnList;
251    }
252
253    public String netcdfAttributeString(int index) {
254        ucar.nc2.Attribute netcdfAttr = (ucar.nc2.Attribute) netcdfAttributeList.get(index);
255        log.trace("netcdfAttributeString(): netcdfAttribute[{}]:{}", index, netcdfAttr.toString());
256        String returnStr = netcdfAttr.toString();
257        return returnStr;
258    }
259
260    public String netcdfDimensionString(int index) {
261        ucar.nc2.Dimension netcdfDim = (ucar.nc2.Dimension) netcdfDimensionList.get(index);
262        log.trace("netcdfDimensionString(): netcdfDimension[{}]:{}", index, netcdfDim.toString());
263        StringBuilder objDimensionStr = new StringBuilder(netcdfDim.getShortName());
264        if (netcdfDim.isShared())
265            objDimensionStr.append("[SHARED]");
266        if (netcdfDim.isUnlimited())
267            objDimensionStr.append(" = UNLIMITED");
268          else if (netcdfDim.isVariableLength())
269              objDimensionStr.append(" = UNKNOWN");
270          else
271              objDimensionStr.append(" = " + netcdfDim.getLength());
272        return objDimensionStr.toString();
273    }
274
275    public String netcdfTypedefString(int index) {
276        ucar.nc2.EnumTypedef netcdfType = (ucar.nc2.EnumTypedef) netcdfTypedefList.get(index);
277        log.trace("netcdfEnumTypedefString(): netcdfTypedef[{}]:{}", index, netcdfType.toString());
278        StringBuilder objEnumTypedefStr = new StringBuilder(netcdfType.getShortName() + " {");
279        int count = 0;
280        List<Object> keyset = Arrays.asList(netcdfType.getMap().keySet().toArray());
281        for (Object key : keyset) {
282          String s = netcdfType.getMap().get(key);
283          if (0 < count++)
284              objEnumTypedefStr.append(", ");
285          objEnumTypedefStr.append("'" + s + "' = " + key);
286        }
287        objEnumTypedefStr.append(" }");
288        return objEnumTypedefStr.toString();
289    }
290
291}