bes  Updated for version 3.20.10
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-2016 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 <libdap/InternalErr.h>
41 #include <BESDebug.h>
42 
43 #include "HDF5RequestHandler.h"
44 #include "h5cfdaputil.h"
45 #include "h5gmcfdap.h"
46 #include "HDF5CFByte.h"
47 #include "HDF5CFInt8.h"
48 #include "HDF5CFUInt16.h"
49 #include "HDF5CFInt16.h"
50 #include "HDF5CFUInt32.h"
51 #include "HDF5CFInt32.h"
52 #include "HDF5CFFloat32.h"
53 #include "HDF5CFFloat64.h"
54 #include "HDF5CFInt64.h"
55 #include "HDF5CFUInt64.h"
56 #include "HDF5CFStr.h"
57 #include "HDF5CFArray.h"
58 #include "HDF5CFGeoCF1D.h"
59 #include "HDF5CFGeoCFProj.h"
60 
61 //#include "HDF5Int64.h"
62 #include "HDF5CFUtil.h"
63 
64 using namespace std;
65 using namespace libdap;
66 using namespace HDF5CF;
67 
68 // Generate DDS from one variable
69 void gen_dap_onevar_dds(DDS &dds, const HDF5CF::Var* var, const hid_t file_id, const string & filename)
70 {
71 
72  BESDEBUG("h5", "Coming to gen_dap_onevar_dds() "<<endl);
73  const vector<HDF5CF::Dimension *>& dims = var->getDimensions();
74 
75  if (dims.empty()) {
76  // Adding 64-bit integer support for DMR
77  if (H5INT64 == var->getType() || H5UINT64 == var->getType()){
78  DMR * dmr = HDF5RequestHandler::get_dmr_64bit_int();
79  if(dmr == NULL)
80  return;
81  else {
82  D4Group* root_grp = dmr->root();
83  if(H5INT64 == var->getType()) {
84  HDF5CFInt64 *sca_int64 = NULL;
85  try {
86  sca_int64 = new HDF5CFInt64(var->getNewName(), var->getFullPath(), filename);
87  }
88  catch (...) {
89  string error_message = "Cannot allocate the HDF5CFInt64: " + error_message;
90  throw InternalErr(__FILE__, __LINE__, error_message);
91  }
92  sca_int64->set_is_dap4(true);
93  map_cfh5_var_attrs_to_dap4_int64(var,sca_int64);
94  root_grp->add_var_nocopy(sca_int64);
95 
96  }
97  else if(H5UINT64 == var->getType()) {
98  HDF5CFUInt64 *sca_uint64 = NULL;
99  try {
100  sca_uint64 = new HDF5CFUInt64(var->getNewName(), var->getFullPath(), filename);
101  }
102  catch (...) {
103  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFInt64.");
104  }
105  sca_uint64->set_is_dap4(true);
106  map_cfh5_var_attrs_to_dap4_int64(var,sca_uint64);
107  root_grp->add_var_nocopy(sca_uint64);
108 
109  }
110 
111  }
112  }
113  else if (H5FSTRING == var->getType() || H5VSTRING == var->getType()) {
114  HDF5CFStr *sca_str = NULL;
115  try {
116  sca_str = new HDF5CFStr(var->getNewName(), filename, var->getFullPath());
117  }
118  catch (...) {
119  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFStr.");
120  }
121  dds.add_var(sca_str);
122  delete sca_str;
123  }
124  else {
125  switch (var->getType()) {
126 
127  case H5UCHAR: {
128  HDF5CFByte * sca_uchar = NULL;
129  try {
130  sca_uchar = new HDF5CFByte(var->getNewName(), var->getFullPath(), filename);
131  }
132  catch (...) {
133  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFByte.");
134  }
135  dds.add_var(sca_uchar);
136  delete sca_uchar;
137 
138  }
139  break;
140  case H5CHAR:
141  case H5INT16: {
142  HDF5CFInt16 * sca_int16 = NULL;
143  try {
144  sca_int16 = new HDF5CFInt16(var->getNewName(), var->getFullPath(), filename);
145  }
146  catch (...) {
147  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFInt16.");
148  }
149  dds.add_var(sca_int16);
150  delete sca_int16;
151  }
152  break;
153  case H5UINT16: {
154  HDF5CFUInt16 * sca_uint16 = NULL;
155  try {
156  sca_uint16 = new HDF5CFUInt16(var->getNewName(), var->getFullPath(), filename);
157  }
158  catch (...) {
159  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFUInt16.");
160  }
161  dds.add_var(sca_uint16);
162  delete sca_uint16;
163  }
164  break;
165  case H5INT32: {
166  HDF5CFInt32 * sca_int32 = NULL;
167  try {
168  sca_int32 = new HDF5CFInt32(var->getNewName(), var->getFullPath(), filename);
169  }
170  catch (...) {
171  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFInt32.");
172  }
173  dds.add_var(sca_int32);
174  delete sca_int32;
175  }
176  break;
177  case H5UINT32: {
178  HDF5CFUInt32 * sca_uint32 = NULL;
179  try {
180  sca_uint32 = new HDF5CFUInt32(var->getNewName(), var->getFullPath(), filename);
181  }
182  catch (...) {
183  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFUInt32.");
184  }
185  dds.add_var(sca_uint32);
186  delete sca_uint32;
187  }
188  break;
189  case H5FLOAT32: {
190  HDF5CFFloat32 * sca_float32 = NULL;
191  try {
192  sca_float32 = new HDF5CFFloat32(var->getNewName(), var->getFullPath(), filename);
193  }
194  catch (...) {
195  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFFloat32.");
196  }
197  dds.add_var(sca_float32);
198  delete sca_float32;
199  }
200  break;
201  case H5FLOAT64: {
202  HDF5CFFloat64 * sca_float64 = NULL;
203  try {
204  sca_float64 = new HDF5CFFloat64(var->getNewName(), var->getFullPath(), filename);
205  }
206  catch (...) {
207  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFFloat64.");
208  }
209  dds.add_var(sca_float64);
210  delete sca_float64;
211 
212  }
213  break;
214  default:
215  throw InternalErr(__FILE__, __LINE__, "unsupported data type.");
216  }
217  }
218  }
219 
220  else {
221 
222  // 64-bit integer support
223  // DMR CHECK
224  bool dap4_int64 = false;
225  if(var->getType() == H5INT64 || var->getType()==H5UINT64) {
226  DMR * dmr = HDF5RequestHandler::get_dmr_64bit_int();
227  if(dmr == NULL)
228  return;
229  else
230  dap4_int64 = true;
231  }
232 
233 #if 0
234  else {
235  D4Group* root_grp = dmr->root();
236  BaseType *bt = NULL;
237  bt = new(HDF5Int64)(var->getNewName(),var->getFullPath(),filename);
238  bt->transform_to_dap4(root_grp,root_grp);
239  delete bt;
240  return;
241  }
242 #endif
243  BaseType *bt = NULL;
244 
245  if(true == dap4_int64) {
246  if(var->getType() == H5INT64)
247  bt = new(HDF5CFInt64)(var->getNewName(),var->getFullPath());
248  else if(var->getType() == H5UINT64)
249  bt = new(HDF5CFUInt64)(var->getNewName(),var->getFullPath());
250  }
251 
252  else {
253  switch (var->getType()) {
254 #define HANDLE_CASE(tid,type) \
255  case tid: \
256  bt = new (type)(var->getNewName(),var->getFullPath()); \
257  break;
258  HANDLE_CASE(H5FLOAT32, HDF5CFFloat32)
259  ;
260  HANDLE_CASE(H5FLOAT64, HDF5CFFloat64)
261  ;
262  HANDLE_CASE(H5CHAR, HDF5CFInt16)
263  ;
264  HANDLE_CASE(H5UCHAR, HDF5CFByte)
265  ;
266  HANDLE_CASE(H5INT16, HDF5CFInt16)
267  ;
268  HANDLE_CASE(H5UINT16, HDF5CFUInt16)
269  ;
270  HANDLE_CASE(H5INT32, HDF5CFInt32)
271  ;
272  HANDLE_CASE(H5UINT32, HDF5CFUInt32)
273  ;
274  HANDLE_CASE(H5FSTRING, Str)
275  ;
276  HANDLE_CASE(H5VSTRING, Str)
277  ;
278  default:
279  throw InternalErr(__FILE__, __LINE__, "unsupported data type.");
280 #undef HANDLE_CASE
281  }
282  }
283 
284  vector<HDF5CF::Dimension*>::const_iterator it_d;
285  vector<size_t> dimsizes;
286  dimsizes.resize(var->getRank());
287  for (int i = 0; i < var->getRank(); i++)
288  dimsizes[i] = (dims[i])->getSize();
289 
290  HDF5CFArray *ar = NULL;
291  try {
292  ar = new HDF5CFArray(var->getRank(), file_id, filename, var->getType(), dimsizes, var->getFullPath(),
293  var->getTotalElems(), CV_UNSUPPORTED, false, var->getCompRatio(), false,var->getNewName(), bt);
294  }
295  catch (...) {
296  delete bt;
297  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFStr.");
298  }
299 
300  for (it_d = dims.begin(); it_d != dims.end(); ++it_d) {
301  if ("" == (*it_d)->getNewName())
302  ar->append_dim((*it_d)->getSize());
303  else
304  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
305  }
306 
307  // When handling DAP4 CF, we need to generate dmr for 64-bit integer separately.
308  if(dap4_int64 == true) {
309  DMR * dmr = HDF5RequestHandler::get_dmr_64bit_int();
310  D4Group* root_grp = dmr->root();
311  // Dimensions need to be translated.
312  BaseType* d4_var = ar->h5cfdims_transform_to_dap4_int64(root_grp);
313  // Attributes.
314  map_cfh5_var_attrs_to_dap4_int64(var,d4_var);
315  root_grp->add_var_nocopy(d4_var);
316  }
317  else
318  dds.add_var(ar);
319 
320  delete bt;
321  delete ar;
322  }
323 
324  return;
325 
326 }
327 
328 // Currently only when the datatype of fillvalue is not the same as the datatype of the variable,
329 // special attribute handling is needed.
330 bool need_special_attribute_handling(const HDF5CF::Attribute* attr, const HDF5CF::Var* var)
331 {
332  return ((("_FillValue" == attr->getNewName()) && (var->getType() != attr->getType())) ? true : false);
333 }
334 
335 // Currently we only handle the case when the datatype of _FillValue is not the same as the variable datatype.
336 void gen_dap_special_oneobj_das(AttrTable*at, const HDF5CF::Attribute* attr, const HDF5CF::Var* var)
337 {
338 
339  BESDEBUG("h5", "Coming to gen_dap_special_oneobj_das() "<<endl);
340  if (attr->getCount() != 1) throw InternalErr(__FILE__, __LINE__, "FillValue attribute can only have one element.");
341 
342  H5DataType var_dtype = var->getType();
343  if ((true == HDF5RequestHandler::get_fillvalue_check())
344  && (false == is_fvalue_valid(var_dtype, attr))) {
345  string msg = "The attribute value is out of the range.\n";
346  msg += "The variable name: " + var->getNewName() + "\n";
347  msg += "The attribute name: " + attr->getNewName() + "\n";
348  msg += "The error occurs inside the gen_dap_special_oneobj_das function in h5commoncfdap.cc.";
349  throw InternalErr(msg);
350  }
351  string print_rep = HDF5CFDAPUtil::print_attr(attr->getType(), 0, (void*) (&(attr->getValue()[0])));
352  at->append_attr(attr->getNewName(), HDF5CFDAPUtil::print_type(var_dtype), print_rep);
353 }
354 
355 // Check if this fillvalue is in the valid datatype range when the fillvalue datatype is changed to follow the CF
356 bool is_fvalue_valid(H5DataType var_dtype, const HDF5CF::Attribute* attr)
357 {
358 
359  BESDEBUG("h5", "Coming to is_fvalue_valid() "<<endl);
360  bool ret_value = true;
361  // We only check 8-bit and 16-bit integers.
362  switch (attr->getType()) {
363  case H5CHAR: {
364  signed char final_fill_value = *((signed char*) ((void*) (&(attr->getValue()[0]))));
365  if ((var_dtype == H5UCHAR) && (final_fill_value<0))
366  ret_value = false;
367  return ret_value;
368 
369  }
370  case H5INT16: {
371  short final_fill_value = *((short*) ((void*) (&(attr->getValue()[0]))));
372  if ((var_dtype == H5UCHAR) &&(final_fill_value > 255 || final_fill_value < 0))
373  ret_value = false;
374 
375  // No need to check the var_dtype==H5CHAR case since it is mapped to int16.
376  else if ((var_dtype == H5UINT16) && (final_fill_value < 0))
377  ret_value = false;
378  return ret_value;
379  }
380  case H5UINT16: {
381  unsigned short final_fill_value = *((unsigned short*) ((void*) (&(attr->getValue()[0]))));
382  if ((var_dtype == H5UCHAR) &&(final_fill_value > 255)) {
383  ret_value = false;
384  }
385  else if ((var_dtype == H5INT16) && (final_fill_value >32767)){
386  ret_value = false;
387  }
388  return ret_value;
389 
390  }
391  // We are supposed to check the case when the datatype of fillvalue is unsigned char.
392  // However, since the variable type signed char is always mapped to int16, so there
393  // will never be an overflow case(the signed char case is the only possible one).
394  // Still the data producer should not do this. We will not check this in the handler.KY 2016-03-04
395 #if 0
396  case H5UCHAR:
397  {
398  unsigned char final_fill_value = *((unsigned char*)((void*)(&(attr->getValue()[0]))));
399  if(var_dtype == H5CHAR) {
400  if(final_fill_value >127)
401  ret_value = false;
402  }
403  return ret_value;
404  }
405 
406  case H5UCHAR:
407  case H5INT32:
408  case H5UINT32:
409 #endif
410 
411  default:
412  return ret_value;
413  }
414 
415 }
416 // Leave the old code for the time being. KY 2015-05-07
417 #if 0
418 void gen_dap_special_oneobj_das(AttrTable*at, const HDF5CF::Attribute* attr,const HDF5CF::Var* var) {
419 
420  if (attr->getCount() != 1)
421  throw InternalErr(__FILE__,__LINE__,"FillValue attribute can only have one element.");
422 
423  H5DataType var_dtype = var->getType();
424  switch(var_dtype) {
425 
426  case H5UCHAR:
427  {
428  unsigned char final_fill_value = *((unsigned char*)((void*)(&(attr->getValue()[0]))));
429  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
430  }
431  break;
432 
433  case H5CHAR:
434  {
435  // Notice HDF5 native char maps to DAP int16.
436  short final_fill_value = *((short*)((void*)(&(attr->getValue()[0]))));
437  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
438  }
439  break;
440  case H5INT16:
441  {
442  short final_fill_value = *((short*)((void*)(&(attr->getValue()[0]))));
443  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
444  }
445  break;
446  case H5UINT16:
447  {
448  unsigned short final_fill_value = *((unsigned short*)((void*)(&(attr->getValue()[0]))));
449  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
450  }
451  break;
452 
453  case H5INT32:
454  {
455  int final_fill_value = *((int*)((void*)(&(attr->getValue()[0]))));
456  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
457  }
458  break;
459  case H5UINT32:
460  {
461  unsigned int final_fill_value = *((unsigned int*)((void*)(&(attr->getValue()[0]))));
462  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
463  }
464  break;
465  case H5FLOAT32:
466  {
467  float final_fill_value = *((float*)((void*)(&(attr->getValue()[0]))));
468 // memcpy(&(attr->getValue()[0]),(void*)(&final_fill_value),sizeof(float));
469 //cerr<<"final_fill_value is "<<final_fill_value <<endl;
470  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
471  }
472  break;
473  case H5FLOAT64:
474  {
475  double final_fill_value = *((double*)((void*)(&(attr->getValue()[0]))));
476  print_rep = HDF5CFDAPUtil::print_attr(var_dtype,0,(void*)&final_fill_value);
477  }
478  break;
479  default:
480  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
481  }
482 
483  at->append_attr(attr->getNewName(), HDF5CFDAPUtil::print_type(var_dtype), print_rep);
484 }
485 #endif
486 
487 // Generate DAS from one variable
488 void gen_dap_oneobj_das(AttrTable*at, const HDF5CF::Attribute* attr, const HDF5CF::Var *var)
489 {
490 
491  BESDEBUG("h5", "Coming to gen_dap_oneobj_das() "<<endl);
492  // DMR support for 64-bit integer
493  if (H5INT64 == attr->getType() || H5UINT64 == attr->getType()) {
494  // TODO: Add code to tackle DMR for the variable datatype that is not 64-bit integer.
495  return;
496 
497  }
498  else if ((H5FSTRING == attr->getType()) || (H5VSTRING == attr->getType())) {
499  gen_dap_str_attr(at, attr);
500  }
501  else {
502 
503  if (NULL == var) {
504 
505  // HDF5 Native Char maps to DAP INT16(DAP doesn't have the corresponding datatype), so needs to
506  // obtain the mem datatype.
507  size_t mem_dtype_size = (attr->getBufSize()) / (attr->getCount());
508  H5DataType mem_dtype = HDF5CFDAPUtil::get_mem_dtype(attr->getType(), mem_dtype_size);
509 
510  for (unsigned int loc = 0; loc < attr->getCount(); loc++) {
511  string print_rep = HDF5CFDAPUtil::print_attr(mem_dtype, loc, (void*) &(attr->getValue()[0]));
512  at->append_attr(attr->getNewName(), HDF5CFDAPUtil::print_type(attr->getType()), print_rep);
513  }
514 
515  }
516 
517  else {
518 
519  // The datatype of _FillValue attribute needs to be the same as the variable datatype for an netCDF C file.
520  // To make OPeNDAP's netCDF file out work, we need to change the attribute datatype of _FillValue to be the
521  // same as the variable datatype if they are not the same. An OMI-Aura_L2-OMUVB file has such a case.
522  // The datatype of "TerrainHeight" is int32 but the datatype of the fillvalue is int16.
523  // KY 2012-11-20
524  bool special_attr_handling = need_special_attribute_handling(attr, var);
525  if (true == special_attr_handling) {
526  gen_dap_special_oneobj_das(at, attr, var);
527  }
528 
529  else {
530 
531  // HDF5 Native Char maps to DAP INT16(DAP doesn't have the corresponding datatype), so needs to
532  // obtain the mem datatype.
533  size_t mem_dtype_size = (attr->getBufSize()) / (attr->getCount());
534  H5DataType mem_dtype = HDF5CFDAPUtil::get_mem_dtype(attr->getType(), mem_dtype_size);
535 
536  for (unsigned int loc = 0; loc < attr->getCount(); loc++) {
537  string print_rep = HDF5CFDAPUtil::print_attr(mem_dtype, loc, (void*) &(attr->getValue()[0]));
538  at->append_attr(attr->getNewName(), HDF5CFDAPUtil::print_type(attr->getType()), print_rep);
539  }
540  }
541  }
542  }
543 }
544 
545 // Generate DMR from one variable
546 void gen_dap_onevar_dmr(libdap::D4Group* d4_grp, const HDF5CF::Var* var, const hid_t file_id, const string & filename) {
547 
548  BESDEBUG("h5", "Coming to gen_dap_onevar_dmr() "<<endl);
549 
550  const vector<HDF5CF::Dimension *>& dims = var->getDimensions();
551 
552  if (dims.empty()) {
553 
554  if (H5FSTRING == var->getType() || H5VSTRING == var->getType()) {
555  HDF5CFStr *sca_str = NULL;
556  try {
557  sca_str = new HDF5CFStr(var->getNewName(), filename, var->getFullPath());
558  sca_str->set_is_dap4(true);
559  map_cfh5_var_attrs_to_dap4(var,sca_str);
560  }
561  catch (...) {
562  delete sca_str;
563  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFStr.");
564  }
565  d4_grp->add_var_nocopy(sca_str);
566  }
567  else {
568  switch (var->getType()) {
569 
570  case H5UCHAR: {
571  HDF5CFByte * sca_uchar = NULL;
572  try {
573  sca_uchar = new HDF5CFByte(var->getNewName(), var->getFullPath(), filename);
574  sca_uchar->set_is_dap4(true);
575  map_cfh5_var_attrs_to_dap4(var,sca_uchar);
576  }
577  catch (...) {
578  delete sca_uchar;
579  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFByte.");
580  }
581  d4_grp->add_var_nocopy(sca_uchar);
582  }
583  break;
584  case H5CHAR: {
585  HDF5CFInt8 * sca_char = NULL;
586  try {
587  sca_char = new HDF5CFInt8(var->getNewName(), var->getFullPath(), filename);
588  sca_char->set_is_dap4(true);
589  map_cfh5_var_attrs_to_dap4(var,sca_char);
590  }
591  catch (...) {
592  delete sca_char;
593  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFByte.");
594  }
595  d4_grp->add_var_nocopy(sca_char);
596  }
597  break;
598 
599  case H5INT16: {
600  HDF5CFInt16 * sca_int16 = NULL;
601  try {
602  sca_int16 = new HDF5CFInt16(var->getNewName(), var->getFullPath(), filename);
603  sca_int16->set_is_dap4(true);
604  map_cfh5_var_attrs_to_dap4(var,sca_int16);
605 
606  }
607  catch (...) {
608  delete sca_int16;
609  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFInt16.");
610  }
611  d4_grp->add_var_nocopy(sca_int16);
612  }
613  break;
614  case H5UINT16: {
615  HDF5CFUInt16 * sca_uint16 = NULL;
616  try {
617  sca_uint16 = new HDF5CFUInt16(var->getNewName(), var->getFullPath(), filename);
618  sca_uint16->set_is_dap4(true);
619  map_cfh5_var_attrs_to_dap4(var,sca_uint16);
620  }
621  catch (...) {
622  delete sca_uint16;
623  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFUInt16.");
624  }
625  d4_grp->add_var_nocopy(sca_uint16);
626  }
627  break;
628  case H5INT32: {
629  HDF5CFInt32 * sca_int32 = NULL;
630  try {
631  sca_int32 = new HDF5CFInt32(var->getNewName(), var->getFullPath(), filename);
632  sca_int32->set_is_dap4(true);
633  map_cfh5_var_attrs_to_dap4(var,sca_int32);
634  }
635  catch (...) {
636  delete sca_int32;
637  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFInt32.");
638  }
639  d4_grp->add_var_nocopy(sca_int32);
640  }
641  break;
642  case H5UINT32: {
643  HDF5CFUInt32 * sca_uint32 = NULL;
644  try {
645  sca_uint32 = new HDF5CFUInt32(var->getNewName(), var->getFullPath(), filename);
646  sca_uint32->set_is_dap4(true);
647  map_cfh5_var_attrs_to_dap4(var,sca_uint32);
648  }
649  catch (...) {
650  delete sca_uint32;
651  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFUInt32.");
652  }
653  d4_grp->add_var_nocopy(sca_uint32);
654  }
655  break;
656  case H5INT64: {
657  HDF5CFInt64 * sca_int64 = NULL;
658  try {
659  sca_int64 = new HDF5CFInt64(var->getNewName(), var->getFullPath(), filename);
660  sca_int64->set_is_dap4(true);
661  map_cfh5_var_attrs_to_dap4(var,sca_int64);
662  }
663  catch (...) {
664  delete sca_int64;
665  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFInt64.");
666  }
667  d4_grp->add_var_nocopy(sca_int64);
668  }
669  break;
670  case H5UINT64: {
671  HDF5CFUInt64 * sca_uint64 = NULL;
672  try {
673  sca_uint64 = new HDF5CFUInt64(var->getNewName(), var->getFullPath(), filename);
674  sca_uint64->set_is_dap4(true);
675  map_cfh5_var_attrs_to_dap4(var,sca_uint64);
676  }
677  catch (...) {
678  delete sca_uint64;
679  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFUInt64.");
680  }
681  d4_grp->add_var_nocopy(sca_uint64);
682  }
683  break;
684  case H5FLOAT32: {
685  HDF5CFFloat32 * sca_float32 = NULL;
686  try {
687  sca_float32 = new HDF5CFFloat32(var->getNewName(), var->getFullPath(), filename);
688  sca_float32->set_is_dap4(true);
689  map_cfh5_var_attrs_to_dap4(var,sca_float32);
690  }
691  catch (...) {
692  delete sca_float32;
693  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFFloat32.");
694  }
695  d4_grp->add_var_nocopy(sca_float32);
696  }
697  break;
698  case H5FLOAT64: {
699  HDF5CFFloat64 * sca_float64 = NULL;
700  try {
701  sca_float64 = new HDF5CFFloat64(var->getNewName(), var->getFullPath(), filename);
702  sca_float64->set_is_dap4(true);
703  map_cfh5_var_attrs_to_dap4(var,sca_float64);
704  }
705  catch (...) {
706  delete sca_float64;
707  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFFloat64.");
708  }
709  d4_grp->add_var_nocopy(sca_float64);
710  }
711  break;
712  default:
713  throw InternalErr(__FILE__, __LINE__, "unsupported data type.");
714  }
715  }
716  }
717 
718  else {
719 
720  BaseType *bt = NULL;
721 
722  switch (var->getType()) {
723 #define HANDLE_CASE(tid,type) \
724  case tid: \
725  bt = new (type)(var->getNewName(),var->getFullPath()); \
726  break;
727  HANDLE_CASE(H5FLOAT32, HDF5CFFloat32)
728  ;
729  HANDLE_CASE(H5FLOAT64, HDF5CFFloat64)
730  ;
731  HANDLE_CASE(H5CHAR, HDF5CFInt8)
732  ;
733  HANDLE_CASE(H5UCHAR, HDF5CFByte)
734  ;
735  HANDLE_CASE(H5INT16, HDF5CFInt16)
736  ;
737  HANDLE_CASE(H5UINT16, HDF5CFUInt16)
738  ;
739  HANDLE_CASE(H5INT32, HDF5CFInt32)
740  ;
741  HANDLE_CASE(H5UINT32, HDF5CFUInt32)
742  ;
743  HANDLE_CASE(H5INT64, HDF5CFInt64)
744  ;
745  HANDLE_CASE(H5UINT64, HDF5CFUInt64)
746  ;
747  HANDLE_CASE(H5FSTRING, Str)
748  ;
749  HANDLE_CASE(H5VSTRING, Str)
750  ;
751  default:
752  throw InternalErr(__FILE__, __LINE__, "unsupported data type.");
753 #undef HANDLE_CASE
754  }
755 
756  vector<HDF5CF::Dimension*>::const_iterator it_d;
757  vector<size_t> dimsizes;
758  dimsizes.resize(var->getRank());
759  for (int i = 0; i < var->getRank(); i++)
760  dimsizes[i] = (dims[i])->getSize();
761 
762  HDF5CFArray *ar = NULL;
763  try {
764  ar = new HDF5CFArray(var->getRank(), file_id, filename, var->getType(), dimsizes, var->getFullPath(),
765  var->getTotalElems(), CV_UNSUPPORTED, false, var->getCompRatio(), true,var->getNewName(), bt);
766  }
767  catch (...) {
768  delete bt;
769  throw InternalErr(__FILE__, __LINE__, "Cannot allocate the HDF5CFStr.");
770  }
771 
772  for (it_d = dims.begin(); it_d != dims.end(); ++it_d) {
773  if ("" == (*it_d)->getNewName())
774  ar->append_dim((*it_d)->getSize());
775  else
776  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
777  }
778 
779  delete bt;
780  ar->set_is_dap4(true);
781  BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_grp);
782  map_cfh5_var_attrs_to_dap4(var,d4_var);
783  d4_grp->add_var_nocopy(d4_var);
784  delete ar;
785 
786  }
787 
788  return;
789 
790 
791 
792 }
793 
794 
795 void gen_dap_str_attr(AttrTable *at, const HDF5CF::Attribute *attr)
796 {
797 
798  BESDEBUG("h5", "Coming to gen_dap_str_attr() "<<endl);
799  const vector<size_t>& strsize = attr->getStrSize();
800 //cerr<<"in DAS strsize is "<<strsize.size() <<endl;
801  unsigned int temp_start_pos = 0;
802  bool is_cset_ascii = attr->getCsetType();
803  for (unsigned int loc = 0; loc < attr->getCount(); loc++) {
804  if (strsize[loc] != 0) {
805  string tempstring(attr->getValue().begin() + temp_start_pos,
806  attr->getValue().begin() + temp_start_pos + strsize[loc]);
807  temp_start_pos += strsize[loc];
808 
809  // If the string size is longer than the current netCDF JAVA
810  // string and the "EnableDropLongString" key is turned on,
811  // No string is generated.
812  // The above statement is no longer true. The netCDF Java can handle long string
813  // attributes. The long string can be kept and I do think the
814  // performance penalty should be small. KY 2018-02-26
815  if ((attr->getNewName() != "origname") && (attr->getNewName() != "fullnamepath") && (true == is_cset_ascii))
816  tempstring = HDF5CFDAPUtil::escattr(tempstring);
817  at->append_attr(attr->getNewName(), "String", tempstring);
818  }
819  }
820 }
821 
822 //#if 0
823 // This function adds the 1-D horizontal coordinate variables as well as the dummy projection variable to the grid.
824 //Note: Since we don't add these artifical CF variables to our main engineering at HDFEOS5CF.cc, the information
825 // to handle DAS won't pass to DDS by the file pointer, we need to re-call the routines to check projection
826 // and dimension. The time to retrieve these information is trivial compared with the whole translation.
827 void add_cf_grid_cvs(DDS & dds, EOS5GridPCType cv_proj_code, float cv_point_lower, float cv_point_upper,
828  float cv_point_left, float cv_point_right, const vector<HDF5CF::Dimension*>& dims)
829 {
830 
831  //1. Check the projection information: we first just handled the sinusoidal projection.
832  // We also add the LAMAZ and PS support. These 1-D varaibles are the same as the sinusoidal one.
833  if (HE5_GCTP_SNSOID == cv_proj_code || HE5_GCTP_LAMAZ == cv_proj_code || HE5_GCTP_PS == cv_proj_code) {
834 
835  //2. Obtain the dimension information from latitude and longitude(fieldtype =1 or fieldtype =2)
836  vector<HDF5CF::Dimension*>::const_iterator it_d;
837  string dim0name = dims[0]->getNewName();
838  int dim0size = dims[0]->getSize();
839  string dim1name = dims[1]->getNewName();
840  int dim1size = dims[1]->getSize();
841 
842  //3. Add the 1-D CV variables and the dummy projection variable
843  BaseType *bt_dim0 = NULL;
844  BaseType *bt_dim1 = NULL;
845 
846  HDF5CFGeoCF1D * ar_dim0 = NULL;
847  HDF5CFGeoCF1D * ar_dim1 = NULL;
848 
849  try {
850 
851  bt_dim0 = new (HDF5CFFloat64)(dim0name, dim0name);
852  bt_dim1 = new (HDF5CFFloat64)(dim1name, dim1name);
853 
854  // Note ar_dim0 is y, ar_dim1 is x.
855  ar_dim0 = new HDF5CFGeoCF1D(HE5_GCTP_SNSOID, cv_point_upper, cv_point_lower, dim0size, dim0name, bt_dim0);
856  ar_dim0->append_dim(dim0size, dim0name);
857 
858  ar_dim1 = new HDF5CFGeoCF1D(HE5_GCTP_SNSOID, cv_point_left, cv_point_right, dim1size, dim1name, bt_dim1);
859  ar_dim1->append_dim(dim1size, dim1name);
860  dds.add_var(ar_dim0);
861  dds.add_var(ar_dim1);
862 
863  }
864  catch (...) {
865  if (bt_dim0) delete bt_dim0;
866  if (bt_dim1) delete bt_dim1;
867  if (ar_dim0) delete ar_dim0;
868  if (ar_dim1) delete ar_dim1;
869  throw InternalErr(__FILE__, __LINE__, "Unable to allocate the HDFEOS2GeoCF1D instance.");
870  }
871 
872  if (bt_dim0) delete bt_dim0;
873  if (bt_dim1) delete bt_dim1;
874  if (ar_dim0) delete ar_dim0;
875  if (ar_dim1) delete ar_dim1;
876 
877  }
878 }
879 
880 // This function adds the grid mapping variables.
881 void add_cf_grid_mapinfo_var(DDS & dds, const EOS5GridPCType grid_proj_code, const unsigned short g_suffix)
882 {
883 
884  //Add the dummy projection variable. The attributes of this variable can be used to store the grid mapping info.
885  // To handle multi-grid cases, we need to add suffixes to distinguish them.
886  string cf_projection_base = "eos_cf_projection";
887 
888  HDF5CFGeoCFProj * dummy_proj_cf = NULL;
889  if(HE5_GCTP_SNSOID == grid_proj_code) {
890  // AFAWK, one grid_mapping variable is necessary for multi-grids. So we just leave one grid here.
891  if(g_suffix == 1) {
892  dummy_proj_cf = new HDF5CFGeoCFProj(cf_projection_base, cf_projection_base);
893  dds.add_var(dummy_proj_cf);
894  }
895  }
896  else {
897  stringstream t_suffix_ss;
898  t_suffix_ss << g_suffix;
899  string cf_projection_name = cf_projection_base + "_" + t_suffix_ss.str();
900  dummy_proj_cf = new HDF5CFGeoCFProj(cf_projection_name, cf_projection_name);
901  dds.add_var(dummy_proj_cf);
902  }
903  if (dummy_proj_cf) delete dummy_proj_cf;
904 
905 }
906 
907 // This function adds 1D grid mapping CF attributes to CV and data variables.
908 #if 0
909 void add_cf_grid_cv_attrs(DAS & das, const vector<HDF5CF::Var*>& vars, EOS5GridPCType cv_proj_code,
910  float /*cv_point_lower*/, float /*cv_point_upper*/, float /*cv_point_left*/, float /*cv_point_right*/,
911  const vector<HDF5CF::Dimension*>& dims,const vector<double> &eos5_proj_params,const unsigned short g_suffix)
912 #endif
913 void add_cf_grid_cv_attrs(DAS & das, const vector<HDF5CF::Var*>& vars, EOS5GridPCType cv_proj_code,
914  const vector<HDF5CF::Dimension*>& dims,const vector<double> &eos5_proj_params,const unsigned short g_suffix)
915 {
916 
917 
918  //1. Check the projection information, now, we handle sinusoidal,PS and LAMAZ projections.
919  if (HE5_GCTP_SNSOID == cv_proj_code || HE5_GCTP_PS == cv_proj_code || HE5_GCTP_LAMAZ== cv_proj_code) {
920 
921  string dim0name = (dims[0])->getNewName();
922  int dim0size = dims[0]->getSize();
923  string dim1name = (dims[1])->getNewName();
924  int dim1size = dims[1]->getSize();
925 
926  //2. Add 1D CF attributes to the 1-D CV variables and the dummy grid_mapping variable
927  AttrTable *at = das.get_table(dim0name);
928  if (!at)
929  at = das.add_table(dim0name, new AttrTable);
930  at->append_attr("standard_name", "String", "projection_y_coordinate");
931 
932  string long_name = "y coordinate of projection ";
933  at->append_attr("long_name", "String", long_name);
934 
935  // Change this to meter.
936  at->append_attr("units", "string", "meter");
937 
938  at->append_attr("_CoordinateAxisType", "string", "GeoY");
939 
940  at = das.get_table(dim1name);
941  if (!at) at = das.add_table(dim1name, new AttrTable);
942 
943  at->append_attr("standard_name", "String", "projection_x_coordinate");
944 
945  long_name = "x coordinate of projection ";
946  at->append_attr("long_name", "String", long_name);
947 
948  // change this to meter.
949  at->append_attr("units", "string", "meter");
950 
951  // This is for CDM conventions. Adding doesn't do harm. Same as GeoY.
952  at->append_attr("_CoordinateAxisType", "string", "GeoX");
953 
954  // Add the attributes for the dummy grid_mapping variable.
955  string cf_projection_base = "eos_cf_projection";
956  string cf_projection;
957  if(HE5_GCTP_SNSOID == cv_proj_code)
958  cf_projection = cf_projection_base;
959  else {
960  stringstream t_suffix_ss;
961  t_suffix_ss << g_suffix;
962  cf_projection = cf_projection_base + "_" + t_suffix_ss.str();
963  }
964  add_cf_projection_attrs(das,cv_proj_code,eos5_proj_params,cf_projection);
965 
966  // Fill in the data fields that contains the dim0name and dim1name dimensions with the grid_mapping
967  // We only apply to >=2D data fields.
968  add_cf_grid_mapping_attr(das, vars, cf_projection, dim0name, dim0size, dim1name, dim1size);
969  }
970 
971 }
972 
973 // Add CF projection attribute
974 
975 void add_cf_projection_attrs(DAS &das,EOS5GridPCType cv_proj_code,const vector<double> &eos5_proj_params,const string& cf_projection) {
976 
977  AttrTable* at = das.get_table(cf_projection);
978  if (!at) {// Only append attributes when the table is created.
979  at = das.add_table(cf_projection, new AttrTable);
980 
981  if (HE5_GCTP_SNSOID == cv_proj_code) {
982  at->append_attr("grid_mapping_name", "String", "sinusoidal");
983  at->append_attr("longitude_of_central_meridian", "Float64", "0.0");
984  at->append_attr("earth_radius", "Float64", "6371007.181");
985  at->append_attr("_CoordinateAxisTypes", "string", "GeoX GeoY");
986  }
987  else if (HE5_GCTP_PS == cv_proj_code) {
988 
989  // The following information is added according to the HDF-EOS5 user's guide and
990  // CF 1.7 grid_mapping requirement.
991 
992  // Longitude down below pole of map
993  double vert_lon_pole = HE5_EHconvAng(eos5_proj_params[4],HE5_HDFE_DMS_DEG);
994 
995  // Latitude of true scale
996  double lat_true_scale = HE5_EHconvAng(eos5_proj_params[5],HE5_HDFE_DMS_DEG);
997 
998  // False easting
999  double fe = eos5_proj_params[6];
1000 
1001  // False northing
1002  double fn = eos5_proj_params[7];
1003 
1004  at->append_attr("grid_mapping_name", "String", "polar_stereographic");
1005 
1006  ostringstream s_vert_lon_pole;
1007  s_vert_lon_pole << vert_lon_pole;
1008 
1009  // I did this map is based on my best understanding. I cannot be certain about south pole. KY
1010  // CF: straight_vertical_longitude_from_pole
1011  at->append_attr("straight_vertical_longitude_from_pole", "Float64", s_vert_lon_pole.str());
1012  ostringstream s_lat_true_scale;
1013  s_lat_true_scale << lat_true_scale;
1014 
1015  at->append_attr("standard_parallel", "Float64", s_lat_true_scale.str());
1016 
1017  if(fe == 0.0)
1018  at->append_attr("false_easting","Float64","0.0");
1019  else {
1020  ostringstream s_fe;
1021  s_fe << fe;
1022  at->append_attr("false_easting","Float64",s_fe.str());
1023  }
1024 
1025 
1026  if(fn == 0.0)
1027  at->append_attr("false_northing","Float64","0.0");
1028  else {
1029  ostringstream s_fn;
1030  s_fn << fn;
1031  at->append_attr("false_northing","Float64",s_fn.str());
1032  }
1033 
1034 
1035  if(lat_true_scale >0)
1036  at->append_attr("latitude_of_projection_origin","Float64","+90.0");
1037  else
1038  at->append_attr("latitude_of_projection_origin","Float64","-90.0");
1039 
1040 
1041  at->append_attr("_CoordinateAxisTypes", "string", "GeoX GeoY");
1042 
1043  // From CF, PS has another parameter,
1044  // Either standard_parallel (EPSG 9829) or scale_factor_at_projection_origin (EPSG 9810)
1045  // I cannot find the corresponding parameter from the EOS5.
1046 
1047  }
1048  else if(HE5_GCTP_LAMAZ == cv_proj_code) {
1049  double lon_proj_origin = HE5_EHconvAng(eos5_proj_params[4],HE5_HDFE_DMS_DEG);
1050  double lat_proj_origin = HE5_EHconvAng(eos5_proj_params[5],HE5_HDFE_DMS_DEG);
1051  double fe = eos5_proj_params[6];
1052  double fn = eos5_proj_params[7];
1053 
1054  at->append_attr("grid_mapping_name", "String", "lambert_azimuthal_equal_area");
1055 
1056  ostringstream s_lon_proj_origin;
1057  s_lon_proj_origin << lon_proj_origin;
1058  at->append_attr("longitude_of_projection_origin", "Float64", s_lon_proj_origin.str());
1059 
1060  ostringstream s_lat_proj_origin;
1061  s_lat_proj_origin << lat_proj_origin;
1062 
1063  at->append_attr("latitude_of_projection_origin", "Float64", s_lat_proj_origin.str());
1064 
1065 
1066  if(fe == 0.0)
1067  at->append_attr("false_easting","Float64","0.0");
1068  else {
1069  ostringstream s_fe;
1070  s_fe << fe;
1071  at->append_attr("false_easting","Float64",s_fe.str());
1072  }
1073 
1074 
1075  if(fn == 0.0)
1076  at->append_attr("false_northing","Float64","0.0");
1077  else {
1078  ostringstream s_fn;
1079  s_fn << fn;
1080  at->append_attr("false_northing","Float64",s_fn.str());
1081  }
1082 
1083  at->append_attr("_CoordinateAxisTypes", "string", "GeoX GeoY");
1084 
1085 
1086  }
1087  }
1088 
1089 }
1090 
1091 
1092 // This function adds the 1-D cf grid projection mapping attribute to data variables
1093 // it is called by the function add_cf_grid_attrs.
1094 void add_cf_grid_mapping_attr(DAS &das, const vector<HDF5CF::Var*>& vars, const string& cf_projection,
1095  const string & dim0name, hsize_t dim0size, const string &dim1name, hsize_t dim1size)
1096 {
1097 
1098 #if 0
1099  cerr<<"dim0name is "<<dim0name <<endl;
1100  cerr<<"dim1name is "<<dim1name <<endl;
1101  cerr<<"dim0size is "<<dim0size <<endl;
1102  cerr<<"dim1size is "<<dim1size <<endl;
1103 #endif
1104 
1105  // Check >=2-D fields, check if they hold the dim0name,dim0size etc., yes, add the attribute cf_projection.
1106  vector<HDF5CF::Var *>::const_iterator it_v;
1107  for (it_v = vars.begin(); it_v != vars.end(); ++it_v) {
1108 
1109  if ((*it_v)->getRank() > 1) {
1110  bool has_dim0 = false;
1111  bool has_dim1 = false;
1112  const vector<HDF5CF::Dimension*>& dims = (*it_v)->getDimensions();
1113  for (vector<HDF5CF::Dimension *>::const_iterator j = dims.begin(); j != dims.end(); ++j) {
1114  if ((*j)->getNewName() == dim0name && (*j)->getSize() == dim0size)
1115  has_dim0 = true;
1116  else if ((*j)->getNewName() == dim1name && (*j)->getSize() == dim1size)
1117  has_dim1 = true;
1118 
1119  }
1120  if (true == has_dim0 && true == has_dim1) { // Need to add the grid_mapping attribute
1121  AttrTable *at = das.get_table((*it_v)->getNewName());
1122  if (!at) at = das.add_table((*it_v)->getNewName(), new AttrTable);
1123 
1124  // The dummy projection name is the value of the grid_mapping attribute
1125  at->append_attr("grid_mapping", "String", cf_projection);
1126  }
1127  }
1128  }
1129 }
1130 // Now this is specially for LAMAZ where the NSIDC EASE-Grid may have points off the earth. So
1131 // The calculated lat/lon are set to number out of the normal range. The valid_range attributes
1132 // will hopefully constrain the applications not to consider those points.
1133 void add_ll_valid_range(AttrTable* at, bool is_lat) {
1134  if(true == is_lat) {
1135  at->append_attr("valid_min", "Float64","-90.0");
1136  at->append_attr("valid_max", "Float64","90.0");
1137  }
1138  else {
1139  at->append_attr("valid_min", "Float64","-180.0");
1140  at->append_attr("valid_max", "Float64","180.0");
1141  }
1142 }
1143 
1144 // This routine is for 64-bit DAP4 CF support: when var type is 64-bit integer.
1145 // Note: the main part of DMR still comes from DDS and DAS.
1146 bool need_attr_values_for_dap4(const HDF5CF::Var *var) {
1147  bool ret_value = false;
1148  if((HDF5RequestHandler::get_dmr_64bit_int()!=NULL) &&
1149  (H5INT64 == var->getType() || H5UINT64 == var->getType()))
1150  ret_value = true;
1151  return ret_value;
1152 }
1153 
1154 // This routine is for 64-bit DAP4 CF support: map all attributes to DAP4 for 64-bit integers.
1155 // Note: the main part of DMR still comes from DDS and DAS.
1156 void map_cfh5_var_attrs_to_dap4_int64(const HDF5CF::Var *var,BaseType* d4_var) {
1157 
1158  vector<HDF5CF::Attribute *>::const_iterator it_ra;
1159  for (it_ra = var->getAttributes().begin();
1160  it_ra != var->getAttributes().end(); ++it_ra) {
1161  // HDF5 Native Char maps to DAP INT16(DAP doesn't have the corresponding datatype), so needs to
1162  // obtain the mem datatype. Keep this in DAP4 mapping.
1163  size_t mem_dtype_size = ((*it_ra)->getBufSize()) / ((*it_ra)->getCount());
1164  H5DataType mem_dtype = HDF5CFDAPUtil::get_mem_dtype((*it_ra)->getType(), mem_dtype_size);
1165 
1166  string dap2_attrtype = HDF5CFDAPUtil::print_type(mem_dtype);
1167  D4AttributeType dap4_attrtype = HDF5CFDAPUtil::daptype_strrep_to_dap4_attrtype(dap2_attrtype);
1168  D4Attribute *d4_attr = new D4Attribute((*it_ra)->getNewName(),dap4_attrtype);
1169  if(dap4_attrtype == attr_str_c) {
1170  if("coordinates" == (*it_ra)->getNewName()) {
1171  bool chg_coor_value = false;
1172  if((true == HDF5RequestHandler::get_enable_coord_attr_add_path())
1173  &&(true == var->getCoorAttrAddPath()))
1174  chg_coor_value = true;
1175  string tempstring;
1176  handle_coor_attr_for_int64_var((*it_ra),var->getFullPath(),tempstring,chg_coor_value);
1177  d4_attr->add_value(tempstring);
1178  }
1179  else {
1180  const vector<size_t>& strsize = (*it_ra)->getStrSize();
1181  unsigned int temp_start_pos = 0;
1182  for (unsigned int loc = 0; loc < (*it_ra)->getCount(); loc++) {
1183  if (strsize[loc] != 0) {
1184  string tempstring((*it_ra)->getValue().begin() + temp_start_pos,
1185  (*it_ra)->getValue().begin() + temp_start_pos + strsize[loc]);
1186  temp_start_pos += strsize[loc];
1187  //The below if is not necessary since the "origname" and "fullnamepath" are not added.KY 2020-02-24
1188  //if (((*it_ra)->getNewName() != "origname") && ((*it_ra)->getNewName() != "fullnamepath"))
1189  tempstring = HDF5CFDAPUtil::escattr(tempstring);
1190  d4_attr->add_value(tempstring);
1191  }
1192  }
1193  }
1194 
1195  }
1196  else {
1197  for (unsigned int loc = 0; loc < (*it_ra)->getCount(); loc++) {
1198  string print_rep = HDF5CFDAPUtil::print_attr(mem_dtype, loc, (void*) &((*it_ra)->getValue()[0]));
1199  d4_attr->add_value(print_rep);
1200  }
1201  }
1202  d4_var->attributes()->add_attribute_nocopy(d4_attr);
1203  }
1204  // Here we add the "origname" and "fullnamepath" attributes since they are crucial to DMRPP generation.
1205  D4Attribute *d4_attr = new D4Attribute("origname",attr_str_c);
1206  d4_attr->add_value(var->getName());
1207  d4_var->attributes()->add_attribute_nocopy(d4_attr);
1208  d4_attr = new D4Attribute("fullnamepath",attr_str_c);
1209  d4_attr->add_value(var->getFullPath());
1210  d4_var->attributes()->add_attribute_nocopy(d4_attr);
1211 }
1212 
1213 // A helper function for 64-bit DAP4 CF support
1214 // Note: the main part of DMR still comes from DDS and DAS.
1215 void check_update_int64_attr(const string & obj_name, const HDF5CF::Attribute * attr) {
1216  if(attr->getType() == H5INT64 || attr->getType() == H5UINT64) {
1217 
1218  DMR * dmr = HDF5RequestHandler::get_dmr_64bit_int();
1219  if(dmr != NULL) {
1220  string dap2_attrtype = HDF5CFDAPUtil::print_type(attr->getType());
1221  D4AttributeType dap4_attrtype = HDF5CFDAPUtil::daptype_strrep_to_dap4_attrtype(dap2_attrtype);
1222  D4Attribute *d4_attr = new D4Attribute(attr->getNewName(),dap4_attrtype);
1223  for (unsigned int loc = 0; loc < attr->getCount(); loc++) {
1224  string print_rep = HDF5CFDAPUtil::print_attr(attr->getType(), loc, (void*) &(attr->getValue()[0]));
1225  d4_attr->add_value(print_rep);
1226  }
1227  D4Group * root_grp = dmr->root();
1228  D4Attribute *d4_hg_container;
1229  if(root_grp->attributes()->empty() == true){
1230 #if 0
1231  //D4Attribute *d4_hg_container = root_grp->attributes()->find("HDF5_GLOBAL");
1232  //if(d4_hg_container == NULL) {
1233 #endif
1234  d4_hg_container = new D4Attribute;
1235  d4_hg_container->set_name("HDF5_GLOBAL_integer_64");
1236  d4_hg_container->set_type(attr_container_c);
1237  root_grp->attributes()->add_attribute_nocopy(d4_hg_container);
1238 #if 0
1239  //root_grp->attributes()->add_attribute(d4_hg_container);
1240 #endif
1241  }
1242  //else
1243  d4_hg_container = root_grp->attributes()->get("HDF5_GLOBAL_integer_64");
1244  if(obj_name != "") {
1245  string test_obj_name = "HDF5_GLOBAL_integer_64."+obj_name;
1246 #if 0
1247  //D4Attribute *d4_container = root_grp->attributes()->find(obj_name);
1248  //D4Attribute *d4_container = root_grp->attributes()->get(obj_name);
1249 #endif
1250  D4Attribute *d4_container = root_grp->attributes()->get(test_obj_name);
1251  // ISSUES need to search the attributes
1252  //
1253 #if 0
1254  //D4Attribute *d4_container = d4_hg_container->attributes()->find(obj_name);
1255 #endif
1256  if(d4_container == NULL) {
1257  d4_container = new D4Attribute;
1258  d4_container->set_name(obj_name);
1259  d4_container->set_type(attr_container_c);
1260 
1261 #if 0
1262  //if(d4_hg_container->attributes()->empty()==true)
1263  // cerr<<"global container is empty"<<endl;
1264  //d4_hg_container->attributes()->add_attribute_nocopy(d4_container);
1265  //cerr<<"end of d4_container "<<endl;
1266 #endif
1267  }
1268  d4_container->attributes()->add_attribute_nocopy(d4_attr);
1269 #if 0
1270  //root_grp->attributes()->add_attribute_nocopy(d4_container);
1271 #endif
1272 //#if 0
1273  if(d4_hg_container->attributes()->get(obj_name)==NULL)
1274  d4_hg_container->attributes()->add_attribute_nocopy(d4_container);
1275 //#endif
1276  }
1277  else
1278  d4_hg_container->attributes()->add_attribute_nocopy(d4_attr);
1279  }
1280  }
1281 }
1282 
1283 // Another helper function for 64-bit DAP4 CF support
1284 // Note: the main part of DMR still comes from DDS and DAS.
1285 void handle_coor_attr_for_int64_var(const HDF5CF::Attribute *attr,const string &var_path,string &tempstring,bool chg_coor_value) {
1286 
1287  string tempstring2(attr->getValue().begin(),attr->getValue().end());
1288  if(true == chg_coor_value) {
1289  char sep=' ';
1290  vector<string>cvalue_vec;
1291  HDF5CFUtil::Split_helper(cvalue_vec,tempstring2,sep);
1292  for (int i = 0; i<cvalue_vec.size();i++) {
1293  HDF5CFUtil::cha_co(cvalue_vec[i],var_path);
1294  string t_str = get_cf_string(cvalue_vec[i]);
1295  if(i == 0)
1296  tempstring = t_str;
1297  else
1298  tempstring += sep+t_str;
1299  }
1300  }
1301  else
1302  tempstring = tempstring2;
1303 
1304 }
1305 
1306 // This routine is for direct mapping from CF to DAP4. We build DMR not from DDS and DAS.
1307 // Hopefully this will be eventually used to build DMR.
1308 void map_cfh5_var_attrs_to_dap4(const HDF5CF::Var *var,BaseType* d4_var) {
1309 
1310  vector<HDF5CF::Attribute *>::const_iterator it_ra;
1311  for (it_ra = var->getAttributes().begin();
1312  it_ra != var->getAttributes().end(); ++it_ra) {
1313 
1314  D4Attribute *d4_attr = gen_dap4_attr((*it_ra));
1315  d4_var->attributes()->add_attribute_nocopy(d4_attr);
1316  }
1317 }
1318 
1319 // This routine is for direct mapping from CF to DAP4. We build DMR not from DDS and DAS.
1320 void map_cfh5_grp_attr_to_dap4(libdap::D4Group *d4_grp,const HDF5CF::Attribute *attr) {
1321 
1322  D4Attribute *d4_attr = gen_dap4_attr(attr);
1323  d4_grp->attributes()->add_attribute_nocopy(d4_attr);
1324 
1325 }
1326 
1327 // This routine is for direct mapping from CF to DAP4. We build DMR not from DDS and DAS.
1328 void map_cfh5_attr_container_to_dap4(libdap::D4Attribute *d4_con,const HDF5CF::Attribute *attr) {
1329 
1330  D4Attribute *d4_attr = gen_dap4_attr(attr);
1331  d4_con->attributes()->add_attribute_nocopy(d4_attr);
1332 
1333 }
1334 
1335 // Helper function to generate a DAP4 attribute.
1336 D4Attribute *gen_dap4_attr(const HDF5CF::Attribute *attr) {
1337 
1338  D4AttributeType dap4_attrtype = HDF5CFDAPUtil::print_type_dap4(attr->getType());
1339  D4Attribute *d4_attr = new D4Attribute(attr->getNewName(),dap4_attrtype);
1340  if(dap4_attrtype == attr_str_c) {
1341 
1342  const vector<size_t>& strsize = attr->getStrSize();
1343 #if 0
1344 if(strsize.size() == 0)
1345 cerr<<"vector string size is 0"<<endl;
1346 for(int i = 0; i<strsize.size(); i++)
1347 cerr<<"attr size is "<<strsize[i] <<endl;
1348 #endif
1349  unsigned int temp_start_pos = 0;
1350  bool is_cset_ascii = attr->getCsetType();
1351  for (unsigned int loc = 0; loc < attr->getCount(); loc++) {
1352  if (strsize[loc] != 0) {
1353  string tempstring(attr->getValue().begin() + temp_start_pos,
1354  attr->getValue().begin() + temp_start_pos + strsize[loc]);
1355  temp_start_pos += strsize[loc];
1356  if ((attr->getNewName() != "origname") && (attr->getNewName() != "fullnamepath") && (true == is_cset_ascii))
1357  tempstring = HDF5CFDAPUtil::escattr(tempstring);
1358  d4_attr->add_value(tempstring);
1359  }
1360  }
1361  }
1362  else {
1363 //cerr<<"not a string type "<<endl;
1364  for (unsigned int loc = 0; loc < attr->getCount(); loc++) {
1365  string print_rep = HDF5CFDAPUtil::print_attr(attr->getType(), loc, (void*) &(attr->getValue()[0]));
1366  d4_attr->add_value(print_rep);
1367  }
1368  }
1369  return d4_attr;
1370 }
1371 
1372 // Direct CF to DAP4, add CF grid_mapping attributes of the projection variable to DAP4.
1373 // we support sinusodial, polar stereographic and lambert azimuthal equal-area(LAMAZ) projections.
1374 void add_gm_oneproj_var_dap4_attrs(BaseType *var,EOS5GridPCType cv_proj_code,const vector<double> &eos5_proj_params) {
1375 
1376  if (HE5_GCTP_SNSOID == cv_proj_code) {
1377 
1378  add_var_dap4_attr(var,"grid_mapping_name",attr_str_c,"sinusoidal");
1379  add_var_dap4_attr(var,"longitude_of_central_meridian",attr_float64_c,"0.0");
1380  add_var_dap4_attr(var,"earth_radius", attr_float64_c, "6371007.181");
1381  add_var_dap4_attr(var,"_CoordinateAxisTypes", attr_str_c, "GeoX GeoY");
1382 
1383  }
1384  else if (HE5_GCTP_PS == cv_proj_code) {
1385 
1386  // The following information is added according to the HDF-EOS5 user's guide and
1387  // CF 1.7 grid_mapping requirement.
1388 
1389  // Longitude down below pole of map
1390  double vert_lon_pole = HE5_EHconvAng(eos5_proj_params[4],HE5_HDFE_DMS_DEG);
1391 
1392  // Latitude of true scale
1393  double lat_true_scale = HE5_EHconvAng(eos5_proj_params[5],HE5_HDFE_DMS_DEG);
1394 
1395  // False easting
1396  double fe = eos5_proj_params[6];
1397 
1398  // False northing
1399  double fn = eos5_proj_params[7];
1400 
1401  add_var_dap4_attr(var,"grid_mapping_name",attr_str_c,"polar_stereographic");
1402 
1403  ostringstream s_vert_lon_pole;
1404  s_vert_lon_pole << vert_lon_pole;
1405 
1406  // I did this map is based on my best understanding. I cannot be certain about south pole. KY
1407  // CF: straight_vertical_longitude_from_pole
1408  //at->append_attr("straight_vertical_longitude_from_pole", "Float64", s_vert_lon_pole.str());
1409  add_var_dap4_attr(var,"straight_vertical_longitude_from_pole", attr_float64_c, s_vert_lon_pole.str());
1410 
1411  ostringstream s_lat_true_scale;
1412  s_lat_true_scale << lat_true_scale;
1413  add_var_dap4_attr(var,"standard_parallel", attr_float64_c, s_lat_true_scale.str());
1414 
1415  if(fe == 0.0)
1416  add_var_dap4_attr(var,"false_easting",attr_float64_c,"0.0");
1417  else {
1418  ostringstream s_fe;
1419  s_fe << fe;
1420  add_var_dap4_attr(var,"false_easting",attr_float64_c,s_fe.str());
1421  }
1422 
1423  if(fn == 0.0)
1424  add_var_dap4_attr(var,"false_northing",attr_float64_c,"0.0");
1425  else {
1426  ostringstream s_fn;
1427  s_fn << fn;
1428  add_var_dap4_attr(var,"false_northing",attr_float64_c,s_fn.str());
1429  }
1430 
1431  if(lat_true_scale >0)
1432  add_var_dap4_attr(var,"latitude_of_projection_origin",attr_float64_c,"+90.0");
1433  else
1434  add_var_dap4_attr(var, "latitude_of_projection_origin",attr_float64_c,"-90.0");
1435 
1436  add_var_dap4_attr(var, "_CoordinateAxisTypes", attr_str_c, "GeoX GeoY");
1437 
1438  // From CF, PS has another parameter,
1439  // Either standard_parallel (EPSG 9829) or scale_factor_at_projection_origin (EPSG 9810)
1440  // I cannot find the corresponding parameter from the EOS5.
1441 
1442  }
1443  else if(HE5_GCTP_LAMAZ == cv_proj_code) {
1444 
1445  double lon_proj_origin = HE5_EHconvAng(eos5_proj_params[4],HE5_HDFE_DMS_DEG);
1446  double lat_proj_origin = HE5_EHconvAng(eos5_proj_params[5],HE5_HDFE_DMS_DEG);
1447  double fe = eos5_proj_params[6];
1448  double fn = eos5_proj_params[7];
1449 
1450  add_var_dap4_attr(var,"grid_mapping_name", attr_str_c, "lambert_azimuthal_equal_area");
1451 
1452  ostringstream s_lon_proj_origin;
1453  s_lon_proj_origin << lon_proj_origin;
1454  add_var_dap4_attr(var,"longitude_of_projection_origin", attr_float64_c, s_lon_proj_origin.str());
1455 
1456  ostringstream s_lat_proj_origin;
1457  s_lat_proj_origin << lat_proj_origin;
1458 
1459  add_var_dap4_attr(var,"latitude_of_projection_origin", attr_float64_c, s_lat_proj_origin.str());
1460 
1461  if(fe == 0.0)
1462  add_var_dap4_attr(var,"false_easting",attr_float64_c,"0.0");
1463  else {
1464  ostringstream s_fe;
1465  s_fe << fe;
1466  add_var_dap4_attr(var,"false_easting",attr_float64_c,s_fe.str());
1467  }
1468 
1469  if(fn == 0.0)
1470  add_var_dap4_attr(var,"false_northing",attr_float64_c,"0.0");
1471  else {
1472  ostringstream s_fn;
1473  s_fn << fn;
1474  add_var_dap4_attr(var,"false_northing",attr_float64_c,s_fn.str());
1475  }
1476 
1477  add_var_dap4_attr(var,"_CoordinateAxisTypes", attr_str_c, "GeoX GeoY");
1478  }
1479 
1480 }
1481 
1482 // Direct CF to DAP4, add the CF "grid_mapping_name" attribute to every variable that uses the grid.
1483 void add_cf_grid_cv_dap4_attrs(D4Group *d4_root, const string& cf_projection,
1484  const vector<HDF5CF::Dimension*>& dims)
1485 {
1486  // dims are dimensions for a grid. It is always 2-D for the projections we support.t
1487  string dim0name = (dims[0])->getNewName();
1488  hsize_t dim0size = dims[0]->getSize();
1489  string dim1name = (dims[1])->getNewName();
1490  hsize_t dim1size = dims[1]->getSize();
1491 
1492  // We only add the attribute to the variables that match the grid dimensions.
1493  Constructor::Vars_iter vi = d4_root->var_begin();
1494  Constructor::Vars_iter ve = d4_root->var_end();
1495  for (; vi != ve; vi++) {
1496  if((*vi)->is_vector_type()) {
1497  Array *t_a = dynamic_cast<Array*>(*vi);
1498  if(t_a->dimensions() >1) {
1499  Array::Dim_iter dim_i = t_a->dim_begin();
1500  Array::Dim_iter dim_e = t_a->dim_end();
1501  bool has_dim0 = false;
1502  bool has_dim1 = false;
1503  for(;dim_i !=dim_e;dim_i++) {
1504  if((*dim_i).name == dim0name && (*dim_i).size == dim0size)
1505  has_dim0 = true;
1506  else if((*dim_i).name == dim1name && (*dim_i).size == dim1size)
1507  has_dim1 = true;
1508  }
1509 
1510  if(true == has_dim0 && true == has_dim1)
1511  add_var_dap4_attr((*vi),"grid_mapping",attr_str_c,cf_projection);
1512  }
1513  }
1514  }
1515 }
1516 
1517 
1518 // Direct CF to DAP4, add special CF grid_mapping variable to DAP4.
1519 // These variables are dimension variables.
1520 void add_gm_spcvs(libdap::D4Group *d4_root, EOS5GridPCType cv_proj_code, float cv_point_lower, float cv_point_upper,
1521  float cv_point_left, float cv_point_right, const std::vector<HDF5CF::Dimension*>& dims) {
1522 
1523  //1. Check the projection information: we first just handled the sinusoidal projection.
1524  // We also add the LAMAZ and PS support. These 1-D varaibles are the same as the sinusoidal one.
1525  if (HE5_GCTP_SNSOID == cv_proj_code || HE5_GCTP_LAMAZ == cv_proj_code || HE5_GCTP_PS == cv_proj_code) {
1526 
1527  //2. Obtain the dimension information from latitude and longitude(fieldtype =1 or fieldtype =2)
1528  vector<HDF5CF::Dimension*>::const_iterator it_d;
1529  string dim0name = dims[0]->getNewName();
1530  int dim0size = dims[0]->getSize();
1531  string dim1name = dims[1]->getNewName();
1532  int dim1size = dims[1]->getSize();
1533 
1534  //3. Add the 1-D CV variables and the dummy projection variable
1535  BaseType *bt_dim0 = NULL;
1536  BaseType *bt_dim1 = NULL;
1537 
1538  HDF5CFGeoCF1D * ar_dim0 = NULL;
1539  HDF5CFGeoCF1D * ar_dim1 = NULL;
1540 
1541  try {
1542 
1543  bt_dim0 = new (HDF5CFFloat64)(dim0name, dim0name);
1544  bt_dim1 = new (HDF5CFFloat64)(dim1name, dim1name);
1545 
1546  // Note ar_dim0 is y, ar_dim1 is x.
1547  ar_dim0 = new HDF5CFGeoCF1D(HE5_GCTP_SNSOID, cv_point_upper, cv_point_lower, dim0size, dim0name, bt_dim0);
1548  ar_dim0->append_dim(dim0size, dim0name);
1549 
1550  ar_dim0->set_is_dap4(true);
1551 
1552  add_gm_spcvs_attrs(ar_dim0,true);
1553 
1554  ar_dim1 = new HDF5CFGeoCF1D(HE5_GCTP_SNSOID, cv_point_left, cv_point_right, dim1size, dim1name, bt_dim1);
1555  ar_dim1->append_dim(dim1size, dim1name);
1556 
1557  ar_dim1->set_is_dap4(true);
1558 
1559  add_gm_spcvs_attrs(ar_dim1,false);
1560 
1561  d4_root->add_var(ar_dim0);
1562  d4_root->add_var(ar_dim1);
1563 
1564  }
1565  catch (...) {
1566  if (bt_dim0) delete bt_dim0;
1567  if (bt_dim1) delete bt_dim1;
1568  if (ar_dim0) delete ar_dim0;
1569  if (ar_dim1) delete ar_dim1;
1570  throw InternalErr(__FILE__, __LINE__, "Unable to allocate the HDFEOS2GeoCF1D instance.");
1571  }
1572 
1573  if (bt_dim0) delete bt_dim0;
1574  if (bt_dim1) delete bt_dim1;
1575  if (ar_dim0) delete ar_dim0;
1576  if (ar_dim1) delete ar_dim1;
1577  }
1578 }
1579 
1580 // Direct CF to DAP4,
1581 // add CF grid_mapping $attributes for the special dimension variables.
1582 void add_gm_spcvs_attrs(libdap::BaseType *var,const bool is_dim0) {
1583 
1584  string standard_name;
1585  string long_name;
1586  string COORAxisTypes;
1587 
1588  if (true == is_dim0) {
1589  standard_name = "projection_y_coordinate";
1590  long_name = "y coordinate of projection ";
1591  COORAxisTypes = "GeoY";
1592  }
1593  else {
1594  standard_name = "projection_x_coordinate";
1595  long_name = "x coordinate of projection ";
1596  COORAxisTypes = "GeoX";
1597  }
1598 
1599  add_var_dap4_attr(var,"standard_name", attr_str_c, standard_name);
1600  add_var_dap4_attr(var,"long_name", attr_str_c, long_name);
1601  add_var_dap4_attr(var,"units", attr_str_c, "meter");
1602  add_var_dap4_attr(var,"_CoordinateAxisType", attr_str_c, COORAxisTypes);
1603 
1604 }
1605 
1606 // Direct CF to DAP4, helper function to DAP4 group attributes.
1607 void add_grp_dap4_attr(D4Group *d4_grp,const string& attr_name, D4AttributeType attr_type, const string& attr_value){
1608 
1609  D4Attribute *d4_attr = new D4Attribute(attr_name,attr_type);
1610  d4_attr->add_value(attr_value);
1611  d4_grp->attributes()->add_attribute_nocopy(d4_attr);
1612 
1613 }
1614 // Direct CF to DAP4, helper function to DAP4 variable attributes.
1615 void add_var_dap4_attr(BaseType *var,const string& attr_name, D4AttributeType attr_type, const string& attr_value){
1616 
1617  D4Attribute *d4_attr = new D4Attribute(attr_name,attr_type);
1618  d4_attr->add_value(attr_value);
1619  var->attributes()->add_attribute_nocopy(d4_attr);
1620 
1621 }
1622 
1623 // Mainly copy from HDF5CF::get_CF_string. Should be
1624 // removed if we can generate DMR independently.
1625 string get_cf_string(string & s) {
1626 
1627  if(s[0] !='/')
1628  return get_cf_string_helper(s);
1629  else {
1630  // The leading underscore should be removed
1631  s.erase(0,1);
1632  return get_cf_string_helper(s);
1633  }
1634 
1635 }
1636 string get_cf_string_helper(string & s) {
1637 
1638  if ("" == s) return s;
1639  string insertString(1, '_');
1640 
1641  // Always start with _ if the first character is not a letter
1642  if (true == isdigit(s[0])) s.insert(0, insertString);
1643 
1644  for (unsigned int i = 0; i < s.length(); i++)
1645  if ((false == isalnum(s[i])) && (s[i] != '_')) s[i] = '_';
1646  return s;
1647 }
This class includes the methods to read data array into DAP buffer from an HDF5 dataset for the CF op...
This class provides a way to map HDF5 byte to DAP byte for the CF option.
This class provides a way to map HDF5 float to DAP float for the CF option.
This class provides a way to map HDF5 64-bit floating-point(double) to DAP 64-bit floating-point for ...
This class provides a way to map HDF5 int16 to DAP int16 for the CF option.
This class provides a way to map HDF5 32-bit integer to DAP Int32 for the CF option.
This class provides a way to map HDF5 64-bit integer to DAP4 Int64 for the CF option.
This class provides a way to map HDF5 int8 to DAP int16 for the CF option.
This class provides a way to map HDF5 Str to DAP Str for the CF option.
This class provides a way to map HDF5 unsigned 16-bit integer to DAP uint16 for the CF option.
This class provides a way to map HDF5 unsigned 32-bit integer to DAP uint32 for the CF option.
This class provides a way to map HDF5 64-bit unsigned integer to DAP4 UInt64 for the CF option.
This file includes several helper functions for translating HDF5 to CF-compliant.
include the entry functions to execute the handlers
static string escattr(string s)
Definition: h5cfdaputil.cc:52
static D4AttributeType daptype_strrep_to_dap4_attrtype(std::string s)
Definition: h5cfdaputil.cc:362
This class represents one attribute.
Definition: HDF5CF.h:189
This class represents one HDF5 dataset(CF variable)
Definition: HDF5CF.h:259
int getRank() const
Get the dimension rank of this variable.
Definition: HDF5CF.h:305
const std::string & getFullPath() const
Get the full path of this variable.
Definition: HDF5CF.h:283
const std::string & getName() const
Get the original name of this variable.
Definition: HDF5CF.h:271
H5DataType getType() const
Get the data type of this variable(Not HDF5 datatype id)
Definition: HDF5CF.h:311
const std::vector< Dimension * > & getDimensions() const
Get the list of the dimensions.
Definition: HDF5CF.h:322
int getCompRatio() const
Get the compression ratio of this dataset.
Definition: HDF5CF.h:328
const std::string & getNewName() const
Get the new name of this variable.
Definition: HDF5CF.h:277
Helper functions for generating DAS attributes and a function to check BES Key.
Map and generate DDS and DAS for the CF option for generic HDF5 products.