OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
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-2013 The HDF Group, Inc. and OPeNDAP, Inc.
5 //
6 // This is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your
9 // option) any later version.
10 //
11 // This software is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
22 // Suite 203, Champaign, IL 61820
23 
32 
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <iostream>
38 #include <sstream>
39 
40 #include <BESLog.h>
41 #include <BESDebug.h>
42 
43 #include "parser.h"
44 #include "heos5cfdap.h"
45 #include "h5cfdaputil.h"
46 #include "HDF5CFByte.h"
47 #include "HDF5CFUInt16.h"
48 #include "HDF5CFInt16.h"
49 #include "HDF5CFUInt32.h"
50 #include "HDF5CFInt32.h"
51 #include "HDF5CFFloat32.h"
52 #include "HDF5CFFloat64.h"
53 #include "HDF5CFStr.h"
54 #include "HDF5CFArray.h"
55 #include "HDFEOS5CFMissLLArray.h"
58 
59 #include "he5dds.tab.hh"
60 #include "HE5Parser.h"
61 #include "HE5Checker.h"
62 #include "he5das.tab.hh"
63 
64 struct yy_buffer_state;
65 
66 yy_buffer_state *he5dds_scan_string(const char *str);
67 int he5ddsparse(HE5Parser *he5parser);
68 int he5dasparse(libdap::parser_arg *arg);
69 int he5ddslex_destroy();
70 int he5daslex_destroy();
71 
73 yy_buffer_state *he5das_scan_string(const char *str);
74 
75 using namespace HDF5CF;
76 
77 void map_eos5_cfdds(DDS &dds, hid_t file_id, const string & filename) {
78 
79  BESDEBUG("h5","Coming to HDF-EOS5 products DDS mapping function map_eos5_cfdds "<<endl);
80  string st_str ="";
81  string core_str="";
82  string arch_str="";
83  string xml_str ="";
84  string subset_str="";
85  string product_str="";
86  string other_str ="";
87  bool st_only = true;
88 
89  // Read ECS metadata: merge them into one C++ string
90  read_ecs_metadata(file_id,st_str,core_str,arch_str,xml_str, subset_str,product_str,other_str,st_only);
91  if(""==st_str) {
92 // H5Fclose(file_id);
93  string msg =
94  "unable to obtain the HDF-EOS5 struct metadata ";
95  throw InternalErr(__FILE__, __LINE__, msg);
96  }
97 
98  string check_objnameclashing_key ="H5.EnableCheckNameClashing";
99  bool is_check_nameclashing = false;
100  is_check_nameclashing = HDF5CFDAPUtil::check_beskeys(check_objnameclashing_key);
101 
102  EOS5File *f = NULL;
103 
104  try {
105  f = new EOS5File(filename.c_str(),file_id);
106  }
107  catch(...) {
108  throw InternalErr(__FILE__,__LINE__,"Cannot allocate the file object.");
109  }
110 
111  bool include_attr = false;
112 
113  // This first "try-catch" block will use the parsed info
114  try {
115 
116  // Parse the structmetadata
117  HE5Parser p;
118  HE5Checker c;
119  he5dds_scan_string(st_str.c_str());
120  he5ddsparse(&p);
122 // p.print();
123 // cerr<<"main loop p.za_list.size() = "<<p.za_list.size() <<endl;
124 
125  // Check if the HDF-EOS5 grid has the valid parameters, projection codes.
126  if (c.check_grids_unknown_parameters(&p)) {
127  throw InternalErr("Unknown HDF-EOS5 grid paramters found in the file");
128  }
129 
130  if (c.check_grids_missing_projcode(&p)) {
131  throw InternalErr("The HDF-EOS5 is missing project code ");
132  }
133 
134  if (c.check_grids_support_projcode(&p)) {
135  throw InternalErr("The current project code is not supported");
136  }
137 
138  // HDF-EOS5 provides default pixel and origin values if they are not defined.
140 
141  // cerr<<"after unknown parameters "<<endl;
142  // Check if this multi-grid file shares the same grid.
143  bool grids_mllcv = c.check_grids_multi_latlon_coord_vars(&p);
144 
145  // Retrieve all HDF5 info(Not the values)
146  f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
147 
148  // Adjust EOS5 Dimension names/sizes based on the parsed results
149  f->Adjust_EOS5Dim_Info(&p);
150 
151  // Translate the parsed output to HDF-EOS5 grids/swaths/zonal.
152  f->Add_EOS5File_Info(&p, grids_mllcv);
153 
154  // Add the dimension names
155  f->Add_Dim_Name(&p);
156  }
157  catch (HDF5CF::Exception &e){
158  if(f!=NULL)
159  delete f;
160  throw InternalErr(e.what());
161  }
162  catch(...) {
163  if(f!=NULL)
164  delete f;
165  throw;
166  }
167 
168  // The parsed struct will no longer be in this "try-catch" block.
169  try {
170 
171  // NASA Aura files need special handlings. So first check if this file is an Aura file.
173 
174  // Adjust the variable name
176 
177  // Handle coordinate variables
178  f->Handle_CVar();
179 
180  // Adjust variable and dimension names again based on the handling coordinate variables.
182 
183  // Remove unsupported datatype
184  f->Handle_Unsupported_Dtype(include_attr);
185 
186  // Remove unsupported dataspace
188 
189  // May need to adjust the object names for special objects. Currently no operations
190  // are done in this routine.
191  f->Adjust_Obj_Name();
192 
193  // Flatten the object name
194  f->Flatten_Obj_Name(include_attr);
195 
196  // Handle name clashing
197  if(true == is_check_nameclashing)
198  f->Handle_Obj_NameClashing(include_attr);
199 
200  // Check if this should follow COARDS, yes, set the COARDS flag.
201  f->Set_COARDS_Status();
202 
203  // For COARDS, the dimension name needs to be changed.
204  f->Adjust_Dim_Name();
205  if(true == is_check_nameclashing)
207  // We need to turn off the very long string in the TES file to avoid
208  // the choking of netCDF Java tools. So this special variable routine
209  // is listed at last. We may need to turn off this if netCDF can handle
210  // long string better.
211  f->Handle_SpVar();
212  }
213  catch (HDF5CF::Exception &e){
214  if(f != NULL)
215  delete f;
216  throw InternalErr(e.what());
217  }
218 
219  try {
220  gen_eos5_cfdds(dds,f);
221  }
222  catch(...) {
223  if (f!=NULL)
224  delete f;
225  throw;
226  }
227 
228  if (f!=NULL)
229  delete f;
230 }
231 
232 void map_eos5_cfdas(DAS &das, hid_t file_id, const string &filename) {
233 
234  BESDEBUG("h5","Coming to HDF-EOS5 products DAS mapping function map_eos5_cfdas "<<endl);
235  string st_str ="";
236  string core_str="";
237  string arch_str="";
238  string xml_str ="";
239  string subset_str="";
240  string product_str="";
241  string other_str ="";
242  bool st_only = true;
243 
244  read_ecs_metadata(file_id,st_str,core_str,arch_str,xml_str, subset_str,product_str,other_str,st_only);
245  if(""==st_str) {
246 // H5Fclose(file_id);
247  string msg =
248  "unable to obtain the HDF-EOS5 struct metadata ";
249  throw InternalErr(__FILE__, __LINE__, msg);
250  }
251 
252  string check_objnameclashing_key ="H5.EnableCheckNameClashing";
253  bool is_check_nameclashing = false;
254  is_check_nameclashing = HDF5CFDAPUtil::check_beskeys(check_objnameclashing_key);
255 
256  string add_path_attrs_key = "H5.EnableAddPathAttrs";
257  bool is_add_path_attrs = false;
258  is_add_path_attrs = HDF5CFDAPUtil::check_beskeys(add_path_attrs_key);
259 
260  EOS5File *f = NULL;
261  try {
262  f = new EOS5File(filename.c_str(),file_id);
263  }
264  catch(...) {
265  throw InternalErr(__FILE__,__LINE__,"Cannot allocate the file object.");
266  }
267  bool include_attr = true;
268 
269  // The first "try-catch" block will use the parsed info.
270  try {
271 
272  HE5Parser p;
273  HE5Checker c;
274  he5dds_scan_string(st_str.c_str());
275 
276  he5ddsparse(&p);
278 // p.print();
279 // cerr<<"main loop p.za_list.size() = "<<p.za_list.size() <<endl;
280 
281  if (c.check_grids_unknown_parameters(&p)) {
282  throw InternalErr("Unknown HDF-EOS5 grid paramters found in the file");
283  }
284 
285  if (c.check_grids_missing_projcode(&p)) {
286  throw InternalErr("The HDF-EOS5 is missing project code ");
287  }
288 
289  if (c.check_grids_support_projcode(&p)) {
290  throw InternalErr("The current project code is not supported");
291  }
293  // cerr<<"after unknown parameters "<<endl;
294 
295  bool grids_mllcv = c.check_grids_multi_latlon_coord_vars(&p);
296 
297  f->Retrieve_H5_Info(filename.c_str(),file_id,include_attr);
298  f->Adjust_EOS5Dim_Info(&p);
299  f->Add_EOS5File_Info(&p, grids_mllcv);
300  f->Add_Dim_Name(&p);
301  }
302  catch (HDF5CF::Exception &e){
303  if(f != NULL)
304  delete f;
305  throw InternalErr(e.what());
306  }
307  catch(...) {
308  if(f != NULL)
309  delete f;
310  throw;
311  }
312 
313  try {
316  f->Handle_CVar();
318  f->Handle_Unsupported_Dtype(include_attr);
319 
320  // Remove unsupported dataspace
322 
323 
324  // Need to retrieve the attribute values.
326 
327  // Add/adjust CF attributes
328  f->Adjust_Attr_Info();
329  f->Adjust_Obj_Name();
330  f->Flatten_Obj_Name(include_attr);
331  if (true == is_check_nameclashing)
332  f->Handle_Obj_NameClashing(include_attr);
333  f->Set_COARDS_Status();
334 
335  // Add supplemental attributes
336  f->Add_Supplement_Attrs(is_add_path_attrs);
337 
338  // Handle coordinate attributes
339  f->Handle_Coor_Attr();
340 
341  f->Handle_SpVar_Attr();
342  }
343  catch (HDF5CF::Exception &e){
344  if(f != NULL)
345  delete f;
346  throw InternalErr(e.what());
347  }
348 
349 
350  try {
351  gen_eos5_cfdas(das,file_id,f);
352  }
353  catch(...) {
354  if (f != NULL)
355  delete f;
356  throw;
357  }
358 
359  if( f != NULL)
360  delete f;
361 
362 }
363 
364 void gen_eos5_cfdds(DDS &dds, HDF5CF::EOS5File *f) {
365 
366  BESDEBUG("h5","Coming to HDF-EOS5 products DDS generation function gen_eos5_cfdds "<<endl);
367  const vector<HDF5CF::Var *>& vars = f->getVars();
368  const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
369  const string filename = f->getPath();
370  const hid_t file_id = f->getFileID();
371 
372  // Read Variable info.
373  vector<HDF5CF::Var *>::const_iterator it_v;
374  vector<HDF5CF::EOS5CVar *>::const_iterator it_cv;
375 
376  for (it_v = vars.begin(); it_v !=vars.end();++it_v) {
377  // cerr <<"variable full path= "<< (*it_v)->getFullPath() <<endl;
378  gen_dap_onevar_dds(dds,*it_v,file_id,filename);
379  }
380 
381  for (it_cv = cvars.begin(); it_cv !=cvars.end();++it_cv) {
382  // cerr <<"variable full path= "<< (*it_cv)->getFullPath() <<endl;
383 //gen_dap_onevar_dds(dds,*it_v,filename);
384  gen_dap_oneeos5cvar_dds(dds,*it_cv,file_id,filename);
385 
386  }
387 
388 }
389 
390 void gen_dap_oneeos5cvar_dds(DDS &dds,const HDF5CF::EOS5CVar* cvar, const hid_t file_id, const string & filename) {
391 
392  BaseType *bt = NULL;
393 
394  switch(cvar->getType()) {
395 #define HANDLE_CASE(tid,type) \
396  case tid: \
397  bt = new (type)(cvar->getNewName(),cvar->getFullPath()); \
398  break;
399 
408  HANDLE_CASE(H5FSTRING, Str);
409  HANDLE_CASE(H5VSTRING, Str);
410  default:
411  throw InternalErr(__FILE__,__LINE__,"unsupported data type.");
412 #undef HANDLE_CASE
413  }
414 
415  if (bt) {
416 
417  const vector<HDF5CF::Dimension *>& dims = cvar->getDimensions();
418  vector <HDF5CF::Dimension*>:: const_iterator it_d;
419 
420  switch(cvar->getCVType()) {
421 
422  case CV_EXIST:
423  {
424  HDF5CFArray *ar = NULL;
425  try {
426  ar = new HDF5CFArray (
427  cvar->getRank(),
428  file_id,
429  filename,
430  cvar->getType(),
431  cvar->getFullPath(),
432  cvar->getNewName(),
433  bt);
434  }
435  catch (...) {
436  delete bt;
437  throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDF5CFArray.");
438  }
439 
440  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
441  if (""==(*it_d)->getNewName())
442  ar->append_dim((*it_d)->getSize());
443  else
444  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
445  }
446 
447  dds.add_var(ar);
448  delete bt;
449  delete ar;
450  }
451  break;
452 
453  case CV_LAT_MISS:
454  case CV_LON_MISS:
455  {
456 
458  try {
459  ar = new HDFEOS5CFMissLLArray (
460  cvar->getRank(),
461  filename,
462  file_id,
463  cvar->getFullPath(),
464  cvar->getCVType(),
465  cvar->getPointLower(),
466  cvar->getPointUpper(),
467  cvar->getPointLeft(),
468  cvar->getPointRight(),
469  cvar->getPixelReg(),
470  cvar->getOrigin(),
471  cvar->getProjCode(),
472  cvar->getXDimSize(),
473  cvar->getYDimSize(),
474  cvar->getNewName(),
475  bt);
476  }
477  catch (...) {
478  delete bt;
479  throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDFEOS5CFMissLLArray.");
480  }
481 
482  for(it_d = dims.begin(); it_d != dims.end(); ++it_d) {
483  if (""==(*it_d)->getNewName())
484  ar->append_dim((*it_d)->getSize());
485  else
486  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
487  }
488 
489  dds.add_var(ar);
490  delete bt;
491  delete ar;
492  }
493  break;
494 
495  case CV_NONLATLON_MISS:
496  {
497 
498  if (cvar->getRank() !=1) {
499  delete bt;
500  throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
501  }
502  int nelem = (cvar->getDimensions()[0])->getSize();
503 
505  try {
506  ar = new HDFEOS5CFMissNonLLCVArray(
507  cvar->getRank(),
508  nelem,
509  cvar->getNewName(),
510  bt);
511  }
512  catch (...) {
513  delete bt;
514  throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDFEOS5CFMissNonLLCVArray.");
515  }
516 
517 
518  for(it_d = dims.begin(); it_d != dims.end(); it_d++) {
519  if (""==(*it_d)->getNewName())
520  ar->append_dim((*it_d)->getSize());
521  else
522  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
523  }
524  dds.add_var(ar);
525  delete bt;
526  delete ar;
527 
528 
529  }
530  break;
531  case CV_SPECIAL:
532  // Currently only support Aura TES files. May need to revise when having more
533  // special products KY 2012-2-3
534  {
535  if (cvar->getRank() !=1) {
536  delete bt;
537  throw InternalErr(__FILE__, __LINE__, "The rank of missing Z dimension field must be 1");
538  }
539  int nelem = (cvar->getDimensions()[0])->getSize();
541 
542  try {
543  ar = new HDFEOS5CFSpecialCVArray(
544  cvar->getRank(),
545  filename,
546  file_id,
547  cvar->getType(),
548  nelem,
549  cvar->getFullPath(),
550  cvar->getNewName(),
551  bt);
552  }
553  catch (...) {
554  delete bt;
555  throw InternalErr(__FILE__,__LINE__,"unable to allocate memory for HDF5CFArray.");
556  }
557 
558 
559  for(it_d = dims.begin(); it_d != dims.end(); ++it_d){
560  if (""==(*it_d)->getNewName())
561  ar->append_dim((*it_d)->getSize());
562  else
563  ar->append_dim((*it_d)->getSize(), (*it_d)->getNewName());
564  }
565  dds.add_var(ar);
566  delete bt;
567  delete ar;
568  }
569  break;
570  case CV_MODIFY:
571  default:
572  delete bt;
573  throw InternalErr(__FILE__,__LINE__,"Unsupported coordinate variable type.");
574  }
575 
576  }
577 
578 }
579 
580 
581 void gen_eos5_cfdas(DAS &das, hid_t file_id, HDF5CF::EOS5File *f) {
582 
583  BESDEBUG("h5","Coming to HDF-EOS5 products DAS generation function gen_eos5_cfdas "<<endl);
584  // cerr<<"read_cfdas()"<<endl;
585 
586  const vector<HDF5CF::Var *>& vars = f->getVars();
587  const vector<HDF5CF::EOS5CVar *>& cvars = f->getCVars();
588  const vector<HDF5CF::Group *>& grps = f->getGroups();
589  const vector<HDF5CF::Attribute *>& root_attrs = f->getAttributes();
590 
591  vector<HDF5CF::Var *>::const_iterator it_v;
592  vector<HDF5CF::EOS5CVar *>::const_iterator it_cv;
593  vector<HDF5CF::Group *>::const_iterator it_g;
594  vector<HDF5CF::Attribute *>::const_iterator it_ra;
595 
596  // Handling the file attributes(attributes under the root group)
597  // The table name is "HDF_GLOBAL".
598  if (false == root_attrs.empty()) {
599  AttrTable *at = das.get_table(FILE_ATTR_TABLE_NAME);
600  if (NULL == at)
601  at = das.add_table(FILE_ATTR_TABLE_NAME, new AttrTable);
602 
603  for (it_ra = root_attrs.begin(); it_ra != root_attrs.end(); it_ra++) {
604  gen_dap_oneobj_das(at,*it_ra,NULL);
605  }
606  }
607 
608  if (false == grps.empty()) {
609  for (it_g = grps.begin();
610  it_g != grps.end(); ++it_g) {
611  AttrTable *at = das.get_table((*it_g)->getNewName());
612  if (NULL == at)
613  at = das.add_table((*it_g)->getNewName(), new AttrTable);
614 
615  for (it_ra = (*it_g)->getAttributes().begin();
616  it_ra != (*it_g)->getAttributes().end(); ++it_ra) {
617  gen_dap_oneobj_das(at,*it_ra,NULL);
618  }
619  }
620  }
621 
622  for (it_v = vars.begin();
623  it_v != vars.end(); ++it_v) {
624  if (false == ((*it_v)->getAttributes().empty())) {
625 
626  AttrTable *at = das.get_table((*it_v)->getNewName());
627  if (NULL == at)
628  at = das.add_table((*it_v)->getNewName(), new AttrTable);
629 
630  for (it_ra = (*it_v)->getAttributes().begin();
631  it_ra != (*it_v)->getAttributes().end(); ++it_ra) {
632  gen_dap_oneobj_das(at,*it_ra,*it_v);
633  }
634  }
635  }
636 
637  for (it_cv = cvars.begin(); it_cv !=cvars.end();it_cv++) {
638  // cerr <<"variable full path= "<< (*it_cv)->getFullPath() <<endl;
639 
640  if (false == ((*it_cv)->getAttributes().empty())) {
641 
642  AttrTable *at = das.get_table((*it_cv)->getNewName());
643  if (NULL == at)
644  at = das.add_table((*it_cv)->getNewName(), new AttrTable);
645 
646  for (it_ra = (*it_cv)->getAttributes().begin();
647  it_ra != (*it_cv)->getAttributes().end(); ++it_ra) {
648  gen_dap_oneobj_das(at,*it_ra,*it_cv);
649  }
650  }
651  }
652 
653 
654  // To keep the backward compatiablity with the old handler,
655  // we parse the special ECS metadata to DAP attributes
656 
657  string st_str ="";
658  string core_str="";
659  string arch_str="";
660  string xml_str ="";
661  string subset_str="";
662  string product_str="";
663  string other_str ="";
664  bool st_only = false;
665 
666  read_ecs_metadata(file_id, st_str, core_str, arch_str, xml_str,
667  subset_str, product_str, other_str, st_only);
668 
669 #if 0
670 if(st_str!="") cerr <<"Final structmetadata "<<st_str <<endl;
671 if(core_str!="") cerr <<"Final coremetadata "<<core_str <<endl;
672 if(arch_str!="") cerr <<"Final archivedmetadata "<<arch_str <<endl;
673 if(xml_str!="") cerr <<"Final xmlmetadata "<<xml_str <<endl;
674 if(subset_str!="") cerr <<"Final subsetmetadata "<<subset_str <<endl;
675 if(product_str!="") cerr <<"Final productmetadata "<<product_str <<endl;
676 if(other_str!="") cerr <<"Final othermetadata "<<other_str <<endl;
677 
678 #endif
679  if(st_str != ""){
680 
681  string check_disable_smetadata_key ="H5.DisableStructMetaAttr";
682  bool is_check_disable_smetadata = false;
683  is_check_disable_smetadata = HDF5CFDAPUtil::check_beskeys(check_disable_smetadata_key);
684 
685  if (false == is_check_disable_smetadata) {
686 
687  AttrTable *at = das.get_table("StructMetadata");
688  if (NULL == at)
689  at = das.add_table("StructMetadata", new AttrTable);
690  parser_arg arg(at);
691 
692  he5das_scan_string((const char*) st_str.c_str());
693  if (he5dasparse(&arg) != 0
694  || false == arg.status()){
695 
696  (*BESLog::TheLog())<< "HDF-EOS5 parse error while processing a "
697  << "StructMetadata " << " HDFEOS attribute" << endl;
698  //cerr << "HDF-EOS StructMetdata parse error!\n";
699  }
700 
702 
703  }
704  }
705 
706  if(core_str != ""){
707  AttrTable *at = das.get_table("CoreMetadata");
708  if (NULL == at)
709  at = das.add_table("CoreMetadata", new AttrTable);
710  parser_arg arg(at);
711  he5das_scan_string((const char*) core_str.c_str());
712  if (he5dasparse(&arg) != 0
713  || false == arg.status()){
714 
715  (*BESLog::TheLog())<< "HDF-EOS5 parse error while processing a "
716  << "CoreMetadata " << " HDFEOS attribute" << endl;
717  //cerr << "HDF-EOS CoreMetadata parse error!\n";
718  }
719 
721  }
722  if(arch_str != ""){
723  AttrTable *at = das.get_table("ArchiveMetadata");
724  if (NULL == at)
725  at = das.add_table("ArchiveMetadata", new AttrTable);
726  parser_arg arg(at);
727  he5das_scan_string((const char*) arch_str.c_str());
728  if (he5dasparse(&arg) != 0
729  || false == arg.status()){
730 
731  (*BESLog::TheLog())<< "HDF-EOS5 parse error while processing a "
732  << "ArchiveMetadata " << " HDFEOS attribute" << endl;
733  // cerr << "HDF-EOS ArchiveMetdata parse error!\n";
734  }
736  }
737 
738  // XML attribute includes double quote("), this will choke netCDF Java library.
739  // So we replace double_quote(") with &quote.This is currently the OPeNDAP way.
740  // XML attribute cannot parsed. So just pass the string.
741  if(xml_str != ""){
742  AttrTable *at = das.get_table("XMLMetadata");
743  if (NULL == at)
744  at = das.add_table("XMLMetadata", new AttrTable);
746  at->append_attr("Contents","String",xml_str);
747  }
748 
749  // SubsetMetadata and ProductMetadata exist in HDF-EOS2 files.
750  // So far we haven't found any metadata in NASA HDF-EOS5 files,
751  // but will keep an eye on it. KY 2012-3-6
752  if(subset_str != ""){
753  AttrTable *at = das.get_table("SubsetMetadata");
754  if (NULL == at)
755  at = das.add_table("SubsetMetadata", new AttrTable);
756  parser_arg arg(at);
757  he5das_scan_string((const char*) subset_str.c_str());
758  if (he5dasparse(&arg) != 0
759  || false == arg.status()) {
760 
761  (*BESLog::TheLog())<< "HDF-EOS5 parse error while processing a "
762  << "SubsetMetadata " << " HDFEOS attribute" << endl;
763  //cerr << "HDF-EOS SubsetMetadata parse error!\n";
764  }
766  }
767  if(product_str != ""){
768  AttrTable *at = das.get_table("ProductMetadata");
769  if (NULL == at)
770  at = das.add_table("ProductMetadata", new AttrTable);
771  parser_arg arg(at);
772  he5das_scan_string((const char*) product_str.c_str());
773  if (he5dasparse(&arg) != 0
774  || false == arg.status()){
775  (*BESLog::TheLog())<< "HDF-EOS5 parse error while processing a "
776  << "ProductMetadata " << " HDFEOS attribute" << endl;
777  //cerr << "HDF-EOS ProductMetadata parse error!\n";
778  }
780  }
781 
782  // All other metadata under "HDF-EOS Information" will not be
783  // parsed since we don't know how to parse them.
784  // We will simply pass a string to the DAS.
785  if (other_str != ""){
786  AttrTable *at = das.get_table("OtherMetadata");
787  if (NULL == at)
788  at = das.add_table("OtherMetadata", new AttrTable);
789  at->append_attr("Contents","String",other_str);
790  }
791 
792 }
793 
794 
795 void read_ecs_metadata(hid_t s_file_id,
796  string &total_strmeta_value,
797  string &total_coremeta_value,
798  string &total_archmeta_value,
799  string &total_xmlmeta_value,
800  string &total_submeta_value,
801  string &total_prometa_value,
802  string &total_othermeta_value,
803  bool s_st_only) {
804 
805  string ecs_group = "/HDFEOS INFORMATION";
806  hid_t ecs_grp_id = -1;
807  if ((ecs_grp_id = H5Gopen(s_file_id, ecs_group.c_str(),H5P_DEFAULT))<0) {
808  // cerr<<"cannot open the group "<<endl;
809  string msg =
810  "h5_ecs_meta: unable to open the HDF5 group ";
811  msg +=ecs_group;
812  // H5Fclose(s_file_id);
813  throw InternalErr(__FILE__, __LINE__, msg);
814  }
815 
816  H5G_info_t g_info;
817  hsize_t nelems = 0;
818 
819  if (H5Gget_info(ecs_grp_id,&g_info) <0) {
820  string msg =
821  "h5_ecs_meta: unable to obtain the HDF5 group info. for ";
822  msg +=ecs_group;
823  H5Gclose(ecs_grp_id);
824  // H5Fclose(s_file_id);
825  throw InternalErr(__FILE__, __LINE__, msg);
826  }
827 
828  nelems = g_info.nlinks;
829 
830  ssize_t oname_size = 0;
831 #if 0
832  int cur_archmeta_suffix = 0;
833  int cur_coremeta_suffix = 0;
834  int cur_strmeta_suffix = 0;
835  int cur_xmlmeta_suffix = 0;
836 #endif
837 
838  int archmeta_num = -1;
839  int coremeta_num = -1;
840  int xmlmeta_num = -1;
841  int strmeta_num = -1;
842  int submeta_num = -1;
843  int prometa_num = -1;
844 
845  // Initalize the total number for different metadata.
846  int archmeta_num_total = 0;
847  int coremeta_num_total = 0;
848  int xmlmeta_num_total = 0;
849  int strmeta_num_total = 0;
850  int submeta_num_total = 0;
851  int prometa_num_total = 0;
852  int othermeta_num_total = 0;
853 
854  bool archmeta_no_suffix = true;
855  bool coremeta_no_suffix = true;
856  bool strmeta_no_suffix = true;
857  bool xmlmeta_no_suffix = true;
858  bool submeta_no_suffix = true;
859  bool prometa_no_suffix = true;
860 
861  // Define a vector of string to hold all dataset names.
862  vector<string> s_oname(nelems);
863 
864  // Define an EOSMetadata array that can describe the metadata type for each object
865  // We initialize the value to OtherMeta.
866  EOS5Metadata metatype[nelems];
867 
868  for (unsigned int i =0; i<nelems; i++)
869  metatype[i] = OtherMeta;
870 
871  for (hsize_t i = 0; i < nelems; i++) {
872 
873  // Query the length of the object name.
874  oname_size =
875  H5Lget_name_by_idx(ecs_grp_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,NULL,
876  0, H5P_DEFAULT);
877  if (oname_size <= 0) {
878  string msg = "hdf5 object name error from: ";
879  msg += ecs_group;
880  H5Gclose(ecs_grp_id);
881 // H5Fclose(s_file_id);
882  throw InternalErr(__FILE__, __LINE__, msg);
883  }
884 
885  // Obtain the name of the object.
886  vector<char> oname(oname_size + 1);
887  if (H5Lget_name_by_idx(ecs_grp_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,&oname[0],
888  (size_t)(oname_size+1), H5P_DEFAULT)<0){
889  string msg = "hdf5 object name error from: ";
890  msg += ecs_group;
891  H5Gclose(ecs_grp_id);
892  // H5Fclose(s_file_id);
893  throw InternalErr(__FILE__, __LINE__, msg);
894  }
895 
896  // Check if this object is an HDF5 dataset, not, throw an error.
897  // First, check if it is the hard link or the soft link
898  H5L_info_t linfo;
899  if (H5Lget_info(ecs_grp_id,&oname[0],&linfo,H5P_DEFAULT)<0) {
900  string msg = "hdf5 link name error from: ";
901  msg += ecs_group;
902  H5Gclose(ecs_grp_id);
903  // H5Fclose(s_file_id);
904  throw InternalErr(__FILE__, __LINE__, msg);
905  }
906 
907  // This is the soft link.
908  if (linfo.type == H5L_TYPE_SOFT){
909  string msg = "hdf5 link name error from: ";
910  msg += ecs_group;
911  H5Gclose(ecs_grp_id);
912  // H5Fclose(s_file_id);
913  throw InternalErr(__FILE__, __LINE__, msg);
914  }
915 
916  // Obtain the object type
917  H5O_info_t oinfo;
918  if (H5Oget_info_by_idx(ecs_grp_id, ".", H5_INDEX_NAME, H5_ITER_NATIVE,
919  i, &oinfo, H5P_DEFAULT)<0) {
920  string msg = "Cannot obtain the object info ";
921  msg += ecs_group;
922  H5Gclose(ecs_grp_id);
923  // H5Fclose(s_file_id);
924  throw InternalErr(__FILE__, __LINE__, msg);
925  }
926 
927  if(oinfo.type != H5O_TYPE_DATASET) {
928  string msg = "hdf5 link name error from: ";
929  msg += ecs_group;
930  H5Gclose(ecs_grp_id);
931  // H5Fclose(s_file_id);
932  throw InternalErr(__FILE__, __LINE__, msg);
933  }
934 
935  // We want to remove the last '\0' character added by C .
936  string s_one_oname(oname.begin(),oname.end()-1);
937  // cerr <<"full object name "<<s_one_oname <<endl;
938  s_oname[i] = s_one_oname;
939 
940  // Calculate how many elements we have for each category(StructMetadata, CoreMetadata, etc.)
941  if (((s_one_oname.find("StructMetadata"))==0) ||
942  ((s_one_oname.find("structmetadata"))==0)){
943 
944  metatype[i] = StructMeta;
945 
946  // Do we have suffix for the metadata?
947  // If this metadata doesn't have any suffix, it should only come to this loop once.
948  // That's why, when checking the first time, no_suffix is always true.
949  // If we have already found that it doesn't have any suffix,
950  // it should not go into this loop. throw an error.
951  if (false == strmeta_no_suffix) {
952  string msg = "StructMetadata/structmetadata without suffix should only appear once. ";
953  H5Gclose(ecs_grp_id);
954  // H5Fclose(s_file_id);
955  throw InternalErr(__FILE__, __LINE__, msg);
956  }
957 
958  else if(strmeta_num_total >0)
959  strmeta_num_total++;
960  else { // either no suffix or the first time to loop the one having the suffix.
961  if ((0 == s_one_oname.compare("StructMetadata"))||
962  (0 == s_one_oname.compare("structmetadata")))
963  strmeta_no_suffix = false;
964  else strmeta_num_total++;
965  }
966 #if 0
967 cerr <<"strmeta_num_total= "<<strmeta_num_total <<endl;
968 if(strmeta_no_suffix) cerr <<"structmeta data has the suffix" <<endl;
969 else cerr <<"structmeta data doesn't have the suffix" <<endl;
970 #endif
971  }
972 
973  if(false == s_st_only) {
974 
975  if ((0 == (s_one_oname.find("CoreMetadata"))) ||
976  (0 == (s_one_oname.find("coremetadata")))){
977 
978  metatype[i] = CoreMeta;
979 
980  // Do we have suffix for the metadata?
981  // When checking the first time, no_suffix is always true.
982  // If we have already found that it doesn't have any suffix,
983  // it should not go into this loop anyway. throw an error.
984  if (false == coremeta_no_suffix) {
985  string msg = "CoreMetadata/coremetadata without suffix should only appear once. ";
986  H5Gclose(ecs_grp_id);
987 // H5Fclose(s_file_id);
988  throw InternalErr(__FILE__, __LINE__, msg);
989  }
990 
991  else if(coremeta_num_total >0)
992  coremeta_num_total++;
993  else { // either no suffix or the first time to loop the one having the suffix.
994  // If no suffix is true, it should be out of the loop. In case it comes
995  // to the loop again, we set "coremeta_no_suffix" be false so an error
996  // can be thrown. This is counter-intutitive. Hopefully people can understand it.
997  if ((0 == s_one_oname.compare("CoreMetadata")) ||
998  (0 == s_one_oname.compare("coremetadata")))
999  coremeta_no_suffix = false;
1000  else coremeta_num_total++;
1001  }
1002 #if 0
1003 cerr <<"coremeta_num_total= "<<coremeta_num_total <<endl;
1004 if(coremeta_no_suffix) cerr <<"coreuctmeta data has the suffix" <<endl;
1005 else cerr <<"coremeta data doesn't have the suffix" <<endl;
1006 #endif
1007  }
1008 
1009  // OMI has the metadata name as "ArchiveMetadata.0"
1010  else if ((0 == (s_one_oname.find("ArchivedMetadata"))) ||
1011  (0 == (s_one_oname.find("archivedmetadata"))) ||
1012  (0 == (s_one_oname.find("ArchiveMetadata"))) ||
1013  (0 == (s_one_oname.find("archivemetadata")))){
1014 
1015  metatype[i] = ArchivedMeta;
1016  // Do we have suffix for the metadata?
1017  // When checking the first time, no_suffix is always true.
1018  // If we have already found that it doesn't have any suffix,
1019  // it should not go into this loop anyway. throw an error.
1020  if (false == archmeta_no_suffix) {
1021  string msg = "archivedmetadata/ArchivedMetadata without suffix should only appear once. ";
1022  H5Gclose(ecs_grp_id);
1023  //H5Fclose(s_file_id);
1024  throw InternalErr(__FILE__, __LINE__, msg);
1025  }
1026 
1027  else if(archmeta_num_total >0)
1028  archmeta_num_total++;
1029  else { // either no suffix or the first time to loop the one having the suffix.
1030  if ((0 == s_one_oname.compare("ArchivedMetadata"))||
1031  (0 == s_one_oname.compare("archivedmetadata")) ||
1032  (0 == s_one_oname.compare("archivemetadata")) ||
1033  (0 == s_one_oname.compare("ArchiveMetadata")))
1034  archmeta_no_suffix = false;
1035  else
1036  archmeta_num_total++;
1037  }
1038 #if 0
1039 cerr <<"archmeta_num_total= "<<archmeta_num_total <<endl;
1040 if(archmeta_no_suffix) cerr <<"archuctmeta data has the suffix" <<endl;
1041 else cerr <<"archmeta data doesn't have the suffix" <<endl;
1042 #endif
1043 
1044  }
1045 
1046  else if (((s_one_oname.find("SubsetMetadata"))==0) ||
1047  ((s_one_oname.find("subsetmetadata"))==0)){
1048 
1049  metatype[i] = SubsetMeta;
1050  // Do we have suffix for the metadata?
1051  // When checking the first time, no_suffix is always true.
1052  // If we have already found that it doesn't have any suffix,
1053  // it should not go into this loop anyway. throw an error.
1054  if (false == submeta_no_suffix) {
1055  H5Gclose(ecs_grp_id);
1056 // H5Fclose(s_file_id);
1057  string msg = "submetadata/SubMetadata without suffix should only appear once. ";
1058  throw InternalErr(__FILE__, __LINE__, msg);
1059  }
1060 
1061  else if(submeta_num_total >0)
1062  submeta_num_total++;
1063  else { // either no suffix or the first time to loop the one having the suffix.
1064  if ((0 == s_one_oname.compare("SubsetMetadata"))||
1065  (0 == s_one_oname.compare("subsetmetadata")))
1066  submeta_no_suffix = false;
1067  else submeta_num_total++;
1068  }
1069 #if 0
1070 cerr <<"submeta_num_total= "<<submeta_num_total <<endl;
1071 if(submeta_no_suffix) cerr <<"subuctmeta data has the suffix" <<endl;
1072 else cerr <<"submeta data doesn't have the suffix" <<endl;
1073 #endif
1074 
1075  }
1076 
1077  else if ((0 == (s_one_oname.find("XmlMetadata"))) ||
1078  (0 == (s_one_oname.find("xmlmetadata")))){
1079 
1080  metatype[i] = XMLMeta;
1081 
1082  // Do we have suffix for the metadata?
1083  // When checking the first time, no_suffix is always true.
1084  // If we have already found that it doesn't have any suffix,
1085  // it should not go into this loop anyway. throw an error.
1086  if (false == xmlmeta_no_suffix) {
1087  H5Gclose(ecs_grp_id);
1088  // H5Fclose(s_file_id);
1089  string msg = "xmlmetadata/Xmlmetadata without suffix should only appear once. ";
1090  throw InternalErr(__FILE__, __LINE__, msg);
1091  }
1092 
1093  else if(xmlmeta_num_total >0)
1094  xmlmeta_num_total++;
1095  else { // either no suffix or the first time to loop the one having the suffix.
1096  if ((0 == s_one_oname.compare("XmlMetadata"))||
1097  (0 == s_one_oname.compare("xmlmetadata")))
1098  xmlmeta_no_suffix = false;
1099  else xmlmeta_num_total++;
1100  }
1101 #if 0
1102 cerr <<"xmlmeta_num_total= "<<xmlmeta_num_total <<endl;
1103 if(xmlmeta_no_suffix) cerr <<"xmluctmeta data doesn't have the suffix" <<endl;
1104 else cerr <<"xmlmeta data has the suffix" <<endl;
1105 #endif
1106 
1107  }
1108 
1109  else if ((0 == (s_one_oname.find("ProductMetadata"))) ||
1110  (0 == (s_one_oname.find("productmetadata")))){
1111 
1112  metatype[i] = ProductMeta;
1113  // Do we have suffix for the metadata?
1114  // When checking the first time, no_suffix is always true.
1115  // If we have already found that it doesn't have any suffix,
1116  // it should not go into this loop anyway. throw an error.
1117  if (!prometa_no_suffix) {
1118  H5Gclose(ecs_grp_id);
1119 // H5Fclose(s_file_id);
1120  string msg = "productmetadata/ProductMetadata without suffix should only appear once. ";
1121  throw InternalErr(__FILE__, __LINE__, msg);
1122  }
1123 
1124  else if(prometa_num_total >0) prometa_num_total++;
1125  else { // either no suffix or the first time to loop the one having the suffix.
1126  if ((0 == s_one_oname.compare("ProductMetadata"))||
1127  (0 == s_one_oname.compare("productmetadata")))
1128  prometa_no_suffix = false;
1129  else prometa_num_total++;
1130  }
1131 
1132  }
1133 
1134  // All other metadata will be merged to one string, no need to check the name.
1135  else othermeta_num_total++;
1136  }
1137 
1138  // cerr <<"object name using s_oname is " <<s_oname[i] <<endl;
1139  oname.clear();
1140  s_one_oname.clear();
1141  }
1142 
1143  // Define a vector of string to hold StructMetadata.
1144  // StructMetadata must exist for a valid HDF-EOS5 file.
1145  vector<string> strmeta_value;
1146  if (strmeta_num_total <= 0) {
1147  string msg = "hdf5 object name error from: ";
1148  H5Gclose(ecs_grp_id);
1149 // H5Fclose(s_file_id);
1150  throw InternalErr(__FILE__, __LINE__, msg);
1151 
1152  // cerr <<"Struct Metadata doesn't exist."<<endl;
1153  }
1154  else {
1155  strmeta_value.resize(strmeta_num_total);
1156  for (int i = 0; i < strmeta_num_total; i++)
1157  strmeta_value[i]="";
1158  }
1159 
1160  // All other metadata are optional.
1161  // Define a vector of string to hold archivedmetadata.
1162  vector<string> archmeta_value;
1163  if (archmeta_num_total >0) {
1164  archmeta_value.resize(archmeta_num_total);
1165  for (int i = 0; i < archmeta_num_total; i++)
1166  archmeta_value[i]="";
1167  }
1168 
1169  // Define a vector of string to hold coremetadata.
1170  vector<string> coremeta_value;
1171  // cerr<<"coremeta_num_total "<<coremeta_num_total <<endl;
1172  if (coremeta_num_total >0) {
1173  coremeta_value.resize(coremeta_num_total);
1174  for (int i = 0; i < coremeta_num_total; i++)
1175  coremeta_value[i]="";
1176  }
1177 
1178  // Define a vector of string to hold xmlmetadata.
1179  vector<string> xmlmeta_value;
1180  if (xmlmeta_num_total >0) {
1181  xmlmeta_value.resize(xmlmeta_num_total);
1182  for (int i = 0; i < xmlmeta_num_total; i++)
1183  xmlmeta_value[i]="";
1184  }
1185 
1186  // Define a vector of string to hold subsetmetadata.
1187  vector<string> submeta_value;
1188  if (submeta_num_total >0) {
1189  submeta_value.resize(submeta_num_total);
1190  for (int i = 0; i < submeta_num_total; i++)
1191  submeta_value[i]="";
1192  }
1193 
1194  // Define a vector of string to hold productmetadata.
1195  vector<string> prometa_value;
1196  if (prometa_num_total >0) {
1197  prometa_value.resize(prometa_num_total);
1198  for (int i = 0; i < prometa_num_total; i++)
1199  prometa_value[i]="";
1200  }
1201 
1202  // For all other metadata, we don't need to calculate the value, just append them.
1203 // string total_othermeta_value ="";
1204 
1205  // Now we want to retrieve the metadata value and combine them into one string.
1206  // Here we have to remember the location of every element of the metadata if
1207  // this metadata has a suffix.
1208  for (hsize_t i = 0; i < nelems; i++) {
1209 
1210  // cerr <<"object name "<<s_oname[i] <<endl;
1211  // DDS parser only needs to parse the struct Metadata. So check
1212  // if st_only flag is true, will only read StructMetadata string.
1213  // Struct Metadata is generated by the HDF-EOS5 library, so the
1214  // name "StructMetadata.??" won't change for real struct metadata.
1215  //However, we still assume that somebody may not use the HDF-EOS5
1216  // library to add StructMetadata, the name may be "structmetadata".
1217  if (true == s_st_only &&
1218  (((s_oname[i].find("StructMetadata"))!=0) &&
1219  ((s_oname[i].find("structmetadata"))!=0))){
1220  continue;
1221  }
1222 
1223  // Open the dataset, dataspace, datatype, number of elements etc. for this metadata
1224  hid_t s_dset_id = -1;
1225  hid_t s_space_id = -1;
1226  hid_t s_ty_id = -1;
1227  hssize_t s_nelms = -1;
1228  size_t dtype_size = -1;
1229 
1230  if ((s_dset_id = H5Dopen(ecs_grp_id,s_oname[i].c_str(),H5P_DEFAULT))<0){
1231  string msg = "Cannot open HDF5 dataset ";
1232  msg += s_oname[i];
1233  H5Gclose(ecs_grp_id);
1234 // H5Fclose(s_file_id);
1235  throw InternalErr(__FILE__, __LINE__, msg);
1236  }
1237 
1238  if ((s_space_id = H5Dget_space(s_dset_id))<0) {
1239  string msg = "Cannot open the data space of HDF5 dataset ";
1240  msg += s_oname[i];
1241  H5Dclose(s_dset_id);
1242  H5Gclose(ecs_grp_id);
1243 // H5Fclose(s_file_id);
1244  throw InternalErr(__FILE__, __LINE__, msg);
1245  }
1246 
1247  if ((s_ty_id = H5Dget_type(s_dset_id)) < 0) {
1248  string msg = "Cannot get the data type of HDF5 dataset ";
1249  msg += s_oname[i];
1250  H5Sclose(s_space_id);
1251  H5Dclose(s_dset_id);
1252  H5Gclose(ecs_grp_id);
1253 // H5Fclose(s_file_id);
1254  throw InternalErr(__FILE__, __LINE__, msg);
1255  }
1256  if ((s_nelms = H5Sget_simple_extent_npoints(s_space_id))<0) {
1257  string msg = "Cannot get the number of points of HDF5 dataset ";
1258  msg += s_oname[i];
1259  H5Tclose(s_ty_id);
1260  H5Sclose(s_space_id);
1261  H5Dclose(s_dset_id);
1262  H5Gclose(ecs_grp_id);
1263 // H5Fclose(s_file_id);
1264  throw InternalErr(__FILE__, __LINE__, msg);
1265  }
1266  if ((dtype_size = H5Tget_size(s_ty_id))==0) {
1267 
1268  string msg = "Cannot get the data type size of HDF5 dataset ";
1269  msg += s_oname[i];
1270  H5Tclose(s_ty_id);
1271  H5Sclose(s_space_id);
1272  H5Dclose(s_dset_id);
1273  H5Gclose(ecs_grp_id);
1274 // H5Fclose(s_file_id);
1275  throw InternalErr(__FILE__, __LINE__, msg);
1276  }
1277 
1278  // Obtain the real value of the metadata
1279  vector<char> s_buf(dtype_size*s_nelms +1);
1280 
1281  if ((H5Dread(s_dset_id,s_ty_id,H5S_ALL,H5S_ALL,H5P_DEFAULT,&s_buf[0]))<0) {
1282 
1283  string msg = "Cannot read HDF5 dataset ";
1284  msg += s_oname[i];
1285  H5Tclose(s_ty_id);
1286  H5Sclose(s_space_id);
1287  H5Dclose(s_dset_id);
1288  H5Gclose(ecs_grp_id);
1289 // H5Fclose(s_file_id);
1290  throw InternalErr(__FILE__, __LINE__, msg);
1291  }
1292 
1293  // Now we can safely close datatype, data space and dataset IDs.
1294  H5Tclose(s_ty_id);
1295  H5Sclose(s_space_id);
1296  H5Dclose(s_dset_id);
1297 
1298 
1299  // Convert from the vector<char> to a C++ string.
1300  string tempstr(s_buf.begin(),s_buf.end());
1301  s_buf.clear();
1302  size_t temp_null_pos = tempstr.find_first_of('\0');
1303 
1304  // temp_null_pos returns the position of NULL,which is the last character of the string.
1305  // so the length of string before null is EQUAL to
1306  // temp_null_pos since pos starts at 0.
1307  string finstr = tempstr.substr(0,temp_null_pos);
1308 
1309  // For the DDS parser, only return StructMetadata
1310  if (StructMeta == metatype[i]) {
1311 
1312  // Now obtain the corresponding value in integer type for the suffix. '0' to 0 etc.
1313  try {
1314  strmeta_num = get_metadata_num(s_oname[i]);
1315  }
1316  catch(...) {
1317  H5Gclose(ecs_grp_id);
1318  throw InternalErr(__FILE__,__LINE__,"Obtain structmetadata suffix error.");
1319 
1320  }
1321  // This is probably not necessary, since structmetadata may always have a suffix.
1322  // Leave here just in case the rules change or a special non-HDF-EOS5 library generated file.
1323  // when strmeta_num is -1, it means no suffix for this metadata. So the total structmetadata
1324  // is this string only.
1325  if (-1 == strmeta_num)
1326  total_strmeta_value = finstr;
1327  // strmeta_value at this point should be empty before assigning any values.
1328  else if (strmeta_value[strmeta_num]!="") {
1329  string msg = "The structmeta value array at this index should be empty string ";
1330  H5Gclose(ecs_grp_id);
1331 // H5Fclose(s_file_id);
1332  throw InternalErr(__FILE__, __LINE__, msg);
1333  }
1334  // assign the string vector to this value.
1335  else
1336  strmeta_value[strmeta_num] = finstr;
1337  }
1338 
1339  // DAS parser needs all metadata.
1340  if (false == s_st_only &&
1341  (metatype[i] != StructMeta)) {
1342 
1343  switch (metatype[i]) {
1344 
1345  case CoreMeta:
1346  {
1347  if (coremeta_num_total < 0) {
1348  string msg = "There may be no coremetadata or coremetadata is not counted ";
1349  H5Gclose(ecs_grp_id);
1350 // H5Fclose(s_file_id);
1351  throw InternalErr(__FILE__, __LINE__, msg);
1352 
1353  }
1354 
1355  try {
1356  coremeta_num = get_metadata_num(s_oname[i]);
1357  }
1358  catch(...) {
1359  H5Gclose(ecs_grp_id);
1360  throw InternalErr(__FILE__,__LINE__,"Obtain coremetadata suffix error.");
1361 
1362  }
1363 
1364  // when coremeta_num is -1, it means no suffix for this metadata. So the total coremetadata
1365  // is this string only. Similar cases apply for the rest metadata.
1366  if ( -1 == coremeta_num )
1367  total_coremeta_value = finstr;
1368  else if (coremeta_value[coremeta_num]!="") {
1369  string msg = "The coremeta value array at this index should be empty string ";
1370  H5Gclose(ecs_grp_id);
1371 // H5Fclose(s_file_id);
1372  throw InternalErr(__FILE__, __LINE__, msg);
1373  }
1374 
1375  // assign the string vector to this value.
1376  else
1377  coremeta_value[coremeta_num] = finstr;
1378  }
1379  break;
1380 
1381  case ArchivedMeta:
1382  {
1383  if (archmeta_num_total < 0) {
1384  string msg = "There may be no archivemetadata or archivemetadata is not counted ";
1385  H5Gclose(ecs_grp_id);
1386 // H5Fclose(s_file_id);
1387  throw InternalErr(__FILE__, __LINE__, msg);
1388  }
1389  try {
1390  archmeta_num = get_metadata_num(s_oname[i]);
1391  }
1392  catch(...) {
1393  H5Gclose(ecs_grp_id);
1394  throw InternalErr(__FILE__,__LINE__,"Obtain archivemetadata suffix error.");
1395  }
1396  if (-1 == archmeta_num )
1397  total_archmeta_value = finstr;
1398  else if (archmeta_value[archmeta_num]!="") {
1399  string msg = "The archivemeta value array at this index should be empty string ";
1400  H5Gclose(ecs_grp_id);
1401 // H5Fclose(s_file_id);
1402  throw InternalErr(__FILE__, __LINE__, msg);
1403 
1404  }
1405  // assign the string vector to this value.
1406  else
1407  archmeta_value[archmeta_num] = finstr;
1408  }
1409  break;
1410  case SubsetMeta:
1411  {
1412  if (submeta_num_total < 0) {
1413  string msg = "The subsetemeta value array at this index should be empty string ";
1414  H5Gclose(ecs_grp_id);
1415 // H5Fclose(s_file_id);
1416  throw InternalErr(__FILE__, __LINE__, msg);
1417  }
1418  try {
1419  submeta_num = get_metadata_num(s_oname[i]);
1420  }
1421  catch(...) {
1422  H5Gclose(ecs_grp_id);
1423  throw InternalErr(__FILE__,__LINE__,"Obtain subsetmetadata suffix error.");
1424  }
1425  if (-1 == submeta_num )
1426  total_submeta_value = finstr;
1427  else if (submeta_value[submeta_num]!="") {
1428  string msg = "The submeta value array at this index should be empty string ";
1429  H5Gclose(ecs_grp_id);
1430 // H5Fclose(s_file_id);
1431  throw InternalErr(__FILE__, __LINE__, msg);
1432  }
1433  // assign the string vector to this value.
1434  else
1435  submeta_value[submeta_num] = finstr;
1436  }
1437  break;
1438  case ProductMeta:
1439  {
1440  if (prometa_num_total < 0) {
1441  string msg = "There may be no productmetadata or productmetadata is not counted ";
1442  H5Gclose(ecs_grp_id);
1443 // H5Fclose(s_file_id);
1444  throw InternalErr(__FILE__, __LINE__, msg);
1445  }
1446  try {
1447  prometa_num = get_metadata_num(s_oname[i]);
1448  }
1449  catch(...) {
1450  H5Gclose(ecs_grp_id);
1451  throw InternalErr(__FILE__,__LINE__,"Obtain productmetadata suffix error.");
1452  }
1453  if (prometa_num == -1)
1454  total_prometa_value = finstr;
1455  else if (prometa_value[prometa_num]!="") {
1456  string msg = "The productmeta value array at this index should be empty string ";
1457  H5Gclose(ecs_grp_id);
1458 // H5Fclose(s_file_id);
1459  throw InternalErr(__FILE__, __LINE__, msg);
1460  }
1461  // assign the string vector to this value.
1462  else
1463  prometa_value[prometa_num] = finstr;
1464  }
1465  break;
1466  case XMLMeta:
1467  {
1468  if (xmlmeta_num_total < 0) {
1469  string msg = "There may be no xmlmetadata or xmlmetadata is not counted ";
1470  H5Gclose(ecs_grp_id);
1471 // H5Fclose(s_file_id);
1472  throw InternalErr(__FILE__, __LINE__, msg);
1473  }
1474  try {
1475  xmlmeta_num = get_metadata_num(s_oname[i]);
1476  }
1477  catch(...) {
1478  H5Gclose(ecs_grp_id);
1479  throw InternalErr(__FILE__,__LINE__,"Obtain XMLmetadata suffix error.");
1480  }
1481  if (-1 == xmlmeta_num )
1482  total_xmlmeta_value = finstr;
1483  else if (xmlmeta_value[xmlmeta_num]!="") {
1484  string msg = "The xmlmeta value array at this index should be empty string ";
1485  H5Gclose(ecs_grp_id);
1486 // H5Fclose(s_file_id);
1487  throw InternalErr(__FILE__, __LINE__, msg);
1488  }
1489  // assign the string vector to this value.
1490  else
1491  xmlmeta_value[xmlmeta_num] = finstr;
1492  }
1493  break;
1494  case OtherMeta:
1495  {
1496  if (othermeta_num_total < 0) {
1497  string msg = "There may be no othermetadata or other metadata is not counted ";
1498  H5Gclose(ecs_grp_id);
1499 // H5Fclose(s_file_id);
1500  throw InternalErr(__FILE__, __LINE__, msg);
1501  }
1502  total_othermeta_value = total_othermeta_value + finstr;
1503  }
1504  break;
1505  default :
1506  {
1507  string msg = "Unsupported metadata type ";
1508  H5Gclose(ecs_grp_id);
1509 // H5Fclose(s_file_id);
1510  throw InternalErr(__FILE__, __LINE__, msg);
1511  }
1512  }
1513  }
1514  tempstr.clear();
1515  finstr.clear();
1516 // H5Sclose(s_space_id);
1517 // H5Tclose(s_ty_id);
1518 // H5Dclose(s_dset_id);
1519  }
1520 
1521  // Now we need to handle the concatenation of the metadata
1522  // first StructMetadata
1523  if (strmeta_num_total > 0) {
1524  // The no suffix one has been taken care.
1525  if (strmeta_num != -1) {
1526  for (int i = 0; i <strmeta_num_total; i++)
1527  total_strmeta_value +=strmeta_value[i];
1528  }
1529  }
1530 
1531  // For the DAS handler
1532  if ( false == s_st_only) {
1533 
1534  if (coremeta_num_total >0) {
1535  if (coremeta_num != -1) {
1536  for(int i = 0; i <coremeta_num_total; i++)
1537  total_coremeta_value +=coremeta_value[i];
1538  }
1539  }
1540 
1541  if (archmeta_num_total >0) {
1542  if (archmeta_num != -1) {
1543  for(int i = 0; i <archmeta_num_total; i++)
1544  total_archmeta_value +=archmeta_value[i];
1545  }
1546  }
1547 
1548  if (submeta_num_total >0) {
1549  if (submeta_num != -1) {
1550  for(int i = 0; i <submeta_num_total; i++)
1551  total_submeta_value +=submeta_value[i];
1552  }
1553  }
1554 
1555  if (xmlmeta_num_total >0) {
1556  if (xmlmeta_num != -1) {
1557  for(int i = 0; i <xmlmeta_num_total; i++)
1558  total_xmlmeta_value +=xmlmeta_value[i];
1559  }
1560  }
1561 
1562  if (prometa_num_total >0) {
1563  if (prometa_num != -1) {
1564  for(int i = 0; i <prometa_num_total; i++)
1565  total_prometa_value +=prometa_value[i];
1566  }
1567  }
1568  }
1569  H5Gclose(ecs_grp_id);
1570 }
1571 
1572 int get_metadata_num(const string & meta_str) {
1573 
1574  // The normal metadata names should be like coremetadata.0, coremetadata.1 etc.
1575  // We just find a not so nice coremetadata names such as coremetadata.0, coremetadata.0.1 for a HIRDLS-MLS-Aura-L3
1576  // We need to handle them. Here we assume no more than two dots in a name series. KY 2012-11-08
1577  size_t dot_pos = meta_str.find(".");
1578  if (dot_pos == string::npos) // No dot
1579  return -1;
1580  else if (meta_str.find_first_of(".") == meta_str.find_last_of(".")) { // One dot
1581  string num_str = meta_str.substr(dot_pos+1);
1582  stringstream ssnum(num_str);
1583  int num;
1584  ssnum >> num;
1585  if (false == ssnum)
1586  throw InternalErr(__FILE__,__LINE__,"Suffix after dots is not a number.");
1587  return num;
1588  }
1589  else { // Two dots
1590  string str_after_first_dot = meta_str.substr(dot_pos+1);
1591  if (str_after_first_dot.find_first_of(".") != str_after_first_dot.find_last_of("."))
1592  throw InternalErr(__FILE__,__LINE__,"Currently don't support metadata names containing more than two dots.");
1593  // Here we don't check if names are like coremetadata.0 coremetadata.0.0 etc., Having ".0 .0.0" is,if not mistaken,
1594  // is insane.
1595  // Instead we hope that the data producers will produce data like coremetadata.0 coremetadata.0.1 coremeatadata.0.2
1596  // KY 2012-11-08
1597  size_t second_dot_pos = str_after_first_dot.find(".");
1598  string num_str = str_after_first_dot.substr(second_dot_pos+1);
1599  stringstream ssnum(num_str);
1600  int num;
1601  ssnum >> num;
1602  return num;
1603  }
1604 
1605 }
1606 
1607 
1608 
1609 
1610 
This class provides a way to map HDF5 Str to DAP Str for the CF option.
Definition: HDF5CF.h:60
bool check_grids_support_projcode(HE5Parser *p)
Definition: HE5Checker.cc:188
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:1218
yy_buffer_state * he5das_scan_string(const char *str)
Buffer state for NASA EOS metadata scanner.
const string & getFullPath() const
Get the full path of this variable.
Definition: HDF5CF.h:279
int getRank() const
Get the dimension rank of this variable.
Definition: HDF5CF.h:285
void Add_Dim_Name(HE5Parser *)
Add the dimension name for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:838
This class specifies the retrieval of special coordinate variable values for HDF-EOS5 products...
void Handle_SpVar()
Handle special variables for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3335
int he5dasparse(libdap::parser_arg *arg)
EOS5Metadata
Definition: heos5cfdap.h:44
This class provides a way to map HDF5 unsigned 16-bit integer to DAP uint16 for the CF option...
yy_buffer_state * he5dds_scan_string(const char *str)
void Handle_Obj_NameClashing(bool)
Handle the object name clashing for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:2645
This class provides a way to map HDF5 float to DAP float for the CF option.
#define HANDLE_CASE(tid, type)
void Handle_Unsupported_Dtype(bool)
Handle unsupported HDF5 datatypes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:156
static void replace_double_quote(string &str)
Definition: h5cfdaputil.cc:99
static bool check_beskeys(const string key)
Definition: h5cfdaputil.cc:39
void Adjust_EOS5Dim_Info(HE5Parser *strmeta_info)
Adjust HDF-EOS5 dimension information.
Definition: HDFEOS5CF.cc:198
const vector< Attribute * > & getAttributes() const
Public interface to obtain information of all attributes under the root group.
Definition: HDF5CF.h:578
void gen_eos5_cfdas(DAS &das, hid_t file_id, HDF5CF::EOS5File *f)
Definition: heos5cfdap.cc:581
This class provides a way to map HDF5 int16 to DAP int16 for the CF option.
void gen_dap_oneobj_das(AttrTable *at, const HDF5CF::Attribute *attr, const HDF5CF::Var *var)
bool check_grids_unknown_parameters(HE5Parser *p)
Definition: HE5Checker.cc:58
int he5ddsparse(HE5Parser *he5parser)
This class provides a way to map HDF5 64-bit floating-point(double) to DAP 64-bit floating-point for ...
void Adjust_Var_Dim_NewName_Before_Flattening()
Adjust variable dimension names before the flattening for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:2431
void Handle_DimNameClashing()
Handle dimension name clashing. Since COARDS requires the change of cv names, So we need to handle di...
Definition: HDFEOS5CF.cc:2720
void Handle_CVar()
Handle coordinate variable for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:1269
This class is a derived class of CVar. It represents a coordinate variable for HDF-EOS5 files...
Definition: HDF5CF.h:404
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.
float getPointRight() const
Definition: HDF5CF.h:424
void map_eos5_cfdas(DAS &das, hid_t file_id, const string &filename)
Definition: heos5cfdap.cc:232
#define NULL
Definition: wcsUtil.h:65
H5DataType getType() const
Get the data type of this variable(Not HDF5 datatype id)
Definition: HDF5CF.h:291
EOS5GridOriginType getOrigin() const
Definition: HDF5CF.h:431
EOS5GridPCType getProjCode() const
Definition: HDF5CF.h:435
void Adjust_Obj_Name()
This method is a no-op operation. Leave here since the method in the base class is pure virtual...
Definition: HDFEOS5CF.cc:3501
void set_grids_missing_pixreg_orig(HE5Parser *p)
Definition: HE5Checker.cc:75
void Handle_Unsupported_Dspace()
Handle unsupported HDF5 dataspaces for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:183
Map and generate DDS and DAS for the CF option for HDF-EOS5 products.
int getYDimSize() const
Definition: HDF5CF.h:443
void map_eos5_cfdds(DDS &dds, hid_t file_id, const string &filename)
Definition: heos5cfdap.cc:77
void Adjust_Var_NewName_After_Parsing()
Adjust variable names for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:749
float getPointLeft() const
Definition: HDF5CF.h:421
CVType getCVType() const
Get the coordinate variable type of this variable.
Definition: HDF5CF.h:337
const hid_t getFileID() const
Obtain the HDF5 file ID.
Definition: HDF5CF.h:559
int he5daslex_destroy()
Definition: lex.he5das.cc:2019
int get_metadata_num(const string &meta_str)
Definition: heos5cfdap.cc:1572
const string & getNewName() const
Get the new name of this variable.
Definition: HDF5CF.h:273
const string & getPath() const
Obtain the path of the file.
Definition: HDF5CF.h:566
This class provides a way to map HDF5 32-bit integer to DAP Int32 for the CF option.
int he5ddslex_destroy()
Definition: lex.he5dds.cc:2187
This class includes the methods to read data array into DAP buffer from an HDF5 dataset for the CF op...
void Handle_SpVar_Attr()
Handle special variables for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3466
This class is a derived class of File. It includes methods applied to HDF-EOS5 files only...
Definition: HDF5CF.h:880
const vector< Dimension * > & getDimensions() const
Get the list of the dimensions.
Definition: HDF5CF.h:302
const vector< EOS5CVar * > & getCVars() const
Obtain coordinate variables for HDF-EOS5 products.
Definition: HDF5CF.h:893
void Add_EOS5File_Info(HE5Parser *, bool)
Add HDF-EOS5 dimension and coordinate variable related info. to EOS5Grid,EOS5Swath etc...
Definition: HDFEOS5CF.cc:369
EOS5GridPRType getPixelReg() const
Definition: HDF5CF.h:428
void Retrieve_H5_Info(const char *path, hid_t file_id, bool include_attr)
Retrieve DDS information from the HDF5 file; a real implementation for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:131
A class for parsing NASA HDF-EOS5 StructMetadata.
int getXDimSize() const
Definition: HDF5CF.h:439
Helper functions for generating DAS attributes and a function to check BES Key.
void Flatten_Obj_Name(bool include_attr)
Flatten the object name for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:2623
This class provides a way to map HDF5 unsigned 32-bit integer to DAP uint32 for the CF option...
void Set_COARDS_Status()
Set COARDS flag.
Definition: HDFEOS5CF.cc:2786
bool check_grids_multi_latlon_coord_vars(HE5Parser *p)
Definition: HE5Checker.cc:116
void Add_Supplement_Attrs(bool)
Add the supplemental attributes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3037
static BESLog * TheLog()
Definition: BESLog.cc:347
const vector< Var * > & getVars() const
Public interface to obtain information of all variables.
Definition: HDF5CF.h:572
virtual const char * what() const
Definition: HDF5CF.h:79
const vector< Group * > & getGroups() const
Public interface to obtain all the group info.
Definition: HDF5CF.h:584
A class for parsing NASA HDF-EOS5 StructMetadata.
float getPointLower() const
Definition: HDF5CF.h:414
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
void Adjust_Attr_Info()
Adjust the attribute info for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:2809
void gen_dap_onevar_dds(DDS &dds, const HDF5CF::Var *var, const hid_t file_id, const string &filename)
This class provides a way to map HDF5 byte to DAP byte for the CF option.
void gen_dap_oneeos5cvar_dds(DDS &dds, const HDF5CF::EOS5CVar *cvar, const hid_t file_id, const string &filename)
Definition: heos5cfdap.cc:390
void gen_eos5_cfdds(DDS &dds, HDF5CF::EOS5File *f)
Definition: heos5cfdap.cc:364
bool check_grids_missing_projcode(HE5Parser *p)
Definition: HE5Checker.cc:44
void Retrieve_H5_Supported_Attr_Values()
Retrieve attribute values for the supported HDF5 datatypes for HDF-EOS5 products. ...
Definition: HDFEOS5CF.cc:138
float getPointUpper() const
Definition: HDF5CF.h:417
void read_ecs_metadata(hid_t s_file_id, string &total_strmeta_value, string &total_coremeta_value, string &total_archmeta_value, string &total_xmlmeta_value, string &total_submeta_value, string &total_prometa_value, string &total_othermeta_value, bool s_st_only)
Definition: heos5cfdap.cc:795
void Adjust_Dim_Name()
Adjust the dimension name for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3005
void Handle_Coor_Attr()
Handle the coordinates attribute for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3121