37#include "nlohmann/json.hpp"
39#include <libdap/util.h>
40#include <libdap/debug.h>
45#include "BESInternalError.h"
46#include "BESStopWatch.h"
47#include "BESNotFoundError.h"
50#include "TheBESKeys.h"
54#include "CmrInternalError.h"
55#include "CmrNotFoundError.h"
59using json = nlohmann::json;
61#define prolog string("CmrApi::").append(__func__).append("() - ")
65std::string truth(
bool t){
if(t){
return "true";}
return "false"; }
70 string cmr_endpoint_url;
73 d_cmr_endpoint_url = cmr_endpoint_url;
75 BESDEBUG(MODULE, prolog <<
"d_cmr_endpoint_url: " << d_cmr_endpoint_url << endl);
78 CMR_PROVIDERS_SEARCH_ENDPOINT);
80 prolog <<
"d_cmr_providers_search_endpoint_url: " << d_cmr_providers_search_endpoint_url << endl);
83 CMR_COLLECTIONS_SEARCH_API_ENDPOINT);
85 prolog <<
"d_cmr_collections_search_endpoint_url: " << d_cmr_collections_search_endpoint_url << endl);
88 CMR_GRANULES_SEARCH_API_ENDPOINT);
90 prolog <<
"d_cmr_granules_search_endpoint_url: " << d_cmr_granules_search_endpoint_url << endl);
93 CMR_GRANULES_SEARCH_API_UMM_ENDPOINT);
95 prolog <<
"d_cmr_granules_umm_search_endpoint_url: " << d_cmr_granules_umm_search_endpoint_url << endl);
104 return json.
qc_get_array(CMR_UMM_RELATED_URLS_KEY,json_obj);
113const nlohmann::json &CmrApi::get_children(
const nlohmann::json &jobj)
const
116 BESDEBUG(MODULE, prolog << json.probe_json(jobj) << endl);
117 bool result = jobj.is_null();
120 msg.append(
"ERROR: Json document is NULL. json: ").append(jobj.dump());
121 BESDEBUG(MODULE, prolog << msg <<
"\n");
125 result = jobj.is_object();
128 msg.append(
"ERROR: Json document is NOT an object. json: ").append(jobj.dump());
129 BESDEBUG(MODULE, prolog << msg <<
"\n");
130 throw CmrInternalError(msg, __FILE__, __LINE__);
133 const auto &has_children_j = jobj[CMR_V2_HAS_CHILDREN_KEY];
134 if(!has_children_j.get<
bool>()){
136 msg.append(
"This json object does not have a child property of type ").append(CMR_V2_HAS_CHILDREN_KEY);
137 msg.append(
". json: ").append(jobj.dump());
138 BESDEBUG(MODULE, msg <<
"\n");
142 return json.qc_get_array(CMR_V2_CHILDREN_KEY,jobj);
150const nlohmann::json &CmrApi::get_feed(
const nlohmann::json &cmr_doc)
const
153 return json.qc_get_object(CMR_V2_FEED_KEY, cmr_doc);
161const json& CmrApi::get_entries(
const json &cmr_doc)
const
165 BESDEBUG(MODULE, prolog <<
"cmr_doc" << endl << cmr_doc.dump(2) << endl);
166 const auto &feed = get_feed(cmr_doc);
167 return json.qc_get_array(CMR_V2_ENTRY_KEY,feed);
176const json& CmrApi::get_items(
const json &cmr_doc)
const
179 BESDEBUG(MODULE, prolog <<
"cmr_doc" << endl << cmr_doc.dump(2) << endl);
180 return json.qc_get_array(CMR_UMM_ITEMS_KEY,cmr_doc);
189const nlohmann::json &CmrApi::get_temporal_group(
const nlohmann::json &cmr_doc)
const
192 const auto &feed = get_feed(cmr_doc);
194 const auto &facets_obj = json.qc_get_object(CMR_V2_FACETS_KEY, feed);
196 const auto &facets_array = get_children(facets_obj);
197 for(
const auto &facet:facets_array){
198 string facet_title = facet[CMR_V2_TITLE_KEY].get<
string>();
199 if(facet_title == CMR_V2_TEMPORAL_TITLE_VALUE){
200 string msg = prolog +
"Found Temporal object.";
201 BESDEBUG(MODULE, msg << endl);
205 string msg = prolog +
"The child of 'facets' with title '"+facet_title+
"' does not match "+ CMR_V2_TEMPORAL_TITLE_VALUE;
206 BESDEBUG(MODULE, msg << endl);
211 msg <<
"Failed to locate the Temporal facet in : " << endl << cmr_doc.dump(2) << endl;
212 BESDEBUG(MODULE, prolog << msg.str() << endl);
213 throw BESNotFoundError(msg.str(), __FILE__, __LINE__);
222const nlohmann::json &CmrApi::get_year_group(
const nlohmann::json &cmr_doc)
const
225 const auto &temporal_group = get_temporal_group(cmr_doc);
226 const auto &temporal_children = get_children(temporal_group);
227 for(
const auto &temporal_child : temporal_children){
228 string temporal_child_title = temporal_child[CMR_V2_TITLE_KEY].get<
string>();
229 if ( temporal_child_title == CMR_V2_YEAR_TITLE_VALUE ){
230 string msg = prolog +
"Found Year object.";
231 BESDEBUG(MODULE, msg << endl);
232 return temporal_child;
235 string msg = prolog +
"The child of 'Temporal' with title '"+temporal_child_title+
"' does not match 'Year'";
236 BESDEBUG(MODULE, msg << endl);
239 string msg = prolog +
"Failed to locate the Year group.";
240 BESDEBUG(MODULE, msg << endl);
241 throw CmrInternalError(msg, __FILE__, __LINE__);
249const nlohmann::json &CmrApi::get_years(
const nlohmann::json &cmr_doc)
const
251 auto &year_group = get_year_group(cmr_doc);
252 if (year_group[CMR_V2_HAS_CHILDREN_KEY]) {
253 return get_children(year_group);
255 throw CmrNotFoundError(
"The Year object had no children.", __FILE__, __LINE__);
264const nlohmann::json &CmrApi::get_year(
const std::string &target_year,
const nlohmann::json &cmr_doc)
const
266 const auto &years = get_years(cmr_doc);
267 for(
auto &year:years) {
268 string year_title = year[CMR_V2_TITLE_KEY].get<
string>();
269 if (target_year == year_title) {
270 BESDEBUG(MODULE, prolog +
"Found matching Year object. target_year: " << target_year << endl);
273 BESDEBUG(MODULE, prolog +
"The current year: " << year_title <<
274 " does not match the target_year of: " << target_year << endl);
276 throw CmrNotFoundError(
"The list of years did not contain on the matched: "+target_year, __FILE__, __LINE__);
285const nlohmann::json &CmrApi::get_month_group(
const std::string &target_year,
const nlohmann::json &cmr_doc)
const
289 auto &year = get_year(target_year,cmr_doc);
290 auto &months = get_children(year);
291 for(
auto &month: months){
292 string title = month[CMR_V2_TITLE_KEY];
293 if( title == CMR_V2_MONTH_TITLE_VALUE ){
294 BESDEBUG(MODULE, prolog +
"Found Month object." << endl);
299 msg << prolog <<
"The child of '" << CMR_V2_YEAR_TITLE_VALUE <<
"' with title '"+title+
"' does not match 'Month'";
300 BESDEBUG(MODULE, msg.str() << endl);
305 auto &year_group = get_year_group(cmr_doc);
306 if(year_group[CMR_V2_HAS_CHILDREN_KEY]){
307 auto &years = get_children(year_group);
308 for(
auto &year:years){
309 string year_title = year[CMR_V2_TITLE_KEY].get<
string>();
310 if(target_year == year_title){
311 BESDEBUG(MODULE, prolog +
"Found matching Year object. target_year: " << target_year << endl);
312 auto &months = get_children(year);
313 for(
auto &month: months){
314 string title = month[CMR_V2_TITLE_KEY];
315 if( title == CMR_V2_MONTH_TITLE_VALUE ){
316 BESDEBUG(MODULE, prolog +
"Found Month object." << endl);
321 msg << prolog <<
"The child of '" << CMR_V2_YEAR_TITLE_VALUE <<
"' with title '"+title+
"' does not match 'Month'";
322 BESDEBUG(MODULE, msg.str() << endl);
330 string msg = prolog +
"Failed to locate the Month group.";
331 BESDEBUG(MODULE, msg << endl);
332 throw CmrInternalError(msg, __FILE__, __LINE__);
345const nlohmann::json &
346CmrApi::get_month(
const std::string &target_month,
347 const std::string &target_year,
348 const nlohmann::json &cmr_doc)
352 auto &month_group = get_month_group(target_year, cmr_doc);
353 auto &months = get_children(month_group);
354 for (
auto &month: months){
355 string month_id = month[CMR_V2_TITLE_KEY].get<
string>();
356 if(month_id == target_month){
358 msg << prolog <<
"Located requested month ("<< target_month <<
")";
359 BESDEBUG(MODULE, msg.str() << endl);
364 msg << prolog <<
"The month titled '"<<month_id <<
"' does not match the requested month ("<< target_month <<
")";
365 BESDEBUG(MODULE, msg.str() << endl);
369 msg << prolog <<
"Failed to locate request Year/Month.";
370 BESDEBUG(MODULE, msg.str() << endl);
371 throw CmrInternalError(msg.str(), __FILE__, __LINE__);
386const nlohmann::json &
387CmrApi::get_day_group(
const std::string &target_month,
388 const std::string &target_year,
389 const nlohmann::json &cmr_doc)
392 const auto &month = get_month( target_month, target_year,cmr_doc);
393 const auto &m_kids = get_children(month);
394 for (
const auto &m_kid : m_kids ) {
395 string title = m_kid[CMR_V2_TITLE_KEY].get<
string>();
396 if(title == CMR_V2_DAY_TITLE_VALUE){
398 msg << prolog <<
"Located Day group for year: " << target_year <<
" month: "<< target_month;
399 BESDEBUG(MODULE, msg.str() << endl);
404 msg << prolog <<
"Failed to locate requested Day, year: " << target_year <<
" month: "<< target_month;
405 BESDEBUG(MODULE, msg.str() << endl);
406 throw CmrInternalError(msg.str(), __FILE__, __LINE__);
417void CmrApi::get_years(
const string &collection_name, vector<string> &years_result)
const
420 stringstream cmr_query_url;
422 cmr_query_url << d_cmr_granules_search_endpoint_url;
423 cmr_query_url <<
"?concept_id=" + collection_name <<
"&";
424 cmr_query_url <<
"include_facets=v2&page_size="<<CMR_MAX_PAGE_SIZE;
426 BESDEBUG(MODULE, prolog <<
"CMR Query URL: "<< cmr_query_url.str() << endl);
428 const auto &cmr_doc = json.get_as_json(cmr_query_url.str());
430 const auto &year_group = get_year_group(cmr_doc);
431 if(year_group[CMR_V2_HAS_CHILDREN_KEY].get<bool>()) {
432 for (
const auto &year_obj: year_group[CMR_V2_CHILDREN_KEY]) {
433 years_result.emplace_back(year_obj[CMR_V2_TITLE_KEY].get<string>());
450 const string &r_year,
456 cmr_query_url << d_cmr_granules_search_endpoint_url <<
"?" ;
457 cmr_query_url <<
"concept_id=" << collection_name <<
"&";
458 cmr_query_url <<
"include_facets=v2&";
459 cmr_query_url <<
http::url_encode(
"temporal_facet[0][year]") <<
"=" << r_year;
460 BESDEBUG(MODULE, prolog <<
"CMR Query URL: "<< cmr_query_url.str() << endl);
462 const auto &cmr_doc = json.get_as_json(cmr_query_url.str());
463 BESDEBUG(MODULE, prolog <<
"Got JSON Document: "<< endl << cmr_doc.dump(2) << endl);
465 const auto &year_group = get_year_group(cmr_doc);
466 const auto &years = get_children(year_group);
467 if(years.size() != 1){
469 msg << prolog <<
"We expected to get back one year (" << r_year <<
") but we got back " << years.size();
470 BESDEBUG(MODULE, msg.str() << endl);
474 const auto &year = years[0];
476 string year_title = year[CMR_V2_TITLE_KEY].get<
string>();
477 if(year_title != r_year){
479 msg << prolog <<
"The returned year (" << year_title <<
") does not match the requested year ("<< r_year <<
")";
480 BESDEBUG(MODULE, msg.str() << endl);
484 const auto &year_children = get_children(year);
485 if(year_children.size() != 1){
487 msg << prolog <<
"We expected to get back one child for the year (" << r_year <<
") but we got back " << years.size();
488 BESDEBUG(MODULE, msg.str() << endl);
492 const auto &month_group = year_children[0];
493 string month_title = month_group[CMR_V2_TITLE_KEY].get<
string>();
494 if(month_title != CMR_V2_MONTH_TITLE_VALUE){
496 msg << prolog <<
"We expected to get back a Month object, but we did not.";
497 BESDEBUG(MODULE, msg.str() << endl);
501 const auto &months = get_children(month_group);
502 for (
const auto &month: months) {
503 months_result.push_back(month[CMR_V2_TITLE_KEY].get<string>());
519 const string& r_year,
520 const string &r_month,
524 cmr_query_url << d_cmr_granules_search_endpoint_url <<
"?";
527 cmr_query_string <<
"concept_id=" << collection_concept_id <<
"&";
528 cmr_query_string <<
"include_facets=v2" <<
"&";
529 cmr_query_string <<
http::url_encode(
"temporal_facet[0][year]") <<
"=" << r_year <<
"&";
530 cmr_query_string <<
http::url_encode(
"temporal_facet[0][month]") <<
"=" << r_month;
531 cmr_query_url << cmr_query_string.str();
532 BESDEBUG(MODULE, prolog <<
"CMR Query URL: " << cmr_query_url.str() << endl);
535 const auto &cmr_doc = json.
get_as_json(cmr_query_url.str());
537 const auto &day_group = get_day_group(r_month, r_year, cmr_doc);
538 const auto &days = get_children(day_group);
539 for (
const auto &day : days ){
540 string day_title = json.get_str_if_present(CMR_V2_TITLE_KEY,day);
541 if(day_title.empty())
542 day_title =
"MISSING DAY TITLE";
544 days_result.push_back(day_title);
562 const std::string& r_year,
563 const std::string &r_month,
564 const std::string &r_day,
565 std::vector<std::string> &granule_ids)
const
569 granule_search(collection_name, r_year, r_month, r_day, cmr_doc);
571 const auto &granules = get_entries(cmr_doc);
572 for(
const auto &granule : granules){
573 string day_id = granule[CMR_GRANULE_ID_KEY].get<
string>();
574 granule_ids.push_back(day_id);
590 const string &r_year,
591 const string &r_month,
592 const string &r_day)
const
596 granule_search(collection_name, r_year, r_month, r_day, cmr_doc);
597 const auto &entries = get_entries(cmr_doc);
598 return entries.size();
608void CmrApi::granule_search(
const std::string &collection_name,
609 const std::string &r_year,
610 const std::string &r_month,
611 const std::string &r_day,
612 nlohmann::json &cmr_doc)
const
618 cmr_query_url << d_cmr_granules_search_endpoint_url <<
"?";
619 cmr_query_url <<
"concept_id=" << collection_name <<
"&";
620 cmr_query_url <<
"include_facets=v2&";
621 cmr_query_url <<
"page_size=" << CMR_MAX_PAGE_SIZE <<
"&";
623 if(!r_year.empty()) {
624 cmr_query_url <<
http::url_encode(
"temporal_facet[0][year]") <<
"=" << r_year<<
"&";
626 if(!r_month.empty()) {
627 cmr_query_url <<
http::url_encode(
"temporal_facet[0][month]") <<
"=" << r_month<<
"&";
630 cmr_query_url <<
http::url_encode(
"temporal_facet[0][day]") <<
"=" << r_day;
633 BESDEBUG(MODULE, prolog <<
"CMR Granule Search Request Url: " << cmr_query_url.str() << endl);
635 cmr_doc = json.get_as_json(cmr_query_url.str());
636 BESDEBUG(MODULE, prolog <<
"Got JSON Document: "<< endl << cmr_doc.dump(4) << endl);
645void CmrApi::granule_umm_search(
const std::string &collection_name,
646 const std::string &r_year,
647 const std::string &r_month,
648 const std::string &r_day,
649 nlohmann::json &cmr_doc)
654 stringstream cmr_query_url;
655 cmr_query_url << d_cmr_granules_umm_search_endpoint_url <<
"?";
656 cmr_query_url <<
"concept_id=" << collection_name <<
"&";
657 cmr_query_url <<
"page_size=" << CMR_MAX_PAGE_SIZE <<
"&";
659 if(!r_year.empty()) {
660 cmr_query_url <<
http::url_encode(
"temporal_facet[0][year]") <<
"=" << r_year<<
"&";
662 if(!r_month.empty()) {
663 cmr_query_url <<
http::url_encode(
"temporal_facet[0][month]") <<
"=" << r_month<<
"&";
666 cmr_query_url <<
http::url_encode(
"temporal_facet[0][day]") <<
"=" << r_day;
669 BESDEBUG(MODULE, prolog <<
"CMR Granule Search Request Url: " << cmr_query_url.str() << endl);
671 cmr_doc = json.get_as_json(cmr_query_url.str());
672 BESDEBUG(MODULE, prolog <<
"Got JSON Document: "<< endl << cmr_doc.dump(4) << endl);
681 const std::string &r_year,
682 const std::string &r_month,
683 const std::string &r_day,
689 granule_search(collection_name, r_year, r_month, r_day, cmr_doc);
691 const auto& granules = get_entries(cmr_doc);
692 for (
auto &granule : granules){
694 granule_objs.emplace_back(std::move(g));
703 const std::string &r_year,
704 const std::string &r_month,
705 const std::string &r_day,
711 granule_umm_search(collection_name, r_year, r_month, r_day, cmr_doc);
712 const auto& granules = get_items(cmr_doc);
713 for (
auto &granule : granules){
715 granule_objs.emplace_back(std::move(g));
723void CmrApi::get_collection_ids(std::vector<std::string> &collection_ids)
const
729 +
"' field has not been configured.", __FILE__, __LINE__);
746 const string& r_year,
747 const string& r_month,
749 const string& r_granule_ur)
753 std::vector<unique_ptr<cmr::Granule>> granules;
756 get_granules(collection_name, r_year, r_month, r_day, granules);
757 for(
auto & granule : granules){
758 string id = granule->getName();
759 BESDEBUG(MODULE, prolog <<
"Comparing granule_ur: '" << r_granule_ur <<
"' to collection member id: " <<
id << endl);
760 if(
id == r_granule_ur){
761 result = std::move(granule);
780 BES_STOPWATCH_START(MODULE, prolog +
"Timing");
782 const auto &cmr_doc = json.get_as_json(d_cmr_providers_search_endpoint_url);
783 unsigned int hits = cmr_doc[
"hits"];
784 BESDEBUG(MODULE, prolog <<
"hits: " << hits << endl);
788 for (
const auto &provider_json : cmr_doc[
"items"]) {
789 if(provider_json.type() != nlohmann::detail::value_t::null) {
790 auto prvdr = std::make_unique<Provider>(provider_json);
792 providers.emplace_back(std::move(prvdr));
806 BES_STOPWATCH_START(MODULE, prolog +
"Timing");
808 for(
auto &provider: all_providers){
809 BESDEBUG(MODULE, prolog <<
"Processing PROVIDER: " << provider->id() << endl);
812 provider->set_opendap_collection_count(hits);
813 opendap_providers.emplace(provider->id(), std::move(provider));
829 cmr_query_url << d_cmr_collections_search_endpoint_url;
830 cmr_query_url <<
"?has_opendap_url=true&page_size=0";
831 cmr_query_url <<
"&provider=" << provider_id;
832 BESDEBUG(MODULE, prolog <<
"cmr_query_url: " << cmr_query_url.str() << endl);
833 const auto &cmr_doc = json.get_as_json(cmr_query_url.str());
835 unsigned long int hits = json.qc_integer(CMR_HITS_KEY,cmr_doc);
836 BESDEBUG(MODULE, prolog << CMR_HITS_KEY <<
": " << hits << endl);
842void CmrApi::get_collections_worker(
const std::string &provider_id,
843 std::map<std::string, std::unique_ptr<cmr::Collection>> &collections,
844 unsigned int page_size,
847 unsigned int page_num=1;
849 string cmr_query_url_base;
850 cmr_query_url_base = d_cmr_collections_search_endpoint_url +
"?";
851 cmr_query_url_base +=
"provider=" + provider_id +
"&";
853 cmr_query_url_base +=
"has_opendap_url=true&";
855 cmr_query_url_base +=
"page_size=" + to_string(page_size) +
"&";
856 BESDEBUG(MODULE, prolog <<
"cmr_query_url_base: " << cmr_query_url_base << endl);
858 string cmr_query_url = cmr_query_url_base +
"page_num=" + to_string(page_num);
859 BESDEBUG(MODULE, prolog <<
"cmr_query_url: " << cmr_query_url << endl);
861 const auto &cmr_doc = json.get_as_json(cmr_query_url);
863 unsigned int hits = cmr_doc[
"hits"];
864 BESDEBUG(MODULE, prolog <<
"hits: " << hits << endl);
868 for (
const auto &collection_json : cmr_doc[
"items"]) {
869 auto collection = unique_ptr<Collection>(
new Collection(collection_json));
870 collections.emplace(collection->id(), std::move(collection));
872 BESDEBUG(MODULE, prolog <<
"collections.size(): " << collections.size() << endl);
874 while (collections.size() < hits){
876 cmr_query_url = cmr_query_url_base +
"page_num=" + to_string(page_num);
877 BESDEBUG(MODULE, prolog <<
"cmr_query_url: " << cmr_query_url << endl);
878 const auto &cmr_collection_doc = json.get_as_json(cmr_query_url);
880 for (
const auto &collection_json : cmr_collection_doc[
"items"]) {
881 auto collection = unique_ptr<Collection>(
new Collection(collection_json));
882 collections.emplace(collection->id(), std::move(collection));
884 BESDEBUG(MODULE, prolog <<
"collections.size(): " << collections.size() << endl);
891void CmrApi::get_opendap_collections(
const std::string &provider_id,
892 std::map<std::string,std::unique_ptr<cmr::Collection>> &collections)
const{
893 get_collections_worker(provider_id,collections, CMR_MAX_PAGE_SIZE,
true);
895void CmrApi::get_collections(
const std::string &provider_id,
896 std::map<std::string,std::unique_ptr<cmr::Collection>> &collections)
const{
897 get_collections_worker(provider_id,collections, CMR_MAX_PAGE_SIZE,
false);
exception thrown if internal error encountered
static std::string assemblePath(const std::string &firstPart, const std::string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Access to the singleton.
void get_values(const std::string &s, std::vector< std::string > &vals, bool &found)
Retrieve the values of a given key, if set.
unsigned long granule_count(const std::string &collection_name, const std::string &r_year, const std::string &r_month, const std::string &r_day) const
void get_granules_umm(const std::string &collection_name, const std::string &r_year, const std::string &r_month, const std::string &r_day, std::vector< std::unique_ptr< cmr::GranuleUMM > > &granule_objs) const
const nlohmann::json & get_related_urls_array(const nlohmann::json &go) const
unsigned long int get_opendap_collections_count(const std::string &provider_id) const
void get_providers(std::vector< std::unique_ptr< cmr::Provider > > &providers) const
void get_opendap_providers(std::map< std::string, std::unique_ptr< cmr::Provider > > &providers) const
void get_granules(const std::string &collection_name, const std::string &r_year, const std::string &r_month, const std::string &r_day, std::vector< std::unique_ptr< cmr::Granule > > &granule_objs) const
void get_days(const std::string &collection_name, const std::string &r_year, const std::string &r_month, std::vector< std::string > &days_result) const
void get_granule_ids(const std::string &collection_name, const std::string &r_year, const std::string &r_month, const std::string &r_day, std::vector< std::string > &granule_ids) const
void get_months(const std::string &collection_name, const std::string &year, std::vector< std::string > &months_result) const
nlohmann::json get_as_json(const std::string &url) const
const nlohmann::json & qc_get_array(const std::string &key, const nlohmann::json &json_obj) const
string url_encode(const string &s)