bes  Updated for version 3.20.10
h5gmcfdap.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 <BESDebug.h>
41 #include <libdap/InternalErr.h>
42 
43 #include "HDF5RequestHandler.h"
44 #include "h5cfdaputil.h"
45 #include "h5gmcfdap.h"
46 #include "HDF5CFInt8.h"
47 #include "HDF5CFByte.h"
48 #include "HDF5CFUInt16.h"
49 #include "HDF5CFInt16.h"
50 #include "HDF5CFUInt32.h"
51 #include "HDF5CFInt32.h"
52 #include "HDF5CFInt64.h"
53 #include "HDF5CFUInt64.h"
54 #include "HDF5CFFloat32.h"
55 #include "HDF5CFFloat64.h"
56 #include "HDF5CFStr.h"
57 #include "HDF5CFArray.h"
58 #include "HDF5GMCFMissLLArray.h"
59 #include "HDF5GMCFFillIndexArray.h"
61 #include "HDF5GMCFSpecialCVArray.h"
62 #include "HDF5GMSPCFArray.h"
63 
64 using namespace std;
65 using namespace libdap;
66 using namespace HDF5CF;
67 
68 // Map general HDF5 products to DAP DDS
69 void map_gmh5_cfdds(DDS &dds, hid_t file_id, const string& filename){
70 
71  BESDEBUG("h5","Coming to GM products DDS mapping function map_gmh5_cfdds() "<<endl);
72 
73  H5GCFProduct product_type = check_product(file_id);
74 
75  GMPattern gproduct_pattern = OTHERGMS;
76 
77  GMFile * f = NULL;
78 
79  try {
80  f = new GMFile(filename.c_str(),file_id,product_type,gproduct_pattern);
81  }
82  catch(...) {
83  throw InternalErr(__FILE__,__LINE__,"Cannot allocate memory for GMFile ");
84  }
85  // Generally don't need to handle attributes when handling DDS.
86  bool include_attr = false;
87  try {
88  // Retrieve all HDF5 info(Not the values)
89  f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
90 
91  // Update product type
92  // Newer version of a product may have different layout and the
93  // product type needs to be changed to reflect it. We also want
94  // to support the older version in case people still use them.
95  // This routine will check if newer layout can be applied. If yes,
96  // update the product type.
98 
100 
101  // Need to add dimension names.
102  f->Add_Dim_Name();
103 
104  // Handle coordinate variables
105  f->Handle_CVar();
106 #if 0
107  // We need to retrieve coordinate variable attributes for memory cache use.
108  //f->Retrieve_H5_CVar_Supported_Attr_Values();
109  //if((HDF5RequestHandler::get_lrdata_mem_cache() != NULL) ||
110  // (HDF5RequestHandler::get_srdata_mem_cache() != NULL)){
111  // f->Retrieve_H5_Supported_Attr_Values();
112 #endif
113 
114 
115  // Handle special variables
116  f->Handle_SpVar();
117 
118  // When cv memory cache is on, the unit attributes are needed to
119  // distinguish whether this is lat/lon. Generally, memory cache
120  // is not used. This snipnet will not be accessed.
121  if((HDF5RequestHandler::get_lrdata_mem_cache() != NULL) ||
122  (HDF5RequestHandler::get_srdata_mem_cache() != NULL)){
123 
124  // Handle unsupported datatypes including the attributes
125  f->Handle_Unsupported_Dtype(true);
126 
127  // Handle unsupported dataspaces including the attributes
128  f->Handle_Unsupported_Dspace(true);
129 
130  // We need to retrieve coordinate variable attributes for memory cache use.
132 
133  }
134  else {
135 
136  // Handle unsupported datatypes
137  f->Handle_Unsupported_Dtype(include_attr);
138 
139  // Handle unsupported dataspaces
140  f->Handle_Unsupported_Dspace(include_attr);
141 
142  }
143 
144  // Need to handle the "coordinate" attributes when memory cache is turned on.
145  if((HDF5RequestHandler::get_lrdata_mem_cache() != NULL) ||
146  (HDF5RequestHandler::get_srdata_mem_cache() != NULL))
147  f->Add_Supplement_Attrs(HDF5RequestHandler::get_add_path_attrs());
148 
149  // Adjust object names(may remove redundant paths)
150  f->Adjust_Obj_Name();
151 
152  // Flatten the object names
153  f->Flatten_Obj_Name(include_attr);
154 
155  // Handle Object name clashings
156  // Only when the check_nameclashing key is turned on or
157  // general product.
158  if(General_Product == product_type ||
159  true == HDF5RequestHandler::get_check_name_clashing())
160  f->Handle_Obj_NameClashing(include_attr);
161 
162  // Adjust Dimension name
163  f->Adjust_Dim_Name();
164  if(General_Product == product_type ||
165  true == HDF5RequestHandler::get_check_name_clashing())
167 
168  f->Handle_Hybrid_EOS5();
169  if(true == f->Have_Grid_Mapping_Attrs())
171  // Need to handle the "coordinate" attributes when memory cache is turned on.
172  if((HDF5RequestHandler::get_lrdata_mem_cache() != NULL) ||
173  (HDF5RequestHandler::get_srdata_mem_cache() != NULL))
174  f->Handle_Coor_Attr();
175 
178  }
179  catch (HDF5CF::Exception &e){
180  if (f != NULL)
181  delete f;
182  throw InternalErr(e.what());
183  }
184 
185  // generate DDS.
186  try {
187  gen_gmh5_cfdds(dds,f);
188  }
189  catch(...) {
190  if (f != NULL)
191  delete f;
192  throw;
193  }
194 
195  if (f != NULL)
196  delete f;
197 }
198 
199 // Map general HDF5 products to DAP DAS
200 void map_gmh5_cfdas(DAS &das, hid_t file_id, const string& filename){
201 
202  BESDEBUG("h5","Coming to GM products DAS mapping function map_gmh5_cfdas() "<<endl);
203 
204  H5GCFProduct product_type = check_product(file_id);
205  GMPattern gproduct_pattern = OTHERGMS;
206 
207  GMFile *f = NULL;
208 
209  try {
210  f = new GMFile(filename.c_str(),file_id,product_type,gproduct_pattern);
211  }
212  catch(...) {
213  throw InternalErr(__FILE__,__LINE__,"Cannot allocate memory for GMFile ");
214  }
215 
216  bool include_attr = true;
217  try {
218  f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
219 
220  // Update product type(check comments of map_gmh5_cfdds)
221  f->Update_Product_Type();
222 
224 
225  f->Add_Dim_Name();
226  f->Handle_CVar();
227  f->Handle_SpVar();
228  f->Handle_Unsupported_Dtype(include_attr);
229 
230  // Remove unsupported dataspace
231  f->Handle_Unsupported_Dspace(include_attr);
232 
233  // Need to retrieve the attribute values to feed DAS
235 
236  // Handle other unsupported objects,
237  // currently it mainly generates the info. for the
238  // unsupported objects other than datatype, dataspace,links and named datatype
239  // One area is maybe very long string. So we retrieve the attribute
240  // values before calling this function.
241  f->Handle_Unsupported_Others(include_attr);
242 
243 
244  // Need to add original variable name and path
245  // and other special attributes
246  // Can be turned on/off by using the check_path_attrs keys.
247  f->Add_Supplement_Attrs(HDF5RequestHandler::get_add_path_attrs());
248  f->Adjust_Obj_Name();
249  f->Flatten_Obj_Name(include_attr);
250  if(General_Product == product_type ||
251  true == HDF5RequestHandler::get_check_name_clashing())
252  f->Handle_Obj_NameClashing(include_attr);
253  if(f->HaveUnlimitedDim() == true)
254  f->Adjust_Dim_Name();
255  // Handle the "coordinate" attributes.
256  f->Handle_Coor_Attr();
257 
258  f->Handle_Hybrid_EOS5();
259  if(true == f->Have_Grid_Mapping_Attrs())
261 
263 
265 
266  if(true == HDF5RequestHandler::get_enable_coord_attr_add_path())
267  f->Add_Path_Coord_Attr();
268  }
269  catch (HDF5CF::Exception &e){
270  if (f!= NULL)
271  delete f;
272  throw InternalErr(e.what());
273  }
274 
275  // Generate the DAS attributes.
276  try {
277  gen_gmh5_cfdas(das,f);
278  }
279  catch (...) {
280  if (f!= NULL)
281  delete f;
282  throw;
283 
284  }
285 
286  if (f != NULL)
287  delete f;
288 }
289 
290 
291 void map_gmh5_cfdmr(D4Group *d4_root, hid_t file_id, const string& filename){
292 
293  BESDEBUG("h5","Coming to GM products DMR mapping function map_gmh5_cfdmr() "<<endl);
294 
295  H5GCFProduct product_type = check_product(file_id);
296 
297  GMPattern gproduct_pattern = OTHERGMS;
298 
299  GMFile * f = NULL;
300 
301  try {
302  f = new GMFile(filename.c_str(),file_id,product_type,gproduct_pattern);
303  }
304  catch(...) {
305  throw InternalErr(__FILE__,__LINE__,"Cannot allocate memory for GMFile ");
306  }
307 
308  // Both variables and attributes are in DMR.
309  bool include_attr = true;
310  try {
311 
312  // Set the is_dap4 flag be true.
313  f->setDap4(true);
314 
315  // Retrieve all HDF5 info(Not the values)
316  f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
317 
318  // Update product type
319  // Newer version of a product may have different layout and the
320  // product type needs to be changed to reflect it. We also want
321  // to support the older version in case people still use them.
322  // This routine will check if newer layout can be applied. If yes,
323  // update the product type.
324  f->Update_Product_Type();
325 
327 
328  // Need to add dimension names.
329  f->Add_Dim_Name();
330 
331  // Handle coordinate variables
332  f->Handle_CVar();
333 #if 0
334  // We need to retrieve coordinate variable attributes for memory cache use.
335  //f->Retrieve_H5_CVar_Supported_Attr_Values();
336  //if((HDF5RequestHandler::get_lrdata_mem_cache() != NULL) ||
337  // (HDF5RequestHandler::get_srdata_mem_cache() != NULL)){
338  // f->Retrieve_H5_Supported_Attr_Values();
339 #endif
340 
341 
342  // Handle special variables
343  f->Handle_SpVar();
344 
345  // When cv memory cache is on, the unit attributes are needed to
346  // distinguish whether this is lat/lon. Generally, memory cache
347  // is not used. This snipnet will not be accessed.
348  //if((HDF5RequestHandler::get_lrdata_mem_cache() != NULL) ||
349  // (HDF5RequestHandler::get_srdata_mem_cache() != NULL)){
350 
351  // Handle unsupported datatypes including the attributes
352  f->Handle_Unsupported_Dtype(true);
353 
354  // Handle unsupported dataspaces including the attributes
355  f->Handle_Unsupported_Dspace(true);
356 
357  // We need to retrieve variable attributes.
359 
360  // Include handling internal netCDF-4 attributes
361  f->Handle_Unsupported_Others(include_attr);
362 
363 #if 0
364  else {
365 
366  // Handle unsupported datatypes
367  f->Handle_Unsupported_Dtype(include_attr);
368 
369  // Handle unsupported dataspaces
370  f->Handle_Unsupported_Dspace(include_attr);
371 
372  }
373 #endif
374  // Need to handle the "coordinate" attributes
375  f->Add_Supplement_Attrs(HDF5RequestHandler::get_add_path_attrs());
376 
377  // Adjust object names(may remove redundant paths)
378  f->Adjust_Obj_Name();
379 
380  // Flatten the object names
381  f->Flatten_Obj_Name(include_attr);
382 
383  // Handle Object name clashings
384  // Only when the check_nameclashing key is turned on or
385  // general product.
386  if(General_Product == product_type ||
387  true == HDF5RequestHandler::get_check_name_clashing())
388  f->Handle_Obj_NameClashing(include_attr);
389 
390  // Adjust Dimension name, CHECK: the das generation has a f->HaveUnlimitedDim() condition
391  f->Adjust_Dim_Name();
392  if(General_Product == product_type ||
393  true == HDF5RequestHandler::get_check_name_clashing())
395 
396  // Handle the "coordinate" attributes.
397  f->Handle_Coor_Attr();
398 
399  f->Handle_Hybrid_EOS5();
400  if(true == f->Have_Grid_Mapping_Attrs())
402 #if 0
403  // Need to handle the "coordinate" attributes when memory cache is turned on.
404  if((HDF5RequestHandler::get_lrdata_mem_cache() != NULL) ||
405  (HDF5RequestHandler::get_srdata_mem_cache() != NULL))
406  f->Handle_Coor_Attr();
407 #endif
408 
411 
412  if(true == HDF5RequestHandler::get_enable_coord_attr_add_path())
413  f->Add_Path_Coord_Attr();
414 
415  }
416  catch (HDF5CF::Exception &e){
417  if (f != NULL)
418  delete f;
419  throw InternalErr(e.what());
420  }
421 
422  // generate DMR.
423  try {
424  gen_gmh5_cfdmr(d4_root,f);
425  }
426  catch(...) {
427  if (f != NULL)
428  delete f;
429  throw;
430  }
431 
432  if (f != NULL)
433  delete f;
434 
435 }
436 
437 // Generate DDS mapped from general HDF5 products
438 void gen_gmh5_cfdds( DDS & dds, HDF5CF:: GMFile *f) {
439 
440  BESDEBUG("h5","Coming to GM DDS generation function gen_gmh5_cfdds() "<<endl);
441 
442  const vector<HDF5CF::Var *>& vars = f->getVars();
443  const vector<HDF5CF::GMCVar *>& cvars = f->getCVars();
444  const vector<HDF5CF::GMSPVar *>& spvars = f->getSPVars();
445  const string filename = f->getPath();
446  const hid_t fileid = f->getFileID();
447 
448  // Read Variable info.
449 
450  vector<HDF5CF::Var *>::const_iterator it_v;
451  vector<HDF5CF::GMCVar *>::const_iterator it_cv;
452  vector<HDF5CF::GMSPVar *>::const_iterator it_spv;
453 
454  // Since we need to use dds to add das for 64-bit dmr,we need to check if
455  // this case includes 64-bit integer variables and this is for dmr response.
456  bool dmr_64bit_support = false;
457  if(HDF5RequestHandler::get_dmr_long_int()==true &&
458  HDF5RequestHandler::get_dmr_64bit_int()!=NULL) {
459  for (it_v = vars.begin(); it_v !=vars.end();++it_v) {
460  if (H5INT64 == (*it_v)->getType() || H5UINT64 == (*it_v)->getType()){
461  dmr_64bit_support = true;
462  break;
463  }
464  }
465  }
466 
467  // We need to remove the unsupported attributes.
468  if(true == dmr_64bit_support) {
469  //STOP: add non-support stuff
470  f->Handle_Unsupported_Dtype(true);
471 
472  // Remove unsupported dataspace
473  f->Handle_Unsupported_Dspace(true);
474 
475  }
476 
477  for (it_v = vars.begin(); it_v !=vars.end();++it_v) {
478  BESDEBUG("h5","variable full path= "<< (*it_v)->getFullPath() <<endl);
479  // Handle 64-integer DAP4 CF mapping
480  if(need_attr_values_for_dap4(*it_v) == true)
481  f->Retrieve_H5_Var_Attr_Values(*it_v);
482  gen_dap_onevar_dds(dds,*it_v,fileid, filename);
483  }
484  for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
485  BESDEBUG("h5","variable full path= "<< (*it_cv)->getFullPath() <<endl);
486  gen_dap_onegmcvar_dds(dds,*it_cv,fileid, filename);
487  }
488 
489  for (it_spv = spvars.begin(); it_spv !=spvars.end();it_spv++) {
490  BESDEBUG("h5","variable full path= "<< (*it_spv)->getFullPath() <<endl);
491  gen_dap_onegmspvar_dds(dds,*it_spv,fileid, filename);
492  }
493 
494 }
495 
496 // Generate DAS mapped from general HDF5 products
497 void gen_gmh5_cfdas( DAS & das, HDF5CF:: GMFile *f) {
498 
499  BESDEBUG("h5","Coming to GM DAS generation function gen_gmh5_cfdas() "<<endl);
500 
501  // First check if this is for generating the ignored object info.
502  if(true == f->Get_IgnoredInfo_Flag()) {
503  gen_gmh5_cf_ignored_obj_info(das, f);
504  return;
505  }
506 
507  const vector<HDF5CF::Var *>& vars = f->getVars();
508  const vector<HDF5CF::GMCVar *>& cvars = f->getCVars();
509  const vector<HDF5CF::GMSPVar *>& spvars = f->getSPVars();
510  const vector<HDF5CF::Group *>& grps = f->getGroups();
511  const vector<HDF5CF::Attribute *>& root_attrs = f->getAttributes();
512 
513 
514  vector<HDF5CF::Var *>::const_iterator it_v;
515  vector<HDF5CF::GMCVar *>::const_iterator it_cv;
516  vector<HDF5CF::GMSPVar *>::const_iterator it_spv;
517  vector<HDF5CF::Group *>::const_iterator it_g;
518  vector<HDF5CF::Attribute *>::const_iterator it_ra;
519 
520  // Handling the file attributes(attributes under the root group)
521  // The table name is "HDF_GLOBAL".
522 
523  if (false == root_attrs.empty()) {
524 
525  AttrTable *at = das.get_table(FILE_ATTR_TABLE_NAME);
526  if (NULL == at)
527  at = das.add_table(FILE_ATTR_TABLE_NAME, new AttrTable);
528 
529  for (it_ra = root_attrs.begin(); it_ra != root_attrs.end(); ++it_ra) {
530  // Check and may update the 64-bit integer attributes in DAP4.
531  check_update_int64_attr("",*it_ra);
532  gen_dap_oneobj_das(at,*it_ra,NULL);
533  }
534  }
535 
536  if (false == grps.empty()) {
537  for (it_g = grps.begin();
538  it_g != grps.end(); ++it_g) {
539  AttrTable *at = das.get_table((*it_g)->getNewName());
540  if (NULL == at)
541  at = das.add_table((*it_g)->getNewName(), new AttrTable);
542 
543  for (it_ra = (*it_g)->getAttributes().begin();
544  it_ra != (*it_g)->getAttributes().end(); ++it_ra) {
545  check_update_int64_attr((*it_g)->getNewName(),*it_ra);
546  gen_dap_oneobj_das(at,*it_ra,NULL);
547  }
548  }
549  }
550 
551  for (it_v = vars.begin();
552  it_v != vars.end(); ++it_v) {
553  if (false == ((*it_v)->getAttributes().empty())) {
554 
555  // Skip the 64-bit integer variables. The attribute mapping of
556  // DAP4 CF 64-bit integer variable support
557  // has been taken care at the routine gen_dap_onevar_dds()
558  // defined at h5commoncfdap.cc
559  if(H5INT64 == (*it_v)->getType() || H5UINT64 == (*it_v)->getType()){
560  continue;
561  }
562 
563  AttrTable *at = das.get_table((*it_v)->getNewName());
564  if (NULL == at)
565  at = das.add_table((*it_v)->getNewName(), new AttrTable);
566 
567  for (it_ra = (*it_v)->getAttributes().begin();
568  it_ra != (*it_v)->getAttributes().end(); ++it_ra) {
569  gen_dap_oneobj_das(at,*it_ra,*it_v);
570  }
571  // TODO: If a var has integer-64 bit datatype attributes, maybe
572  // we can just keep that attributes(not consistent but
573  // easy to implement) or we have to duplicate all
574  // the var in dmr and delete this var from dds.
575 
576  }
577 
578  // GPM needs to be handled in a special way(mostly _FillValue)
579  if(GPMS_L3 == f->getProductType() || GPMM_L3 == f->getProductType()
580  || GPM_L1 == f->getProductType())
581  update_GPM_special_attrs(das,*it_v,false);
582 
583  }
584 
585  for (it_cv = cvars.begin();
586  it_cv != cvars.end(); ++it_cv) {
587  if (false == ((*it_cv)->getAttributes().empty())) {
588 
589  // TODO: Add 64-bit int support for coordinates, this has not been tackled.
590  if(H5INT64 == (*it_cv)->getType() || H5UINT64 == (*it_cv)->getType()){
591  continue;
592  }
593 
594  AttrTable *at = das.get_table((*it_cv)->getNewName());
595  if (NULL == at)
596  at = das.add_table((*it_cv)->getNewName(), new AttrTable);
597 
598  for (it_ra = (*it_cv)->getAttributes().begin();
599  it_ra != (*it_cv)->getAttributes().end(); ++it_ra){
600  gen_dap_oneobj_das(at,*it_ra,*it_cv);
601  }
602 
603  }
604  // Though CF doesn't allow _FillValue, still keep it to keep the original form.
605  if(GPMS_L3 == f->getProductType() || GPMM_L3 == f->getProductType()
606  || GPM_L1 == f->getProductType())
607  update_GPM_special_attrs(das,*it_cv,true);
608 
609  }
610 
611  // Currently the special variables are only limited to the ACOS/OCO2 64-bit integer variables
612  for (it_spv = spvars.begin();
613  it_spv != spvars.end(); ++it_spv) {
614  if (false == ((*it_spv)->getAttributes().empty())) {
615 
616  AttrTable *at = das.get_table((*it_spv)->getNewName());
617  if (NULL == at)
618  at = das.add_table((*it_spv)->getNewName(), new AttrTable);
619 #if 0
620  // cerr<<"spv coordinate variable name "<<(*it_spv)->getNewName() <<endl;
621 #endif
622 
623  for (it_ra = (*it_spv)->getAttributes().begin();
624  it_ra != (*it_spv)->getAttributes().end(); ++it_ra)
625  gen_dap_oneobj_das(at,*it_ra,*it_spv);
626  }
627  }
628 
629  // CHECK ALL UNLIMITED DIMENSIONS from the coordinate variables based on the names.
630  if(f->HaveUnlimitedDim() == true) {
631 
632  BESDEBUG("h5","Find unlimited dimension in the GM DAS generation function gen_gmh5_cfdas() "<<endl);
633 
634  // Currently there is no way for DAP to present the unlimited dimension info.
635  // when there are no dimension names. So don't create DODS_EXTRA even if
636  // there is an unlimited dimension in the file. KY 2016-02-18
637  if(cvars.empty()==false ){
638 
639  // First check if we do have unlimited dimension in the coordinate variables.
640  // Since unsupported fakedims are removed, we may not have unlimited dimensions.
641  bool still_has_unlimited = false;
642  for (it_cv = cvars.begin();
643  it_cv != cvars.end(); ++it_cv) {
644  // Check unlimited dimension names.
645  for (vector<Dimension*>::const_iterator ird = (*it_cv)->getDimensions().begin();
646  ird != (*it_cv)->getDimensions().end(); ++ird) {
647 
648  // Currently we only check one unlimited dimension, which is the most
649  // common case. When receiving the conventions from JG, will add
650  // the support of multi-unlimited dimension. KY 2016-02-09
651  if((*ird)->HaveUnlimitedDim() == true) {
652  still_has_unlimited = true;
653  break;
654  }// if((*ird) is HaveUnlimitedDim()
655  }// for (vector<Dimension*>::
656  if(true == still_has_unlimited)
657  break;
658  }// for (it_cv=cvars.begin();
659 
660  if(true == still_has_unlimited) {
661  AttrTable* at = das.get_table("DODS_EXTRA");
662  if (NULL == at)
663  at = das.add_table("DODS_EXTRA", new AttrTable);
664 
665  string unlimited_names;
666 
667  for (it_cv = cvars.begin();
668  it_cv != cvars.end(); ++it_cv) {
669 #if 0
670  bool has_unlimited_dim = false;
671 #endif
672  // Check unlimited dimension names.
673  for (vector<Dimension*>::const_iterator ird = (*it_cv)->getDimensions().begin();
674  ird != (*it_cv)->getDimensions().end(); ++ird) {
675 
676  // Currently we only check one unlimited dimension, which is the most
677  // common case. When receiving the conventions from JG, will add
678  // the support of multi-unlimited dimension. KY 2016-02-09
679  if((*ird)->HaveUnlimitedDim() == true) {
680  if(unlimited_names=="") {
681  unlimited_names = (*ird)->getNewName();
682  if(at !=NULL)
683  at->append_attr("Unlimited_Dimension","String",unlimited_names);
684  }
685  else {
686  if(unlimited_names.rfind((*ird)->getNewName()) == string::npos) {
687  unlimited_names = unlimited_names+" "+(*ird)->getNewName();
688  if(at !=NULL)
689  at->append_attr("Unlimited_Dimension","String",(*ird)->getNewName());
690  }
691  }
692  }// if((*ird)->HaveUnlimitedDim()
693  }// for (vector<Dimension*>::
694  }// for (it_cv=cvars.begin();
695  }// if(true == still_has_unlimited)
696 
697  }//if(cvars.size()>0)
698 #if 0
699  // The following line will generate the string like "Band1 str1 str2".
700  //if(unlimited_names!="")
701  // // at->append_attr("Unlimited_Dimension","String",unlimited_names);
702 #endif
703  }
704 }
705 
706 void gen_gmh5_cfdmr(D4Group* d4_root,HDF5CF::GMFile *f) {
707 
708  BESDEBUG("h5","Coming to GM DDS generation function gen_gmh5_cfdmr() "<<endl);
709 
710  const vector<HDF5CF::Var *>& vars = f->getVars();
711  const vector<HDF5CF::GMCVar *>& cvars = f->getCVars();
712  const vector<HDF5CF::GMSPVar *>& spvars = f->getSPVars();
713  const string filename = f->getPath();
714  const hid_t fileid = f->getFileID();
715  const vector<HDF5CF::Group *>& grps = f->getGroups();
716  const vector<HDF5CF::Attribute *>& root_attrs = f->getAttributes();
717 
718  vector<HDF5CF::Var *>::const_iterator it_v;
719  vector<HDF5CF::GMCVar *>::const_iterator it_cv;
720  vector<HDF5CF::GMSPVar *>::const_iterator it_spv;
721  vector<HDF5CF::Group *>::const_iterator it_g;
722  vector<HDF5CF::Attribute *>::const_iterator it_ra;
723 
724  // Root and low-level group attributes.
725  if (false == root_attrs.empty()) {
726  for (it_ra = root_attrs.begin(); it_ra != root_attrs.end(); ++it_ra)
727  map_cfh5_grp_attr_to_dap4(d4_root,*it_ra);
728  }
729 
730  // Read Variable info.
731  for (it_v = vars.begin(); it_v !=vars.end();++it_v) {
732  BESDEBUG("h5","variable full path= "<< (*it_v)->getFullPath() <<endl);
733  gen_dap_onevar_dmr(d4_root,*it_v,fileid, filename);
734  }
735 
736  for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
737  BESDEBUG("h5","variable full path= "<< (*it_cv)->getFullPath() <<endl);
738  gen_dap_onegmcvar_dmr(d4_root,*it_cv,fileid, filename);
739  }
740 
741  for (it_spv = spvars.begin(); it_spv !=spvars.end();it_spv++) {
742  BESDEBUG("h5","variable full path= "<< (*it_spv)->getFullPath() <<endl);
743  gen_dap_onegmspvar_dmr(d4_root,*it_spv,fileid, filename);
744  }
745 
746  // We use the attribute container to store the group attributes.
747  if (false == grps.empty()) {
748  for (it_g = grps.begin();
749  it_g != grps.end(); ++it_g) {
750 
751  D4Attribute *tmp_grp = new D4Attribute;
752  tmp_grp->set_name((*it_g)->getNewName());
753 
754  // Make the type as a container
755  tmp_grp->set_type(attr_container_c);
756 
757  for (it_ra = (*it_g)->getAttributes().begin();
758  it_ra != (*it_g)->getAttributes().end(); ++it_ra) {
759  map_cfh5_attr_container_to_dap4(tmp_grp,(*it_ra));
760  }
761 
762  d4_root->attributes()->add_attribute_nocopy(tmp_grp);
763  }
764  }
765 
766  // CHECK ALL UNLIMITED DIMENSIONS from the coordinate variables based on the names.
767  if(f->HaveUnlimitedDim() == true) {
768 
769  BESDEBUG("h5","Find unlimited dimension in the GM DMR generation function gen_gmh5_cfdmr() "<<endl);
770 
771  // Currently there is no way for DAP to present the unlimited dimension info.
772  // when there are no dimension names. So don't create DODS_EXTRA even if
773  // there is an unlimited dimension in the file. KY 2016-02-18
774  if(cvars.empty()==false ){
775 
776  // First check if we do have unlimited dimension in the coordinate variables.
777  // Since unsupported fakedims are removed, we may not have unlimited dimensions.
778  bool still_has_unlimited = false;
779  for (it_cv = cvars.begin();
780  it_cv != cvars.end(); ++it_cv) {
781  // Check unlimited dimension names.
782  for (vector<Dimension*>::const_iterator ird = (*it_cv)->getDimensions().begin();
783  ird != (*it_cv)->getDimensions().end(); ++ird) {
784 
785  // Currently we only check one unlimited dimension, which is the most
786  // common case. When receiving the conventions from JG, will add
787  // the support of multi-unlimited dimension. KY 2016-02-09
788  if((*ird)->HaveUnlimitedDim() == true) {
789  still_has_unlimited = true;
790  break;
791  }// if((*ird) is HaveUnlimitedDim()
792  }// for (vector<Dimension*>::
793  if(true == still_has_unlimited)
794  break;
795  }// for (it_cv=cvars.begin();
796 
797  if(true == still_has_unlimited) {
798 
799  string dods_extra = "DODS_EXTRA";
800 
801  // If DODS_EXTRA exists, we will not create the unlimited dimensions.
802  if(d4_root->attributes() != NULL) {
803  // The following lines cause seg. fault in libdap4, needs to investigate
804  //if((d4_root->attributes()->find(dods_extra))==NULL)
805 
806  string unlimited_dim_names ="";
807 
808  for (it_cv = cvars.begin();
809  it_cv != cvars.end(); it_cv++) {
810 
811  // Check unlimited dimension names.
812  for (vector<Dimension*>::const_iterator ird = (*it_cv)->getDimensions().begin();
813  ird != (*it_cv)->getDimensions().end(); ++ird) {
814 
815  // Currently we only check one unlimited dimension, which is the most
816  // common case. When receiving the conventions from JG, will add
817  // the support of multi-unlimited dimension. KY 2016-02-09
818  if((*ird)->HaveUnlimitedDim() == true) {
819 
820  string unlimited_dim_name = (*ird)->getNewName();
821  if(unlimited_dim_names=="")
822  unlimited_dim_names = unlimited_dim_name;
823  else {
824  if(unlimited_dim_names.rfind(unlimited_dim_name) == string::npos)
825  unlimited_dim_names = unlimited_dim_names+" "+unlimited_dim_name;
826  }
827  }
828  }
829  }
830 
831  if(unlimited_dim_names != "") {
832  D4Attribute *dods_extra_attr = new D4Attribute(dods_extra,attr_container_c);
833  D4Attribute *unlimited_dim_attr = new D4Attribute("Unlimited_Dimension",attr_str_c);
834  unlimited_dim_attr->add_value(unlimited_dim_names);
835  dods_extra_attr->attributes()->add_attribute_nocopy(unlimited_dim_attr);
836  d4_root->attributes()->add_attribute_nocopy(dods_extra_attr);
837 
838  }
839  else
840  throw InternalErr(__FILE__, __LINE__, "Unlimited dimension should exist.");
841  }
842 
843  }
844  }
845  }
846 
847 
848 }
849 
850 // Generate the ignored object info. for the CF option of the general products
851 void gen_gmh5_cf_ignored_obj_info(DAS &das, HDF5CF::GMFile *f) {
852 
853  BESDEBUG("h5","Coming to gen_gmh5_cf_ignored_obj_info() "<<endl);
854  AttrTable *at = das.get_table("Ignored_Object_Info");
855  if (NULL == at)
856  at = das.add_table("Ignored_Object_Info", new AttrTable);
857 
858  at->append_attr("Message","String",f->Get_Ignored_Msg());
859 
860 }
861 
862 // Generate the DDS for a coordinate variable of the General products
863 void gen_dap_onegmcvar_dds(DDS &dds,const HDF5CF::GMCVar* cvar, const hid_t file_id, const string & filename) {
864 
865  BESDEBUG("h5","Coming to gen_dap_onegmcvar_dds() "<<endl);
866 
867  if(cvar->getType() == H5INT64 || cvar->getType() == H5UINT64)
868  return;
869  BaseType *bt = NULL;
870 
871  switch(cvar->getType()) {
872 #define HANDLE_CASE(tid,type) \
873  case tid: \
874  bt = new (type)(cvar->getNewName(),cvar->getFullPath()); \
875  break;
876 
877  HANDLE_CASE(H5FLOAT32, HDF5CFFloat32);
878  HANDLE_CASE(H5FLOAT64, HDF5CFFloat64);
879  HANDLE_CASE(H5CHAR,HDF5CFInt16);
880  HANDLE_CASE(H5UCHAR, HDF5CFByte);
881  HANDLE_CASE(H5INT16, HDF5CFInt16);
882  HANDLE_CASE(H5UINT16, HDF5CFUInt16);
883  HANDLE_CASE(H5INT32, HDF5CFInt32);
884  HANDLE_CASE(H5UINT32, HDF5CFUInt32);
885  HANDLE_CASE(H5FSTRING, Str);
886  HANDLE_CASE(H5VSTRING, Str);
887 
888  default:
889  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
890 #undef HANDLE_CASE
891  }
892 
893  if (bt) {
894 
895  const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
896  vector <HDF5CF::Dimension*>:: const_iterator it_d;
897  vector <size_t> dimsizes;
898  dimsizes.resize(cvar->getRank());
899  for(int i = 0; i <cvar->getRank();i++)
900  dimsizes[i] = (dims[i])->getSize();
901 
902 
903  if(dims.empty())
904  throw InternalErr(__FILE__,__LINE__,"the coordinate variable cannot be a scalar");
905 
906  switch(cvar->getCVType()) {
907 
908  case CV_EXIST:
909  {
910  HDF5CFArray *ar = NULL;
911 
912  // Need to check if this CV is lat/lon. This is necessary when data memory cache is turned on.
913  bool is_latlon = cvar->isLatLon();
914 
915  try {
916  ar = new HDF5CFArray (
917  cvar->getRank(),
918  file_id,
919  filename,
920  cvar->getType(),
921  dimsizes,
922  cvar->getFullPath(),
923  cvar->getTotalElems(),
924  CV_EXIST,
925  is_latlon,
926  cvar->getCompRatio(),
927  false,
928  cvar->getNewName(),
929  bt);
930  }
931  catch(...) {
932  delete bt;
933  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5CFArray. ");
934  }
935 
936  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
937  if (""==(*it_d)->getNewName())
938  ar->append_dim((*it_d)->getSize());
939  else
940  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
941  }
942 
943  dds.add_var(ar);
944  delete bt;
945  delete ar;
946  }
947  break;
948 
949  case CV_LAT_MISS:
950  case CV_LON_MISS:
951  {
952  // Using HDF5GMCFMissLLArray
953  HDF5GMCFMissLLArray *ar = NULL;
954  try {
955  ar = new HDF5GMCFMissLLArray (
956  cvar->getRank(),
957  filename,
958  file_id,
959  cvar->getType(),
960  cvar->getFullPath(),
961  cvar->getPtType(),
962  cvar->getCVType(),
963  cvar->getNewName(),
964  bt);
965  }
966  catch(...) {
967  delete bt;
968  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissLLArray. ");
969  }
970 
971 
972  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
973  if (""==(*it_d)->getNewName())
974  ar->append_dim((*it_d)->getSize());
975  else
976  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
977  }
978 
979  dds.add_var(ar);
980  delete bt;
981  delete ar;
982  }
983  break;
984 
985  case CV_NONLATLON_MISS:
986  {
987 
988  if (cvar->getRank() !=1) {
989  delete bt;
990  throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
991  }
992  int nelem = (cvar->getDimensions()[0])->getSize();
993 
994  HDF5GMCFMissNonLLCVArray *ar = NULL;
995 
996  try {
997  ar = new HDF5GMCFMissNonLLCVArray(
998  cvar->getRank(),
999  nelem,
1000  cvar->getNewName(),
1001  bt);
1002  }
1003  catch(...) {
1004  delete bt;
1005  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissNonLLCVArray. ");
1006  }
1007 
1008 
1009  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1010  if (""==(*it_d)->getNewName())
1011  ar->append_dim((*it_d)->getSize());
1012  else
1013  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1014  }
1015  dds.add_var(ar);
1016  delete bt;
1017  delete ar;
1018  }
1019  break;
1020 
1021  case CV_FILLINDEX:
1022  {
1023 
1024  if (cvar->getRank() !=1) {
1025  delete bt;
1026  throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
1027  }
1028 
1029  HDF5GMCFFillIndexArray *ar = NULL;
1030 
1031  try {
1032  ar = new HDF5GMCFFillIndexArray(
1033  cvar->getRank(),
1034  cvar->getType(),
1035  false,
1036  cvar->getNewName(),
1037  bt);
1038  }
1039  catch(...) {
1040  delete bt;
1041  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissNonLLCVArray. ");
1042  }
1043 
1044 
1045  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1046  if (""==(*it_d)->getNewName())
1047  ar->append_dim((*it_d)->getSize());
1048  else
1049  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1050  }
1051  dds.add_var(ar);
1052  delete bt;
1053  delete ar;
1054  }
1055  break;
1056 
1057 
1058  case CV_SPECIAL:
1059  {
1060  // Currently only handle 1-D special CV.
1061  if (cvar->getRank() !=1) {
1062  delete bt;
1063  throw InternalErr(__FILE__, __LINE__, "The rank of special coordinate variable must be 1");
1064  }
1065  int nelem = (cvar->getDimensions()[0])->getSize();
1066 
1067  HDF5GMCFSpecialCVArray * ar = NULL;
1068  ar = new HDF5GMCFSpecialCVArray(
1069  cvar->getType(),
1070  nelem,
1071  cvar->getFullPath(),
1072  cvar->getPtType(),
1073  cvar->getNewName(),
1074  bt);
1075 
1076  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1077  if (""==(*it_d)->getNewName())
1078  ar->append_dim((*it_d)->getSize());
1079  else
1080  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1081  }
1082 
1083  dds.add_var(ar);
1084  delete bt;
1085  delete ar;
1086 
1087  }
1088  break;
1089  case CV_MODIFY:
1090  default:
1091  delete bt;
1092  throw InternalErr(__FILE__,__LINE__,"Coordinate variable type is not supported.");
1093  }
1094  }
1095 }
1096 
1097 // Generate DDS for special variable in a general product
1098 void gen_dap_onegmspvar_dds(DDS &dds,const HDF5CF::GMSPVar* spvar, const hid_t fileid, const string & filename) {
1099 
1100  BESDEBUG("h5","Coming to gen_dap_onegmspvar_dds() "<<endl);
1101  BaseType *bt = NULL;
1102 
1103  switch(spvar->getType()) {
1104 #define HANDLE_CASE(tid,type) \
1105  case tid: \
1106  bt = new (type)(spvar->getNewName(),spvar->getFullPath()); \
1107  break;
1108 
1109  HANDLE_CASE(H5FLOAT32, HDF5CFFloat32);
1110  HANDLE_CASE(H5FLOAT64, HDF5CFFloat64);
1111  HANDLE_CASE(H5CHAR,HDF5CFInt16);
1112  HANDLE_CASE(H5UCHAR, HDF5CFByte);
1113  HANDLE_CASE(H5INT16, HDF5CFInt16);
1114  HANDLE_CASE(H5UINT16, HDF5CFUInt16);
1115  HANDLE_CASE(H5INT32, HDF5CFInt32);
1116  HANDLE_CASE(H5UINT32, HDF5CFUInt32);
1117  HANDLE_CASE(H5FSTRING, Str);
1118  HANDLE_CASE(H5VSTRING, Str);
1119  default:
1120  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
1121 #undef HANDLE_CASE
1122  }
1123 
1124  if (bt) {
1125 
1126  const vector<HDF5CF::Dimension *>& dims = spvar->getDimensions();
1127  vector <HDF5CF::Dimension*>:: const_iterator it_d;
1128 
1129  if(dims.empty())
1130  throw InternalErr(__FILE__,__LINE__,"Currently don't support scalar special variables. ");
1131 
1132  HDF5GMSPCFArray *ar = NULL;
1133 
1134  try {
1135  ar = new HDF5GMSPCFArray (
1136  spvar->getRank(),
1137  filename,
1138  fileid,
1139  spvar->getType(),
1140  spvar->getFullPath(),
1141  spvar->getOriginalType(),
1142  spvar->getStartBit(),
1143  spvar->getBitNum(),
1144  spvar->getNewName(),
1145  bt);
1146  }
1147  catch(...) {
1148  delete bt;
1149  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissNonLLCVArray. ");
1150  }
1151 
1152 
1153  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1154  if (""==(*it_d)->getNewName())
1155  ar->append_dim((*it_d)->getSize());
1156  else
1157  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1158  }
1159 
1160  dds.add_var(ar);
1161  delete bt;
1162  delete ar;
1163  }
1164 
1165 }
1166 
1167 // When we add floating point fill value at HDF5CF.cc, the value will be changed
1168 // a little bit when it changes to string representation.
1169 // For example, -9999.9 becomes -9999.9000123. To reduce the misunderstanding,we
1170 // just add fillvalue in the string type here. KY 2014-04-02
1171 void update_GPM_special_attrs(DAS& das, const HDF5CF::Var *var,bool is_cvar) {
1172 
1173  BESDEBUG("h5","Coming to update_GPM_special_attrs() "<<endl);
1174  if(H5FLOAT64 == var->getType() ||
1175  H5FLOAT32 == var->getType() ||
1176  H5INT16 == var->getType() ||
1177  H5CHAR == var->getType()) {
1178 
1179  AttrTable *at = das.get_table(var->getNewName());
1180  if (NULL == at)
1181  at = das.add_table(var->getNewName(), new AttrTable);
1182  bool has_fillvalue = false;
1183  AttrTable::Attr_iter it = at->attr_begin();
1184  while (it!=at->attr_end() && false==has_fillvalue) {
1185  if (at->get_name(it) =="_FillValue")
1186  {
1187  has_fillvalue = true;
1188  string fillvalue ="";
1189  if(H5FLOAT32 == var->getType()) {
1190  const string cor_fill_value = "-9999.9";
1191  fillvalue = (*at->get_attr_vector(it)->begin());
1192  if((fillvalue.find(cor_fill_value) == 0) && (fillvalue!= cor_fill_value)) {
1193  at->del_attr("_FillValue");
1194  at->append_attr("_FillValue","Float32",cor_fill_value);
1195  }
1196  }
1197  else if(H5FLOAT64 == var->getType()) {
1198  const string cor_fill_value = "-9999.9";
1199  const string exist_fill_value_substr = "-9999.8999";
1200  fillvalue = (*at->get_attr_vector(it)->begin());
1201  if((fillvalue.find(exist_fill_value_substr) == 0) && (fillvalue!= cor_fill_value)) {
1202  at->del_attr("_FillValue");
1203  at->append_attr("_FillValue","Float64",cor_fill_value);
1204  }
1205 
1206  }
1207  }
1208  it++;
1209  }
1210 
1211  // Add the fill value
1212  if(false == is_cvar ) {
1213 
1214  // Current versions of GPM don't add fillvalues. We add the fillvalue according to the document.
1215  if (has_fillvalue != true ) {
1216 
1217  if(H5FLOAT32 == var->getType())
1218  at->append_attr("_FillValue","Float32","-9999.9");
1219  else if(H5FLOAT64 == var->getType())
1220  at->append_attr("_FillValue","Float64","-9999.9");
1221  else if (H5INT16 == var->getType())
1222  at->append_attr("_FillValue","Int16","-9999");
1223  else if (H5CHAR == var->getType())// H5CHAR maps to DAP int16
1224  at->append_attr("_FillValue","Int16","-99");
1225 
1226  }
1227  }
1228  }
1229 }
1230 
1231 void gen_dap_onegmcvar_dmr(D4Group*d4_root,const GMCVar* cvar,const hid_t fileid, const string &filename) {
1232 
1233  BESDEBUG("h5","Coming to gen_dap_onegmcvar_dds() "<<endl);
1234 
1235  BaseType *bt = NULL;
1236 
1237  switch(cvar->getType()) {
1238 #define HANDLE_CASE(tid,type) \
1239  case tid: \
1240  bt = new (type)(cvar->getNewName(),cvar->getFullPath()); \
1241  break;
1242 
1243  HANDLE_CASE(H5FLOAT32, HDF5CFFloat32);
1244  HANDLE_CASE(H5FLOAT64, HDF5CFFloat64);
1245  HANDLE_CASE(H5CHAR,HDF5CFInt8);
1246  HANDLE_CASE(H5UCHAR, HDF5CFByte);
1247  HANDLE_CASE(H5INT16, HDF5CFInt16);
1248  HANDLE_CASE(H5UINT16, HDF5CFUInt16);
1249  HANDLE_CASE(H5INT32, HDF5CFInt32);
1250  HANDLE_CASE(H5UINT32, HDF5CFUInt32);
1251  HANDLE_CASE(H5INT64, HDF5CFInt64);
1252  HANDLE_CASE(H5UINT64, HDF5CFUInt64);
1253  HANDLE_CASE(H5FSTRING, Str);
1254  HANDLE_CASE(H5VSTRING, Str);
1255 
1256  default:
1257  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
1258 #undef HANDLE_CASE
1259  }
1260 
1261  if (bt) {
1262 
1263  const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
1264  vector <HDF5CF::Dimension*>:: const_iterator it_d;
1265  vector <size_t> dimsizes;
1266  dimsizes.resize(cvar->getRank());
1267 
1268  for(int i = 0; i <cvar->getRank();i++)
1269  dimsizes[i] = (dims[i])->getSize();
1270 
1271  if(dims.empty())
1272  throw InternalErr(__FILE__,__LINE__,"the coordinate variable cannot be a scalar");
1273 
1274  switch(cvar->getCVType()) {
1275 
1276  case CV_EXIST:
1277  {
1278  HDF5CFArray *ar = NULL;
1279 
1280  // Need to check if this CV is lat/lon. This is necessary when data memory cache is turned on.
1281  bool is_latlon = cvar->isLatLon();
1282 
1283  try {
1284 
1285  bool is_dap4 = true;
1286  ar = new HDF5CFArray (
1287  cvar->getRank(),
1288  fileid,
1289  filename,
1290  cvar->getType(),
1291  dimsizes,
1292  cvar->getFullPath(),
1293  cvar->getTotalElems(),
1294  CV_EXIST,
1295  is_latlon,
1296  cvar->getCompRatio(),
1297  is_dap4,
1298  cvar->getNewName(),
1299  bt);
1300  }
1301  catch(...) {
1302  delete bt;
1303  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5CFArray. ");
1304  }
1305 
1306  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1307  if (""==(*it_d)->getNewName())
1308  ar->append_dim((*it_d)->getSize());
1309  else
1310  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1311  }
1312 
1313  ar->set_is_dap4(true);
1314  BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
1315  map_cfh5_var_attrs_to_dap4(cvar,d4_var);
1316  d4_root->add_var_nocopy(d4_var);
1317  delete bt;
1318  delete ar;
1319  }
1320  break;
1321 
1322  case CV_LAT_MISS:
1323  case CV_LON_MISS:
1324  {
1325  // Using HDF5GMCFMissLLArray
1326  HDF5GMCFMissLLArray *ar = NULL;
1327  try {
1328  ar = new HDF5GMCFMissLLArray (
1329  cvar->getRank(),
1330  filename,
1331  fileid,
1332  cvar->getType(),
1333  cvar->getFullPath(),
1334  cvar->getPtType(),
1335  cvar->getCVType(),
1336  cvar->getNewName(),
1337  bt);
1338  }
1339  catch(...) {
1340  delete bt;
1341  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissLLArray. ");
1342  }
1343 
1344  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1345  if (""==(*it_d)->getNewName())
1346  ar->append_dim((*it_d)->getSize());
1347  else
1348  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1349  }
1350 
1351  ar->set_is_dap4(true);
1352  BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
1353  map_cfh5_var_attrs_to_dap4(cvar,d4_var);
1354  d4_root->add_var_nocopy(d4_var);
1355  delete bt;
1356  delete ar;
1357  }
1358  break;
1359 
1360  case CV_NONLATLON_MISS:
1361  {
1362 
1363  if (cvar->getRank() !=1) {
1364  delete bt;
1365  throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
1366  }
1367  int nelem = (cvar->getDimensions()[0])->getSize();
1368 
1369  HDF5GMCFMissNonLLCVArray *ar = NULL;
1370 
1371  try {
1372  ar = new HDF5GMCFMissNonLLCVArray(
1373  cvar->getRank(),
1374  nelem,
1375  cvar->getNewName(),
1376  bt);
1377  }
1378  catch(...) {
1379  delete bt;
1380  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissNonLLCVArray. ");
1381  }
1382 
1383 
1384  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1385  if (""==(*it_d)->getNewName())
1386  ar->append_dim((*it_d)->getSize());
1387  else
1388  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1389  }
1390  ar->set_is_dap4(true);
1391  BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
1392  map_cfh5_var_attrs_to_dap4(cvar,d4_var);
1393  d4_root->add_var_nocopy(d4_var);
1394  delete bt;
1395  delete ar;
1396  }
1397  break;
1398 
1399  case CV_FILLINDEX:
1400  {
1401 
1402  if (cvar->getRank() !=1) {
1403  delete bt;
1404  throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
1405  }
1406 
1407  HDF5GMCFFillIndexArray *ar = NULL;
1408 
1409  try {
1410  ar = new HDF5GMCFFillIndexArray(
1411  cvar->getRank(),
1412  cvar->getType(),
1413  true,
1414  cvar->getNewName(),
1415  bt);
1416  }
1417  catch(...) {
1418  delete bt;
1419  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissNonLLCVArray. ");
1420  }
1421 
1422 
1423  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1424  if (""==(*it_d)->getNewName())
1425  ar->append_dim((*it_d)->getSize());
1426  else
1427  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1428  }
1429  ar->set_is_dap4(true);
1430  BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
1431  map_cfh5_var_attrs_to_dap4(cvar,d4_var);
1432  d4_root->add_var_nocopy(d4_var);
1433  delete bt;
1434  delete ar;
1435  }
1436  break;
1437 
1438 
1439  case CV_SPECIAL:
1440  {
1441  // Currently only handle 1-D special CV.
1442  if (cvar->getRank() !=1) {
1443  delete bt;
1444  throw InternalErr(__FILE__, __LINE__, "The rank of special coordinate variable must be 1");
1445  }
1446  int nelem = (cvar->getDimensions()[0])->getSize();
1447 
1448  HDF5GMCFSpecialCVArray * ar = NULL;
1449  ar = new HDF5GMCFSpecialCVArray(
1450  cvar->getType(),
1451  nelem,
1452  cvar->getFullPath(),
1453  cvar->getPtType(),
1454  cvar->getNewName(),
1455  bt);
1456 
1457  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1458  if (""==(*it_d)->getNewName())
1459  ar->append_dim((*it_d)->getSize());
1460  else
1461  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1462  }
1463 
1464  ar->set_is_dap4(true);
1465  BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
1466  map_cfh5_var_attrs_to_dap4(cvar,d4_var);
1467  d4_root->add_var_nocopy(d4_var);
1468  delete bt;
1469  delete ar;
1470 
1471  }
1472  break;
1473  case CV_MODIFY:
1474  default:
1475  delete bt;
1476  throw InternalErr(__FILE__,__LINE__,"Coordinate variable type is not supported.");
1477  }
1478  }
1479 
1480 
1481 }
1482 
1483 void gen_dap_onegmspvar_dmr(D4Group*d4_root,const GMSPVar*spvar,const hid_t fileid, const string &filename) {
1484 
1485  BESDEBUG("h5","Coming to gen_dap_onegmspvar_dmr() "<<endl);
1486  BaseType *bt = NULL;
1487 
1488  // Note: The special variable is actually an ACOS_OCO2 64-bit integer variable.
1489  // We decompose 64-bit to two integer variables according to the specification.
1490  // This product has been served in this way for years. For backward compatibility,
1491  // we will not change this in the CF DMR implementation. So Int64/UInt64 are not added.
1492  // KY 2021-03-09
1493  switch(spvar->getType()) {
1494 #define HANDLE_CASE(tid,type) \
1495  case tid: \
1496  bt = new (type)(spvar->getNewName(),spvar->getFullPath()); \
1497  break;
1498 
1499  HANDLE_CASE(H5FLOAT32, HDF5CFFloat32);
1500  HANDLE_CASE(H5FLOAT64, HDF5CFFloat64);
1501  HANDLE_CASE(H5CHAR,HDF5CFByte);
1502  HANDLE_CASE(H5UCHAR, HDF5CFByte);
1503  HANDLE_CASE(H5INT16, HDF5CFInt16);
1504  HANDLE_CASE(H5UINT16, HDF5CFUInt16);
1505  HANDLE_CASE(H5INT32, HDF5CFInt32);
1506  HANDLE_CASE(H5UINT32, HDF5CFUInt32);
1507  HANDLE_CASE(H5FSTRING, Str);
1508  HANDLE_CASE(H5VSTRING, Str);
1509  default:
1510  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
1511 #undef HANDLE_CASE
1512  }
1513 
1514  if (bt) {
1515 
1516  const vector<HDF5CF::Dimension *>& dims = spvar->getDimensions();
1517  vector <HDF5CF::Dimension*>:: const_iterator it_d;
1518 
1519  if(dims.empty())
1520  throw InternalErr(__FILE__,__LINE__,"Currently don't support scalar special variables. ");
1521 
1522  HDF5GMSPCFArray *ar = NULL;
1523 
1524  try {
1525  ar = new HDF5GMSPCFArray (
1526  spvar->getRank(),
1527  filename,
1528  fileid,
1529  spvar->getType(),
1530  spvar->getFullPath(),
1531  spvar->getOriginalType(),
1532  spvar->getStartBit(),
1533  spvar->getBitNum(),
1534  spvar->getNewName(),
1535  bt);
1536  }
1537  catch(...) {
1538  delete bt;
1539  throw InternalErr(__FILE__,__LINE__,"Unable to allocate HDF5GMCFMissNonLLCVArray. ");
1540  }
1541 
1542 
1543  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
1544  if (""==(*it_d)->getNewName())
1545  ar->append_dim((*it_d)->getSize());
1546  else
1547  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
1548  }
1549 
1550  ar->set_is_dap4(true);
1551  BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
1552  map_cfh5_var_attrs_to_dap4(spvar,d4_var);
1553  d4_root->add_var_nocopy(d4_var);
1554 
1555  //dds.add_var(ar);
1556  delete bt;
1557  delete ar;
1558  }
1559 
1560 }
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 class includes the methods to read data array into DAP buffer from an HDF5 dataset for the CF op...
This class specifies the retrieval of the missing lat/lon values for general HDF5 products.
This class specifies the retrieval of the values of non-lat/lon coordinate variables for general HDF5...
This class specifies the retrieval of the missing lat/lon values for general HDF5 products.
This class specifies the retrieval of data values for special HDF5 products Currently this only appli...
include the entry functions to execute the handlers
CVType getCVType() const
Get the coordinate variable type of this variable.
Definition: HDF5CF.h:372
bool HaveUnlimitedDim() const
Has unlimited dimensions.
Definition: HDF5CF.h:691
virtual void Retrieve_H5_Var_Attr_Values(Var *var)
Retrieve attribute values for a variable.
Definition: HDF5CF.cc:748
const std::string & getPath() const
Obtain the path of the file.
Definition: HDF5CF.h:667
hid_t getFileID() const
Obtain the HDF5 file ID.
Definition: HDF5CF.h:661
const std::vector< Attribute * > & getAttributes() const
Public interface to obtain information of all attributes under the root group.
Definition: HDF5CF.h:679
const std::vector< Var * > & getVars() const
Public interface to obtain information of all variables.
Definition: HDF5CF.h:673
const std::vector< Group * > & getGroups() const
Public interface to obtain all the group info.
Definition: HDF5CF.h:685
This class is a derived class of CVar. It represents a coordinate variable for general HDF5 files.
Definition: HDF5CF.h:427
H5GCFProduct getPtType() const
Get the data type of this variable.
Definition: HDF5CF.h:439
This class is a derived class of File. It includes methods applied to general HDF5 files only.
Definition: HDF5CF.h:845
virtual void Handle_Unsupported_Dtype(bool)
Handle unsupported HDF5 datatypes for general HDF5 products.
Definition: HDF5GMCF.cc:400
virtual void Adjust_Obj_Name()
Adjust object names based on different general NASA HDF5 products.
Definition: HDF5GMCF.cc:4912
virtual void Retrieve_H5_CVar_Supported_Attr_Values()
Retrieve coordinate variable attributes.
Definition: HDF5GMCF.cc:333
void Add_Path_Coord_Attr()
Update the coordinate attribute to include path and also flatten.
Definition: HDF5GMCF.cc:7026
virtual bool Have_Grid_Mapping_Attrs()
Check if having Grid Mapping Attrs.
Definition: HDF5GMCF.cc:6950
virtual void Adjust_Dim_Name()
Adjust dimension name for general NASA HDF5 products.
Definition: HDF5GMCF.cc:5225
void Handle_Obj_NameClashing(bool)
Handle object name clashing for general NASA HDF5 products.
Definition: HDF5GMCF.cc:5055
void Remove_Unused_FakeDimVars()
Unsupported datatype array may generate FakeDim. Remove them.
Definition: HDF5GMCF.cc:6958
void Update_Product_Type()
Update "product type" attributes for general HDF5 products.
Definition: HDF5GMCF.cc:238
virtual void Retrieve_H5_Info(const char *path, hid_t file_id, bool include_attr)
Retrieve DDS information from the HDF5 file; real implementation for general HDF5 products.
Definition: HDF5GMCF.cc:219
virtual void Handle_SpVar()
Handle special variables for general NASA HDF5 products.
Definition: HDF5GMCF.cc:4822
virtual bool Get_IgnoredInfo_Flag()
Obtain ignored info. flag.
Definition: HDF5CF.h:947
virtual void Handle_Unsupported_Dspace(bool)
Handle unsupported HDF5 dataspaces for general HDF5 products.
Definition: HDF5GMCF.cc:597
virtual void Handle_Unsupported_Others(bool)
Handle other unmapped objects/attributes for general HDF5 products.
Definition: HDF5GMCF.cc:694
virtual const std::string & Get_Ignored_Msg()
Get the message that contains the ignored obj. info.
Definition: HDF5CF.h:953
void Remove_Unneeded_Objects()
Remove unneeded objects.
Definition: HDF5GMCF.cc:261
void Add_Dim_Name()
Add dimension name.
Definition: HDF5GMCF.cc:833
virtual void Flatten_Obj_Name(bool include_attr)
Flatten the object name for general NASA HDF5 products.
Definition: HDF5GMCF.cc:4997
virtual void Handle_Grid_Mapping_Vars()
Handle Grid Mapping Vars.
Definition: HDF5GMCF.cc:6954
virtual void Handle_DimNameClashing()
Definition: HDF5GMCF.cc:5160
virtual void Handle_Coor_Attr()
Handle "coordinates" attributes for general HDF5 products.
Definition: HDF5GMCF.cc:6016
void Rename_NC4_NonCoordVars()
Remove the _nc4_non_coord from the variable new names.
Definition: HDF5GMCF.cc:7006
virtual void Retrieve_H5_Supported_Attr_Values()
Retrieve attribute values for the supported HDF5 datatypes for general HDF5 products.
Definition: HDF5GMCF.cc:348
virtual void Add_Supplement_Attrs(bool)
Add supplemental attributes such as fullpath and original name for general NASA HDF5 products.
Definition: HDF5GMCF.cc:5287
virtual void Handle_CVar()
Handle coordinate variables for general NASA HDF5 products.
Definition: HDF5GMCF.cc:2939
This class is a derived class of Var. It represents a special general HDF5 product(currently ACOS and...
Definition: HDF5CF.h:392
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
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.