33#include "rapidjson/writer.h"
34#include "rapidjson/prettywriter.h"
35#include "rapidjson/stringbuffer.h"
36#include "rapidjson/filereadstream.h"
43#include <libdap/util.h>
44#include <libdap/debug.h>
47#include <BESSyntaxUserError.h>
50#include <TheBESKeys.h>
55#include "rjson_utils.h"
59#define CMR_HOST_URL_KEY "CMR.host.url"
60#define DEFAULT_CMR_HOST_URL "https://cmr.earthdata.nasa.gov/"
61#define CMR_SEARCH_SERVICE "/search"
62#define prolog string("CmrApi::").append(__func__).append("() - ")
66 CmrApi::CmrApi() : d_cmr_search_endpoint_url(DEFAULT_CMR_HOST_URL){
68 string cmr_search_endpoint_url;
71 d_cmr_search_endpoint_url = cmr_search_endpoint_url;
73 string search(CMR_SEARCH_SERVICE);
74 if (d_cmr_search_endpoint_url.length() >= search.length()) {
75 if (0 != d_cmr_search_endpoint_url.compare (d_cmr_search_endpoint_url.length() - search.length(), search.length(), search)){
79 BESDEBUG(MODULE, prolog <<
"Using CMR search endpoint: " << d_cmr_search_endpoint_url << endl);
85const rapidjson::Value&
86CmrApi::get_children(
const rapidjson::Value& obj) {
89 itr = obj.FindMember(
"children");
90 bool result = itr != obj.MemberEnd();
91 string msg = prolog + (result?
"Located":
"FAILED to locate") +
" the value 'children' in the object.";
92 BESDEBUG(MODULE, msg << endl);
94 throw CmrError(msg,__FILE__,__LINE__);
97 const rapidjson::Value& children = itr->value;
98 result = children.IsArray();
99 msg = prolog +
"The value 'children' is" + (result?
"":
" NOT") +
" an array.";
100 BESDEBUG(MODULE, msg << endl);
102 throw CmrError(msg,__FILE__,__LINE__);
110const rapidjson::Value&
111CmrApi::get_feed(
const rapidjson::Document &cmr_doc){
113 bool result = cmr_doc.IsObject();
114 string msg = prolog +
"Json document is" + (result?
"":
" NOT") +
" an object.";
115 BESDEBUG(MODULE, msg << endl);
117 throw CmrError(msg,__FILE__,__LINE__);
122 result = itr != cmr_doc.MemberEnd();
123 msg = prolog + (result?
"Located":
"FAILED to locate") +
" the value 'feed'.";
124 BESDEBUG(MODULE, msg << endl);
126 throw CmrError(msg,__FILE__,__LINE__);
129 const rapidjson::Value& feed = itr->value;
130 result = feed.IsObject();
131 msg = prolog +
"The value 'feed' is" + (result?
"":
" NOT") +
" an object.";
132 BESDEBUG(MODULE, msg << endl);
134 throw CmrError(msg,__FILE__,__LINE__);
142const rapidjson::Value&
143CmrApi::get_entries(
const rapidjson::Document &cmr_doc){
147 const rapidjson::Value& feed = get_feed(cmr_doc);
150 result = itr != feed.MemberEnd();
151 msg = prolog + (result?
"Located":
"FAILED to locate") +
" the value 'entry'.";
152 BESDEBUG(MODULE, msg << endl);
154 throw CmrError(msg,__FILE__,__LINE__);
157 const rapidjson::Value& entry = itr->value;
158 result = entry.IsArray();
159 msg = prolog +
"The value 'entry' is" + (result?
"":
" NOT") +
" an Array.";
160 BESDEBUG(MODULE, msg << endl);
162 throw CmrError(msg,__FILE__,__LINE__);
170const rapidjson::Value&
171CmrApi::get_temporal_group(
const rapidjson::Document &cmr_doc){
176 const rapidjson::Value& feed = get_feed(cmr_doc);
180 result = itr != feed.MemberEnd();
181 msg = prolog + (result?
"Located":
"FAILED to locate") +
" the value 'facets'." ;
182 BESDEBUG(MODULE, msg << endl);
184 throw CmrError(msg,__FILE__,__LINE__);
187 const rapidjson::Value& facets_obj = itr->value;
188 result = facets_obj.IsObject();
189 msg = prolog +
"The value 'facets' is" + (result?
"":
" NOT") +
" an object.";
190 BESDEBUG(MODULE, msg << endl);
192 throw CmrError(msg,__FILE__,__LINE__);
195 const rapidjson::Value& facets = get_children(facets_obj);
196 for (rapidjson::SizeType i = 0; i < facets.Size(); i++) {
197 const rapidjson::Value& facet = facets[i];
199 string facet_title = ru.getStringValue(facet,
"title");
200 string temporal_title(
"Temporal");
201 if(facet_title == temporal_title){
202 msg = prolog +
"Found Temporal object.";
203 BESDEBUG(MODULE, msg << endl);
207 msg = prolog +
"The child of 'facets' with title '"+facet_title+
"' does not match 'Temporal'";
208 BESDEBUG(MODULE, msg << endl);
211 msg = prolog +
"Failed to locate the Temporal facet.";
212 BESDEBUG(MODULE, msg << endl);
213 throw CmrError(msg,__FILE__,__LINE__);
220const rapidjson::Value&
221CmrApi::get_year_group(
const rapidjson::Document &cmr_doc){
225 const rapidjson::Value& temporal_group = get_temporal_group(cmr_doc);
226 const rapidjson::Value& temporal_children = get_children(temporal_group);
227 for (rapidjson::SizeType j = 0; j < temporal_children.Size(); j++) {
228 const rapidjson::Value& temporal_child = temporal_children[j];
230 string temporal_child_title = rju.getStringValue(temporal_child,
"title");
231 string year_title(
"Year");
232 if(temporal_child_title == year_title){
233 msg = prolog +
"Found Year object.";
234 BESDEBUG(MODULE, msg << endl);
235 return temporal_child;
238 msg = prolog +
"The child of 'Temporal' with title '"+temporal_child_title+
"' does not match 'Year'";
239 BESDEBUG(MODULE, msg << endl);
242 msg = prolog +
"Failed to locate the Year group.";
243 BESDEBUG(MODULE, msg << endl);
244 throw CmrError(msg,__FILE__,__LINE__);
250const rapidjson::Value&
251CmrApi::get_month_group(
const string r_year,
const rapidjson::Document &cmr_doc){
255 const rapidjson::Value& year_group = get_year_group(cmr_doc);
256 const rapidjson::Value& years = get_children(year_group);
257 for (rapidjson::SizeType i = 0; i < years.Size(); i++) {
258 const rapidjson::Value& year_obj = years[i];
260 string year_title = rju.getStringValue(year_obj,
"title");
261 if(r_year == year_title){
262 msg = prolog +
"Found Year object.";
263 BESDEBUG(MODULE, msg << endl);
265 const rapidjson::Value& year_children = get_children(year_obj);
266 for (rapidjson::SizeType j = 0; j < year_children.Size(); j++) {
267 const rapidjson::Value& child = year_children[i];
268 string title = rju.getStringValue(child,
"title");
269 string month_title(
"Month");
270 if(title == month_title){
271 msg = prolog +
"Found Month object.";
272 BESDEBUG(MODULE, msg << endl);
276 msg = prolog +
"The child of 'Year' with title '"+title+
"' does not match 'Month'";
277 BESDEBUG(MODULE, msg << endl);
282 msg = prolog +
"The child of 'Year' group with title '"+year_title+
"' does not match the requested year ("+r_year+
")";
283 BESDEBUG(MODULE, msg << endl);
286 msg = prolog +
"Failed to locate the Year group.";
287 BESDEBUG(MODULE, msg << endl);
288 throw CmrError(msg,__FILE__,__LINE__);
291const rapidjson::Value&
292CmrApi::get_month(
const string r_month,
const string r_year,
const rapidjson::Document &cmr_doc){
296 const rapidjson::Value& month_group = get_month_group(r_year,cmr_doc);
297 const rapidjson::Value& months = get_children(month_group);
298 for (rapidjson::SizeType i = 0; i < months.Size(); i++) {
299 const rapidjson::Value& month = months[i];
300 string month_id = rju.getStringValue(month,
"title");
301 if(month_id == r_month){
303 msg << prolog <<
"Located requested month ("<<r_month <<
")";
304 BESDEBUG(MODULE, msg.str() << endl);
309 msg << prolog <<
"The month titled '"<<month_id <<
"' does not match the requested month ("<< r_month <<
")";
310 BESDEBUG(MODULE, msg.str() << endl);
314 msg << prolog <<
"Failed to locate request Year/Month.";
315 BESDEBUG(MODULE, msg.str() << endl);
316 throw CmrError(msg.str(),__FILE__,__LINE__);
319const rapidjson::Value&
320CmrApi::get_day_group(
const string r_month,
const string r_year,
const rapidjson::Document &cmr_doc){
324 const rapidjson::Value& month = get_month(r_month, r_year, cmr_doc);
325 const rapidjson::Value& month_children = get_children(month);
327 for (rapidjson::SizeType k = 0; k < month_children.Size(); k++) {
328 const rapidjson::Value&
object = month_children[k];
329 string title = rju.getStringValue(
object,
"title");
330 string day_group_title =
"Day";
331 if(title == day_group_title){
333 msg << prolog <<
"Located Day group for year: " << r_year <<
" month: "<< r_month;
334 BESDEBUG(MODULE, msg.str() << endl);
339 msg << prolog <<
"Failed to locate requested Day year: " << r_year <<
" month: "<< r_month;
340 BESDEBUG(MODULE, msg.str() << endl);
341 throw CmrError(msg.str(),__FILE__,__LINE__);
352CmrApi::get_years(
string collection_name, vector<string> &years_result){
358 "?concept_id=" + collection_name +
"&include_facets=v2";
360 rapidjson::Document doc;
363 const rapidjson::Value& year_group = get_year_group(doc);
364 const rapidjson::Value& years = get_children(year_group);
365 for (rapidjson::SizeType k = 0; k < years.Size(); k++) {
366 const rapidjson::Value& year_obj = years[k];
368 years_result.push_back(year);
382CmrApi::get_months(
string collection_name,
string r_year, vector<string> &months_result){
388 +
"?concept_id="+collection_name
389 +
"&include_facets=v2"
390 +
"&temporal_facet[0][year]="+r_year;
392 rapidjson::Document doc;
394 BESDEBUG(MODULE, prolog <<
"Got JSON Document: "<< endl << rju.
jsonDocToString(doc) << endl);
396 const rapidjson::Value& year_group = get_year_group(doc);
397 const rapidjson::Value& years = get_children(year_group);
398 if(years.Size() != 1){
400 msg << prolog <<
"We expected to get back one year (" << r_year <<
") but we got back " << years.Size();
401 BESDEBUG(MODULE, msg.str() << endl);
402 throw CmrError(msg.str(),__FILE__,__LINE__);
405 const rapidjson::Value& year = years[0];
407 if(year_title != r_year){
409 msg << prolog <<
"The returned year (" << year_title <<
") does not match the requested year ("<< r_year <<
")";
410 BESDEBUG(MODULE, msg.str() << endl);
411 throw CmrError(msg.str(),__FILE__,__LINE__);
414 const rapidjson::Value& year_children = get_children(year);
415 if(year_children.Size() != 1){
417 msg << prolog <<
"We expected to get back one child for the year (" << r_year <<
") but we got back " << years.Size();
418 BESDEBUG(MODULE, msg.str() << endl);
419 throw CmrError(msg.str(),__FILE__,__LINE__);
422 const rapidjson::Value& month_group = year_children[0];
424 if(title !=
string(
"Month")){
426 msg << prolog <<
"We expected to get back a Month object, but we did not.";
427 BESDEBUG(MODULE, msg.str() << endl);
428 throw CmrError(msg.str(),__FILE__,__LINE__);
431 const rapidjson::Value& months = get_children(month_group);
432 for (rapidjson::SizeType i = 0; i < months.Size(); i++) {
433 const rapidjson::Value& month = months[i];
435 months_result.push_back(month_id);
445CmrApi::get_days(
string collection_name,
string r_year,
string r_month, vector<string> &days_result){
450 +
"?concept_id="+collection_name
451 +
"&include_facets=v2"
452 +
"&temporal_facet[0][year]="+r_year
453 +
"&temporal_facet[0][month]="+r_month;
455 rapidjson::Document cmr_doc;
457 BESDEBUG(MODULE, prolog <<
"Got JSON Document: "<< endl << rju.
jsonDocToString(cmr_doc) << endl);
459 const rapidjson::Value& day_group = get_day_group(r_month, r_year, cmr_doc);
460 const rapidjson::Value& days = get_children(day_group);
461 for (rapidjson::SizeType i = 0; i < days.Size(); i++) {
462 const rapidjson::Value& day = days[i];
464 days_result.push_back(day_id);
474CmrApi::get_granule_ids(
string collection_name,
string r_year,
string r_month,
string r_day, vector<string> &granules_ids){
477 rapidjson::Document cmr_doc;
479 granule_search(collection_name, r_year, r_month, r_day, cmr_doc);
481 const rapidjson::Value& entries = get_entries(cmr_doc);
482 for (rapidjson::SizeType i = 0; i < entries.Size(); i++) {
483 const rapidjson::Value& granule = entries[i];
485 granules_ids.push_back(day_id);
495CmrApi::granule_count(
string collection_name,
string r_year,
string r_month,
string r_day){
497 rapidjson::Document cmr_doc;
498 granule_search(collection_name, r_year, r_month, r_day, cmr_doc);
499 const rapidjson::Value& entries = get_entries(cmr_doc);
500 return entries.Size();
508CmrApi::granule_search(
string collection_name,
string r_year,
string r_month,
string r_day, rapidjson::Document &result_doc){
512 +
"?concept_id="+collection_name
513 +
"&include_facets=v2"
517 url +=
"&temporal_facet[0][year]="+r_year;
520 url +=
"&temporal_facet[0][month]="+r_month;
523 url +=
"&temporal_facet[0][day]="+r_day;
525 BESDEBUG(MODULE, prolog <<
"CMR Granule Search Request Url: : " << url << endl);
526 rju.getJsonDoc(url,result_doc);
527 BESDEBUG(MODULE, prolog <<
"Got JSON Document: "<< endl << rju.jsonDocToString(result_doc) << endl);
536CmrApi::get_granules(
string collection_name,
string r_year,
string r_month,
string r_day, vector<Granule *> &granules){
538 rapidjson::Document cmr_doc;
540 granule_search(collection_name, r_year, r_month, r_day, cmr_doc);
542 const rapidjson::Value& entries = get_entries(cmr_doc);
543 for (rapidjson::SizeType i = 0; i < entries.Size(); i++) {
544 const rapidjson::Value& granule_obj = entries[i];
547 granules.push_back(g);
555CmrApi::get_collection_ids(std::vector<std::string> &collection_ids){
557 string key = CMR_COLLECTIONS;
561 +
"' field has not been configured.", __FILE__, __LINE__);
569cmr::Granule* CmrApi::get_granule(
string collection_name,
string r_year,
string r_month,
string r_day,
string granule_id)
571 vector<Granule *> granules;
574 get_granules(collection_name, r_year, r_month, r_day, granules);
575 for(
size_t i=0; i<granules.size() ;i++){
576 string id = granules[i]->getName();
577 BESDEBUG(MODULE, prolog <<
"Comparing granule id: " << granule_id <<
" to collection member id: " <<
id << endl);
578 if(
id == granule_id){
579 result = granules[i];
exception thrown if internal error encountered
static std::string pathConcat(const std::string &firstPart, const std::string &secondPart, char separator='/')
Concatenate path fragments making sure that they are separated by a single '/' character.
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.
(Constant) member iterator for a JSON object value
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
void get_values(const std::string &s, std::vector< std::string > &vals, bool &found)
Retrieve the values of a given key, if set.
std::string jsonDocToString(rapidjson::Document &d)
void getJsonDoc(const std::string &url, rapidjson::Document &d)
std::string getStringValue(const rapidjson::Value &object, const std::string &name)