NASA Logo
Ocean Color Science Software

ocssw V2022
productInfo.cpp
Go to the documentation of this file.
1 #include <productInfo.h>
2 
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <pugixml.hpp>
8 #include <genutils.h>
9 #include <sensorInfo.h>
10 
11 #include <string>
12 #include <map>
13 #include <fstream>
14 #include <rapidjson/document.h>
15 #include <rapidjson/istreamwrapper.h>
16 
17 #define XML_STRING_SIZE 512
18 
19 using namespace std;
20 using namespace pugi;
21 using namespace rapidjson;
22 
23 /*
24  * global variables
25  */
26 static bool productInitialized = false;
27 static char productXMLFileName[FILENAME_MAX];
28 static xml_document rootNode;
29 static xml_node productsNode;
30 static xml_node productNode;
31 static xml_node algorithmNode;
32 
33 static productInfo_t* productInfo = NULL;
34 static productInfo_t* algorithmInfo = NULL;
35 
36 static string aliasFileName = "product_alias.json";
37 
38 static map<string, ProductAlias> aliasMap;
39 static int aliasSensorId = -1;
40 
41 
42 /*
43  * dup string if src is not NULL.
44  */
45 static char* duplicateString(const char* src) {
46  if (src == NULL)
47  return NULL;
48  else
49  return strdup(src);
50 }
51 
57 extern "C" void clearProductInfo(productInfo_t* info) {
58  if (info->description)
59  free(info->description);
60  info->description = duplicateString(PRODUCT_DEFAULT_description);
61  if (info->units)
62  free(info->units);
63  info->units = duplicateString(PRODUCT_DEFAULT_units);
64  if (info->palette)
65  free(info->palette);
66  info->palette = duplicateString(PRODUCT_DEFAULT_palette);
67  if (info->paramDesignator)
68  free(info->paramDesignator);
69  info->paramDesignator = duplicateString(PRODUCT_DEFAULT_paramDesignator);
70  info->paramWaveMin = PRODUCT_DEFAULT_paramWaveMin;
71  info->paramWaveMax = PRODUCT_DEFAULT_paramWaveMax;
72  if (info->standardName)
73  free(info->standardName);
74  info->standardName = duplicateString(PRODUCT_DEFAULT_standardName);
75  if (info->category)
76  free(info->category);
77  info->category = duplicateString(PRODUCT_DEFAULT_category);
78  if (info->dataType)
79  free(info->dataType);
80  info->dataType = duplicateString(PRODUCT_DEFAULT_dataType);
81  if (info->prefix)
82  free(info->prefix);
83  info->prefix = duplicateString(PRODUCT_DEFAULT_prefix);
84  if (info->suffix)
85  free(info->suffix);
86  info->suffix = duplicateString(PRODUCT_DEFAULT_suffix);
87  if (info->algorithmName)
88  free(info->algorithmName);
89  info->algorithmName = duplicateString(PRODUCT_DEFAULT_algorithmName);
90  if (info->productName)
91  free(info->productName);
92  info->productName = duplicateString(PRODUCT_DEFAULT_productName);
93  info->cat_ix = PRODUCT_DEFAULT_cat_ix;
94  info->prod_ix = PRODUCT_DEFAULT_prod_ix;
95  info->rank = PRODUCT_DEFAULT_rank;
96  info->fillValue = PRODUCT_DEFAULT_fillValue;
97  info->validMin = PRODUCT_DEFAULT_validMin;
98  info->validMax = PRODUCT_DEFAULT_validMax;
99  if (info->displayScale)
100  free(info->displayScale);
101  info->displayScale = duplicateString(PRODUCT_DEFAULT_displayScale);
102  info->displayMin = PRODUCT_DEFAULT_displayMin;
103  info->displayMax = PRODUCT_DEFAULT_displayMax;
104  info->scaleFactor = PRODUCT_DEFAULT_scaleFactor;
105  info->addOffset = PRODUCT_DEFAULT_addOffset;
106  if (info->reference)
107  free(info->reference);
108  info->reference = duplicateString(PRODUCT_DEFAULT_reference);
109  if (info->comment)
110  free(info->comment);
111  info->comment = duplicateString(PRODUCT_DEFAULT_comment);
112  if (info->titleFormat)
113  free(info->titleFormat);
114  info->titleFormat = duplicateString(PRODUCT_DEFAULT_titleFormat);
115 }
116 
122 extern "C" void initProductInfo(productInfo_t* info) {
123  bzero(info, sizeof (productInfo_t));
124  clearProductInfo(info);
125 }
126 
133 extern "C" productInfo_t* allocateProductInfo() {
134  productInfo_t* info = (productInfo_t*) allocateMemory(sizeof (productInfo_t),
135  "productInfo");
136  clearProductInfo(info);
137  return info;
138 }
139 
145 extern "C" void freeProductInfo(productInfo_t* info) {
146  if (info->description)
147  free(info->description);
148  if (info->units)
149  free(info->units);
150  if (info->palette)
151  free(info->palette);
152  if (info->paramDesignator)
153  free(info->paramDesignator);
154  if (info->standardName)
155  free(info->standardName);
156  if (info->category)
157  free(info->category);
158  if (info->dataType)
159  free(info->dataType);
160  if (info->prefix)
161  free(info->prefix);
162  if (info->suffix)
163  free(info->suffix);
164  if (info->algorithmName)
165  free(info->algorithmName);
166  if (info->productName)
167  free(info->productName);
168  if (info->displayScale)
169  free(info->displayScale);
170  if (info->reference)
171  free(info->reference);
172  if (info->comment)
173  free(info->comment);
174  if (info->titleFormat)
175  free(info->titleFormat);
176  free(info);
177 }
178 
185 void copyProductInfoHeader(productInfo_t* dest, const productInfo_t* src) {
186  if (dest->productName)
187  free(dest->productName);
188  dest->productName = duplicateString(src->productName);
189  if (dest->paramDesignator)
190  free(dest->paramDesignator);
191  dest->paramDesignator = duplicateString(src->paramDesignator);
192  dest->paramWaveMin = src->paramWaveMin;
193  dest->paramWaveMax = src->paramWaveMax;
194 }
195 
202 extern "C" void copyProductInfo(productInfo_t* dest, const productInfo_t* src) {
203  if (dest->description && strlen(dest->description) > 0)
204  free(dest->description);
205  dest->description = duplicateString(src->description);
206  if (dest->units)
207  free(dest->units);
208  dest->units = duplicateString(src->units);
209  if (dest->palette)
210  free(dest->palette);
211  dest->palette = duplicateString(src->palette);
212  if (dest->paramDesignator)
213  free(dest->paramDesignator);
214  dest->paramDesignator = duplicateString(src->paramDesignator);
215  dest->paramWaveMin = src->paramWaveMin;
216  dest->paramWaveMax = src->paramWaveMax;
217  if (dest->standardName)
218  free(dest->standardName);
219  dest->standardName = duplicateString(src->standardName);
220  if (dest->category)
221  free(dest->category);
222  dest->category = duplicateString(src->category);
223  if (dest->dataType)
224  free(dest->dataType);
225  dest->dataType = duplicateString(src->dataType);
226  if (dest->prefix)
227  free(dest->prefix);
228  dest->prefix = duplicateString(src->prefix);
229  if (dest->suffix)
230  free(dest->suffix);
231  dest->suffix = duplicateString(src->suffix);
232  if (dest->algorithmName)
233  free(dest->algorithmName);
234  dest->algorithmName = duplicateString(src->algorithmName);
235  if (dest->productName)
236  free(dest->productName);
237  dest->productName = duplicateString(src->productName);
238  dest->cat_ix = src->cat_ix;
239  dest->prod_ix = src->prod_ix;
240  dest->rank = src->rank;
241  dest->fillValue = src->fillValue;
242  dest->validMin = src->validMin;
243  dest->validMax = src->validMax;
244  if (dest->displayScale)
245  free(dest->displayScale);
246  dest->displayScale = duplicateString(src->displayScale);
247  dest->displayMin = src->displayMin;
248  dest->displayMax = src->displayMax;
249  dest->scaleFactor = src->scaleFactor;
250  dest->addOffset = src->addOffset;
251  if (dest->reference)
252  free(dest->reference);
253  dest->reference = duplicateString(src->reference);
254  if (dest->comment)
255  free(dest->comment);
256  dest->comment = duplicateString(src->comment);
257  if (dest->titleFormat)
258  free(dest->titleFormat);
259  dest->titleFormat = duplicateString(src->titleFormat);
260 }
261 
265 void initXmlFile() {
266 
267  // bail if root node is already set
268  if (productInitialized)
269  return;
270  productInitialized = true;
271 
272  char *dataRoot;
273  if ((dataRoot = getenv("OCDATAROOT")) == NULL) {
274  printf("OCDATAROOT environment variable is not defined.\n");
275  exit(1);
276  }
277  strcpy(productXMLFileName, dataRoot);
278  strcat(productXMLFileName, "/common/product.xml");
279 
280  xml_parse_result result = rootNode.load_file(productXMLFileName);
281  if (!result) {
282  printf("%s Line %d: could not open product XML file = %s\n",
283  __FILE__, __LINE__, productXMLFileName);
284  printf(" %s", result.description());
285  exit(1);
286  }
287  productsNode = rootNode.child("products");
288  if (!productsNode) {
289  printf("%s Line %d: could not find products tag in XML file = %s\n",
290  __FILE__, __LINE__, productXMLFileName);
291  exit(1);
292  }
293 
294  productInfo = allocateProductInfo();
295  algorithmInfo = allocateProductInfo();
296 
297 }
298 
303  const char *tmpStr;
304 
305  tmpStr = productNode.name();
306  if (strcmp(tmpStr, "product") != 0) {
307  printf("%s Line %d: \"product\" node expected, found \"%s\" in file %s\n",
308  __FILE__, __LINE__, tmpStr, productXMLFileName);
309  exit(1);
310  }
311 }
312 
317  const char *tmpStr;
318 
319  tmpStr = algorithmNode.name();
320  if (strcmp(tmpStr, "algorithm") != 0) {
321  printf("%s Line %d: \"algorithm\" node expected, found \"%s\" in file %s\n",
322  __FILE__, __LINE__, tmpStr, productXMLFileName);
323  exit(1);
324  }
325 }
326 
330 void readParamDesignator(productInfo_t* info, xml_node node) {
331  char *tmpStr;
332  const char *tmpStr1;
333  xml_node tmpNode;
334 
335  tmpNode = node.child("paramDesignator");
336 
337  // reset the param designator to none if there is one
338  if (tmpNode) {
339  free(info->paramDesignator);
340  info->paramDesignator = strdup(PRODUCT_DEFAULT_paramDesignator);
341  info->paramWaveMin = PRODUCT_DEFAULT_paramWaveMin;
342  info->paramWaveMax = PRODUCT_DEFAULT_paramWaveMax;
343  }
344 
345  while (tmpNode) {
346 
347  // grab the text
348 
349  tmpStr1 = tmpNode.child_value();
350  tmpStr = trimBlanksDup(tmpStr1);
351 
352  if (strcmp(tmpStr, "none") == 0 ||
353  strcmp(tmpStr, "band") == 0 ||
354  strcmp(tmpStr, "int") == 0) {
355  free(info->paramDesignator);
356  info->paramDesignator = tmpStr;
357  info->paramWaveMin = PRODUCT_DEFAULT_paramWaveMin;
358  info->paramWaveMax = PRODUCT_DEFAULT_paramWaveMax;
359  return;
360  } else if (strcmp(tmpStr, "uv") == 0) {
361  if (strcmp(info->paramDesignator, "wave") != 0) {
362  free(info->paramDesignator);
363  info->paramDesignator = strdup("wave");
364  }
365  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
366  info->paramWaveMin > 100)
367  info->paramWaveMin = 100;
368  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
369  info->paramWaveMax < 400)
370  info->paramWaveMax = 400;
371  } else if (strcmp(tmpStr, "visible") == 0) {
372  if (strcmp(info->paramDesignator, "wave") != 0) {
373  free(info->paramDesignator);
374  info->paramDesignator = strdup("wave");
375  }
376  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
377  info->paramWaveMin > 400)
378  info->paramWaveMin = 400;
379  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
380  info->paramWaveMax < 725)
381  info->paramWaveMax = 725;
382  } else if (strcmp(tmpStr, "nir") == 0) {
383  if (strcmp(info->paramDesignator, "wave") != 0) {
384  free(info->paramDesignator);
385  info->paramDesignator = strdup("wave");
386  }
387  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
388  info->paramWaveMin > 725)
389  info->paramWaveMin = 725;
390  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
391  info->paramWaveMax < 1400)
392  info->paramWaveMax = 1400;
393  } else if (strcmp(tmpStr, "swir") == 0) {
394  if (strcmp(info->paramDesignator, "wave") != 0) {
395  free(info->paramDesignator);
396  info->paramDesignator = strdup("wave");
397  }
398  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
399  info->paramWaveMin > 1400)
400  info->paramWaveMin = 1400;
401  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
402  info->paramWaveMax < 3000)
403  info->paramWaveMax = 3000;
404  } else if (strcmp(tmpStr, "emissive") == 0) {
405  if (strcmp(info->paramDesignator, "wave") != 0) {
406  free(info->paramDesignator);
407  info->paramDesignator = strdup("wave");
408  }
409  if (info->paramWaveMin == PRODUCT_DEFAULT_paramWaveMin ||
410  info->paramWaveMin > 3000)
411  info->paramWaveMin = 3000;
412  if (info->paramWaveMax == PRODUCT_DEFAULT_paramWaveMax ||
413  info->paramWaveMax < 15000)
414  info->paramWaveMax = 15000;
415  } else {
416  printf("%s Line %d: \"paramDesignator\" node has illegal value \"%s\" in file %s\n",
417  __FILE__, __LINE__, tmpStr, productXMLFileName);
418  exit(1);
419  }
420 
421  free(tmpStr);
422 
423  // grab next node
424  tmpNode = tmpNode.next_sibling("paramDesignator");
425  }
426 }
427 
434 void readSingleRange(productInfo_t* productInfo, xml_node rangeNode) {
435  xml_node node;
436  if ((node = rangeNode.child("validMin")))
437  productInfo->validMin = atof(node.child_value());
438  if ((node = rangeNode.child("validMax")))
439  productInfo->validMax = atof(node.child_value());
440  if ((node = rangeNode.child("displayMin")))
441  productInfo->displayMin = atof(node.child_value());
442  if ((node = rangeNode.child("displayMax")))
443  productInfo->displayMax = atof(node.child_value());
444  if ((node = rangeNode.child("scaleFactor")))
445  productInfo->scaleFactor = atof(node.child_value());
446  if ((node = rangeNode.child("addOffset")))
447  productInfo->addOffset = atof(node.child_value());
448 }
449 
457 void readRange(productInfo_t* productInfo, xml_node productNode, int paramVal) {
458  int min, max;
459  xml_node rangeNode;
460  xml_attribute attr;
461 
462  // set the default
463  rangeNode = productNode.child("range");
464  do {
465 
466  // make sure min and max are not defined
467  if (rangeNode.attribute("min"))
468  continue;
469  if (rangeNode.attribute("max"))
470  continue;
471 
472  readSingleRange(productInfo, rangeNode);
473 
474  } while ((rangeNode = rangeNode.next_sibling("range")));
475 
476  // now search for the matching range
477  rangeNode = productNode.child("range");
478  do {
479  // make sure min and max are defined
480  if ((attr = rangeNode.attribute("min"))) {
481  min = attr.as_int();
482  if ((attr = rangeNode.attribute("max"))) {
483  max = attr.as_int();
484  if (min <= paramVal && paramVal <= max) {
485  readSingleRange(productInfo, rangeNode);
486  break;
487  }
488  }
489  }
490  } while ((rangeNode = rangeNode.next_sibling("range")));
491 
492 }
493 
498 
499  // clear and set productName
500  if (productInfo->productName)
501  free(productInfo->productName);
502  productInfo->productName = trimBlanksDup(productNode.attribute("name").value());
503 
504  // clear and set paramDesignator
505  if (productInfo->paramDesignator)
506  free(productInfo->paramDesignator);
507  productInfo->paramDesignator = duplicateString(PRODUCT_DEFAULT_paramDesignator);
508  readParamDesignator(productInfo, productNode);
509 }
510 
514 void readProduct(int paramVal) {
515  xml_node node;
516 
517  // clear product structure to defaults
518  clearProductInfo(productInfo);
519 
520  if (productInfo->productName)
521  free(productInfo->productName);
522  productInfo->productName = trimBlanksDup(productNode.attribute("name").value());
523 
524  if ((node = productNode.child("standardName"))) {
525  if (productInfo->standardName)
526  free(productInfo->standardName);
527  productInfo->standardName = trimBlanksDup(node.child_value());
528  }
529 
530  if ((node = productNode.child("units"))) {
531  if (productInfo->units)
532  free(productInfo->units);
533  productInfo->units = trimBlanksDup(node.child_value());
534  }
535 
536 
537  if ((node = productNode.child("palette"))) {
538  if (productInfo->palette)
539  free(productInfo->palette);
540  productInfo->palette = trimBlanksDup(node.child_value());
541  }
542 
543  node = productNode.child("category");
544  if (!node) {
545  printf("-E- Need to define \"category\" in product \"%s\" in product.xml\n",
546  productInfo->productName);
547  exit(EXIT_FAILURE);
548  }
549  if (productInfo->category)
550  free(productInfo->category);
551  productInfo->category = trimBlanksDup(node.child_value());
552 
553  if ((node = productNode.child("displayScale"))) {
554  if (productInfo->displayScale)
555  free(productInfo->displayScale);
556  productInfo->displayScale = trimBlanksDup(node.child_value());
557  }
558 
559  if ((node = productNode.child("type"))) {
560  if (productInfo->dataType)
561  free(productInfo->dataType);
562  productInfo->dataType = trimBlanksDup(node.child_value());
563  if(!strcmp(productInfo->dataType, "byte")) {
564  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
565  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_byte;
566  }
567  } else if(!strcmp(productInfo->dataType, "ubyte")) {
568  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
569  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_ubyte;
570  }
571  } else if(!strcmp(productInfo->dataType, "ushort")) {
572  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
573  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_ushort;
574  }
575  } else if(!strcmp(productInfo->dataType, "uint")) {
576  if(productInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
577  productInfo->fillValue = PRODUCT_DEFAULT_fillValue_uint;
578  }
579  }
580  }
581 
582  if ((node = productNode.child("reference"))) {
583  if (productInfo->reference)
584  free(productInfo->reference);
585  productInfo->reference = trimBlanksDup(node.child_value());
586  }
587 
588  if ((node = productNode.child("comment"))) {
589  if (productInfo->comment)
590  free(productInfo->comment);
591  productInfo->comment = trimBlanksDup(node.child_value());
592  }
593 
594  readParamDesignator(productInfo, productNode);
595  if (strcmp(productInfo->paramDesignator, "none") != 0) {
596  productInfo->prod_ix = paramVal;
597  }
598 
599  readRange(productInfo, productNode, paramVal);
600 }
601 
607 
608  xml_attribute attr;
609  xml_node node;
610 
611  // copy header info from the productInfo
612  copyProductInfoHeader(algorithmInfo, productInfo);
613 
614  // clear algorithm header
615  if (algorithmInfo->algorithmName) {
616  free(algorithmInfo->algorithmName);
617  algorithmInfo->algorithmName = NULL;
618  }
619  if (algorithmInfo->prefix) {
620  free(algorithmInfo->prefix);
621  algorithmInfo->prefix = NULL;
622  }
623  if (algorithmInfo->suffix) {
624  free(algorithmInfo->suffix);
625  algorithmInfo->suffix = NULL;
626  }
627 
628  // populate the fields
629  if ((attr = algorithmNode.attribute("name"))) {
630  algorithmInfo->algorithmName = trimBlanksDup(attr.value());
631  } else {
632  algorithmInfo->algorithmName = strdup("");
633  }
634 
635  readParamDesignator(algorithmInfo, algorithmNode);
636 
637  char defaultPrefix[XML_STRING_SIZE];
638  if (strcmp(algorithmInfo->paramDesignator, "none") == 0) {
639  strcpy(defaultPrefix, algorithmInfo->productName);
640  } else {
641  strcpy(defaultPrefix, algorithmInfo->productName);
642  strcat(defaultPrefix, "_");
643  }
644 
645  if ((node = algorithmNode.child("prefix"))) {
646  algorithmInfo->prefix = trimBlanksDup(node.child_value());
647  } else {
648  algorithmInfo->prefix = strdup(defaultPrefix);
649  }
650  if ((node = algorithmNode.child("suffix"))) {
651  algorithmInfo->suffix = trimBlanksDup(node.child_value());
652  } else {
653  if (strlen(algorithmInfo->algorithmName) > 0) {
654  algorithmInfo->suffix = (char*) malloc(strlen(algorithmInfo->algorithmName) + 2);
655  strcpy(algorithmInfo->suffix, "_");
656  strcat(algorithmInfo->suffix, algorithmInfo->algorithmName);
657  } else {
658  algorithmInfo->suffix = strdup("");
659  }
660  }
661 }
662 
666 void readAlgorithm(int paramVal) {
667  char tmpStr[XML_STRING_SIZE];
668  xml_node node;
669 
670  // start with the productInfo as default values
671  copyProductInfo(algorithmInfo, productInfo);
673 
674  algorithmInfo->cat_ix = atoi(algorithmNode.child_value("cat_ix"));
675  if ((node = algorithmNode.child("rank")))
676  algorithmInfo->rank = atoi(node.child_value());
677 
678 
679  if ((node = algorithmNode.child("units"))) {
680  if (algorithmInfo->units)
681  free(algorithmInfo->units);
682  algorithmInfo->units = trimBlanksDup(node.child_value());
683  }
684 
685  if ((node = algorithmNode.child("fillValue")))
686  algorithmInfo->fillValue = atof(node.child_value());
687 
688  node = algorithmNode.child("description");
689  if (!node) {
690  printf("-E- Need to define \"description\" in product \"%s_%s\" in product.xml\n",
691  productInfo->productName, productInfo->algorithmName);
692  exit(EXIT_FAILURE);
693 
694  }
695  strcpy(tmpStr, node.child_value());
696  trimBlanks(tmpStr);
697 
698  if (algorithmInfo->titleFormat)
699  free(algorithmInfo->titleFormat);
700  algorithmInfo->titleFormat = strdup(tmpStr);
701  if (algorithmInfo->description)
702  free(algorithmInfo->description);
703  if (strcmp(algorithmInfo->paramDesignator, "none") == 0) {
704  if ((node = algorithmNode.child("prod_ix")))
705  algorithmInfo->prod_ix = atoi(node.child_value());
706  algorithmInfo->description = trimBlanksDup(tmpStr);
707  } else {
708  algorithmInfo->description = (char*) malloc(strlen(tmpStr) + 64);
709  algorithmInfo->prod_ix = paramVal;
710  sprintf(algorithmInfo->description, tmpStr, algorithmInfo->prod_ix);
711  }
712 
713  if ((node = algorithmNode.child("reference"))) {
714  if (algorithmInfo->reference)
715  free(algorithmInfo->reference);
716  algorithmInfo->reference = trimBlanksDup(node.child_value());
717  }
718 
719  if ((node = algorithmNode.child("comment"))) {
720  if (algorithmInfo->comment)
721  free(algorithmInfo->comment);
722  algorithmInfo->comment = trimBlanksDup(node.child_value());
723  }
724 
725  if ((node = algorithmNode.child("type"))) {
726  if (algorithmInfo->dataType)
727  free(algorithmInfo->dataType);
728  algorithmInfo->dataType = trimBlanksDup(node.child_value());
729  if(!strcmp(algorithmInfo->dataType, "byte")) {
730  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
731  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_byte;
732  }
733  } else if(!strcmp(algorithmInfo->dataType, "ubyte")) {
734  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
735  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_ubyte;
736  }
737  } else if(!strcmp(algorithmInfo->dataType, "ushort")) {
738  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
739  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_ushort;
740  }
741  } else if(!strcmp(algorithmInfo->dataType, "uint")) {
742  if(algorithmInfo->fillValue == PRODUCT_DEFAULT_fillValue) {
743  algorithmInfo->fillValue = PRODUCT_DEFAULT_fillValue_uint;
744  }
745  }
746  }
747 
748  readRange(algorithmInfo, algorithmNode, paramVal);
749 }
750 
755  productNode = productsNode.child("product");
756  if (!productNode) {
757  printf("%s Line %d: could not find first product tag in XML file = %s\n",
758  __FILE__, __LINE__, productXMLFileName);
759  exit(1);
760  }
763 
764  algorithmNode = productNode.child("algorithm");
765  if (!algorithmNode) {
766  printf("%s Line %d: could not find first algorithm tag for product=%s in XML file = %s\n",
767  __FILE__, __LINE__, productInfo->productName, productXMLFileName);
768  exit(1);
769  }
772 }
773 
780  algorithmNode = algorithmNode.next_sibling("algorithm");
781  if (!algorithmNode) {
782 
783  // try next product
784  productNode = productNode.next_sibling("product");
785  if (!productNode)
786  return 0;
789 
790  algorithmNode = productNode.child("algorithm");
791  if (!algorithmNode) {
792  printf("%s Line %d: could not find first algorithm tag for product=%s in XML file = %s\n",
793  __FILE__, __LINE__, productInfo->productName, productXMLFileName);
794  exit(1);
795  }
796  }
799  return 1;
800 }
801 
810 int compareAlgorithmHeader(const char* productFullName, int sensorId, int* paramVal) {
811 
812  // see if prefix matches
813  if (strncmp(productFullName, algorithmInfo->prefix, strlen(algorithmInfo->prefix)))
814  return 0;
815 
816  char tmpStr[XML_STRING_SIZE];
817  if (strcmp(algorithmInfo->paramDesignator, "none") == 0) {
818  strcpy(tmpStr, algorithmInfo->prefix);
819  strcat(tmpStr, algorithmInfo->suffix);
820  if (strcmp(tmpStr, productFullName) == 0) {
821  *paramVal = PRODUCT_DEFAULT_prod_ix;
822  return 1;
823  } else {
824  return 0;
825  }
826  } else {
827  int nameLen = strlen(productFullName);
828  int prefixLen = strlen(algorithmInfo->prefix);
829  int suffixLen = strlen(algorithmInfo->suffix);
830  int paramLen = nameLen - prefixLen - suffixLen;
831 
832  // need at least one char to be a valid param
833  if (paramLen < 1)
834  return 0;
835 
836  // check the suffix
837  if (strcmp(algorithmInfo->suffix, productFullName + nameLen - suffixLen) != 0)
838  return 0;
839 
840  // get the param value
841  char paramStr[XML_STRING_SIZE];
842  if (paramLen > XML_STRING_SIZE - 1) // just in case
843  paramLen = XML_STRING_SIZE - 1;
844  paramStr[0] = 0;
845  strncat(paramStr, productFullName + prefixLen, paramLen);
846 
847  if (!isValidInt(paramStr))
848  return 0;
849 
850  int i = atoi(paramStr);
851  if (strcmp(algorithmInfo->paramDesignator, "wave") == 0) {
852  if (algorithmInfo->paramWaveMin <= i && i <= algorithmInfo->paramWaveMax) {
853  int32_t numBands;
854  int32_t *iwave;
855  int waveIndex;
856  int old_verbose = want_verbose;
857  want_verbose = 0;
858  numBands = rdsensorinfo(sensorId, 0, "iwave", (void**) &iwave);
859  numBands += rdsensorinfo(sensorId, 0, "NbandsIR", NULL);
860  want_verbose = old_verbose;
861  if (numBands != -1) {
862  for (waveIndex = 0; waveIndex < numBands; waveIndex++) {
863  if (i == iwave[waveIndex]) {
864  *paramVal = i;
865  return 1;
866  }
867  }
868  }
869 
870  }
871  } else {
872  *paramVal = i;
873  return 1;
874  }
875  }
876  return 0;
877 }
878 
884 extern "C" void getFirstProductInfo(productInfo_t* info) {
885  initXmlFile();
887  readProduct(-1);
888  readAlgorithm(-1);
889  copyProductInfo(info, algorithmInfo);
890 }
891 
898 extern "C" int getNextProductInfo(productInfo_t* info) {
899  if (findNextAlgorithmHeader()) {
900  readProduct(-1);
901  readAlgorithm(-1);
902  copyProductInfo(info, algorithmInfo);
903  return 1;
904  }
905  return 0;
906 }
907 
908 /* json alias file
909 {
910  "alias" : {
911  "name" : "realProduct",
912  "prefix" : "prefixReplacement",
913  "suffix" : "suffixReplacement"
914  }
915 }
916 */
917 
918 void readProductAliasFile(string fileName, map<string, ProductAlias> &aliasMap) {
919  char fileNameFixed[FILENAME_MAX];
920  parse_file_name(fileName.c_str(), fileNameFixed);
921 
922  // does the file exist
923  if (access(fileNameFixed, R_OK) != -1) {
924  ifstream ifs(fileNameFixed);
925  IStreamWrapper isw(ifs);
926  Document document;
927  document.ParseStream(isw);
928 
929  for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr) {
930  ProductAlias alias;
931  alias.name = itr->value["name"].GetString();
932  alias.prefix = itr->value["prefix"].GetString();
933  alias.suffix = itr->value["suffix"].GetString();
934 
935  aliasMap[itr->name.GetString()] = alias;
936  }
937  }
938 }
939 
940 void initProductAliasMap(int sensorId) {
941  if(sensorId != aliasSensorId) {
942  aliasSensorId = sensorId;
943  aliasMap.clear();
944 
945  // read aliases file from common
946  string fileName = (string)"$OCDATAROOT/common/" + aliasFileName;
947  readProductAliasFile(fileName, aliasMap);
948 
949  // read aliases file from sensor
950  fileName = (string)"$OCDATAROOT/" + sensorId2SensorDir(sensorId) + "/" + aliasFileName;
951  readProductAliasFile(fileName, aliasMap);
952 
953  // read aliases file from sub-sensor
954  int subsensorId = sensorId2SubsensorId(sensorId);
955  if(subsensorId != -1) {
956  fileName = (string)"$OCDATAROOT/" + sensorId2SensorDir(sensorId) + "/" + subsensorId2SubsensorDir(subsensorId) + "/" + aliasFileName;
957  readProductAliasFile(fileName, aliasMap);
958  }
959  }
960 }
961 
962 bool findProductAlias(string productName, int sensorId, ProductAlias &productAlias) {
963  initProductAliasMap(sensorId);
964 
965  // search for alias
966  try {
967  productAlias = aliasMap.at(productName);
968  return true;
969  } catch (const std::out_of_range& oor) {
970  //std::cerr << "Out of Range error: " << oor.what() << '\n';
971  }
972  return false;
973 }
974 
983 extern "C" int findProductInfo(const char* productName, int sensorId, productInfo_t* info) {
984  int paramVal;
985  const char* tmpProductName = productName;
986 
987  // search for alias
988  ProductAlias productAlias;
989  bool isAlias = findProductAlias(productName, sensorId, productAlias);
990  if(isAlias) {
991  tmpProductName = productAlias.name.c_str();
992  }
993 
994  initXmlFile();
996  do {
997  if (compareAlgorithmHeader(tmpProductName, sensorId, &paramVal)) {
998  readProduct(paramVal);
999  readAlgorithm(paramVal);
1000  copyProductInfo(info, algorithmInfo);
1001 
1002  // fix up the record for aliases
1003  if(isAlias) {
1004  free(info->prefix);
1005  info->prefix = strdup(productAlias.prefix.c_str());
1006  free(info->suffix);
1007  info->suffix = strdup(productAlias.suffix.c_str());
1008  }
1009 
1010  return 1;
1011  }
1012  } while (findNextAlgorithmHeader());
1013 
1014  return 0;
1015 }
1016 
1022 extern "C" char* getProductNameFull(productInfo_t* info) {
1023  static char name[XML_STRING_SIZE];
1024 
1025  if (strcmp(info->paramDesignator, "none") == 0) {
1026  strcpy(name, info->prefix);
1027  strcat(name, info->suffix);
1028  } else {
1029  sprintf(name, "%s%d%s", info->prefix, info->prod_ix, info->suffix);
1030  }
1031  return name;
1032 }
1033 
1040 extern "C" void printProductInfo(const char* productFullName, const productInfo_t* info) {
1041  printf("fullProductName=%s\n", productFullName);
1042  printf("description=%s\n", info->description);
1043  printf("units=%s\n", info->units);
1044  printf("palette=%s\n", info->palette);
1045  printf("paramDesignator=%s\n", info->paramDesignator);
1046  printf("paramWaveMin=%d\n", info->paramWaveMin);
1047  printf("paramWaveMax=%d\n", info->paramWaveMax);
1048  printf("standardName=%s\n", info->standardName);
1049  printf("category=%s\n", info->category);
1050  printf("dataType=%s\n", info->dataType);
1051  printf("prefix=%s\n", info->prefix);
1052  printf("suffix=%s\n", info->suffix);
1053  printf("algorithmName=%s\n", info->algorithmName);
1054  printf("productName=%s\n", info->productName);
1055  printf("cat_ix=%d\n", info->cat_ix);
1056  printf("prod_ix=%d\n", info->prod_ix);
1057  printf("rank=%d\n", info->rank);
1058  printf("fillValue=%g\n", info->fillValue);
1059  printf("validMin=%g\n", info->validMin);
1060  printf("validMax=%g\n", info->validMax);
1061  printf("displayScale=%s\n", info->displayScale);
1062  printf("displayMin=%g\n", info->displayMin);
1063  printf("displayMax=%g\n", info->displayMax);
1064  printf("scaleFactor=%g\n", info->scaleFactor);
1065  printf("addOffset=%g\n", info->addOffset);
1066  printf("reference=%s\n", info->reference);
1067  printf("comment=%s\n", info->comment);
1068  printf("titleFormat=%s\n", info->titleFormat);
1069 }
const char * sensorId2SensorDir(int sensorId)
Definition: sensorInfo.c:315
void checkAlgorithmNode()
void initProductAliasMap(int sensorId)
void freeProductInfo(productInfo_t *info)
#define PRODUCT_DEFAULT_standardName
Definition: productInfo.h:19
void readParamDesignator(productInfo_t *info, xml_node node)
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
void initProductInfo(productInfo_t *info)
void getFirstProductInfo(productInfo_t *info)
#define PRODUCT_DEFAULT_validMax
Definition: productInfo.h:35
#define PRODUCT_DEFAULT_addOffset
Definition: productInfo.h:40
#define PRODUCT_DEFAULT_paramWaveMin
Definition: productInfo.h:17
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
void printProductInfo(const char *productFullName, const productInfo_t *info)
#define NULL
Definition: decode_rs.h:63
#define PRODUCT_DEFAULT_suffix
Definition: productInfo.h:23
#define PRODUCT_DEFAULT_prod_ix
Definition: productInfo.h:27
void trimBlanks(char *str)
Definition: trimBlanks.c:10
#define PRODUCT_DEFAULT_algorithmName
Definition: productInfo.h:24
int isValidInt(const char *str)
Definition: isValidInt.c:9
#define PRODUCT_DEFAULT_category
Definition: productInfo.h:20
#define PRODUCT_DEFAULT_comment
Definition: productInfo.h:42
#define PRODUCT_DEFAULT_scaleFactor
Definition: productInfo.h:39
#define PRODUCT_DEFAULT_description
Definition: productInfo.h:13
@ string
int sensorId2SubsensorId(int sensorId)
Definition: sensorInfo.c:438
void bzero()
void clearProductInfo(productInfo_t *info)
Definition: productInfo.cpp:57
void readProductAliasFile(string fileName, map< string, ProductAlias > &aliasMap)
#define PRODUCT_DEFAULT_fillValue
Definition: productInfo.h:29
bool findProductAlias(string productName, int sensorId, ProductAlias &productAlias)
#define PRODUCT_DEFAULT_paramDesignator
Definition: productInfo.h:16
void readRange(productInfo_t *productInfo, xml_node productNode, int paramVal)
void readSingleRange(productInfo_t *productInfo, xml_node rangeNode)
#define XML_STRING_SIZE
Definition: productInfo.cpp:17
#define PRODUCT_DEFAULT_fillValue_byte
Definition: productInfo.h:30
int findNextAlgorithmHeader()
#define PRODUCT_DEFAULT_reference
Definition: productInfo.h:41
productInfo_t * allocateProductInfo()
char * strdup(const char *)
#define PRODUCT_DEFAULT_palette
Definition: productInfo.h:15
#define PRODUCT_DEFAULT_paramWaveMax
Definition: productInfo.h:18
#define PRODUCT_DEFAULT_displayMin
Definition: productInfo.h:37
#define PRODUCT_DEFAULT_units
Definition: productInfo.h:14
#define PRODUCT_DEFAULT_displayMax
Definition: productInfo.h:38
#define PRODUCT_DEFAULT_titleFormat
Definition: productInfo.h:43
void readAlgorithm(int paramVal)
#define PRODUCT_DEFAULT_prefix
Definition: productInfo.h:22
#define PRODUCT_DEFAULT_rank
Definition: productInfo.h:28
int want_verbose
#define PRODUCT_DEFAULT_dataType
Definition: productInfo.h:21
#define PRODUCT_DEFAULT_fillValue_uint
Definition: productInfo.h:33
void initXmlFile()
#define PRODUCT_DEFAULT_fillValue_ubyte
Definition: productInfo.h:31
void readAlgorithmHeader()
void readProductHeader()
void parse_file_name(const char *inpath, char *outpath)
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
char * getProductNameFull(productInfo_t *info)
void checkProductNode()
#define PRODUCT_DEFAULT_displayScale
Definition: productInfo.h:36
void copyProductInfo(productInfo_t *dest, const productInfo_t *src)
#define PRODUCT_DEFAULT_validMin
Definition: productInfo.h:34
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
char * trimBlanksDup(const char *str)
Definition: trimBlanks.c:58
const char * subsensorId2SubsensorDir(int subsensorId)
Definition: sensorInfo.c:329
void findFirstAlgorithmHeader()
void readProduct(int paramVal)
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
#define PRODUCT_DEFAULT_productName
Definition: productInfo.h:25
#define PRODUCT_DEFAULT_cat_ix
Definition: productInfo.h:26
void copyProductInfoHeader(productInfo_t *dest, const productInfo_t *src)
#define PRODUCT_DEFAULT_fillValue_ushort
Definition: productInfo.h:32
int getNextProductInfo(productInfo_t *info)
int compareAlgorithmHeader(const char *productFullName, int sensorId, int *paramVal)
l2prod max