OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
h5commoncfdap.cc
Go to the documentation of this file.
1 // This file is part of hdf5_handler: an HDF5 file handler for the OPeNDAP
2 // data server.
3 
4 // Copyright (c) 2011-2013 The HDF Group, Inc. and OPeNDAP, Inc.
5 //
6 // This is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your
9 // option) any later version.
10 //
11 // This software is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
22 // Suite 203, Champaign, IL 61820
23 
32 
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <iostream>
38 #include <sstream>
39 
40 #include <InternalErr.h>
41 
42 #include "h5cfdaputil.h"
43 #include "h5gmcfdap.h"
44 #include "HDF5CFByte.h"
45 #include "HDF5CFUInt16.h"
46 #include "HDF5CFInt16.h"
47 #include "HDF5CFUInt32.h"
48 #include "HDF5CFInt32.h"
49 #include "HDF5CFFloat32.h"
50 #include "HDF5CFFloat64.h"
51 #include "HDF5CFStr.h"
52 #include "HDF5CFArray.h"
53 
54 using namespace HDF5CF;
55 
56 
57 void gen_dap_onevar_dds(DDS &dds,const HDF5CF::Var* var, const hid_t file_id, const string & filename) {
58 
59  BaseType *bt = NULL;
60 
61  switch(var->getType()) {
62 #define HANDLE_CASE(tid,type) \
63  case tid: \
64  bt = new (type)(var->getNewName(),var->getFullPath()); \
65  break;
74  HANDLE_CASE(H5FSTRING, Str);
75  HANDLE_CASE(H5VSTRING, Str);
76  default:
77  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
78 #undef HANDLE_CASE
79  }
80 
81  if (bt != NULL) {
82 
83  const vector<HDF5CF::Dimension *>& dims = var->getDimensions();
84 
85 //cerr<<"coming to the variable "<<endl;
86  vector <HDF5CF::Dimension*>:: const_iterator it_d;
87  if (0 == dims.size()) {
88  if (H5FSTRING == var->getType() || H5VSTRING == var->getType()) {
89  HDF5CFStr *sca_str = NULL;
90  try {
91  sca_str = new HDF5CFStr(var->getNewName(),filename,var->getFullPath());
92  }
93  catch(...) {
94  delete bt;
95  throw InternalErr(__FILE__,__LINE__,"Cannot allocate the HDF5CFStr.");
96  }
97  dds.add_var(sca_str);
98  delete bt;
99  delete sca_str;
100  }
101  else {
102  delete bt;
103  throw InternalErr(__FILE__,__LINE__,"Non string scalar data is not supported");
104  }
105  }
106  else {
107 
108  HDF5CFArray *ar = NULL;
109  try {
110  ar = new HDF5CFArray (
111  var->getRank(),
112  file_id,
113  filename,
114  var->getType(),
115  var->getFullPath(),
116  var->getNewName(),
117  bt);
118  }
119  catch(...) {
120  delete bt;
121  throw InternalErr(__FILE__,__LINE__,"Cannot allocate the HDF5CFStr.");
122  }
123 
124 //cerr<<"dims size "<<dims.size() <<endl;
125  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
126 //cerr<<"Dimen name "<<(*it_d)->getNewName() <<endl;
127  if (""==(*it_d)->getNewName())
128  ar->append_dim((*it_d)->getSize());
129  else
130  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
131  }
132 
133  dds.add_var(ar);
134  delete bt;
135  delete ar;
136  }
137  }
138 }
139 
140 // Currently only when the datatype of fillvalue is not the same as the datatype of the variable,
141 // special attribute handling is needed.
143  return ((("_FillValue" == attr->getNewName()) && (var->getType() != attr->getType()))?true:false);
144 }
145 
146 
147 // Currently we only handle the case when the datatype of _FillValue is not the same as the variable datatype.
148 void gen_dap_special_oneobj_das(AttrTable*at, const HDF5CF::Attribute* attr,const HDF5CF::Var* var) {
149 
150  if (attr->getCount() != 1)
151  throw InternalErr(__FILE__,__LINE__,"FillValue attribute can only have one element.");
152 
153  H5DataType var_dtype = var->getType();
154  string print_rep;
155 
156  switch(var_dtype) {
157 
158  case H5UCHAR:
159  {
160  unsigned char final_fill_value = (unsigned char)(attr->getValue()[0]);
161  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
162  }
163  break;
164 
165  case H5CHAR:
166  {
167  // Notice HDF5 native char maps to DAP int16.
168  short final_fill_value = (short)(attr->getValue()[0]);
169  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
170  }
171  break;
172  case H5INT16:
173  {
174  short final_fill_value = (short)(attr->getValue()[0]);
175  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
176  }
177  break;
178  case H5UINT16:
179  {
180  unsigned short final_fill_value = (unsigned short)(attr->getValue()[0]);
181  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
182  }
183  break;
184 
185  case H5INT32:
186  {
187  int final_fill_value = (int)(attr->getValue()[0]);
188  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
189  }
190  break;
191  case H5UINT32:
192  {
193  unsigned int final_fill_value = (unsigned int)(attr->getValue()[0]);
194  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
195  }
196  break;
197  case H5FLOAT32:
198  {
199  float final_fill_value = (float)(attr->getValue()[0]);
200  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
201  }
202  break;
203  case H5FLOAT64:
204  {
205  double final_fill_value = (double)(attr->getValue()[0]);
206  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
207  }
208  break;
209  default:
210  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
211  }
212 
213  at->append_attr(attr->getNewName(), HDF5CFDAPUtil::print_type(var_dtype), print_rep);
214 }
215 
216 #if 0
217  switch(var_dtype) {
218 
219  case H5UCHAR:
220  {
221  unsigned char final_fill_value = (unsigned char)(attr->getValue()[0]);
222  string print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
223 
224  }
225  break;
226 
227 #endif
228 
229 
230 
231 
232 
233 
234 void gen_dap_oneobj_das(AttrTable*at,const HDF5CF::Attribute* attr, const HDF5CF::Var *var) {
235 
236  if ((H5FSTRING == attr->getType()) ||
237  (H5VSTRING == attr->getType())) {
238  gen_dap_str_attr(at,attr);
239  }
240  else {
241 
242  if (NULL == var) {
243 
244  // HDF5 Native Char maps to DAP INT16(DAP doesn't have the corresponding datatype), so needs to
245  // obtain the mem datatype.
246  size_t mem_dtype_size = (attr->getBufSize())/(attr->getCount());
247  H5DataType mem_dtype = HDF5CFDAPUtil::get_mem_dtype(attr->getType(),mem_dtype_size);
248 
249  for (unsigned int loc=0; loc < attr->getCount() ; loc++) {
250  string print_rep = HDF5CFDAPUtil::print_attr(mem_dtype, loc, (void*) &(attr->getValue()[0]));
251  at->append_attr(attr->getNewName(), HDF5CFDAPUtil::print_type(attr->getType()), print_rep);
252  }
253 
254  }
255 
256  else {
257 
258  // The datatype of _FillValue attribute needs to be the same as the variable datatype for an netCDF C file.
259  // To make OPeNDAP's netCDF file out work, we need to change the attribute datatype of _FillValue to be the
260  // same as the variable datatype if they are not the same. An OMI-Aura_L2-OMUVB file has such a case.
261  // The datatype of "TerrainHeight" is int32 but the datatype of the fillvalue is int16.
262  // KY 2012-11-20
263  bool special_attr_handling = need_special_attribute_handling(attr,var);
264  if (true == special_attr_handling) {
265  gen_dap_special_oneobj_das(at,attr,var);
266  }
267 
268  else {
269 
270  // HDF5 Native Char maps to DAP INT16(DAP doesn't have the corresponding datatype), so needs to
271  // obtain the mem datatype.
272  size_t mem_dtype_size = (attr->getBufSize())/(attr->getCount());
273  H5DataType mem_dtype = HDF5CFDAPUtil::get_mem_dtype(attr->getType(),mem_dtype_size);
274 
275  for (unsigned int loc=0; loc < attr->getCount() ; loc++) {
276  string print_rep = HDF5CFDAPUtil::print_attr(mem_dtype, loc, (void*) &(attr->getValue()[0]));
277  at->append_attr(attr->getNewName(), HDF5CFDAPUtil::print_type(attr->getType()), print_rep);
278  }
279  }
280  }
281  }
282 }
283 
284 void gen_dap_str_attr(AttrTable *at, const HDF5CF::Attribute *attr) {
285 
286  string check_droplongstr_key ="H5.EnableDropLongString";
287  bool is_droplongstr = false;
288  is_droplongstr = HDF5CFDAPUtil::check_beskeys(check_droplongstr_key);
289 
290  const vector<size_t>& strsize = attr->getStrSize();
291  unsigned int temp_start_pos = 0;
292  for (unsigned int loc=0; loc < attr->getCount() ; loc++) {
293  if (strsize[loc] !=0) {
294  string tempstring(attr->getValue().begin()+temp_start_pos,
295  attr->getValue().begin()+temp_start_pos+strsize[loc]);
296  temp_start_pos += strsize[loc];
297 
298  // If the string size is longer than the current netCDF JAVA
299  // string and the "EnableDropLongString" key is turned on,
300  // No string is generated.
301  if (false == is_droplongstr ||
302  tempstring.size() <= NC_JAVA_STR_SIZE_LIMIT) {
303  if((attr->getNewName()!="origname")&&(attr->getNewName()!="fullnamepath"))
304  tempstring = HDF5CFDAPUtil::escattr(tempstring);
305  at->append_attr(attr->getNewName(),"String",tempstring);
306  }
307  }
308  }
309 }
310 
This class provides a way to map HDF5 Str to DAP Str for the CF option.
Definition: HDF5CF.h:60
const string & getFullPath() const
Get the full path of this variable.
Definition: HDF5CF.h:279
This class represents one HDF5 dataset(CF variable)
Definition: HDF5CF.h:251
int getRank() const
Get the dimension rank of this variable.
Definition: HDF5CF.h:285
This class provides a way to map HDF5 unsigned 16-bit integer to DAP uint16 for the CF option...
const string & getNewName() const
Definition: HDF5CF.h:199
This class provides a way to map HDF5 float to DAP float for the CF option.
#define NC_JAVA_STR_SIZE_LIMIT
Definition: h5cfdaputil.h:42
static bool check_beskeys(const string key)
Definition: h5cfdaputil.cc:39
const std::vector< char > & getValue() const
Definition: HDF5CF.h:219
bool need_special_attribute_handling(const HDF5CF::Attribute *attr, const HDF5CF::Var *var)
static H5DataType get_mem_dtype(H5DataType, size_t)
Definition: h5cfdaputil.cc:171
This class provides a way to map HDF5 int16 to DAP int16 for the CF option.
const std::vector< size_t > & getStrSize() const
Definition: HDF5CF.h:224
void gen_dap_oneobj_das(AttrTable *at, const HDF5CF::Attribute *attr, const HDF5CF::Var *var)
Map and generate DDS and DAS for the CF option for generic HDF5 products.
H5DataType
Definition: HDF5CFUtil.h:54
void gen_dap_special_oneobj_das(AttrTable *at, const HDF5CF::Attribute *attr, const HDF5CF::Var *var)
This class provides a way to map HDF5 64-bit floating-point(double) to DAP 64-bit floating-point for ...
#define NULL
Definition: wcsUtil.h:65
H5DataType getType() const
Get the data type of this variable(Not HDF5 datatype id)
Definition: HDF5CF.h:291
const string & getNewName() const
Get the new name of this variable.
Definition: HDF5CF.h:273
static string print_attr(H5DataType h5type, int loc, void *vals)
Definition: h5cfdaputil.cc:180
This class provides a way to map HDF5 32-bit integer to DAP Int32 for the CF option.
This class includes the methods to read data array into DAP buffer from an HDF5 dataset for the CF op...
static string print_type(H5DataType h5type)
Definition: h5cfdaputil.cc:115
const vector< Dimension * > & getDimensions() const
Get the list of the dimensions.
Definition: HDF5CF.h:302
H5DataType getType() const
Definition: HDF5CF.h:204
static string escattr(string s)
A customized escaping function to escape special characters following OPeNDAP's escattr function that...
Definition: h5cfdaputil.cc:57
This class represents one attribute.
Definition: HDF5CF.h:184
void gen_dap_str_attr(AttrTable *at, const HDF5CF::Attribute *attr)
Helper functions for generating DAS attributes and a function to check BES Key.
This class provides a way to map HDF5 unsigned 32-bit integer to DAP uint32 for the CF option...
void gen_dap_onevar_dds(DDS &dds, const HDF5CF::Var *var, const hid_t file_id, const string &filename)
This class provides a way to map HDF5 byte to DAP byte for the CF option.
#define HANDLE_CASE(tid, type)
size_t getBufSize() const
Definition: HDF5CF.h:214
hsize_t getCount() const
Definition: HDF5CF.h:209