bes Updated for version 3.20.13
heos5cfdap.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#include "config_hdf5.h"
33
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <unistd.h>
38#include <iostream>
39#include <sstream>
40
41#include <BESLog.h>
42#include <BESDebug.h>
43
44#include <libdap/parser.h>
45#include "heos5cfdap.h"
46#include "h5cfdaputil.h"
47#include "HDF5CFByte.h"
48#include "HDF5CFInt8.h"
49#include "HDF5CFUInt16.h"
50#include "HDF5CFInt16.h"
51#include "HDF5CFUInt32.h"
52#include "HDF5CFInt32.h"
53#include "HDF5CFUInt64.h"
54#include "HDF5CFInt64.h"
55#include "HDF5CFFloat32.h"
56#include "HDF5CFFloat64.h"
57#include "HDF5CFStr.h"
58#include "HDF5CFArray.h"
62#include "HDF5CFGeoCF1D.h"
63#include "HDF5CFGeoCFProj.h"
64#include "HDF5RequestHandler.h"
65#include "h5apicompatible.h"
66
67#include "he5dds.tab.hh"
68#include "HE5Parser.h"
69#include "HE5Checker.h"
70#include "he5das.tab.hh"
71
72struct yy_buffer_state;
73
74yy_buffer_state *he5dds_scan_string(const char *str);
75int he5ddsparse(HE5Parser *he5parser);
76int he5dasparse(libdap::parser_arg *arg);
77int he5ddslex_destroy();
78int he5daslex_destroy();
79
81yy_buffer_state *he5das_scan_string(const char *str);
82
83using namespace HDF5CF;
84
85// Map EOS5 to DAP DDS
86void map_eos5_cfdds(DDS &dds, hid_t file_id, const string & filename) {
87
88 BESDEBUG("h5","Coming to HDF-EOS5 products DDS mapping function map_eos5_cfdds "<<endl);
89
90
91 string st_str ="";
92 string core_str="";
93 string arch_str="";
94 string xml_str ="";
95 string subset_str="";
96 string product_str="";
97 string other_str ="";
98 bool st_only = true;
99
100 // Read ECS metadata: merge them into one C++ string
101 read_ecs_metadata(file_id,st_str,core_str,arch_str,xml_str, subset_str,product_str,other_str,st_only);
102 if(""==st_str) {
103 string msg =
104 "unable to obtain the HDF-EOS5 struct metadata ";
105 throw InternalErr(__FILE__, __LINE__, msg);
106 }
107
108 bool is_check_nameclashing = HDF5RequestHandler::get_check_name_clashing();
109
110 EOS5File *f = nullptr;
111
112 try {
113 f = new EOS5File(filename.c_str(),file_id);
114 }
115 catch(...) {
116 throw InternalErr(__FILE__,__LINE__,"Cannot allocate the file object.");
117 }
118
119 bool include_attr = false;
120
121 // This first "try-catch" block will use the parsed info
122 try {
123
124 // Parse the structmetadata
125 HE5Parser p;
126 HE5Checker c;
127 he5dds_scan_string(st_str.c_str());
128 he5ddsparse(&p);
129 he5ddslex_destroy();
130
131 // Retrieve ProjParams from StructMetadata
132 p.add_projparams(st_str);
133#if 0
134 //p.print();
135#endif
136
137 // Check if the HDF-EOS5 grid has the valid parameters, projection codes.
138 if (c.check_grids_unknown_parameters(&p)) {
139 throw InternalErr("Unknown HDF-EOS5 grid paramters found in the file");
140 }
141
142 if (c.check_grids_missing_projcode(&p)) {
143 throw InternalErr("The HDF-EOS5 is missing project code ");
144 }
145
146 // We gradually add the support of different projection codes
147 if (c.check_grids_support_projcode(&p)) {
148 throw InternalErr("The current project code is not supported");
149 }
150
151 // HDF-EOS5 provides default pixel and origin values if they are not defined.
152 c.set_grids_missing_pixreg_orig(&p);
153
154 // Check if this multi-grid file shares the same grid.
155 bool grids_mllcv = c.check_grids_multi_latlon_coord_vars(&p);
156
157 // Retrieve all HDF5 info(Not the values)
158 f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
159
160 // Adjust EOS5 Dimension names/sizes based on the parsed results
161 f->Adjust_EOS5Dim_Info(&p);
162
163 // Translate the parsed output to HDF-EOS5 grids/swaths/zonal.
164 // Several maps related to dimension and coordiantes are set up here.
165 f->Add_EOS5File_Info(&p, grids_mllcv);
166
167 // Add the dimension names
168 f->Add_Dim_Name(&p);
169 }
170 catch (HDF5CF::Exception &e){
171 if(f!=nullptr)
172 delete f;
173 throw InternalErr(e.what());
174 }
175 catch(...) {
176 if(f!=nullptr)
177 delete f;
178 throw;
179 }
180
181 // The parsed struct will no longer be in this "try-catch" block.
182 try {
183
184 // NASA Aura files need special handlings. So first check if this file is an Aura file.
186
187 // Adjust the variable name
189
190 // Handle coordinate variables
191 f->Handle_CVar();
192
193 // Adjust variable and dimension names again based on the handling of coordinate variables.
195
196
197 // We need to use the CV units to distinguish lat/lon from th 3rd CV when
198 // memory cache is turned on.
199 if((HDF5RequestHandler::get_lrdata_mem_cache() != nullptr) ||
200 (HDF5RequestHandler::get_srdata_mem_cache() != nullptr)){
201
202 // Handle unsupported datatypes including the attributes
204
205 // Handle unsupported dataspaces including the attributes
207
208 // We need to retrieve coordinate variable attributes for memory cache use.
210
211 }
212 else {
213
214 // Handle unsupported datatypes
215 f->Handle_Unsupported_Dtype(include_attr);
216
217 // Handle unsupported dataspaces
218 f->Handle_Unsupported_Dspace(include_attr);
219
220 }
221
222
223 // Need to retrieve the units of CV when memory cache is turned on.
224 // The units of CV will be used to distinguish whether this CV is
225 // latitude/longitude or a third-dimension CV.
226 // isLatLon() will use the units value.
227 if((HDF5RequestHandler::get_lrdata_mem_cache() != nullptr) ||
228 (HDF5RequestHandler::get_srdata_mem_cache() != nullptr))
229 f->Adjust_Attr_Info();
230
231 // May need to adjust the object names for special objects. Currently no operations
232 // are done in this routine.
233 f->Adjust_Obj_Name();
234
235 // Flatten the object name
236 f->Flatten_Obj_Name(include_attr);
237
238 // Handle name clashing
239 if(true == is_check_nameclashing)
240 f->Handle_Obj_NameClashing(include_attr);
241
242 // Check if this should follow COARDS, yes, set the COARDS flag.
244
245 // For COARDS, the dimension name needs to be changed.
246 f->Adjust_Dim_Name();
247 if(true == is_check_nameclashing)
249
250 // We need to turn off the very long string in the TES file to avoid
251 // the choking of netCDF Java tools. So this special variable routine
252 // is listed at last. We may need to turn off this if netCDF can handle
253 // long string better.
254 f->Handle_SpVar();
255 }
256 catch (HDF5CF::Exception &e){
257 if(f != nullptr)
258 delete f;
259 throw InternalErr(e.what());
260 }
261
262 // Generate EOS5 DDS
263 try {
264 gen_eos5_cfdds(dds,f);
265 }
266 catch(...) {
267 if (f!=nullptr)
268 delete f;
269 throw;
270 }
271
272 if (f!=nullptr)
273 delete f;
274}
275
276// Map EOS5 to DAP DAS
277void map_eos5_cfdas(DAS &das, hid_t file_id, const string &filename) {
278
279 BESDEBUG("h5","Coming to HDF-EOS5 products DAS mapping function map_eos5_cfdas "<<endl);
280 string st_str ="";
281 string core_str="";
282 string arch_str="";
283 string xml_str ="";
284 string subset_str="";
285 string product_str="";
286 string other_str ="";
287 bool st_only = true;
288
289 read_ecs_metadata(file_id,st_str,core_str,arch_str,xml_str, subset_str,product_str,other_str,st_only);
290 if(""==st_str) {
291 string msg =
292 "unable to obtain the HDF-EOS5 struct metadata ";
293 throw InternalErr(__FILE__, __LINE__, msg);
294 }
295
296 bool is_check_nameclashing = HDF5RequestHandler::get_check_name_clashing();
297
298 bool is_add_path_attrs = HDF5RequestHandler::get_add_path_attrs();
299
300 EOS5File *f = nullptr;
301 try {
302 f = new EOS5File(filename.c_str(),file_id);
303 }
304 catch(...) {
305 throw InternalErr(__FILE__,__LINE__,"Cannot allocate the file object.");
306 }
307 bool include_attr = true;
308
309 // The first "try-catch" block will use the parsed info.
310 try {
311
312 HE5Parser p;
313 HE5Checker c;
314 he5dds_scan_string(st_str.c_str());
315
316 he5ddsparse(&p);
317 he5ddslex_destroy();
318 p.add_projparams(st_str);
319#if 0
320 //p.print();
321 // cerr<<"main loop p.za_list.size() = "<<p.za_list.size() <<endl;
322#endif
323
324 if (c.check_grids_unknown_parameters(&p)) {
325 throw InternalErr("Unknown HDF-EOS5 grid paramters found in the file");
326 }
327
328 if (c.check_grids_missing_projcode(&p)) {
329 throw InternalErr("The HDF-EOS5 is missing project code ");
330 }
331 if (c.check_grids_support_projcode(&p)) {
332 throw InternalErr("The current project code is not supported");
333 }
334 c.set_grids_missing_pixreg_orig(&p);
335
336 bool grids_mllcv = c.check_grids_multi_latlon_coord_vars(&p);
337
338 f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
339 f->Adjust_EOS5Dim_Info(&p);
340 f->Add_EOS5File_Info(&p, grids_mllcv);
341 f->Add_Dim_Name(&p);
342 }
343 catch (HDF5CF::Exception &e){
344 if(f != nullptr)
345 delete f;
346 throw InternalErr(e.what());
347 }
348 catch(...) {
349 if(f != nullptr)
350 delete f;
351 throw;
352 }
353
354 try {
357 f->Handle_CVar();
359 f->Handle_Unsupported_Dtype(include_attr);
360
361 // Remove unsupported dataspace
362 f->Handle_Unsupported_Dspace(include_attr);
363
364 // Need to retrieve the attribute values.
366
367
368 // Handle other unsupported objects,
369 // currently it mainly generates the info. for the
370 // unsupported objects other than datatype, dataspace,links and named datatype
371 // This function needs to be called after retrieving supported attributes.
372 f->Handle_Unsupported_Others(include_attr);
373
374 // Add/adjust CF attributes
375 f->Adjust_Attr_Info();
376 f->Adjust_Obj_Name();
377 f->Flatten_Obj_Name(include_attr);
378 if (true == is_check_nameclashing)
379 f->Handle_Obj_NameClashing(include_attr);
381
382#if 0
383 //f->Adjust_Dim_Name();
384 //if(true == is_check_nameclashing)
385 // f->Handle_DimNameClashing();
386#endif
387
388 // Add supplemental attributes
389 f->Add_Supplement_Attrs(is_add_path_attrs);
390
391 // Handle coordinate attributes
392 f->Handle_Coor_Attr();
394 }
395 catch (HDF5CF::Exception &e){
396 if(f != nullptr)
397 delete f;
398 throw InternalErr(e.what());
399 }
400
401 // Generate DAS for the EOS5
402 try {
403 gen_eos5_cfdas(das,file_id,f);
404 }
405 catch(...) {
406 if (f != nullptr)
407 delete f;
408 throw;
409 }
410
411 if( f != nullptr)
412 delete f;
413
414}
415
416// Generate DDS for the EOS5
417void gen_eos5_cfdds(DDS &dds, HDF5CF::EOS5File *f) {
418
419 BESDEBUG("h5","Coming to HDF-EOS5 products DDS generation function gen_eos5_cfdds "<<endl);
420 const vector<HDF5CF::Var *>& vars = f->getVars();
421 const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
422 const string filename = f->getPath();
423 const hid_t file_id = f->getFileID();
424
425 // Read Variable info.
426 vector<HDF5CF::EOS5CVar *>::const_iterator it_cv;
427
428 for (auto it_v = vars.begin(); it_v !=vars.end();++it_v) {
429 BESDEBUG("h5","variable full path= "<< (*it_v)->getFullPath() <<endl);
430 gen_dap_onevar_dds(dds,*it_v,file_id,filename);
431 }
432
433 for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
434 BESDEBUG("h5","variable full path= "<< (*it_cv)->getFullPath() <<endl);
435 gen_dap_oneeos5cvar_dds(dds,*it_cv,file_id,filename);
436
437 }
438
439 // We need to provide grid_mapping info. for multiple grids.
440 // Here cv_lat_miss_index represents the missing latitude(HDF-EOS grid without the latitude field) cv index
441 // This index is used to create the grid_mapping variable for different grids.
442 unsigned short cv_lat_miss_index = 1;
443 for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
444 if((*it_cv)->getCVType() == CV_LAT_MISS) {
445 if((*it_cv)->getProjCode() != HE5_GCTP_GEO) {
446 // Here we need to add grid_mapping variables for each grid
447 // For projections other than sinusoidal since attribute values for LAMAZ and PS
448 // are different for each grid.
449 gen_dap_oneeos5cf_dds(dds,*it_cv);
450 add_cf_grid_mapinfo_var(dds,(*it_cv)->getProjCode(),cv_lat_miss_index);
451 cv_lat_miss_index++;
452 }
453 }
454 }
455}
456
457void gen_dap_oneeos5cf_dds(DDS &dds,const HDF5CF::EOS5CVar* cvar) {
458
459 BESDEBUG("h5","Coming to gen_dap_oneeos5cf_dds() "<<endl);
460
461 float cv_point_lower = cvar->getPointLower();
462 float cv_point_upper = cvar->getPointUpper();
463 float cv_point_left = cvar->getPointLeft();
464 float cv_point_right = cvar->getPointRight();
465 EOS5GridPCType cv_proj_code = cvar->getProjCode();
466 const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
467 if(dims.size() !=2)
468 throw InternalErr(__FILE__,__LINE__,"Currently we only support the 2-D CF coordinate projection system.");
469 add_cf_grid_cvs(dds,cv_proj_code,cv_point_lower,cv_point_upper,cv_point_left,cv_point_right,dims);
470
471}
472
473void gen_dap_oneeos5cf_das(DAS &das,const vector<HDF5CF::Var*>& vars, const HDF5CF::EOS5CVar* cvar,const unsigned short g_suffix) {
474
475 BESDEBUG("h5","Coming to gen_dap_oneeos5cf_das() "<<endl);
476#if 0
477 float cv_point_lower = cvar->getPointLower();
478 float cv_point_upper = cvar->getPointUpper();
479 float cv_point_left = cvar->getPointLeft();
480 float cv_point_right = cvar->getPointRight();
481#endif
482 EOS5GridPCType cv_proj_code = cvar->getProjCode();
483 const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
484
485#if 0
486cerr<<"cv_point_lower is "<<cv_point_lower <<endl;
487cerr<<"cvar name is "<<cvar->getName() <<endl;
488for(vector<HDF5CF::Dimension*>::const_iterator it_d = dims.begin(); it_d != dims.end(); ++it_d)
489 cerr<<"dim name das is "<<(*it_d)->getNewName() <<endl;
490#endif
491
492 if(dims.size() !=2)
493 throw InternalErr(__FILE__,__LINE__,"Currently we only support the 2-D CF coordinate projection system.");
494#if 0
495 add_cf_grid_cv_attrs(das,vars,cv_proj_code,cv_point_lower,cv_point_upper,cv_point_left,cv_point_right,dims,cvar->getParams(),g_suffix);
496#endif
497 add_cf_grid_cv_attrs(das,vars,cv_proj_code,dims,cvar->getParams(),g_suffix);
498
499}
500
501//For EOS5, generate the ignored object info. for the CF option
502void gen_eos5_cf_ignored_obj_info(DAS &das, HDF5CF::EOS5File *f) {
503
504 BESDEBUG("h5","Coming to gen_eos5_cf_ignored_obj_info() "<<endl);
505 AttrTable *at = das.get_table("Ignored_Object_Info");
506 if (nullptr == at)
507 at = das.add_table("Ignored_Object_Info", new AttrTable);
508
509 at->append_attr("Message","String",f->Get_Ignored_Msg());
510
511
512}
513
514// Generate DDS for EOS5 coordinate variables
515void gen_dap_oneeos5cvar_dds(DDS &dds,const HDF5CF::EOS5CVar* cvar, const hid_t file_id, const string & filename) {
516
517 BESDEBUG("h5","Coming to gen_dap_oneeos5cvar_dds() "<<endl);
518 BaseType *bt = nullptr;
519
520 // TODO: need to handle 64-bit integer for DAP4 CF
521 if(cvar->getType()==H5INT64 || cvar->getType() == H5UINT64)
522 return;
523 switch(cvar->getType()) {
524#define HANDLE_CASE(tid,type) \
525 case tid: \
526 bt = new (type)(cvar->getNewName(),cvar->getFullPath()); \
527 break;
528
529 HANDLE_CASE(H5FLOAT32, HDF5CFFloat32)
530 HANDLE_CASE(H5FLOAT64, HDF5CFFloat64)
531 HANDLE_CASE(H5CHAR,HDF5CFInt16)
532 HANDLE_CASE(H5UCHAR, HDF5CFByte)
533 HANDLE_CASE(H5INT16, HDF5CFInt16)
534 HANDLE_CASE(H5UINT16, HDF5CFUInt16)
535 HANDLE_CASE(H5INT32, HDF5CFInt32)
536 HANDLE_CASE(H5UINT32, HDF5CFUInt32)
537 HANDLE_CASE(H5FSTRING, Str)
538 HANDLE_CASE(H5VSTRING, Str)
539 default:
540 throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
541#undef HANDLE_CASE
542 }
543
544 if (bt) {
545
546 const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
547 vector <HDF5CF::Dimension*>:: const_iterator it_d;
548 vector <size_t> dimsizes;
549 dimsizes.resize(cvar->getRank());
550 for(int i = 0; i <cvar->getRank();i++)
551 dimsizes[i] = (dims[i])->getSize();
552
553
554 if(dims.empty())
555 throw InternalErr(__FILE__,__LINE__,"the coordinate variables cannot be scalar.");
556 switch(cvar->getCVType()) {
557
558 case CV_EXIST:
559 {
560
561#if 0
562for(vector<HDF5CF::Attribute *>::const_iterator it_ra = cvar->getAttributes().begin();
563 it_ra != cvar->getAttributes().end(); ++it_ra) {
564cerr<<"cvar attribute name is "<<(*it_ra)->getNewName() <<endl;
565cerr<<"cvar attribute value type is "<<(*it_ra)->getType() <<endl;
566}
567cerr<<"cvar new name exist at he s5cfdap.cc is "<<cvar->getNewName() <<endl;
568#endif
569 bool is_latlon = cvar->isLatLon();
570 HDF5CFArray *ar = nullptr;
571 try {
572 ar = new HDF5CFArray (
573 cvar->getRank(),
574 file_id,
575 filename,
576 cvar->getType(),
577 dimsizes,
578 cvar->getFullPath(),
579 cvar->getTotalElems(),
580 CV_EXIST,
581 is_latlon,
582 cvar->getCompRatio(),
583 false,
584 cvar->getNewName(),
585 bt);
586 }
587 catch (...) {
588 delete bt;
589 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDF5CFArray.");
590 }
591
592 for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
593 if (""==(*it_d)->getNewName())
594 ar->append_dim((int)((*it_d)->getSize()));
595 else
596 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
597 }
598
599 dds.add_var(ar);
600 delete bt;
601 delete ar;
602 }
603 break;
604
605 case CV_LAT_MISS:
606 case CV_LON_MISS:
607 {
608
609 HDFEOS5CFMissLLArray *ar = nullptr;
610 try {
611#if 0
612cerr<<"cvar zone here is "<<cvar->getZone() <<endl;
613cerr<<"cvar Sphere here is "<<cvar->getSphere() <<endl;
614cerr<<"cvar getParams here 1 is "<<cvar->getParams()[0]<<endl;
615#endif
616 ar = new HDFEOS5CFMissLLArray (
617 cvar->getRank(),
618 filename,
619 file_id,
620 cvar->getFullPath(),
621 cvar->getCVType(),
622 cvar->getPointLower(),
623 cvar->getPointUpper(),
624 cvar->getPointLeft(),
625 cvar->getPointRight(),
626 cvar->getPixelReg(),
627 cvar->getOrigin(),
628 cvar->getProjCode(),
629 cvar->getParams(),
630 cvar->getZone(),
631 cvar->getSphere(),
632 cvar->getXDimSize(),
633 cvar->getYDimSize(),
634 cvar->getNewName(),
635 bt);
636 }
637 catch (...) {
638 delete bt;
639 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDFEOS5CFMissLLArray.");
640 }
641
642 for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
643 if (""==(*it_d)->getNewName())
644 ar->append_dim((int)((*it_d)->getSize()));
645 else
646 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
647 }
648
649 dds.add_var(ar);
650 delete bt;
651 delete ar;
652 }
653 break;
654
655 case CV_NONLATLON_MISS:
656 {
657
658 if (cvar->getRank() !=1) {
659 delete bt;
660 throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
661 }
662 auto nelem = (int)((cvar->getDimensions()[0])->getSize());
663
664 HDFEOS5CFMissNonLLCVArray *ar = nullptr;
665 try {
667 cvar->getRank(),
668 nelem,
669 cvar->getNewName(),
670 bt);
671 }
672 catch (...) {
673 delete bt;
674 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDFEOS5CFMissNonLLCVArray.");
675 }
676
677
678 for(it_d = dims.begin(); it_d != dims.end(); it_d++) {
679 if (""==(*it_d)->getNewName())
680 ar->append_dim((int)((*it_d)->getSize()));
681 else
682 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
683 }
684 dds.add_var(ar);
685 delete bt;
686 delete ar;
687
688
689 }
690 break;
691 case CV_SPECIAL:
692 // Currently only support Aura TES files. May need to revise when having more
693 // special products KY 2012-2-3
694 {
695
696 if (cvar->getRank() !=1) {
697 delete bt;
698 throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
699 }
700 auto nelem = (int)((cvar->getDimensions()[0])->getSize());
701 HDFEOS5CFSpecialCVArray *ar = nullptr;
702
703 try {
705 cvar->getRank(),
706 filename,
707 file_id,
708 cvar->getType(),
709 nelem,
710 cvar->getFullPath(),
711 cvar->getNewName(),
712 bt);
713 }
714 catch (...) {
715 delete bt;
716 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDF5CFArray.");
717 }
718
719
720 for(it_d = dims.begin(); it_d != dims.end(); ++it_d){
721 if (""==(*it_d)->getNewName())
722 ar->append_dim((int)((*it_d)->getSize()));
723 else
724 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
725 }
726 dds.add_var(ar);
727 delete bt;
728 delete ar;
729 }
730 break;
731 case CV_MODIFY:
732 default:
733 delete bt;
734 throw InternalErr(__FILE__,__LINE__,"Unsupported coordinate variable type.");
735 }
736
737 }
738
739}
740
741// Generate EOS5 DAS
742void gen_eos5_cfdas(DAS &das, hid_t file_id, HDF5CF::EOS5File *f) {
743
744 BESDEBUG("h5","Coming to HDF-EOS5 products DAS generation function gen_eos5_cfdas "<<endl);
745
746 // First check if this is for generating the ignored object info.
747 if(true == f->Get_IgnoredInfo_Flag()) {
748 gen_eos5_cf_ignored_obj_info(das, f);
749 return;
750 }
751
752 const vector<HDF5CF::Var *>& vars = f->getVars();
753 const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
754 const vector<HDF5CF::Group *>& grps = f->getGroups();
755 const vector<HDF5CF::Attribute *>& root_attrs = f->getAttributes();
756
757 vector<HDF5CF::EOS5CVar *>::const_iterator it_cv;
758 vector<HDF5CF::Attribute *>::const_iterator it_ra;
759
760 // Handling the file attributes(attributes under the root group)
761 // The table name is "HDF_GLOBAL".
762 if (false == root_attrs.empty()) {
763 AttrTable *at = das.get_table(FILE_ATTR_TABLE_NAME);
764 if (nullptr == at)
765 at = das.add_table(FILE_ATTR_TABLE_NAME, new AttrTable);
766
767 for (it_ra = root_attrs.begin(); it_ra != root_attrs.end(); it_ra++) {
768 gen_dap_oneobj_das(at,*it_ra,nullptr);
769 }
770 }
771
772 if (false == grps.empty()) {
773 for (auto it_g = grps.begin(); it_g != grps.end(); ++it_g) {
774 AttrTable *at = das.get_table((*it_g)->getNewName());
775 if (nullptr == at)
776 at = das.add_table((*it_g)->getNewName(), new AttrTable);
777
778 for (it_ra = (*it_g)->getAttributes().begin();
779 it_ra != (*it_g)->getAttributes().end(); ++it_ra) {
780#if 0
781 //gen_dap_oneobj_das(at,*it_ra,nullptr);
782#endif
783 // TODO: ADDING a BES KEY
784 if((*it_ra)->getNewName()=="Conventions" &&((*it_g)->getNewName() == "HDFEOS_ADDITIONAL_FILE_ATTRIBUTES")
785 && (true==HDF5RequestHandler::get_eos5_rm_convention_attr_path())) {
786 AttrTable *at_das = das.get_table(FILE_ATTR_TABLE_NAME);
787 if (nullptr == at_das)
788 at_das = das.add_table(FILE_ATTR_TABLE_NAME, new AttrTable);
789 gen_dap_oneobj_das(at_das,*it_ra,nullptr);
790 }
791 else
792 gen_dap_oneobj_das(at,*it_ra,nullptr);
793 }
794 }
795 }
796
797 for (auto it_v = vars.begin(); it_v != vars.end(); ++it_v) {
798 if (false == ((*it_v)->getAttributes().empty())) {
799
800 // TODO: Need to handle 64-bit int support for DAP4 CF.
801 if(H5INT64 == (*it_v)->getType() || H5UINT64 == (*it_v)->getType()){
802 continue;
803 }
804
805 AttrTable *at = das.get_table((*it_v)->getNewName());
806 if (nullptr == at)
807 at = das.add_table((*it_v)->getNewName(), new AttrTable);
808
809 for (it_ra = (*it_v)->getAttributes().begin();
810 it_ra != (*it_v)->getAttributes().end(); ++it_ra) {
811 gen_dap_oneobj_das(at,*it_ra,*it_v);
812 }
813 }
814 }
815
816 for (it_cv = cvars.begin(); it_cv !=cvars.end();it_cv++) {
817
818 if (false == ((*it_cv)->getAttributes().empty())) {
819
820 // TODO: Need to handle 64-bit int support for DAP4 CF.
821 if(H5INT64 == (*it_cv)->getType() || H5UINT64 == (*it_cv)->getType()){
822 continue;
823 }
824
825 AttrTable *at = das.get_table((*it_cv)->getNewName());
826 if (nullptr == at)
827 at = das.add_table((*it_cv)->getNewName(), new AttrTable);
828
829 for (it_ra = (*it_cv)->getAttributes().begin();
830 it_ra != (*it_cv)->getAttributes().end(); ++it_ra) {
831 gen_dap_oneobj_das(at,*it_ra,*it_cv);
832 }
833 }
834 }
835
836 // Add CF 1-D projection variables
837 unsigned short cv_lat_miss_index = 1;
838 // This code block will add grid_mapping attribute info. to corresponding variables.
839 for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
840 if((*it_cv)->getCVType() == CV_LAT_MISS) {
841 if((*it_cv)->getProjCode() != HE5_GCTP_GEO) {
842 gen_dap_oneeos5cf_das(das,vars,*it_cv,cv_lat_miss_index);
843 cv_lat_miss_index++;
844 }
845 }
846 }
847
848 for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
849 if((*it_cv)->getProjCode() == HE5_GCTP_LAMAZ) {
850 if((*it_cv)->getCVType() == CV_LAT_MISS || (*it_cv)->getCVType() == CV_LON_MISS) {
851 AttrTable *at = das.get_table((*it_cv)->getNewName());
852 if (nullptr == at)
853 at = das.add_table((*it_cv)->getNewName(), new AttrTable);
854 if((*it_cv)->getCVType() == CV_LAT_MISS)
855 add_ll_valid_range(at,true);
856 else
857 add_ll_valid_range(at,false);
858 }
859 }
860 }
861
862
863 bool disable_ecsmetadata = HDF5RequestHandler::get_disable_ecsmeta();
864
865 if(disable_ecsmetadata == false) {
866
867 // To keep the backward compatiablity with the old handler,
868 // we parse the special ECS metadata to DAP attributes
869
870 string st_str ="";
871 string core_str="";
872 string arch_str="";
873 string xml_str ="";
874 string subset_str="";
875 string product_str="";
876 string other_str ="";
877 bool st_only = false;
878
879 read_ecs_metadata(file_id, st_str, core_str, arch_str, xml_str,
880 subset_str, product_str, other_str, st_only);
881
882#if 0
883if(st_str!="") "h5","Final structmetadata "<<st_str <<endl;
884if(core_str!="") "h5","Final coremetadata "<<core_str <<endl;
885if(arch_str!="") "h5","Final archivedmetadata "<<arch_str <<endl;
886if(xml_str!="") "h5","Final xmlmetadata "<<xml_str <<endl;
887if(subset_str!="") "h5","Final subsetmetadata "<<subset_str <<endl;
888if(product_str!="") "h5","Final productmetadata "<<product_str <<endl;
889if(other_str!="") "h5","Final othermetadata "<<other_str <<endl;
890
891#endif
892 if(st_str != ""){
893
894#if 0
895 string check_disable_smetadata_key ="H5.DisableStructMetaAttr";
896 bool is_check_disable_smetadata = false;
897#endif
898 bool is_check_disable_smetadata = HDF5RequestHandler::get_disable_structmeta();
899
900 if (false == is_check_disable_smetadata) {
901
902 AttrTable *at = das.get_table("StructMetadata");
903 if (nullptr == at)
904 at = das.add_table("StructMetadata", new AttrTable);
905 parser_arg arg(at);
906
907 he5das_scan_string((const char*) st_str.c_str());
908 if (he5dasparse(&arg) != 0
909 || false == arg.status()){
910
911 ERROR_LOG("HDF-EOS5 parse error while processing a "
912 << "StructMetadata " << " HDFEOS attribute" << endl);
913 }
914
915 he5daslex_destroy();
916
917 }
918 }
919
920 if(core_str != ""){
921 AttrTable *at = das.get_table("CoreMetadata");
922 if (nullptr == at)
923 at = das.add_table("CoreMetadata", new AttrTable);
924 parser_arg arg(at);
925 he5das_scan_string((const char*) core_str.c_str());
926 if (he5dasparse(&arg) != 0
927 || false == arg.status()){
928
929 ERROR_LOG("HDF-EOS5 parse error while processing a "
930 << "CoreMetadata " << " HDFEOS attribute" << endl);
931 }
932
933 he5daslex_destroy();
934 }
935 if(arch_str != ""){
936 AttrTable *at = das.get_table("ArchiveMetadata");
937 if (nullptr == at)
938 at = das.add_table("ArchiveMetadata", new AttrTable);
939 parser_arg arg(at);
940 he5das_scan_string((const char*) arch_str.c_str());
941 if (he5dasparse(&arg) != 0
942 || false == arg.status()){
943
944 ERROR_LOG("HDF-EOS5 parse error while processing a "
945 << "ArchiveMetadata " << " HDFEOS attribute" << endl);
946 }
947 he5daslex_destroy();
948 }
949
950 // XML attribute includes double quote("), this will choke netCDF Java library.
951 // So we replace double_quote(") with &quote.This is currently the OPeNDAP way.
952 // XML attribute cannot parsed. So just pass the string.
953 if(xml_str != ""){
954 AttrTable *at = das.get_table("XMLMetadata");
955 if (nullptr == at)
956 at = das.add_table("XMLMetadata", new AttrTable);
957 HDF5CFDAPUtil::replace_double_quote(xml_str);
958 at->append_attr("Contents","String",xml_str);
959 }
960
961 // SubsetMetadata and ProductMetadata exist in HDF-EOS2 files.
962 // So far we haven't found any metadata in NASA HDF-EOS5 files,
963 // but will keep an eye on it. KY 2012-3-6
964 if(subset_str != ""){
965 AttrTable *at = das.get_table("SubsetMetadata");
966 if (nullptr == at)
967 at = das.add_table("SubsetMetadata", new AttrTable);
968 parser_arg arg(at);
969 he5das_scan_string((const char*) subset_str.c_str());
970 if (he5dasparse(&arg) != 0
971 || false == arg.status()) {
972
973 ERROR_LOG("HDF-EOS5 parse error while processing a "
974 << "SubsetMetadata " << " HDFEOS attribute" << endl);
975 }
976 he5daslex_destroy();
977 }
978 if(product_str != ""){
979 AttrTable *at = das.get_table("ProductMetadata");
980 if (nullptr == at)
981 at = das.add_table("ProductMetadata", new AttrTable);
982 parser_arg arg(at);
983 he5das_scan_string((const char*) product_str.c_str());
984 if (he5dasparse(&arg) != 0
985 || false == arg.status()){
986 ERROR_LOG("HDF-EOS5 parse error while processing a "
987 << "ProductMetadata " << " HDFEOS attribute" << endl);
988 }
989 he5daslex_destroy();
990 }
991
992 // All other metadata under "HDF-EOS Information" will not be
993 // parsed since we don't know how to parse them.
994 // We will simply pass a string to the DAS.
995 if (other_str != ""){
996 AttrTable *at = das.get_table("OtherMetadata");
997 if (nullptr == at)
998 at = das.add_table("OtherMetadata", new AttrTable);
999 at->append_attr("Contents","String",other_str);
1000 }
1001
1002 }
1003 // CHECK ALL UNLIMITED DIMENSIONS from the coordinate variables based on the names.
1004 if(f->HaveUnlimitedDim() == true) {
1005
1006 AttrTable *at = das.get_table("DODS_EXTRA");
1007 if (nullptr == at)
1008 at = das.add_table("DODS_EXTRA", new AttrTable);
1009 string unlimited_names;
1010
1011 for (it_cv = cvars.begin();
1012 it_cv != cvars.end(); it_cv++) {
1013#if 0
1014 bool has_unlimited_dim = false;
1015#endif
1016 // Check unlimited dimension names.
1017 for (auto ird = (*it_cv)->getDimensions().begin();
1018 ird != (*it_cv)->getDimensions().end(); ++ird) {
1019
1020 // Currently we only check one unlimited dimension, which is the most
1021 // common case. When receiving the conventions from JG, will add
1022 // the support of multi-unlimited dimension. KY 2016-02-09
1023 if((*ird)->HaveUnlimitedDim() == true) {
1024
1025 if(unlimited_names=="") {
1026 unlimited_names = (*ird)->getNewName();
1027 at->append_attr("Unlimited_Dimension","String",unlimited_names);
1028 }
1029 else {
1030 if(unlimited_names.rfind((*ird)->getNewName()) == string::npos) {
1031 unlimited_names = unlimited_names+" "+(*ird)->getNewName();
1032 at->append_attr("Unlimited_Dimension","String",(*ird)->getNewName());
1033 }
1034 }
1035 }
1036
1037 }
1038
1039#if 0
1040 //if(true == has_unlimited_dim)
1041 // break;
1042#endif
1043 }
1044#if 0
1045 //if(unlimited_names!="")
1046 // at->append_attr("Unlimited_Dimension","String",unlimited_names);
1047#endif
1048 }
1049
1050}
1051
1052// Read ECS metadata
1053void read_ecs_metadata(hid_t s_file_id,
1054 string &total_strmeta_value,
1055 string &total_coremeta_value,
1056 string &total_archmeta_value,
1057 string &total_xmlmeta_value,
1058 string &total_submeta_value,
1059 string &total_prometa_value,
1060 string &total_othermeta_value,
1061 bool s_st_only) {
1062
1063 BESDEBUG("h5","Coming to read_ecs_metadata() "<<endl);
1064 string ecs_group = "/HDFEOS INFORMATION";
1065 hid_t ecs_grp_id = -1;
1066 if ((ecs_grp_id = H5Gopen(s_file_id, ecs_group.c_str(),H5P_DEFAULT))<0) {
1067 string msg =
1068 "h5_ecs_meta: unable to open the HDF5 group ";
1069 msg +=ecs_group;
1070 throw InternalErr(__FILE__, __LINE__, msg);
1071 }
1072
1073 H5G_info_t g_info;
1074 hsize_t nelems = 0;
1075
1076 if (H5Gget_info(ecs_grp_id,&g_info) <0) {
1077 string msg =
1078 "h5_ecs_meta: unable to obtain the HDF5 group info. for ";
1079 msg +=ecs_group;
1080 H5Gclose(ecs_grp_id);
1081 throw InternalErr(__FILE__, __LINE__, msg);
1082 }
1083
1084 nelems = g_info.nlinks;
1085
1086 ssize_t oname_size = 0;
1087#if 0
1088 int cur_archmeta_suffix = 0;
1089 int cur_coremeta_suffix = 0;
1090 int cur_strmeta_suffix = 0;
1091 int cur_xmlmeta_suffix = 0;
1092#endif
1093
1094 int archmeta_num = -1;
1095 int coremeta_num = -1;
1096 int xmlmeta_num = -1;
1097 int strmeta_num = -1;
1098 int submeta_num = -1;
1099 int prometa_num = -1;
1100
1101 // Initalize the total number for different metadata.
1102 int archmeta_num_total = 0;
1103 int coremeta_num_total = 0;
1104 int xmlmeta_num_total = 0;
1105 int strmeta_num_total = 0;
1106 int submeta_num_total = 0;
1107 int prometa_num_total = 0;
1108 int othermeta_num_total = 0;
1109
1110 bool archmeta_no_suffix = true;
1111 bool coremeta_no_suffix = true;
1112 bool strmeta_no_suffix = true;
1113 bool xmlmeta_no_suffix = true;
1114 bool submeta_no_suffix = true;
1115 bool prometa_no_suffix = true;
1116
1117 // Define a vector of string to hold all dataset names.
1118 vector<string> s_oname(nelems);
1119
1120 // Define an EOSMetadata array that can describe the metadata type for each object
1121 // We initialize the value to OtherMeta.
1122 EOS5Metadata metatype[nelems];
1123
1124 for (unsigned int i =0; i<nelems; i++)
1125 metatype[i] = OtherMeta;
1126
1127 for (hsize_t i = 0; i < nelems; i++) {
1128
1129 // Query the length of the object name.
1130 oname_size =
1131 H5Lget_name_by_idx(ecs_grp_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,nullptr,
1132 0, H5P_DEFAULT);
1133 if (oname_size <= 0) {
1134 string msg = "hdf5 object name error from: ";
1135 msg += ecs_group;
1136 H5Gclose(ecs_grp_id);
1137 throw InternalErr(__FILE__, __LINE__, msg);
1138 }
1139
1140 // Obtain the name of the object.
1141 vector<char> oname(oname_size + 1);
1142 if (H5Lget_name_by_idx(ecs_grp_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,oname.data(),
1143 (size_t)(oname_size+1), H5P_DEFAULT)<0){
1144 string msg = "hdf5 object name error from: ";
1145 msg += ecs_group;
1146 H5Gclose(ecs_grp_id);
1147 throw InternalErr(__FILE__, __LINE__, msg);
1148 }
1149
1150 // Check if this object is an HDF5 dataset, not, throw an error.
1151 // First, check if it is the hard link or the soft link
1152 H5L_info_t linfo;
1153 if (H5Lget_info(ecs_grp_id,oname.data(),&linfo,H5P_DEFAULT)<0) {
1154 string msg = "hdf5 link name error from: ";
1155 msg += ecs_group;
1156 H5Gclose(ecs_grp_id);
1157 throw InternalErr(__FILE__, __LINE__, msg);
1158 }
1159
1160 // This is the soft link.
1161 if (linfo.type == H5L_TYPE_SOFT){
1162 string msg = "hdf5 link name error from: ";
1163 msg += ecs_group;
1164 H5Gclose(ecs_grp_id);
1165 throw InternalErr(__FILE__, __LINE__, msg);
1166 }
1167
1168 // Obtain the object type
1169 H5O_info_t oinfo;
1170 if (H5OGET_INFO_BY_IDX(ecs_grp_id, ".", H5_INDEX_NAME, H5_ITER_NATIVE,
1171 i, &oinfo, H5P_DEFAULT)<0) {
1172 string msg = "Cannot obtain the object info ";
1173 msg += ecs_group;
1174 H5Gclose(ecs_grp_id);
1175 throw InternalErr(__FILE__, __LINE__, msg);
1176 }
1177
1178 if(oinfo.type != H5O_TYPE_DATASET) {
1179 string msg = "hdf5 link name error from: ";
1180 msg += ecs_group;
1181 H5Gclose(ecs_grp_id);
1182 throw InternalErr(__FILE__, __LINE__, msg);
1183 }
1184
1185 // We want to remove the last '\0' character added by C .
1186 string s_one_oname(oname.begin(),oname.end()-1);
1187 s_oname[i] = s_one_oname;
1188
1189 // Calculate how many elements we have for each category(StructMetadata, CoreMetadata, etc.)
1190 if (((s_one_oname.find("StructMetadata"))==0) ||
1191 ((s_one_oname.find("structmetadata"))==0)){
1192
1193 metatype[i] = StructMeta;
1194
1195 // Do we have suffix for the metadata?
1196 // If this metadata doesn't have any suffix, it should only come to this loop once.
1197 // That's why, when checking the first time, no_suffix is always true.
1198 // If we have already found that it doesn't have any suffix,
1199 // it should not go into this loop. throw an error.
1200 if (false == strmeta_no_suffix) {
1201 string msg = "StructMetadata/structmetadata without suffix should only appear once. ";
1202 H5Gclose(ecs_grp_id);
1203 throw InternalErr(__FILE__, __LINE__, msg);
1204 }
1205
1206 else if(strmeta_num_total >0)
1207 strmeta_num_total++;
1208 else { // either no suffix or the first time to loop the one having the suffix.
1209 if ((0 == s_one_oname.compare("StructMetadata"))||
1210 (0 == s_one_oname.compare("structmetadata")))
1211 strmeta_no_suffix = false;
1212 else strmeta_num_total++;
1213 }
1214#if 0
1215"h5","strmeta_num_total= "<<strmeta_num_total <<endl;
1216if(strmeta_no_suffix) "h5","structmeta data has the suffix" <<endl;
1217else "h5","structmeta data doesn't have the suffix" <<endl;
1218#endif
1219 }
1220
1221 if(false == s_st_only) {
1222
1223 if ((0 == (s_one_oname.find("CoreMetadata"))) ||
1224 (0 == (s_one_oname.find("coremetadata")))){
1225
1226 metatype[i] = CoreMeta;
1227
1228 // Do we have suffix for the metadata?
1229 // When checking the first time, no_suffix is always true.
1230 // If we have already found that it doesn't have any suffix,
1231 // it should not go into this loop anyway. throw an error.
1232 if (false == coremeta_no_suffix) {
1233 string msg = "CoreMetadata/coremetadata without suffix should only appear once. ";
1234 H5Gclose(ecs_grp_id);
1235 throw InternalErr(__FILE__, __LINE__, msg);
1236 }
1237
1238 else if(coremeta_num_total >0)
1239 coremeta_num_total++;
1240 else { // either no suffix or the first time to loop the one having the suffix.
1241 // If no suffix is true, it should be out of the loop. In case it comes
1242 // to the loop again, we set "coremeta_no_suffix" be false so an error
1243 // can be thrown. This is counter-intutitive. Hopefully people can understand it.
1244 if ((0 == s_one_oname.compare("CoreMetadata")) ||
1245 (0 == s_one_oname.compare("coremetadata")))
1246 coremeta_no_suffix = false;
1247 else coremeta_num_total++;
1248 }
1249#if 0
1250"h5","coremeta_num_total= "<<coremeta_num_total <<endl;
1251if(coremeta_no_suffix) "h5","coreuctmeta data has the suffix" <<endl;
1252else "h5","coremeta data doesn't have the suffix" <<endl;
1253#endif
1254 }
1255
1256 // OMI has the metadata name as "ArchiveMetadata.0"
1257 else if ((0 == (s_one_oname.find("ArchivedMetadata"))) ||
1258 (0 == (s_one_oname.find("archivedmetadata"))) ||
1259 (0 == (s_one_oname.find("ArchiveMetadata"))) ||
1260 (0 == (s_one_oname.find("archivemetadata")))){
1261
1262 metatype[i] = ArchivedMeta;
1263 // Do we have suffix for the metadata?
1264 // When checking the first time, no_suffix is always true.
1265 // If we have already found that it doesn't have any suffix,
1266 // it should not go into this loop anyway. throw an error.
1267 if (false == archmeta_no_suffix) {
1268 string msg = "archivedmetadata/ArchivedMetadata without suffix should only appear once. ";
1269 H5Gclose(ecs_grp_id);
1270 throw InternalErr(__FILE__, __LINE__, msg);
1271 }
1272
1273 else if(archmeta_num_total >0)
1274 archmeta_num_total++;
1275 else { // either no suffix or the first time to loop the one having the suffix.
1276 if ((0 == s_one_oname.compare("ArchivedMetadata"))||
1277 (0 == s_one_oname.compare("archivedmetadata")) ||
1278 (0 == s_one_oname.compare("archivemetadata")) ||
1279 (0 == s_one_oname.compare("ArchiveMetadata")))
1280 archmeta_no_suffix = false;
1281 else
1282 archmeta_num_total++;
1283 }
1284#if 0
1285"h5","archmeta_num_total= "<<archmeta_num_total <<endl;
1286if(archmeta_no_suffix) "h5","archuctmeta data has the suffix" <<endl;
1287else "h5","archmeta data doesn't have the suffix" <<endl;
1288#endif
1289
1290 }
1291
1292 else if (((s_one_oname.find("SubsetMetadata"))==0) ||
1293 ((s_one_oname.find("subsetmetadata"))==0)){
1294
1295 metatype[i] = SubsetMeta;
1296 // Do we have suffix for the metadata?
1297 // When checking the first time, no_suffix is always true.
1298 // If we have already found that it doesn't have any suffix,
1299 // it should not go into this loop anyway. throw an error.
1300 if (false == submeta_no_suffix) {
1301 H5Gclose(ecs_grp_id);
1302 string msg = "submetadata/SubMetadata without suffix should only appear once. ";
1303 throw InternalErr(__FILE__, __LINE__, msg);
1304 }
1305
1306 else if(submeta_num_total >0)
1307 submeta_num_total++;
1308 else { // either no suffix or the first time to loop the one having the suffix.
1309 if ((0 == s_one_oname.compare("SubsetMetadata"))||
1310 (0 == s_one_oname.compare("subsetmetadata")))
1311 submeta_no_suffix = false;
1312 else submeta_num_total++;
1313 }
1314#if 0
1315"h5","submeta_num_total= "<<submeta_num_total <<endl;
1316if(submeta_no_suffix) "h5","subuctmeta data has the suffix" <<endl;
1317else "h5","submeta data doesn't have the suffix" <<endl;
1318#endif
1319
1320 }
1321
1322 else if ((0 == (s_one_oname.find("XmlMetadata"))) ||
1323 (0 == (s_one_oname.find("xmlmetadata")))){
1324
1325 metatype[i] = XMLMeta;
1326
1327 // Do we have suffix for the metadata?
1328 // When checking the first time, no_suffix is always true.
1329 // If we have already found that it doesn't have any suffix,
1330 // it should not go into this loop anyway. throw an error.
1331 if (false == xmlmeta_no_suffix) {
1332 H5Gclose(ecs_grp_id);
1333 string msg = "xmlmetadata/Xmlmetadata without suffix should only appear once. ";
1334 throw InternalErr(__FILE__, __LINE__, msg);
1335 }
1336
1337 else if(xmlmeta_num_total >0)
1338 xmlmeta_num_total++;
1339 else { // either no suffix or the first time to loop the one having the suffix.
1340 if ((0 == s_one_oname.compare("XmlMetadata"))||
1341 (0 == s_one_oname.compare("xmlmetadata")))
1342 xmlmeta_no_suffix = false;
1343 else xmlmeta_num_total++;
1344 }
1345#if 0
1346"h5","xmlmeta_num_total= "<<xmlmeta_num_total <<endl;
1347if(xmlmeta_no_suffix) "h5","xmluctmeta data doesn't have the suffix" <<endl;
1348else "h5","xmlmeta data has the suffix" <<endl;
1349#endif
1350
1351 }
1352
1353 else if ((0 == (s_one_oname.find("ProductMetadata"))) ||
1354 (0 == (s_one_oname.find("productmetadata")))){
1355
1356 metatype[i] = ProductMeta;
1357 // Do we have suffix for the metadata?
1358 // When checking the first time, no_suffix is always true.
1359 // If we have already found that it doesn't have any suffix,
1360 // it should not go into this loop anyway. throw an error.
1361 if (!prometa_no_suffix) {
1362 H5Gclose(ecs_grp_id);
1363 string msg = "productmetadata/ProductMetadata without suffix should only appear once. ";
1364 throw InternalErr(__FILE__, __LINE__, msg);
1365 }
1366
1367 else if(prometa_num_total >0) prometa_num_total++;
1368 else { // either no suffix or the first time to loop the one having the suffix.
1369 if ((0 == s_one_oname.compare("ProductMetadata"))||
1370 (0 == s_one_oname.compare("productmetadata")))
1371 prometa_no_suffix = false;
1372 else prometa_num_total++;
1373 }
1374
1375 }
1376
1377 // All other metadata will be merged to one string, no need to check the name.
1378 else othermeta_num_total++;
1379 }
1380
1381 oname.clear();
1382 s_one_oname.clear();
1383 }
1384
1385 // Define a vector of string to hold StructMetadata.
1386 // StructMetadata must exist for a valid HDF-EOS5 file.
1387 vector<string> strmeta_value;
1388 if (strmeta_num_total <= 0) {
1389 string msg = "hdf5 object name error from: ";
1390 H5Gclose(ecs_grp_id);
1391 throw InternalErr(__FILE__, __LINE__, msg);
1392 }
1393 else {
1394 strmeta_value.resize(strmeta_num_total);
1395 for (int i = 0; i < strmeta_num_total; i++)
1396 strmeta_value[i]="";
1397 }
1398
1399 // All other metadata are optional.
1400 // Define a vector of string to hold archivedmetadata.
1401 vector<string> archmeta_value;
1402 if (archmeta_num_total >0) {
1403 archmeta_value.resize(archmeta_num_total);
1404 for (int i = 0; i < archmeta_num_total; i++)
1405 archmeta_value[i]="";
1406 }
1407
1408 // Define a vector of string to hold coremetadata.
1409 vector<string> coremeta_value;
1410 if (coremeta_num_total >0) {
1411 coremeta_value.resize(coremeta_num_total);
1412 for (int i = 0; i < coremeta_num_total; i++)
1413 coremeta_value[i]="";
1414 }
1415
1416 // Define a vector of string to hold xmlmetadata.
1417 vector<string> xmlmeta_value;
1418 if (xmlmeta_num_total >0) {
1419 xmlmeta_value.resize(xmlmeta_num_total);
1420 for (int i = 0; i < xmlmeta_num_total; i++)
1421 xmlmeta_value[i]="";
1422 }
1423
1424 // Define a vector of string to hold subsetmetadata.
1425 vector<string> submeta_value;
1426 if (submeta_num_total >0) {
1427 submeta_value.resize(submeta_num_total);
1428 for (int i = 0; i < submeta_num_total; i++)
1429 submeta_value[i]="";
1430 }
1431
1432 // Define a vector of string to hold productmetadata.
1433 vector<string> prometa_value;
1434 if (prometa_num_total >0) {
1435 prometa_value.resize(prometa_num_total);
1436 for (int i = 0; i < prometa_num_total; i++)
1437 prometa_value[i]="";
1438 }
1439
1440 // For all other metadata, we don't need to calculate the value, just append them.
1441
1442 // Now we want to retrieve the metadata value and combine them into one string.
1443 // Here we have to remember the location of every element of the metadata if
1444 // this metadata has a suffix.
1445 for (hsize_t i = 0; i < nelems; i++) {
1446
1447 // DDS parser only needs to parse the struct Metadata. So check
1448 // if st_only flag is true, will only read StructMetadata string.
1449 // Struct Metadata is generated by the HDF-EOS5 library, so the
1450 // name "StructMetadata.??" won't change for real struct metadata.
1451 //However, we still assume that somebody may not use the HDF-EOS5
1452 // library to add StructMetadata, the name may be "structmetadata".
1453 if (true == s_st_only &&
1454 (((s_oname[i].find("StructMetadata"))!=0) &&
1455 ((s_oname[i].find("structmetadata"))!=0))){
1456 continue;
1457 }
1458
1459 // Open the dataset, dataspace, datatype, number of elements etc. for this metadata
1460 hid_t s_dset_id = -1;
1461 hid_t s_space_id = -1;
1462 hid_t s_ty_id = -1;
1463 hssize_t s_nelms = -1;
1464 size_t dtype_size = -1;
1465
1466 if ((s_dset_id = H5Dopen(ecs_grp_id,s_oname[i].c_str(),H5P_DEFAULT))<0){
1467 string msg = "Cannot open HDF5 dataset ";
1468 msg += s_oname[i];
1469 H5Gclose(ecs_grp_id);
1470 throw InternalErr(__FILE__, __LINE__, msg);
1471 }
1472
1473 if ((s_space_id = H5Dget_space(s_dset_id))<0) {
1474 string msg = "Cannot open the data space of HDF5 dataset ";
1475 msg += s_oname[i];
1476 H5Dclose(s_dset_id);
1477 H5Gclose(ecs_grp_id);
1478 throw InternalErr(__FILE__, __LINE__, msg);
1479 }
1480
1481 if ((s_ty_id = H5Dget_type(s_dset_id)) < 0) {
1482 string msg = "Cannot get the data type of HDF5 dataset ";
1483 msg += s_oname[i];
1484 H5Sclose(s_space_id);
1485 H5Dclose(s_dset_id);
1486 H5Gclose(ecs_grp_id);
1487 throw InternalErr(__FILE__, __LINE__, msg);
1488 }
1489 if ((s_nelms = H5Sget_simple_extent_npoints(s_space_id))<0) {
1490 string msg = "Cannot get the number of points of HDF5 dataset ";
1491 msg += s_oname[i];
1492 H5Tclose(s_ty_id);
1493 H5Sclose(s_space_id);
1494 H5Dclose(s_dset_id);
1495 H5Gclose(ecs_grp_id);
1496 throw InternalErr(__FILE__, __LINE__, msg);
1497 }
1498 if ((dtype_size = H5Tget_size(s_ty_id))==0) {
1499
1500 string msg = "Cannot get the data type size of HDF5 dataset ";
1501 msg += s_oname[i];
1502 H5Tclose(s_ty_id);
1503 H5Sclose(s_space_id);
1504 H5Dclose(s_dset_id);
1505 H5Gclose(ecs_grp_id);
1506 throw InternalErr(__FILE__, __LINE__, msg);
1507 }
1508
1509 // Obtain the real value of the metadata
1510 vector<char> s_buf(dtype_size*s_nelms +1);
1511
1512 if ((H5Dread(s_dset_id,s_ty_id,H5S_ALL,H5S_ALL,H5P_DEFAULT,s_buf.data()))<0) {
1513
1514 string msg = "Cannot read HDF5 dataset ";
1515 msg += s_oname[i];
1516 H5Tclose(s_ty_id);
1517 H5Sclose(s_space_id);
1518 H5Dclose(s_dset_id);
1519 H5Gclose(ecs_grp_id);
1520 throw InternalErr(__FILE__, __LINE__, msg);
1521 }
1522
1523 // Now we can safely close datatype, data space and dataset IDs.
1524 H5Tclose(s_ty_id);
1525 H5Sclose(s_space_id);
1526 H5Dclose(s_dset_id);
1527
1528
1529 // Convert from the vector<char> to a C++ string.
1530 string tempstr(s_buf.begin(),s_buf.end());
1531 s_buf.clear();
1532 size_t temp_null_pos = tempstr.find_first_of('\0');
1533
1534 // temp_null_pos returns the position of nullptr,which is the last character of the string.
1535 // so the length of string before null is EQUAL to
1536 // temp_null_pos since pos starts at 0.
1537 string finstr = tempstr.substr(0,temp_null_pos);
1538
1539 // For the DDS parser, only return StructMetadata
1540 if (StructMeta == metatype[i]) {
1541
1542 // Now obtain the corresponding value in integer type for the suffix. '0' to 0 etc.
1543 try {
1544 strmeta_num = get_metadata_num(s_oname[i]);
1545 }
1546 catch(...) {
1547 H5Gclose(ecs_grp_id);
1548 throw InternalErr(__FILE__,__LINE__,"Obtain structmetadata suffix error.");
1549
1550 }
1551 // This is probably not necessary, since structmetadata may always have a suffix.
1552 // Leave here just in case the rules change or a special non-HDF-EOS5 library generated file.
1553 // when strmeta_num is -1, it means no suffix for this metadata. So the total structmetadata
1554 // is this string only.
1555 if (-1 == strmeta_num)
1556 total_strmeta_value = finstr;
1557 // strmeta_value at this point should be empty before assigning any values.
1558 else if (strmeta_value[strmeta_num]!="") {
1559 string msg = "The structmeta value array at this index should be empty string ";
1560 H5Gclose(ecs_grp_id);
1561 throw InternalErr(__FILE__, __LINE__, msg);
1562 }
1563 // assign the string vector to this value.
1564 else
1565 strmeta_value[strmeta_num] = finstr;
1566 }
1567
1568 // DAS parser needs all metadata.
1569 if (false == s_st_only &&
1570 (metatype[i] != StructMeta)) {
1571
1572 switch (metatype[i]) {
1573
1574 case CoreMeta:
1575 {
1576 if (coremeta_num_total < 0) {
1577 string msg = "There may be no coremetadata or coremetadata is not counted ";
1578 H5Gclose(ecs_grp_id);
1579 throw InternalErr(__FILE__, __LINE__, msg);
1580
1581 }
1582
1583 try {
1584 coremeta_num = get_metadata_num(s_oname[i]);
1585 }
1586 catch(...) {
1587 H5Gclose(ecs_grp_id);
1588 throw InternalErr(__FILE__,__LINE__,"Obtain coremetadata suffix error.");
1589
1590 }
1591
1592 // when coremeta_num is -1, it means no suffix for this metadata. So the total coremetadata
1593 // is this string only. Similar cases apply for the rest metadata.
1594 if ( -1 == coremeta_num )
1595 total_coremeta_value = finstr;
1596 else if (coremeta_value[coremeta_num]!="") {
1597 string msg = "The coremeta value array at this index should be empty string ";
1598 H5Gclose(ecs_grp_id);
1599 throw InternalErr(__FILE__, __LINE__, msg);
1600 }
1601
1602 // assign the string vector to this value.
1603 else
1604 coremeta_value[coremeta_num] = finstr;
1605 }
1606 break;
1607
1608 case ArchivedMeta:
1609 {
1610 if (archmeta_num_total < 0) {
1611 string msg = "There may be no archivemetadata or archivemetadata is not counted ";
1612 H5Gclose(ecs_grp_id);
1613 throw InternalErr(__FILE__, __LINE__, msg);
1614 }
1615 try {
1616 archmeta_num = get_metadata_num(s_oname[i]);
1617 }
1618 catch(...) {
1619 H5Gclose(ecs_grp_id);
1620 throw InternalErr(__FILE__,__LINE__,"Obtain archivemetadata suffix error.");
1621 }
1622 if (-1 == archmeta_num )
1623 total_archmeta_value = finstr;
1624 else if (archmeta_value[archmeta_num]!="") {
1625 string msg = "The archivemeta value array at this index should be empty string ";
1626 H5Gclose(ecs_grp_id);
1627 throw InternalErr(__FILE__, __LINE__, msg);
1628
1629 }
1630 // assign the string vector to this value.
1631 else
1632 archmeta_value[archmeta_num] = finstr;
1633 }
1634 break;
1635 case SubsetMeta:
1636 {
1637 if (submeta_num_total < 0) {
1638 string msg = "The subsetemeta value array at this index should be empty string ";
1639 H5Gclose(ecs_grp_id);
1640 throw InternalErr(__FILE__, __LINE__, msg);
1641 }
1642 try {
1643 submeta_num = get_metadata_num(s_oname[i]);
1644 }
1645 catch(...) {
1646 H5Gclose(ecs_grp_id);
1647 throw InternalErr(__FILE__,__LINE__,"Obtain subsetmetadata suffix error.");
1648 }
1649 if (-1 == submeta_num )
1650 total_submeta_value = finstr;
1651 else if (submeta_value[submeta_num]!="") {
1652 string msg = "The submeta value array at this index should be empty string ";
1653 H5Gclose(ecs_grp_id);
1654 throw InternalErr(__FILE__, __LINE__, msg);
1655 }
1656 // assign the string vector to this value.
1657 else
1658 submeta_value[submeta_num] = finstr;
1659 }
1660 break;
1661 case ProductMeta:
1662 {
1663 if (prometa_num_total < 0) {
1664 string msg = "There may be no productmetadata or productmetadata is not counted ";
1665 H5Gclose(ecs_grp_id);
1666 throw InternalErr(__FILE__, __LINE__, msg);
1667 }
1668 try {
1669 prometa_num = get_metadata_num(s_oname[i]);
1670 }
1671 catch(...) {
1672 H5Gclose(ecs_grp_id);
1673 throw InternalErr(__FILE__,__LINE__,"Obtain productmetadata suffix error.");
1674 }
1675 if (prometa_num == -1)
1676 total_prometa_value = finstr;
1677 else if (prometa_value[prometa_num]!="") {
1678 string msg = "The productmeta value array at this index should be empty string ";
1679 H5Gclose(ecs_grp_id);
1680 throw InternalErr(__FILE__, __LINE__, msg);
1681 }
1682 // assign the string vector to this value.
1683 else
1684 prometa_value[prometa_num] = finstr;
1685 }
1686 break;
1687 case XMLMeta:
1688 {
1689 if (xmlmeta_num_total < 0) {
1690 string msg = "There may be no xmlmetadata or xmlmetadata is not counted ";
1691 H5Gclose(ecs_grp_id);
1692 throw InternalErr(__FILE__, __LINE__, msg);
1693 }
1694 try {
1695 xmlmeta_num = get_metadata_num(s_oname[i]);
1696 }
1697 catch(...) {
1698 H5Gclose(ecs_grp_id);
1699 throw InternalErr(__FILE__,__LINE__,"Obtain XMLmetadata suffix error.");
1700 }
1701 if (-1 == xmlmeta_num )
1702 total_xmlmeta_value = finstr;
1703 else if (xmlmeta_value[xmlmeta_num]!="") {
1704 string msg = "The xmlmeta value array at this index should be empty string ";
1705 H5Gclose(ecs_grp_id);
1706 throw InternalErr(__FILE__, __LINE__, msg);
1707 }
1708 // assign the string vector to this value.
1709 else
1710 xmlmeta_value[xmlmeta_num] = finstr;
1711 }
1712 break;
1713 case OtherMeta:
1714 {
1715 if (othermeta_num_total < 0) {
1716 string msg = "There may be no othermetadata or other metadata is not counted ";
1717 H5Gclose(ecs_grp_id);
1718 throw InternalErr(__FILE__, __LINE__, msg);
1719 }
1720 total_othermeta_value = total_othermeta_value + finstr;
1721 }
1722 break;
1723 default :
1724 {
1725 string msg = "Unsupported metadata type ";
1726 H5Gclose(ecs_grp_id);
1727 throw InternalErr(__FILE__, __LINE__, msg);
1728 }
1729 }
1730 }
1731 tempstr.clear();
1732 finstr.clear();
1733 }
1734
1735 // Now we need to handle the concatenation of the metadata
1736 // first StructMetadata
1737 if (strmeta_num_total > 0) {
1738 // The no suffix one has been taken care.
1739 if (strmeta_num != -1) {
1740 for (int i = 0; i <strmeta_num_total; i++)
1741 total_strmeta_value +=strmeta_value[i];
1742 }
1743 }
1744
1745 // For the DAS handler
1746 if ( false == s_st_only) {
1747
1748 if (coremeta_num_total >0) {
1749 if (coremeta_num != -1) {
1750 for(int i = 0; i <coremeta_num_total; i++)
1751 total_coremeta_value +=coremeta_value[i];
1752 }
1753 }
1754
1755 if (archmeta_num_total >0) {
1756 if (archmeta_num != -1) {
1757 for(int i = 0; i <archmeta_num_total; i++)
1758 total_archmeta_value +=archmeta_value[i];
1759 }
1760 }
1761
1762 if (submeta_num_total >0) {
1763 if (submeta_num != -1) {
1764 for(int i = 0; i <submeta_num_total; i++)
1765 total_submeta_value +=submeta_value[i];
1766 }
1767 }
1768
1769 if (xmlmeta_num_total >0) {
1770 if (xmlmeta_num != -1) {
1771 for(int i = 0; i <xmlmeta_num_total; i++)
1772 total_xmlmeta_value +=xmlmeta_value[i];
1773 }
1774 }
1775
1776 if (prometa_num_total >0) {
1777 if (prometa_num != -1) {
1778 for(int i = 0; i <prometa_num_total; i++)
1779 total_prometa_value +=prometa_value[i];
1780 }
1781 }
1782 }
1783 H5Gclose(ecs_grp_id);
1784}
1785
1786// Helper function for read_ecs_metadata. Get the number after metadata.
1787int get_metadata_num(const string & meta_str) {
1788
1789 // The normal metadata names should be like coremetadata.0, coremetadata.1 etc.
1790 // We just find a not so nice coremetadata names such as coremetadata.0, coremetadata.0.1 for a HIRDLS-MLS-Aura-L3
1791 // We need to handle them. Here we assume no more than two dots in a name series. KY 2012-11-08
1792 size_t dot_pos = meta_str.find(".");
1793 if (dot_pos == string::npos) // No dot
1794 return -1;
1795 else if (meta_str.find_first_of(".") == meta_str.find_last_of(".")) { // One dot
1796 string num_str = meta_str.substr(dot_pos+1);
1797 stringstream ssnum(num_str);
1798 int num;
1799 ssnum >> num;
1800 if (ssnum.fail())
1801 throw InternalErr(__FILE__,__LINE__,"Suffix after dots is not a number.");
1802 return num;
1803 }
1804 else { // Two dots
1805 string str_after_first_dot = meta_str.substr(dot_pos+1);
1806 if (str_after_first_dot.find_first_of(".") != str_after_first_dot.find_last_of("."))
1807 throw InternalErr(__FILE__,__LINE__,"Currently don't support metadata names containing more than two dots.");
1808 // Here we don't check if names are like coremetadata.0 coremetadata.0.0 etc., Having ".0 .0.0" is,if not mistaken,
1809 // is insane.
1810 // Instead we hope that the data producers will produce data like coremetadata.0 coremetadata.0.1 coremeatadata.0.2
1811 // KY 2012-11-08
1812 size_t second_dot_pos = str_after_first_dot.find(".");
1813 string num_str = str_after_first_dot.substr(second_dot_pos+1);
1814 stringstream ssnum(num_str);
1815 int num;
1816 ssnum >> num;
1817 return num;
1818 }
1819
1820}
1821
1822void map_eos5_cfdmr(D4Group *d4_root, hid_t file_id, const string &filename) {
1823
1824 BESDEBUG("h5","Coming to HDF-EOS5 products DDS mapping function map_eos5_cfdds "<<endl);
1825
1826 string st_str ="";
1827 string core_str="";
1828 string arch_str="";
1829 string xml_str ="";
1830 string subset_str="";
1831 string product_str="";
1832 string other_str ="";
1833 bool st_only = false;
1834
1835 // Read ECS metadata: merge them into one C++ string
1836 read_ecs_metadata(file_id,st_str,core_str,arch_str,xml_str, subset_str,product_str,other_str,st_only);
1837 if(""==st_str) {
1838 string msg =
1839 "unable to obtain the HDF-EOS5 struct metadata ";
1840 throw InternalErr(__FILE__, __LINE__, msg);
1841 }
1842
1843 bool disable_ecsmetadata = HDF5RequestHandler::get_disable_ecsmeta();
1844 if(disable_ecsmetadata == false) {
1845
1846 bool is_check_disable_smetadata = HDF5RequestHandler::get_disable_structmeta();
1847
1848 if (false == is_check_disable_smetadata)
1849 add_grp_dap4_attr(d4_root,"StructMetadata",attr_str_c,st_str);
1850
1851 if(core_str != "")
1852 add_grp_dap4_attr(d4_root,"CoreMetadata",attr_str_c,core_str);
1853
1854 if(arch_str != "")
1855 add_grp_dap4_attr(d4_root,"ArchiveMetadata",attr_str_c,arch_str);
1856
1857 if(xml_str != "")
1858 add_grp_dap4_attr(d4_root,"XMLMetadata",attr_str_c,xml_str);
1859
1860 if(subset_str !="")
1861 add_grp_dap4_attr(d4_root,"SubsetMetadata",attr_str_c,subset_str);
1862
1863 if(product_str != "")
1864 add_grp_dap4_attr(d4_root,"ProductMetadata",attr_str_c,product_str);
1865
1866 if(other_str !="")
1867 add_grp_dap4_attr(d4_root,"OtherMetadata",attr_str_c,other_str);
1868 }
1869
1870 bool is_check_nameclashing = HDF5RequestHandler::get_check_name_clashing();
1871
1872 bool is_add_path_attrs = HDF5RequestHandler::get_add_path_attrs();
1873
1874 EOS5File *f = nullptr;
1875
1876 try {
1877 f = new EOS5File(filename.c_str(),file_id);
1878 }
1879 catch(...) {
1880 throw InternalErr(__FILE__,__LINE__,"Cannot allocate the file object.");
1881 }
1882
1883 bool include_attr = true;
1884
1885 // This first "try-catch" block will use the parsed info
1886 try {
1887
1888 // Parse the structmetadata
1889 // Note: he5dds_scan_string just retrieves the variable info.
1890 // It is still used to handle DMR, no need to write another parser.
1891 // KY 2021-05-21
1892 HE5Parser p;
1893 HE5Checker c;
1894 he5dds_scan_string(st_str.c_str());
1895 he5ddsparse(&p);
1896 he5ddslex_destroy();
1897
1898 // Retrieve ProjParams from StructMetadata
1899 p.add_projparams(st_str);
1900#if 0
1901 //p.print();
1902#endif
1903
1904 // Check if the HDF-EOS5 grid has the valid parameters, projection codes.
1905 if (c.check_grids_unknown_parameters(&p)) {
1906 throw InternalErr("Unknown HDF-EOS5 grid paramters found in the file");
1907 }
1908
1909 if (c.check_grids_missing_projcode(&p)) {
1910 throw InternalErr("The HDF-EOS5 is missing project code ");
1911 }
1912
1913 // We gradually add the support of different projection codes
1914 if (c.check_grids_support_projcode(&p)) {
1915 throw InternalErr("The current project code is not supported");
1916 }
1917
1918 // HDF-EOS5 provides default pixel and origin values if they are not defined.
1919 c.set_grids_missing_pixreg_orig(&p);
1920
1921 // Check if this multi-grid file shares the same grid.
1922 bool grids_mllcv = c.check_grids_multi_latlon_coord_vars(&p);
1923
1924 // Retrieve all HDF5 info(Not the values)
1925 f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
1926
1927 // Adjust EOS5 Dimension names/sizes based on the parsed results
1928 f->Adjust_EOS5Dim_Info(&p);
1929
1930 // Translate the parsed output to HDF-EOS5 grids/swaths/zonal.
1931 // Several maps related to dimension and coordiantes are set up here.
1932 f->Add_EOS5File_Info(&p, grids_mllcv);
1933
1934 // Add the dimension names
1935 f->Add_Dim_Name(&p);
1936 }
1937 catch (HDF5CF::Exception &e){
1938 if(f!=nullptr)
1939 delete f;
1940 throw InternalErr(e.what());
1941 }
1942 catch(...) {
1943 if(f!=nullptr)
1944 delete f;
1945 throw;
1946 }
1947
1948 // The parsed struct will no longer be in this "try-catch" block.
1949 try {
1950
1951 // NASA Aura files need special handlings. So first check if this file is an Aura file.
1953
1954 // Adjust the variable name
1956
1957 // Handle coordinate variables
1958 f->Handle_CVar();
1959
1960 // Adjust variable and dimension names again based on the handling of coordinate variables.
1962
1963
1964 // Old comments, leave them for the time being:
1965 // We need to use the CV units to distinguish lat/lon from th 3rd CV when
1966 // memory cache is turned on.
1967#if 0
1968 //if((HDF5RequestHandler::get_lrdata_mem_cache() != nullptr) ||
1969 // (HDF5RequestHandler::get_srdata_mem_cache() != nullptr)){
1970#endif
1971
1972 // Handle unsupported datatypes including the attributes
1973 f->Handle_Unsupported_Dtype(true);
1974
1975 // Handle unsupported dataspaces including the attributes
1977
1978 // We need to retrieve coordinate variable attributes for memory cache use.
1980
1982
1983 // Handle other unsupported objects,
1984 // currently it mainly generates the info. for the
1985 // unsupported objects other than datatype, dataspace,links and named datatype
1986 // This function needs to be called after retrieving supported attributes.
1987 f->Handle_Unsupported_Others(include_attr);
1988
1989#if 0
1990 else {
1991
1992 // Handle unsupported datatypes
1993 f->Handle_Unsupported_Dtype(include_attr);
1994
1995 // Handle unsupported dataspaces
1996 f->Handle_Unsupported_Dspace(include_attr);
1997
1998 }
1999#endif
2000
2001
2002 // Need to retrieve the units of CV when memory cache is turned on.
2003 // The units of CV will be used to distinguish whether this CV is
2004 // latitude/longitude or a third-dimension CV.
2005 // isLatLon() will use the units value.
2006#if 0
2007 //if((HDF5RequestHandler::get_lrdata_mem_cache() != nullptr) ||
2008 // (HDF5RequestHandler::get_srdata_mem_cache() != nullptr))
2009#endif
2010 f->Adjust_Attr_Info();
2011
2012 // May need to adjust the object names for special objects. Currently no operations
2013 // are done in this routine.
2014 f->Adjust_Obj_Name();
2015
2016 // Flatten the object name
2017 f->Flatten_Obj_Name(include_attr);
2018
2019 // Handle name clashing
2020 if(true == is_check_nameclashing)
2021 f->Handle_Obj_NameClashing(include_attr);
2022
2023 // Check if this should follow COARDS, yes, set the COARDS flag.
2024 f->Set_COARDS_Status();
2025
2026 // For COARDS, the dimension name needs to be changed.
2027 f->Adjust_Dim_Name();
2028 if(true == is_check_nameclashing)
2030
2031 f->Add_Supplement_Attrs(is_add_path_attrs);
2032
2033 // We need to turn off the very long string in the TES file to avoid
2034 // the choking of netCDF Java tools. So this special variable routine
2035 // is listed at last. We may need to turn off this if netCDF can handle
2036 // long string better.
2037 f->Handle_SpVar_DMR();
2038
2039 // Handle coordinate attributes
2040 f->Handle_Coor_Attr();
2041#if 0
2042 //f->Handle_SpVar_Attr();
2043#endif
2044 }
2045 catch (HDF5CF::Exception &e){
2046 if(f != nullptr)
2047 delete f;
2048 throw InternalErr(e.what());
2049 }
2050
2051 // Generate EOS5 DMR
2052 try {
2053 gen_eos5_cfdmr(d4_root,f);
2054 }
2055 catch(...) {
2056 if (f!=nullptr)
2057 delete f;
2058 throw;
2059 }
2060
2061 if (f!=nullptr)
2062 delete f;
2063
2064}
2065
2066void gen_eos5_cfdmr(D4Group *d4_root, HDF5CF::EOS5File *f) {
2067
2068 BESDEBUG("h5","Coming to HDF-EOS5 products DDS generation function "<<endl);
2069 const vector<HDF5CF::Var *>& vars = f->getVars();
2070 const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
2071 const string filename = f->getPath();
2072 const hid_t file_id = f->getFileID();
2073 const vector<HDF5CF::Group *>& grps = f->getGroups();
2074 const vector<HDF5CF::Attribute *>& root_attrs = f->getAttributes();
2075
2076 vector<HDF5CF::Attribute *>::const_iterator it_ra;
2077
2078 if (false == root_attrs.empty()) {
2079 for (it_ra = root_attrs.begin(); it_ra != root_attrs.end(); ++it_ra)
2080 map_cfh5_grp_attr_to_dap4(d4_root,*it_ra);
2081 }
2082
2083 // We use the container since we claim to have no hierarchy.
2084 if (false == grps.empty()) {
2085 for (auto it_g = grps.begin(); it_g != grps.end(); ++it_g) {
2086 auto tmp_grp = new D4Attribute;
2087 tmp_grp->set_name((*it_g)->getNewName());
2088 tmp_grp->set_type(attr_container_c);
2089
2090 for (it_ra = (*it_g)->getAttributes().begin();
2091 it_ra != (*it_g)->getAttributes().end(); ++it_ra) {
2092 map_cfh5_attr_container_to_dap4(tmp_grp,(*it_ra));
2093 }
2094 d4_root->attributes()->add_attribute_nocopy(tmp_grp);
2095 }
2096 }
2097
2098 // Read Variable info.
2099 // TODO: We may need to make the cvar first for coverage support.
2100 vector<HDF5CF::Var *>::const_iterator it_v;
2101 vector<HDF5CF::EOS5CVar *>::const_iterator it_cv;
2102
2103 if (HDF5RequestHandler::get_add_dap4_coverage() == true) {
2104 for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
2105 BESDEBUG("h5","variable full path= "<< (*it_cv)->getFullPath() <<endl);
2106 gen_dap_oneeos5cvar_dmr(d4_root,*it_cv,file_id,filename);
2107
2108 }
2109 for (it_v = vars.begin(); it_v !=vars.end();++it_v) {
2110 BESDEBUG("h5","variable full path= "<< (*it_v)->getFullPath() <<endl);
2111 gen_dap_onevar_dmr(d4_root,*it_v,file_id,filename);
2112 }
2113
2114 // Handle EOS5 grid mapping info.
2115 if (f->Have_EOS5_Grids()==true)
2116 gen_dap_eos5cf_gm_dmr(d4_root,f);
2117
2118 }
2119 else {
2120 for (it_v = vars.begin(); it_v !=vars.end();++it_v) {
2121 BESDEBUG("h5","variable full path= "<< (*it_v)->getFullPath() <<endl);
2122 gen_dap_onevar_dmr(d4_root,*it_v,file_id,filename);
2123 }
2124
2125 // Handle EOS5 grid mapping info.
2126 if (f->Have_EOS5_Grids()==true)
2127 gen_dap_eos5cf_gm_dmr(d4_root,f);
2128
2129 for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
2130 BESDEBUG("h5","variable full path= "<< (*it_cv)->getFullPath() <<endl);
2131 gen_dap_oneeos5cvar_dmr(d4_root,*it_cv,file_id,filename);
2132
2133 }
2134
2135 }
2136
2137 // CHECK ALL UNLIMITED DIMENSIONS from the coordinate variables based on the names.
2138 if(f->HaveUnlimitedDim() == true) {
2139
2140 string dods_extra = "DODS_EXTRA";
2141
2142 // If DODS_EXTRA exists, we will not create the unlimited dimensions.
2143 if(d4_root->attributes() != nullptr) {
2144#if 0
2145 //if((d4_root->attributes()->find(dods_extra))==nullptr) {
2146#endif
2147 string unlimited_dim_names ="";
2148
2149 for (it_cv = cvars.begin();
2150 it_cv != cvars.end(); it_cv++) {
2151
2152 // Check unlimited dimension names.
2153 for (auto ird = (*it_cv)->getDimensions().begin();
2154 ird != (*it_cv)->getDimensions().end(); ++ird) {
2155
2156 // Currently we only check one unlimited dimension, which is the most
2157 // common case. When receiving the conventions from JG, will add
2158 // the support of multi-unlimited dimension. KY 2016-02-09
2159 if((*ird)->HaveUnlimitedDim() == true) {
2160
2161 if(unlimited_dim_names=="")
2162 unlimited_dim_names = (*ird)->getNewName();
2163 else {
2164 if(unlimited_dim_names.rfind((*ird)->getNewName()) == string::npos) {
2165 unlimited_dim_names = unlimited_dim_names+" "+(*ird)->getNewName();
2166 }
2167 }
2168 }
2169 }
2170 }
2171
2172 if(unlimited_dim_names != "") {
2173 auto dods_extra_attr = new D4Attribute(dods_extra,attr_container_c);
2174 auto unlimited_dim_attr = new D4Attribute("Unlimited_Dimension",attr_str_c);
2175 unlimited_dim_attr->add_value(unlimited_dim_names);
2176 dods_extra_attr->attributes()->add_attribute_nocopy(unlimited_dim_attr);
2177 d4_root->attributes()->add_attribute_nocopy(dods_extra_attr);
2178 }
2179 else
2180 throw InternalErr(__FILE__, __LINE__, "Unlimited dimension should exist.");
2181 //}
2182 }
2183
2184 }
2185
2186 // Add DAP4 map for coverage
2187 if (HDF5RequestHandler::get_add_dap4_coverage() == true) {
2188
2189 // Obtain the coordinate variable names, these are mapped variables.
2190 vector <string> cvar_name;
2191 for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv)
2192 cvar_name.emplace_back((*it_cv)->getNewName());
2193
2194 add_dap4_coverage(d4_root,cvar_name,f->getIsCOARD());
2195 }
2196}
2197
2198
2199void gen_dap_oneeos5cvar_dmr(D4Group* d4_root,const EOS5CVar* cvar,const hid_t file_id,const string & filename){
2200
2201 BESDEBUG("h5","Coming to gen_dap_oneeos5cvar_dmr() "<<endl);
2202 BaseType *bt = nullptr;
2203
2204 switch(cvar->getType()) {
2205#define HANDLE_CASE(tid,type) \
2206 case tid: \
2207 bt = new (type)(cvar->getNewName(),cvar->getFullPath()); \
2208 break;
2209
2210 HANDLE_CASE(H5FLOAT32, HDF5CFFloat32)
2211 HANDLE_CASE(H5FLOAT64, HDF5CFFloat64)
2212 HANDLE_CASE(H5CHAR,HDF5CFInt8)
2213 HANDLE_CASE(H5UCHAR, HDF5CFByte)
2214 HANDLE_CASE(H5INT16, HDF5CFInt16)
2215 HANDLE_CASE(H5UINT16, HDF5CFUInt16)
2216 HANDLE_CASE(H5INT32, HDF5CFInt32)
2217 HANDLE_CASE(H5UINT32, HDF5CFUInt32)
2218 HANDLE_CASE(H5INT64, HDF5CFInt64)
2219 HANDLE_CASE(H5UINT64, HDF5CFUInt64)
2220 HANDLE_CASE(H5FSTRING, Str)
2221 HANDLE_CASE(H5VSTRING, Str)
2222 default:
2223 throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
2224#undef HANDLE_CASE
2225 }
2226
2227 if (bt) {
2228
2229 const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
2230 vector <HDF5CF::Dimension*>:: const_iterator it_d;
2231 vector <size_t> dimsizes;
2232 dimsizes.resize(cvar->getRank());
2233 for(int i = 0; i <cvar->getRank();i++)
2234 dimsizes[i] = (dims[i])->getSize();
2235
2236
2237 if(dims.empty())
2238 throw InternalErr(__FILE__,__LINE__,"the coordinate variables cannot be scalar.");
2239 switch(cvar->getCVType()) {
2240
2241 case CV_EXIST:
2242 {
2243
2244 bool is_latlon = cvar->isLatLon();
2245 HDF5CFArray *ar = nullptr;
2246 try {
2247 bool is_dap4 = true;
2248 ar = new HDF5CFArray (
2249 cvar->getRank(),
2250 file_id,
2251 filename,
2252 cvar->getType(),
2253 dimsizes,
2254 cvar->getFullPath(),
2255 cvar->getTotalElems(),
2256 CV_EXIST,
2257 is_latlon,
2258 cvar->getCompRatio(),
2259 is_dap4,
2260 cvar->getNewName(),
2261 bt);
2262 }
2263 catch (...) {
2264 delete bt;
2265 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDF5CFArray.");
2266 }
2267
2268 for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
2269 if (""==(*it_d)->getNewName())
2270 ar->append_dim((int)((*it_d)->getSize()));
2271 else
2272 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
2273 }
2274
2275 ar->set_is_dap4(true);
2276 BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
2277 map_cfh5_var_attrs_to_dap4(cvar,d4_var);
2278 d4_root->add_var_nocopy(d4_var);
2279
2280 delete bt;
2281 delete ar;
2282 }
2283 break;
2284
2285 case CV_LAT_MISS:
2286 case CV_LON_MISS:
2287 {
2288
2289 HDFEOS5CFMissLLArray *ar = nullptr;
2290 try {
2291#if 0
2292cerr<<"cvar zone here is "<<cvar->getZone() <<endl;
2293cerr<<"cvar Sphere here is "<<cvar->getSphere() <<endl;
2294cerr<<"cvar getParams here 1 is "<<cvar->getParams()[0]<<endl;
2295#endif
2296 ar = new HDFEOS5CFMissLLArray (
2297 cvar->getRank(),
2298 filename,
2299 file_id,
2300 cvar->getFullPath(),
2301 cvar->getCVType(),
2302 cvar->getPointLower(),
2303 cvar->getPointUpper(),
2304 cvar->getPointLeft(),
2305 cvar->getPointRight(),
2306 cvar->getPixelReg(),
2307 cvar->getOrigin(),
2308 cvar->getProjCode(),
2309 cvar->getParams(),
2310 cvar->getZone(),
2311 cvar->getSphere(),
2312 cvar->getXDimSize(),
2313 cvar->getYDimSize(),
2314 cvar->getNewName(),
2315 bt);
2316 }
2317 catch (...) {
2318 delete bt;
2319 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDFEOS5CFMissLLArray.");
2320 }
2321
2322 for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
2323 if (""==(*it_d)->getNewName())
2324 ar->append_dim((int)((*it_d)->getSize()));
2325 else
2326 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
2327 }
2328
2329 ar->set_is_dap4(true);
2330 BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
2331 map_cfh5_var_attrs_to_dap4(cvar,d4_var);
2332 add_var_sp_attrs_to_dap4(d4_var,cvar);
2333 d4_root->add_var_nocopy(d4_var);
2334
2335 delete bt;
2336 delete ar;
2337 }
2338 break;
2339
2340 case CV_NONLATLON_MISS:
2341 {
2342
2343 if (cvar->getRank() !=1) {
2344 delete bt;
2345 throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
2346 }
2347 int nelem = (int)((cvar->getDimensions()[0])->getSize());
2348
2349 HDFEOS5CFMissNonLLCVArray *ar = nullptr;
2350 try {
2352 cvar->getRank(),
2353 nelem,
2354 cvar->getNewName(),
2355 bt);
2356 }
2357 catch (...) {
2358 delete bt;
2359 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDFEOS5CFMissNonLLCVArray.");
2360 }
2361
2362
2363 for(it_d = dims.begin(); it_d != dims.end(); it_d++) {
2364 if (""==(*it_d)->getNewName())
2365 ar->append_dim((int)((*it_d)->getSize()));
2366 else
2367 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
2368 }
2369
2370 ar->set_is_dap4(true);
2371 BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
2372 map_cfh5_var_attrs_to_dap4(cvar,d4_var);
2373 d4_root->add_var_nocopy(d4_var);
2374
2375 delete bt;
2376 delete ar;
2377
2378
2379 }
2380 break;
2381 case CV_SPECIAL:
2382 // Currently only support Aura TES files. May need to revise when having more
2383 // special products KY 2012-2-3
2384 {
2385
2386 if (cvar->getRank() !=1) {
2387 delete bt;
2388 throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
2389 }
2390 int nelem = (int)((cvar->getDimensions()[0])->getSize());
2391 HDFEOS5CFSpecialCVArray *ar = nullptr;
2392
2393 try {
2394 ar = new HDFEOS5CFSpecialCVArray(
2395 cvar->getRank(),
2396 filename,
2397 file_id,
2398 cvar->getType(),
2399 nelem,
2400 cvar->getFullPath(),
2401 cvar->getNewName(),
2402 bt);
2403 }
2404 catch (...) {
2405 delete bt;
2406 throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDF5CFArray.");
2407 }
2408
2409
2410 for(it_d = dims.begin(); it_d != dims.end(); ++it_d){
2411 if (""==(*it_d)->getNewName())
2412 ar->append_dim((int)((*it_d)->getSize()));
2413 else
2414 ar->append_dim((int)((*it_d)->getSize()), (*it_d)->getNewName());
2415 }
2416
2417 ar->set_is_dap4(true);
2418 BaseType* d4_var=ar->h5cfdims_transform_to_dap4(d4_root);
2419 map_cfh5_var_attrs_to_dap4(cvar,d4_var);
2420 d4_root->add_var_nocopy(d4_var);
2421 delete bt;
2422 delete ar;
2423 }
2424 break;
2425 case CV_MODIFY:
2426 default:
2427 delete bt;
2428 throw InternalErr(__FILE__,__LINE__,"Unsupported coordinate variable type.");
2429 }
2430
2431 }
2432
2433}
2434
2435
2436// generate dmr info for grid mapping (gm: grid mapping)
2437void gen_dap_eos5cf_gm_dmr(libdap::D4Group* d4_root,HDF5CF::EOS5File*f) {
2438
2439 // grid mapping projection vars
2440 // and add grid_mapping attribute for non-cv vars
2441 gen_gm_proj_var_info(d4_root,f);
2442
2443 // special grid mapping dimension variables.
2444 gen_gm_proj_spvar_info(d4_root,f);
2445
2446}
2447
2448//(1) Add grid mapping projection vars if we have any
2449//(2) Add grid_mapping attributes for all non-cv vars
2450void gen_gm_proj_var_info(libdap::D4Group* d4_root,const HDF5CF::EOS5File* f) {
2451
2452 BESDEBUG("h5","Coming to HDF-EOS5 products DDS generation function "<<endl);
2453 const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
2454
2455 // For multiple grids, multiple grid mapping variables are needed.
2456 // We use EOS5 coordinate variables to track this.
2457 unsigned short cv_lat_miss_index = 1;
2458 for (auto it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
2459 if((*it_cv)->getCVType() == CV_LAT_MISS) {
2460 if((*it_cv)->getProjCode() != HE5_GCTP_GEO) {
2461 gen_gm_oneproj_var(d4_root,*it_cv,cv_lat_miss_index,f);
2462 cv_lat_miss_index++;
2463 }
2464 }
2465 }
2466}
2467
2468// Generate the dummy grid_mapping variables,attributes and
2469// grid_mapping attributes for all the non-cv variables.
2470void gen_gm_oneproj_var(libdap::D4Group*d4_root,
2471 const HDF5CF::EOS5CVar* cvar,
2472 const unsigned short g_suffix, const HDF5CF::EOS5File* f) {
2473
2474 BESDEBUG("h5","Coming to gen_gm_oneproj_var() "<<endl);
2475 EOS5GridPCType cv_proj_code = cvar->getProjCode();
2476 const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
2477
2478 if(dims.size() !=2)
2479 throw InternalErr(__FILE__,__LINE__,"Currently we only support the 2-D CF coordinate projection system.");
2480
2481 // 1. Add the grid mapping dummy projection variable dmr for each grid
2482 // 2. Add the grid_mapping attribute for each variable that this projection applies
2483 // now, we handle sinusoidal,PS and LAMAZ projections.
2484 if (HE5_GCTP_SNSOID == cv_proj_code || HE5_GCTP_PS == cv_proj_code || HE5_GCTP_LAMAZ== cv_proj_code) {
2485
2486 // Add the dummy projection variable.
2487 // The attributes of this variable can be used to store the grid mapping info.
2488 // To handle multi-grid cases, we need to add suffixes to distinguish them.
2489 string cf_projection_base = "eos_cf_projection";
2490 string cf_projection_name;
2491
2492 HDF5CFGeoCFProj * dummy_proj_cf = nullptr;
2493
2494 if(HE5_GCTP_SNSOID == cv_proj_code) {
2495
2496 // AFAIK, one grid_mapping variable is necessary for multi-grids.
2497 // So we just leave one grid here.
2498 cf_projection_name = cf_projection_base;
2499 if(g_suffix == 1)
2500 dummy_proj_cf = new HDF5CFGeoCFProj(cf_projection_name, cf_projection_name);
2501 }
2502 else {
2503 stringstream t_suffix_ss;
2504 t_suffix_ss << g_suffix;
2505 cf_projection_name = cf_projection_base + "_" + t_suffix_ss.str();
2506 dummy_proj_cf = new HDF5CFGeoCFProj(cf_projection_name, cf_projection_name);
2507 }
2508
2509 if(dummy_proj_cf != nullptr) {
2510 dummy_proj_cf->set_is_dap4(true);
2511 add_gm_oneproj_var_dap4_attrs(dummy_proj_cf,cv_proj_code,cvar->getParams());
2512 d4_root->add_var_nocopy(dummy_proj_cf);
2513 }
2514
2515 // Add the grid_mapping attributes to all non-cv variables for the grid.
2516 vector<string> cvar_name;
2517 if (HDF5RequestHandler::get_add_dap4_coverage() == true) {
2518 const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
2519 for (auto it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv)
2520 cvar_name.emplace_back((*it_cv)->getNewName());
2521
2522 }
2523 add_cf_grid_cv_dap4_attrs(d4_root,cf_projection_name,dims,cvar_name);
2524 }
2525
2526}
2527
2528//Generate DMR of special dimension variables.
2529void gen_gm_proj_spvar_info(libdap::D4Group* d4_root,const HDF5CF::EOS5File* f){
2530
2531 BESDEBUG("h5","Coming to HDF-EOS5 products grid mapping variable generation function "<<endl);
2532 const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
2533
2534 for (auto it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
2535 if((*it_cv)->getCVType() == CV_LAT_MISS) {
2536 if((*it_cv)->getProjCode() != HE5_GCTP_GEO)
2537 gen_gm_oneproj_spvar(d4_root,*it_cv);
2538 }
2539 }
2540}
2541
2542void gen_gm_oneproj_spvar(libdap::D4Group *d4_root,const HDF5CF::EOS5CVar *cvar) {
2543
2544 BESDEBUG("h5","Coming to gen_gm_oneproj_spvar() "<<endl);
2545
2546 float cv_point_lower = cvar->getPointLower();
2547 float cv_point_upper = cvar->getPointUpper();
2548 float cv_point_left = cvar->getPointLeft();
2549 float cv_point_right = cvar->getPointRight();
2550 EOS5GridPCType cv_proj_code = cvar->getProjCode();
2551 const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
2552 if(dims.size() !=2)
2553 throw InternalErr(__FILE__,__LINE__,"Currently we only support the 2-D CF coordinate projection system.");
2554 add_gm_spcvs(d4_root,cv_proj_code,cv_point_lower,cv_point_upper,cv_point_left,cv_point_right,dims);
2555
2556}
2557
2558void add_var_sp_attrs_to_dap4(BaseType *d4_var,const EOS5CVar* cvar) {
2559
2560 if(cvar->getProjCode() == HE5_GCTP_LAMAZ) {
2561 if(cvar->getCVType() == CV_LAT_MISS) {
2562 add_var_dap4_attr(d4_var,"valid_min", attr_float64_c, "-90.0");
2563 add_var_dap4_attr(d4_var,"valid_max", attr_float64_c, "90.0");
2564 }
2565 else {
2566 add_var_dap4_attr(d4_var,"valid_min", attr_float64_c, "-180.0");
2567 add_var_dap4_attr(d4_var,"valid_max", attr_float64_c, "180.0");
2568 }
2569 }
2570
2571}
2572
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.
include the entry functions to execute the handlers
This class specifies the retrieval of the missing lat/lon values for HDF-EOS5 products.
This class specifies the retrieval of the missing lat/lon values for HDFEOS5 products.
This class specifies the retrieval of special coordinate variable values for HDF-EOS5 products.
A class for parsing NASA HDF-EOS5 StructMetadata.
A class for parsing NASA HDF-EOS5 StructMetadata.
CVType getCVType() const
Get the coordinate variable type of this variable.
Definition: HDF5CF.h:362
This class is a derived class of CVar. It represents a coordinate variable for HDF-EOS5 files.
Definition: HDF5CF.h:431
This class is a derived class of File. It includes methods applied to HDF-EOS5 files only.
Definition: HDF5CF.h:1164
bool Get_IgnoredInfo_Flag() override
Obtain the flag to see if ignored objects should be generated.
Definition: HDF5CF.h:1264
const std::string & Get_Ignored_Msg() override
Obtain the message that contains the ignored object info.
Definition: HDF5CF.h:1269
void Adjust_Obj_Name() override
This method is a no-op operation. Leave here since the method in the base class is pure virtual.
Definition: HDFEOS5CF.cc:4197
void Add_EOS5File_Info(HE5Parser *, bool)
Add HDF-EOS5 dimension and coordinate variable related info. to EOS5Grid,EOS5Swath etc.
Definition: HDFEOS5CF.cc:838
void Retrieve_H5_Info(const char *path, hid_t file_id, bool include_attr) override
Retrieve DDS information from the HDF5 file; a real implementation for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:161
void Add_Supplement_Attrs(bool) override
Add the supplemental attributes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3670
void Set_COARDS_Status()
Set COARDS flag.
Definition: HDFEOS5CF.cc:3384
void Adjust_Var_Dim_NewName_Before_Flattening()
Adjust variable dimension names before the flattening for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3033
void Handle_CVar() override
Handle coordinate variable for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:1770
void Adjust_Attr_Info()
Adjust the attribute info for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3407
void Handle_SpVar_Attr() override
Handle special variables for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:4099
void Handle_Obj_NameClashing(bool)
Handle the object name clashing for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3233
void Handle_Unsupported_Dtype(bool) override
Handle unsupported HDF5 datatypes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:207
void Handle_DimNameClashing() override
Definition: HDFEOS5CF.cc:3319
void Handle_Unsupported_Others(bool) override
Handle other unmapped objects/attributes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:360
void Retrieve_H5_CVar_Supported_Attr_Values() override
Retrieve coordinate variable attributes.
Definition: HDFEOS5CF.cc:168
void Handle_SpVar() override
Handle special variables for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3977
void Adjust_Var_NewName_After_Parsing()
Adjust variable names for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:1224
void Retrieve_H5_Supported_Attr_Values() override
Retrieve attribute values for the supported HDF5 datatypes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:184
void Add_Dim_Name(HE5Parser *)
Add the dimension name for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:1316
void Adjust_Dim_Name() override
Adjust the dimension name for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3640
void Handle_SpVar_DMR() override
Handle special variables and attributes for HDF-EOS5 files(for DMR)
Definition: HDFEOS5CF.cc:4139
void Handle_Unsupported_Dspace(bool) override
Handle unsupported HDF5 dataspaces for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:301
void Flatten_Obj_Name(bool include_attr) override
Flatten the object name for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3211
void Check_Aura_Product_Status()
Check if the HDF-EOS5 file is an Aura file. Special CF operations need to be used.
Definition: HDFEOS5CF.cc:1718
const std::vector< EOS5CVar * > & getCVars() const
Obtain coordinate variables for HDF-EOS5 products.
Definition: HDF5CF.h:1175
void Adjust_EOS5Dim_Info(HE5Parser *strmeta_info)
Adjust HDF-EOS5 dimension information.
Definition: HDFEOS5CF.cc:537
void Handle_Coor_Attr() override
Handle the coordinates attribute for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3763
bool HaveUnlimitedDim() const
Has unlimited dimensions.
Definition: HDF5CF.h:661
hid_t getFileID() const
Obtain the HDF5 file ID.
Definition: HDF5CF.h:631
const std::vector< Attribute * > & getAttributes() const
Public interface to obtain information of all attributes under the root group.
Definition: HDF5CF.h:649
const std::vector< Group * > & getGroups() const
Public interface to obtain all the group info.
Definition: HDF5CF.h:655
const std::string & getPath() const
Obtain the path of the file.
Definition: HDF5CF.h:637
const std::vector< Var * > & getVars() const
Public interface to obtain information of all variables.
Definition: HDF5CF.h:643
float getCompRatio() const
Get the compression ratio of this dataset.
Definition: HDF5CF.h:321
int getRank() const
Get the dimension rank of this variable.
Definition: HDF5CF.h:298
const std::string & getFullPath() const
Get the full path of this variable.
Definition: HDF5CF.h:276
const std::string & getName() const
Get the original name of this variable.
Definition: HDF5CF.h:264
H5DataType getType() const
Get the data type of this variable(Not HDF5 datatype id)
Definition: HDF5CF.h:304
const std::vector< Dimension * > & getDimensions() const
Get the list of the dimensions.
Definition: HDF5CF.h:315
const std::string & getNewName() const
Get the new name of this variable.
Definition: HDF5CF.h:270
Helper functions for generating DAS attributes and a function to check BES Key.
yy_buffer_state * he5das_scan_string(const char *str)
Buffer state for NASA EOS metadata scanner.
Map and generate DDS and DAS for the CF option for HDF-EOS5 products.