OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
HE2CF.cc
Go to the documentation of this file.
1 // This file is part of the hdf4 data handler for the OPeNDAP data server.
3 // Copyright (c) 2010-2012 The HDF Group
4 //
5 // Author: Hyo-Kyung Lee <hyoklee@hdfgroup.org>
6 //
7 // This is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your
10 // option) any later version.
11 //
12 // This software is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with this software; if not, write to the Free Software Foundation,
19 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
23 #include "HE2CF.h"
24 #include "escaping.h"
25 #include "InternalErr.h"
26 #include "HDFCFUtil.h"
27 #include <iomanip>
28 
29 // Private member functions
30 bool
31 HE2CF::get_vgroup_field_refids(const string& _gname,
32  int32* _ref_df,
33  int32* _ref_gf)
34 {
35 
36  int32 vrefid = Vfind(file_id, (char*)_gname.c_str());
37  if (FAIL == vrefid) {
38  Vend(file_id);
39  ostringstream error;
40  error <<"cannot obtain the reference number for vgroup "<<_gname;
41  throw_error(error.str());
42  return false;
43  }
44 
45  int32 vgroup_id = Vattach(file_id, vrefid, "r");
46  if (FAIL == vgroup_id) {
47  Vend(file_id);
48  ostringstream error;
49  error <<"cannot obtain the group id for vgroup "<<_gname;
50  throw_error(error.str());
51  return false;
52  }
53 
54  int32 npairs = Vntagrefs(vgroup_id);
55  int32 ref_df = -1;
56  int32 ref_gf = -1;;
57 
58  if(npairs < 0){
59  Vdetach(vgroup_id);
60  Vend(file_id);
61  ostringstream error;
62  error << "Got " << npairs
63  << " npairs for " << _gname;
64  throw_error(error.str());
65  return false;
66  }
67 
68  for (int i = 0; i < npairs; ++i) {
69 
70  int32 tag, ref;
71 
72  if (Vgettagref(vgroup_id, i, &tag, &ref) < 0){
73 
74  // Previously just output stderr, it doesn't throw an internal error.
75  // I believe this is wrong. Use DAP's internal error to throw an error.KY 2011-4-26
76  Vdetach(vgroup_id);
77  Vend(file_id);
78  ostringstream error;
79  error << "failed to get tag / ref";
80  throw_error(error.str());
81  return false;
82  }
83 
84  if(Visvg(vgroup_id, ref)){
85  char cvgroup_name[VGNAMELENMAX*4]; // the child vgroup name
86  int32 istat;
87  int32 vgroup_cid; // Vgroup id
88 
89  vgroup_cid = Vattach(file_id, ref,"r");
90 
91  if (FAIL == vgroup_cid) {
92 
93  Vdetach(vgroup_id);
94  Vend(file_id);
95  ostringstream error;
96  error << "cannot obtain the vgroup id";
97  throw_error(error.str());
98  return false;
99 
100  }
101 
102  istat = Vgetname(vgroup_cid,cvgroup_name);
103 
104  if (FAIL == istat) {
105  Vdetach(vgroup_cid);
106  Vdetach(vgroup_id);
107  Vend(file_id);
108  ostringstream error;
109  error << "cannot obtain the vgroup id";
110  throw_error(error.str());
111  return false;
112  }
113 
114  if(strncmp(cvgroup_name, "Data Fields", 11) == 0){
115  ref_df = ref;
116  }
117 
118  if(strncmp(cvgroup_name, "Geolocation Fields", 18) == 0){
119  ref_gf = ref;
120  }
121 
122  if (FAIL == Vdetach(vgroup_cid)) {
123  Vdetach(vgroup_id);
124  Vend(file_id);
125  ostringstream error;
126  error << "cannot close the vgroup "<< cvgroup_name <<"Successfully";
127  throw_error(error.str());
128  return false;
129  }
130 
131  }
132  }
133  *_ref_df = ref_df;
134  *_ref_gf = ref_gf;
135 
136  if (FAIL == Vdetach(vgroup_id)) {
137  Vend(file_id);
138  ostringstream error;
139  error << "cannot close the vgroup "<< _gname <<"Successfully";
140  throw_error(error.str());
141  return false;
142  }
143  return true;
144 }
145 
146 bool
147 HE2CF::open_sd(const string& _filename,const int sd_id_in)
148 {
149  int32 num_datasets = -1;
150 
151  sd_id = sd_id_in;
152  if(SDfileinfo(sd_id, &num_datasets, &num_global_attributes)
153  == FAIL){
154 
155  if(file_id != -1)
156  Vend(file_id);
157 
158  ostringstream error;
159  error << "Failed to call SDfileinfo() on "
160  << _filename
161  << " file.";
162  throw_error(error.str());
163  return false;
164  }
165  return true;
166 }
167 
168 bool
169 HE2CF::open_vgroup(const string& _filename,const int file_id_in)
170 {
171 
172  file_id = file_id_in;
173  if (Vstart(file_id) < 0){
174  ostringstream error;
175  error << "Failed to call Vstart on " << _filename << endl;
176  throw_error(error.str());
177  return false;
178  }
179  return true;
180 }
181 
182 #if 0
183 // Borrowed codes from ncdas.cc in netcdf_handle4 module.
184 string
185 HE2CF::print_attr(int32 type, int loc, void *vals)
186 {
187  ostringstream rep;
188 
189  union {
190  char *cp;
191  short *sp;
192  unsigned short *usp;
193  int32 /*nclong*/ *lp;
194  unsigned int *ui;
195  float *fp;
196  double *dp;
197  } gp;
198 
199  switch (type) {
200 
201  case DFNT_UINT8:
202  case DFNT_INT8:
203  {
204  unsigned char uc;
205  gp.cp = (char *) vals;
206 
207  uc = *(gp.cp+loc);
208  rep << (int)uc;
209  return rep.str();
210  }
211 
212  case DFNT_CHAR:
213  {
214  // Using the customized escattr. Don't escape \n,\r and \t. KY 2013-10-14
215  return HDFCFUtil::escattr(static_cast<const char*>(vals));
216  }
217 
218  case DFNT_INT16:
219  {
220  gp.sp = (short *) vals;
221  rep << *(gp.sp+loc);
222  return rep.str();
223  }
224 
225  case DFNT_UINT16:
226  {
227  gp.usp = (unsigned short *) vals;
228  rep << *(gp.usp+loc);
229  return rep.str();
230  }
231 
232  case DFNT_INT32:
233  {
234  gp.lp = (int32 *) vals;
235  rep << *(gp.lp+loc);
236  return rep.str();
237  }
238 
239  case DFNT_UINT32:
240  {
241  gp.ui = (unsigned int *) vals;
242  rep << *(gp.ui+loc);
243  return rep.str();
244  }
245 
246  case DFNT_FLOAT:
247  {
248  gp.fp = (float *) vals;
249  rep << showpoint;
250  rep << setprecision(10);
251  rep << *(gp.fp+loc);
252  if (rep.str().find('.') == string::npos
253  && rep.str().find('e') == string::npos)
254  rep << ".";
255  return rep.str();
256  }
257 
258  case DFNT_DOUBLE:
259  {
260  gp.dp = (double *) vals;
261  rep << std::showpoint;
262  rep << std::setprecision(17);
263  rep << *(gp.dp+loc);
264  if (rep.str().find('.') == string::npos
265  && rep.str().find('e') == string::npos)
266  rep << ".";
267  return rep.str();
268  break;
269  }
270  default:
271  return string("UNKNOWN");
272  }
273 
274 }
275 
276 string
277 HE2CF::print_type(int32 type)
278 {
279 
280  // I expanded the list based on libdap/AttrTable.h.
281  static const char UNKNOWN[]="Unknown";
282  static const char BYTE[]="Byte";
283  static const char INT16[]="Int16";
284  static const char UINT16[]="UInt16";
285  static const char INT32[]="Int32";
286  static const char UINT32[]="UInt32";
287  static const char FLOAT32[]="Float32";
288  static const char FLOAT64[]="Float64";
289  static const char STRING[]="String";
290 
291  // I got different cases from hntdefs.h.
292  switch (type) {
293 
294  case DFNT_CHAR:
295  return STRING;
296 
297  case DFNT_UCHAR8:
298  return STRING;
299 
300  case DFNT_UINT8:
301  return BYTE;
302 
303  case DFNT_INT8:
304  return INT32;
305 
306  case DFNT_UINT16:
307  return UINT16;
308 
309  case DFNT_INT16:
310  return INT16;
311 
312  case DFNT_INT32:
313  return INT32;
314 
315  case DFNT_UINT32:
316  return UINT32;
317 
318  case DFNT_FLOAT:
319  return FLOAT32;
320 
321  case DFNT_DOUBLE:
322  return FLOAT64;
323 
324  default:
325  return UNKNOWN;
326  }
327 
328 }
329 #endif
330 
331 
332 void HE2CF::set_DAS(DAS* _das)
333 {
334  das = _das;
335 }
336 
338 
339  for(int i = 0; i < num_global_attributes; i++){
340 
341  // H4_MAX_NC_NAME is from the user guide example. It's 256.
342  char temp_name[H4_MAX_NC_NAME];
343  int32 attr_type = 0;
344  int32 attr_count = 0;
345  if(SDattrinfo(sd_id, i, temp_name, &attr_type, &attr_count) == FAIL) {
346  Vend(file_id);
347  ostringstream error;
348  error << "Fail to obtain SDS global attribute info." << endl;
349  throw_error(error.str());
350  }
351 
352  string attr_namestr(temp_name);
353 //cerr<<"namestr "<<attr_namestr <<endl;
354 
355  // Check if this attribute is an HDF-EOS2 metadata(coremeta etc. ) attribute
356  // If yes, ignore this attribute.
357  if (true == is_eosmetadata(attr_namestr))
358  continue;
359 
360  // When DisableStructMetaAttr key is true, StructMetadata.0 is not in the
361  // ECS metadata list. So this routine will pick up this attribute and generate
362  // the DAP output here. Anyhow,
363  // StructMetadata attribute should not be generated here. We will turn it off.
364  if (attr_namestr.compare(0,14, "StructMetadata" )== 0)
365  continue;
366 
367  // When DisableECSMetaDataAll key is true, All ECS attributes(Coremetadata etc.)
368  // should not be in the
369  // ECS metadata list. But this routine will pick up those attributes and generate
370  // the DAP output here. Anyhow,
371  // these attributes should not be generated here. We will turn it off.
372  if (attr_namestr.compare(0,12, "CoreMetadata" )== 0)
373  continue;
374  if (attr_namestr.compare(0,12, "coremetadata" )== 0)
375  continue;
376  if (attr_namestr.compare(0,15, "ArchiveMetadata" )== 0)
377  continue;
378  if (attr_namestr.compare(0,15, "archivemetadata" )== 0)
379  continue;
380  if (attr_namestr.compare(0,15, "Productmetadata" )== 0)
381  continue;
382  if (attr_namestr.compare(0,15, "productmetadata" )== 0)
383  continue;
384 
385 
386  // USE VECTOR
387  //char* attr_data = new char [(attr_count+1) *DFKNTsize(attr_type)];
388  vector<char>attr_data;
389  attr_data.resize((attr_count+1) *DFKNTsize(attr_type));
390 #if 0
391  if(attr_data == NULL){
392  Vend(file_id);
393  ostringstream error;
394  error << "Fail to calloc memory" << endl;
395  throw_error(error.str());
396  }
397 #endif
398 
399  //if(SDreadattr(sd_id, i, attr_data) == FAIL){
400  if(SDreadattr(sd_id, i, &attr_data[0]) == FAIL){
401  Vend(file_id);
402  //delete[] attr_data;
403  ostringstream error;
404  error << "Fail to read SDS global attributes" << endl;
405  throw_error(error.str());
406 
407  }
408 #if 0
409 if (1==attr_count && DFNT_INT32==attr_type) {
410 cerr<<"attr_name is "<< attr_namestr<<endl;
411 cerr<<"attr value is "<<*(int*)&attr_data[0] <<endl;
412 }
413 #endif
414 
415 
416  // Handle character type attribute as a string.
417  if (attr_type == DFNT_CHAR || attr_type == DFNT_UCHAR) {
418  //*(value + n_values) = '\0';
419  // value[n_values] = '\0';
420  //n_values = 1;
421  attr_data[attr_count] = '\0';
422  attr_count = 1;
423  }
424 
425 
426  AttrTable *at = das->get_table("HDF_GLOBAL");
427  if (!at)
428  at = das->add_table("HDF_GLOBAL", new AttrTable);
429 
430  attr_namestr = HDFCFUtil::get_CF_string(attr_namestr);
431 
432 #if 0
433  if(attr_type == DFNT_UCHAR || attr_type == DFNT_CHAR){
434  string tempstring2(attr_data);
435  string tempfinalstr= string(tempstring2.c_str());
436 
437  // Using the customized escattr. Don't escape \n,\r and \t. KY 2013-10-14
438  //tempfinalstr=escattr(tempfinalstr);
439  at->append_attr(attr_namestr, "String" , HDFCFUtil::escattr(tempfinalstr));
440  }
441 
442 #endif
443 
444  for (int loc=0; loc < attr_count ; loc++) {
445  string print_rep = HDFCFUtil::print_attr(attr_type, loc, (void*)&attr_data[0] );
446  at->append_attr(attr_namestr, HDFCFUtil::print_type(attr_type), print_rep);
447  }
448 
449 
450 
451 
452  //delete[] attr_data;
453  //attr_data = NULL;
454 
455  }
456 
457  return true;
458 }
459 
460 
461 
462 // Combine ECS metadata coremetadata.0,coremetadata.1 etc. into one string.
463 bool HE2CF::set_metadata(const string& metadata_basename,vector<string>& non_number_names, vector<string>& no_num_data)
464 {
465  bool suffix_is_num_or_null = true;
466  metadata.clear();
467 
468  // Metadata like coremetadata,coremetadata.0,coremetadata.1
469  list<string> one_dot_names;
470 
471  // Metadata like coremetadata, coremetadata.0, coremetadata.0.1
472  list<string> two_dots_names;
473 
474  // Metadata with the suffix as .s, .t, like productmetadta.s, productmetadata.t
475  // is non_number_names passed from the function
476 
477  int list_flag = -1;
478 
479  for(int i = 0; i < num_global_attributes; i++){
480 
481  // H4_MAX_NC_NAME is from the user guide example. It's 256.
482  char temp_name[H4_MAX_NC_NAME];
483  int32 attr_type=0;
484  int32 attr_count = 0;
485  if(SDattrinfo(sd_id, i, temp_name, &attr_type, &attr_count) == FAIL) {
486  Vend(file_id);
487  ostringstream error;
488  error << "Fail to obtain SDS global attribute info." << endl;
489  throw_error(error.str());
490  }
491 
492  string temp_name_str(temp_name);
493 
494  // Find the basename, arrange the metadata name list.
495  if(temp_name_str.find(metadata_basename)==0) {
496 //cerr<<"ECS metadata name "<<temp_name_str <<endl;
497  arrange_list(one_dot_names,two_dots_names,non_number_names,temp_name_str,list_flag);
498  }
499  }
500 
501  list<string>::const_iterator lit;
502 
503  // list_flag = 0, no suffix
504  // list_flag = 1, only .0, coremetadata.0
505  // list_flag = 2, coremetadata.0, coremetadata.1 etc
506  // list_flag = 3, coremeatadata.0, coremetadata.0.1 etc
507 //cerr<<"list_flag "<<list_flag <<endl;
508  if ( list_flag >= 0 && list_flag <=2) {
509  for (lit = one_dot_names.begin();lit!=one_dot_names.end();++lit) {
510  set_eosmetadata_namelist(*lit);
511  string cur_data;
512  obtain_SD_attr_value(*lit,cur_data);
513 //cerr<<"metadata "<<cur_data <<endl;
514  metadata.append(cur_data);
515  }
516  }
517 
518  if( 3== list_flag) {
519  for (lit = two_dots_names.begin();lit!=two_dots_names.end();++lit){
520  set_eosmetadata_namelist(*lit);
521  string cur_data;
522  obtain_SD_attr_value(*lit,cur_data);
523  metadata.append(cur_data);
524  }
525  }
526 
527  if(non_number_names.size() >0) {
528  suffix_is_num_or_null = false;
529  no_num_data.resize(non_number_names.size());
530  }
531 
532  for (unsigned int i =0; i<non_number_names.size();i++) {
533  set_eosmetadata_namelist(non_number_names[i]);
534  obtain_SD_attr_value(non_number_names[i],no_num_data[i]);
535  }
536 
537  return suffix_is_num_or_null;
538 
539 }
540 
541 // This routine will generate three ECS metadata lists. Note in theory list sl1 and sl2 should be sorted.
542 // Since the ECS metadata is always written(sorted) in increasing numeric order, we don't perform this now.
543 // Should watch if there are any outliers. KY 2012-08-31
544 void HE2CF::arrange_list(list<string> & sl1, list<string>&sl2,vector<string>&v1,string name,int& flag) {
545 
546 
547  if(name.find(".") == string::npos) {
548  sl1.push_front(name);
549  sl2.push_front(name);
550  flag = 0;
551  }
552  else if (name.find_first_of(".") == name.find_last_of(".")) {
553 
554  size_t dot_pos = name.find_first_of(".");
555 
556  if((dot_pos+1)==name.size())
557  throw InternalErr(__FILE__, __LINE__,"Should have characters or numbers after ." );
558 
559  string str_after_dot = name.substr(dot_pos+1);
560  stringstream sstr(str_after_dot);
561  int number_after_dot;
562  sstr >> number_after_dot;
563  if (!sstr)
564  v1.push_back(name);
565  else if(0 == number_after_dot) {
566  sl1.push_back(name);
567  sl2.push_back(name);
568  // For only .0 case, set flag to 1.
569  if(flag!=1)
570  flag =1;
571  }
572  else {
573  sl1.push_back(name);
574  if (3 == flag)
575  throw InternalErr(__FILE__, __LINE__,
576  "ecs metadata suffix .1 and .0.1 cannot exist at the same file" );
577  if (flag !=2)
578  flag = 2;
579  }
580  }
581 
582  else {// We don't distinguish if .0.1 and .0.0.1 will appear.
583  sl2.push_back(name);
584  if (2 == flag)
585  throw InternalErr(__FILE__, __LINE__,"ecs metadata suffix .1 and .0.1 cannot exist at the same file" );
586  if (flag !=3)
587  flag = 3;
588  }
589 
590 }
591 
592 // Obtain SD attribute value
593 void HE2CF::obtain_SD_attr_value(const string& attrname, string &cur_data) {
594 
595  int32 sds_index = SDfindattr(sd_id, attrname.c_str());
596  if(sds_index == FAIL){
597  Vend(file_id);
598  ostringstream error;
599  error << "Failed to obtain the SDS global attribute" << attrname << endl;
600  throw InternalErr(__FILE__, __LINE__,error.str());
601  }
602 
603  // H4_MAX_NC_NAME is from the user guide example. It's 256.
604  char temp_name[H4_MAX_NC_NAME];
605  int32 type = 0;
606  int32 count = 0;
607 
608  if(SDattrinfo(sd_id, sds_index, temp_name, &type, &count) == FAIL) {
609  Vend(file_id);
610  ostringstream error;
611  error << "Failed to obtain the SDS global attribute" << attrname << "information" << endl;
612  throw InternalErr(__FILE__, __LINE__,error.str());
613  }
614 
615  vector<char> attrvalue;
616  attrvalue.resize((count+1)*DFKNTsize(type));
617 
618  if(SDreadattr(sd_id, sds_index, &attrvalue[0]) == FAIL){
619  Vend(file_id);
620  ostringstream error;
621  error << "Failed to read the SDS global attribute" << attrname << endl;
622  throw InternalErr(__FILE__, __LINE__,error.str());
623 
624  }
625  // Remove the last NULL character
626  // string temp_data(attrvalue.begin(),attrvalue.end()-1);
627  // cur_data = temp_data;
628 
629  if(attrvalue[count] != '\0')
630  throw InternalErr(__FILE__,__LINE__,"the last character of the attribute buffer should be NULL");
631 
632  // No need to escape the special characters since they are ECS metadata. Will see. KY 2013-10-14
633  cur_data.resize(attrvalue.size()-1);
634  copy(attrvalue.begin(),attrvalue.end()-1,cur_data.begin());
635 }
636 
637 
638 bool HE2CF::set_vgroup_map(int32 _refid)
639 {
640  // Clear existing maps first.
641  vg_sd_map.clear();
642  vg_vd_map.clear();
643 
644 //cerr<<"before Vattach ref id "<<_refid <<endl;
645  int32 vgroup_id = Vattach(file_id, _refid, "r");
646  if (FAIL == vgroup_id) {
647  Vend(file_id);
648  ostringstream error;
649  error << "Fail to attach the vgroup " ;
650  throw_error(error.str());
651  return false;
652  }
653 
654  int32 npairs = Vntagrefs(vgroup_id);
655 
656  if (FAIL == npairs) {
657  Vdetach(vgroup_id);
658  Vend(file_id);
659  ostringstream error;
660  error << "Fail to obtain the number of objects in a group " ;
661  throw_error(error.str());
662  return false;
663  }
664 
665  for (int i = 0; i < npairs; ++i) {
666 
667  int32 tag2, ref2;
668  char buf[H4_MAX_NC_NAME];
669 
670  if (Vgettagref(vgroup_id, i, &tag2, &ref2) < 0){
671  Vdetach(vgroup_id);
672  Vend(file_id);
673  ostringstream error;
674  error << "Vgettagref failed for vgroup_id=." << vgroup_id;
675  throw_error(error.str());
676  return false;
677  }
678 
679  if(tag2 == DFTAG_NDG){
680 
681  int32 sds_index = SDreftoindex(sd_id, ref2); // index
682  if (FAIL == sds_index) {
683  Vdetach(vgroup_id);
684  Vend(file_id);
685  ostringstream error;
686  error << "Cannot obtain the SDS index ";
687  throw_error(error.str());
688  return false;
689  }
690 
691  int32 sds_id = SDselect(sd_id, sds_index); // sds_id
692  if (FAIL == sds_id) {
693 
694  Vdetach(vgroup_id);
695  Vend(file_id);
696  ostringstream error;
697  error << "Cannot obtain the SDS ID ";
698  throw_error(error.str());
699  return false;
700 
701  }
702 
703  int32 rank;
704  int32 dimsizes[H4_MAX_VAR_DIMS];
705  int32 datatype;
706  int32 num_attrs;
707 
708  if(FAIL == SDgetinfo(sds_id, buf, &rank, dimsizes, &datatype, &num_attrs)) {
709 
710  Vdetach(vgroup_id);
711  Vend(file_id);
712  ostringstream error;
713  error << "Cannot obtain the SDS info.";
714  throw_error(error.str());
715  return false;
716 
717  }
718  vg_sd_map[string(buf)] = sds_id;
719 
720  }
721 
722  if(tag2 == DFTAG_VH){
723 
724  int vid;
725  if ((vid = VSattach(file_id, ref2, "r")) < 0) {
726 
727  Vdetach(vgroup_id);
728  Vend(file_id);
729  ostringstream error;
730  error << "VSattach failed for file_id=." << file_id;
731  throw_error(error.str());
732  }
733  if (FAIL == VSgetname(vid, buf)) {
734 
735  Vdetach(vgroup_id);
736  Vend(file_id);
737  ostringstream error;
738  error << "VSgetname failed for file_id=." << file_id;
739  throw_error(error.str());
740  }
741  vg_vd_map[string(buf)] = ref2;
742  if (FAIL == VSdetach(vid)) {
743 
744  Vdetach(vgroup_id);
745  Vend(file_id);
746  ostringstream error;
747  error << "VSdetach failed for file_id=." << file_id;
748  throw_error(error.str());
749 
750  }
751  }
752  } // for
753 
754  if (FAIL == Vdetach(vgroup_id)){
755  Vend(file_id);
756  ostringstream error;
757  error << "VSdetach failed for file_id=." << file_id;
758  throw_error(error.str());
759  }
760 
761  return true;
762 }
763 
764 bool HE2CF::write_attr_long_name(const string& _long_name,
765  const string& _varname,
766  int _fieldtype)
767 {
768  AttrTable *at = das->get_table(_varname);
769  if (!at){
770  at = das->add_table(_varname, new AttrTable);
771  }
772  if(_fieldtype > 3){
773  at->append_attr("long_name", "String", _long_name + "(fake)");
774  }
775  else{
776  at->append_attr("long_name", "String", _long_name);
777  }
778  return true;
779 }
780 bool HE2CF::write_attr_long_name(const string& _group_name,
781  const string& _long_name,
782  const string& _varname,
783  int _fieldtype)
784 {
785  AttrTable *at = das->get_table(_varname);
786  if (!at){
787  at = das->add_table(_varname, new AttrTable);
788  }
789  if(_fieldtype > 3){
790  at->append_attr("long_name", "String",
791  _group_name + ":" + _long_name + "(fake)");
792  }
793  else{
794  at->append_attr("long_name", "String",
795  _group_name + ":" + _long_name);
796  }
797  return true;
798 }
799 
800 
801 bool
802 HE2CF::write_attr_sd(int32 _sds_id, const string& _newfname)
803 {
804  char buf_var[H4_MAX_NC_NAME];
805  char buf_attr[H4_MAX_NC_NAME];
806  int32 rank;
807  int32 dimsizes[H4_MAX_VAR_DIMS];
808  int32 datatype;
809  int32 num_attrs;
810  int32 n_values;
811  intn status;
812 
813  status = SDgetinfo(_sds_id, buf_var,
814  &rank, dimsizes, &datatype, &num_attrs);
815 
816  if (FAIL == status) {
817 
818  Vend(file_id);
819  SDendaccess(_sds_id);
820  ostringstream error;
821  error << "Cannot obtain the SDS info. ";
822  throw_error(error.str());
823 
824  }
825 //cerr<<"datatype "<<datatype <<endl;
826 //cerr<<"attribute name " << _newfname <<endl;
827 
828  for (int j=0; j < num_attrs; j++){
829 
830  status = SDattrinfo(_sds_id, j, buf_attr, &datatype, &n_values);
831 
832  if (status < 0){
833 
834  Vend(file_id);
835  SDendaccess(_sds_id);
836 
837  ostringstream error;
838  error << "SDattrinfo() failed on " << buf_attr;
839  throw_error(error.str());
840 
841  }
842 
843  // AttrTable *at = das->get_table(buf_var);
844  AttrTable *at = das->get_table(_newfname);
845 
846  if (!at){
847  // at = das->add_table(buf_var, new AttrTable);
848  at = das->add_table(_newfname, new AttrTable);
849  }
850 
851  // USE VECTOR
852  //char* value = new char [(n_values+1) * DFKNTsize(datatype)];
853  vector<char> value;
854  value.resize((n_values+1) * DFKNTsize(datatype));
855  //status = SDreadattr(_sds_id, j, value);
856  status = SDreadattr(_sds_id, j, &value[0]);
857 
858  if (status < 0){
859 
860  Vend(file_id);
861  SDendaccess(_sds_id);
862  ostringstream error;
863  error << "SDreadattr() failed on " << buf_attr << endl;
864  throw_error(error.str());
865  }
866 
867  // Handle character type attribute as a string.
868  if (datatype == DFNT_CHAR || datatype == DFNT_UCHAR) {
869  //*(value + n_values) = '\0';
870  value[n_values] = '\0';
871  n_values = 1;
872  }
873 
874  // Need to check and change if attribute names contain special characters. KY 2012-6-8
875 
876  string attr_cf_name = string(buf_attr,strlen(buf_attr));
877  attr_cf_name = HDFCFUtil::get_CF_string(attr_cf_name);
878  for (int loc=0; loc < n_values ; loc++) {
879  //string print_rep = HDFCFUtil::print_attr(datatype, loc, (void *)value);
880  string print_rep = HDFCFUtil::print_attr(datatype, loc, (void *)&value[0]);
881 
882  // Override any existing _FillValue attribute.
883  // if(!strncmp(buf_attr, "_FillValue", H4_MAX_NC_NAME)){
884  //at->del_attr(buf_attr);
885  if (attr_cf_name == "_FillValue") {
886  at->del_attr(attr_cf_name);
887  }
888  // Override any existing long_name attribute.
889  // if(!strncmp(buf_attr, "long_name", H4_MAX_NC_NAME)){
890  // at->del_attr(buf_attr);
891 
892  if (attr_cf_name == "long_name") {
893  at->del_attr(attr_cf_name);
894  }
895  //at->append_attr(buf_attr, print_type(datatype), print_rep);
896  // No need to escape special characters since print_rep already does that.
897  at->append_attr(attr_cf_name, HDFCFUtil::print_type(datatype), print_rep);
898 
899  }
900  status = SDendaccess(_sds_id);
901  //delete[] value;
902  }
903  return true;
904 }
905 
906 bool HE2CF::write_attr_vdata(int32 _vd_id, const string& _newfname)
907 {
908  int32 number_type, count, size;
909  char buf[H4_MAX_NC_NAME];
910 
911  int vid;
912 
913  if ((vid = VSattach(file_id, _vd_id, "r")) < 0) {
914 
915  Vend(file_id);
916 
917  ostringstream error;
918  error << "VSattach failed.";
919  throw_error(error.str());
920  }
921 
922  // Don't use VSnattrs - it returns the TOTAL number of attributes
923  // of a vdata and its fields. We should use VSfnattrs.
924  count = VSfnattrs(vid, _HDF_VDATA);
925 
926  if (FAIL == count) {
927 
928  VSdetach(vid);
929  Vend(file_id);
930  ostringstream error;
931  error << "VSfnattrs failed.";
932  throw_error(error.str());
933  }
934 
935  AttrTable *at = das->get_table(_newfname);
936  if (!at)
937  at = das->add_table(_newfname, new AttrTable);
938 
939 
940  for(int i=0; i < count; i++){
941  int32 count_v = 0;
942  if (VSattrinfo(vid, _HDF_VDATA, i, buf,
943  &number_type, &count_v, &size) < 0) {
944 
945  VSdetach(vid);
946  Vend(file_id);
947  ostringstream error;
948  error << "VSattrinfo failed.";
949  throw_error(error.str());
950  }
951 
952  // char *data = NULL;
953  vector<char> data;
954 
955  // try {
956 
957  // data = new char [(count_v+1) * DFKNTsize(number_type)];
958  data.resize((count_v+1) * DFKNTsize(number_type));
959  if (VSgetattr(vid, _HDF_VDATA, i, &data[0]) < 0) {
960 
961  // problem: clean up and throw an exception
962  //delete []data;
963  VSdetach(vid);
964  Vend(file_id);
965  ostringstream error;
966  error << "VSgetattr failed.";
967  throw_error(error.str());
968  }
969  // Handle character type attribute as a string.
970  if (number_type == DFNT_CHAR || number_type == DFNT_UCHAR8) {
971  //*(data + count_v) = '\0';
972  data[count_v] ='\0';
973  count_v = 1;
974  }
975 
976 
977  for(int j=0; j < count_v ; j++){
978 
979  //string print_rep = HDFCFUtil::print_attr(number_type, j, (void *)data);
980  string print_rep = HDFCFUtil::print_attr(number_type, j, (void *)&data[0]);
981 
982  // Override any existing _FillValue attribute.
983  if(!strncmp(buf, "_FillValue", H4_MAX_NC_NAME)){
984  at->del_attr(buf);
985  }
986  // Override any existing long_name attribute.
987  if(!strncmp(buf, "long_name", H4_MAX_NC_NAME)){
988  at->del_attr(buf);
989  }
990 
991  string vdataname(buf);
992 //cerr<<"vdata name "<<vdataname <<endl;
993 //cerr<<"vdata value "<<print_rep << endl;
994  at->append_attr(HDFCFUtil::get_CF_string(buf), HDFCFUtil::print_type(number_type), print_rep);
995 
996  }
997 
998  // if(data != NULL)
999  // delete[] data;
1000  //}
1001 
1002 #if 0
1003  catch (...) {
1004  if (data != NULL)
1005  delete[] data;
1006  throw_error("Cannot allocate enough memory for the data buffer");
1007  }
1008 #endif
1009 
1010  } // for
1011  // We need to call VFnfields to process fields as well in near future.
1012  VSdetach(vid);
1013 
1014  return true;
1015 }
1016 
1017 void
1018 HE2CF::throw_error(string _error)
1019 {
1020  throw InternalErr(__FILE__, __LINE__,
1021  _error);
1022 }
1023 
1024 
1025 // Public member functions
1027 {
1028  num_global_attributes = -1;
1029  file_id = -1;
1030  sd_id = -1;
1031  metadata = "";
1032  gname = "";
1033  das = NULL;
1034 }
1035 
1037 {
1038  // Actually this is not necessary since C++ will clean up the string.
1039  metadata.clear();
1040 }
1041 
1042 bool
1044 {
1045 
1046  // Close Vgroup interface.
1047  int istat = Vend(file_id);
1048  if(istat == FAIL){
1049  ostringstream error;
1050  error << "Failed to call Vend in HE2CF::close.";
1051  throw_error(error.str());
1052  return false;
1053  }
1054 
1055  return true;
1056 }
1057 
1058 string
1059 HE2CF::get_metadata(const string& _name, bool& suffix_is_number,vector<string>&meta_nonnum_names, vector<string>& meta_nonum_data)
1060 {
1061  suffix_is_number = set_metadata(_name,meta_nonnum_names,meta_nonum_data);
1062 //meta_nonnum_names.resize(1);
1063 //meta_nonnum_names[0] ="test metadata";
1064  return metadata;
1065 }
1066 
1067 bool
1068 HE2CF::open(const string& _filename,const int sd_id, const int file_id)
1069 {
1070  if(_filename == ""){
1071  ostringstream error;
1072  error << "=open(): filename is empty.";
1073  throw_error(error.str());
1074  return false;
1075  }
1076 
1077  if(!open_vgroup(_filename,file_id)){
1078  ostringstream error;
1079  error << "=open(): failed to open vgroup.";
1080  throw_error(error.str());
1081  return false;
1082  }
1083 
1084  if(!open_sd(_filename,sd_id)){
1085  ostringstream error;
1086  error << "=open(): failed to open sd.";
1087  throw_error(error.str());
1088  return false;
1089  }
1090 
1091  return true;
1092 }
1093 
1094 
1095 
1096 
1097 bool
1098 HE2CF::write_attribute(const string& _gname,
1099  const string& _fname,
1100  const string& _newfname,
1101  int _n_groups,
1102  int _fieldtype)
1103 {
1104 
1105  if(_n_groups > 1){
1106  write_attr_long_name(_gname, _fname, _newfname, _fieldtype);
1107  }
1108  else{
1109  write_attr_long_name(_fname, _newfname, _fieldtype);
1110  }
1111  int32 ref_df = -1; // ref id for /Data Fields/
1112  int32 ref_gf = -1; // ref id for /Geolocaion Fields/
1113 
1114  // This if block effectively constructs the vg_sd_map and vg_vd_map at most once
1115  // since starting from the second time, gname will be equal to _gname. KY 2012-7-3
1116  if(gname != _gname){
1117  // Construct field:(SD|Vdata)ref table for faster lookup.
1118  gname = _gname;
1119  get_vgroup_field_refids(_gname, &ref_df, &ref_gf);
1120 
1121  if (ref_gf !=-1)
1122  set_vgroup_map(ref_gf);
1123  if (ref_df != 1)
1124  set_vgroup_map(ref_df);
1125  }
1126 
1127  // Use a cached table.
1128  int32 id = -1;
1129 
1130  // Using SDS name to SDS id table is fine for the HDF-EOS2 case since under one grid/swath,
1131  // the data field name is unique. Generally SDS name cannot be used as a key since one may have
1132  // the same SDS name for two different SDS objects. But in this context(HDF-EOS2 objects), it is okay.
1133  // KY 2012-7-3
1134  // Retrive sds_id for SDS
1135  id = vg_sd_map[_fname];
1136  if(id > 0){
1137  write_attr_sd(id, _newfname);
1138  }
1139  // Retrieve ref_id for Vdata
1140  // The Vdata we retrieve here are HDF-EOS2 objects(Swath 1-D data)
1141  // Not all Vdata from the HDF file.
1142  id = vg_vd_map[_fname];
1143  if(id > 0){
1144  write_attr_vdata(id, _newfname);
1145  }
1146  return true;
1147 }
1148 
1149 // The application will make sure the fill value falls in the valid range of the datatype values.
1150 bool
1151 HE2CF::write_attribute_FillValue(const string& _varname,
1152  int _type,
1153  float value)
1154 {
1155  void* v_ptr = NULL;
1156 
1157  // Cast the value depending on the type.
1158  switch (_type) {
1159 
1160  case DFNT_UINT8:
1161  {
1162  uint8 val = (uint8) value;
1163  v_ptr = (void*)&val;
1164  }
1165 
1166  break;
1167  case DFNT_INT8:
1168  {
1169  int8 val = (int8) value;
1170  v_ptr = (void*)&val;
1171 
1172  }
1173  break;
1174  case DFNT_INT16:
1175  {
1176  int16 val = (int16) value;
1177  v_ptr = (void*)&val;
1178  }
1179  break;
1180 
1181  case DFNT_UINT16:
1182  {
1183  uint16 val = (uint16) value;
1184  v_ptr = (void*)&val;
1185  }
1186  break;
1187 
1188  case DFNT_INT32:
1189  {
1190  int32 val = (int32) value;
1191  v_ptr = (void*)&val;
1192 
1193  }
1194  break;
1195  case DFNT_UINT32:
1196  {
1197  uint32 val = (uint32) value;
1198  v_ptr = (void*)&val;
1199 
1200  }
1201  break;
1202  case DFNT_FLOAT:
1203  {
1204  v_ptr = (void*)&value;
1205  }
1206  break;
1207  case DFNT_DOUBLE:
1208  {
1209  float64 val = (float64) value;
1210  v_ptr = (void*)&val;
1211 
1212  }
1213  break;
1214  default:
1215  throw_error("Invalid FillValue Type - ");
1216  break;
1217  }
1218 
1219  AttrTable *at = das->get_table(_varname);
1220  if (!at){
1221  at = das->add_table(_varname, new AttrTable);
1222  }
1223  string print_rep = HDFCFUtil::print_attr(_type, 0, v_ptr);
1224  at->append_attr("_FillValue", HDFCFUtil::print_type(_type), print_rep);
1225 
1226  return true;
1227 }
1228 
1229 bool
1230 HE2CF::write_attribute_coordinates(const string& _varname, string _coordinates)
1231 {
1232 
1233  AttrTable *at = das->get_table(_varname);
1234  if (!at){
1235  at = das->add_table(_varname, new AttrTable);
1236  }
1237  at->append_attr("coordinates", "String", _coordinates);
1238 
1239  return true;
1240 }
1241 
1242 bool
1243 HE2CF::write_attribute_units(const string& _varname, string _units)
1244 {
1245 
1246  AttrTable *at = das->get_table(_varname);
1247  if (!at){
1248  at = das->add_table(_varname, new AttrTable);
1249  }
1250  at->del_attr("units"); // Override any existing units attribute.
1251  at->append_attr("units", "String", _units);
1252 
1253  return true;
1254 }
1255 
1256 
1257 
bool open(const string &filename, const int sd_id, const int file_id)
openes HDF4 file.
Definition: HE2CF.cc:1068
bool write_attribute_FillValue(const string &varname, int type, float val)
writes _FillValue attribute into varname attribute table.
Definition: HE2CF.cc:1151
bool set_non_ecsmetadata_attrs()
Definition: HE2CF.cc:337
virtual ~HE2CF()
Definition: HE2CF.cc:1036
bool write_attribute_units(const string &varname, string units)
writes units attribute into varname attribute table.
Definition: HE2CF.cc:1243
#define NULL
Definition: wcsUtil.h:65
static std::string print_type(int32)
Print datatype in string.
Definition: HDFCFUtil.cc:290
HE2CF()
Definition: HE2CF.cc:1026
static std::string escattr(std::string s)
A customized escaping function to escape special characters following OPeNDAP's escattr function that...
Definition: HDFCFUtil.cc:2502
bool close()
closes the opened file.
Definition: HE2CF.cc:1043
bool write_attribute_coordinates(const string &varname, string coord)
writes coordinates attribute into varname attribute table.
Definition: HE2CF.cc:1230
void set_DAS(DAS *das)
sets DAS pointer so that we can bulid attribute tables.
Definition: HE2CF.cc:332
static std::string print_attr(int32, int, void *)
Print attribute values in string.
Definition: HDFCFUtil.cc:184
static std::string get_CF_string(std::string s)
Change special characters to "_".
Definition: HDFCFUtil.cc:80
string get_metadata(const string &metadataname, bool &suffix_is_num, vector< string > &non_num_names, vector< string > &non_num_data)
retrieves the merged metadata.
Definition: HE2CF.cc:1059
bool write_attribute(const string &gname, const string &fname, const string &newfname, int n_groups, int fieldtype)
writes attribute table into DAS given grid/swath name and its field name.
Definition: HE2CF.cc:1098
string print_attr(hid_t type, int loc, void *sm_buf)
will get the printed representation of an attribute.
Definition: h5das.cc:288