You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.0 KiB
168 lines
5.0 KiB
#define MICHLIB_NOSOURCE |
|
#include "copcat.h" |
|
#include "GPL.h" |
|
#include "mirrorfuncs.h" |
|
|
|
const MString CopernicusCatalog::caturl = "https://stac.marine.copernicus.eu/metadata/catalog.stac.json"; |
|
|
|
CopernicusCatalog::CopernicusCatalog() |
|
{ |
|
// Cache |
|
auto oldprefix = michlib::GPL.UsePrefix("COPERNICUS"); |
|
cache.reset(CreateCache(michlib::GPL.ParameterSValue("Cache", ""))); |
|
michlib::GPL.UsePrefix(oldprefix); |
|
if(!cache) |
|
{ |
|
michlib::errmessage("Can't init cache"); |
|
cache.reset(new FakeCache); |
|
} |
|
|
|
GetCatalog(); |
|
} |
|
|
|
Error CopernicusCatalog::GetCatalog() |
|
{ |
|
if(Valid()) return Error(); |
|
auto ret = GetJSON(caturl); |
|
if(ret) |
|
catalog = ret.Value(); |
|
else |
|
return ret.Add("CopernicusCatalog::GetCatalog", "can't download catalog"); |
|
return Error(); |
|
} |
|
|
|
RetVal<std::vector<MString>> CopernicusCatalog::ProductList() const |
|
{ |
|
static const MString pref = "CopernicusCatalog::ProductList"; |
|
|
|
if(!Valid()) return {pref, "no catalog"}; |
|
|
|
const auto& links = catalog["links"]; |
|
if(links.type() != Json::arrayValue) return {pref, "no \"links\" section in the catalog"}; |
|
|
|
std::vector<MString> out; |
|
for(Json::ArrayIndex i = 0; i < links.size(); i++) |
|
{ |
|
const auto& rel = links[i]["rel"]; |
|
const auto& titl = links[i]["title"]; |
|
|
|
if(rel.type() == Json::stringValue && titl.type() == Json::stringValue && rel.asString() == "child") out.emplace_back(titl.asString().c_str()); |
|
} |
|
return out; |
|
} |
|
|
|
RetVal<MString> CopernicusCatalog::ProductURL(const MString& prod) const |
|
{ |
|
static const MString pref = "CopernicusCatalog::ProductURL"; |
|
|
|
if(!Valid()) return {pref, "no catalog"}; |
|
|
|
const auto& links = catalog["links"]; |
|
if(links.type() != Json::arrayValue) return {pref, "no \"links\" section in the catalog"}; |
|
|
|
for(Json::ArrayIndex i = 0; i < links.size(); i++) |
|
{ |
|
const auto& titl = links[i]["title"]; |
|
const auto& href = links[i]["href"]; |
|
if(titl.type() == Json::stringValue && href.type() == Json::stringValue && titl.asString().c_str() == prod) return DirName(caturl) + "/" + MString(href.asString().c_str()); |
|
} |
|
return {pref, "unknown product: " + prod}; |
|
} |
|
|
|
RetVal<std::vector<MString>> CopernicusCatalog::DatasetList(const MString& prod) const |
|
{ |
|
static const MString pref = "CopernicusCatalog::DatasetList"; |
|
|
|
MString url; |
|
{ |
|
auto ret = ProductURL(prod); |
|
if(!ret) return ret.Add(pref, "Can't get url for the product " + prod); |
|
url = ret.Value(); |
|
} |
|
|
|
auto ret = GetJSON(url); |
|
if(!ret) return ret.Add(pref, "Can't download product " + prod); |
|
|
|
const auto& links = ret.Value()["links"]; |
|
if(links.type() != Json::arrayValue) return {pref, "no \"links\" section in the product " + prod + " description"}; |
|
|
|
std::vector<MString> out; |
|
for(Json::ArrayIndex i = 0; i < links.size(); i++) |
|
{ |
|
const auto& rel = links[i]["rel"]; |
|
const auto& titl = links[i]["title"]; |
|
|
|
if(rel.type() == Json::stringValue && titl.type() == Json::stringValue && rel.asString() == "item") out.emplace_back(titl.asString().c_str()); |
|
} |
|
return out; |
|
} |
|
|
|
RetVal<MString> CopernicusCatalog::DatasetURL(const MString& prod, const MString& dataset) const |
|
{ |
|
static const MString pref = "CopernicusCatalog::DatasetURL"; |
|
|
|
MString url; |
|
{ |
|
auto ret = ProductURL(prod); |
|
if(!ret) return ret.Add(pref, "Can't get url for the product " + prod); |
|
url = ret.Value(); |
|
} |
|
|
|
auto ret = GetJSON(url); |
|
if(!ret) return ret.Add(pref, "Can't download product " + prod); |
|
|
|
const auto& links = ret.Value()["links"]; |
|
if(links.type() != Json::arrayValue) return {pref, "no \"links\" section in the product " + prod + " description"}; |
|
|
|
for(Json::ArrayIndex i = 0; i < links.size(); i++) |
|
{ |
|
const auto& titl = links[i]["title"]; |
|
const auto& href = links[i]["href"]; |
|
if(titl.type() == Json::stringValue && href.type() == Json::stringValue && titl.asString().c_str() == dataset) return DirName(url) + "/" + MString(href.asString().c_str()); |
|
} |
|
return {pref, "unknown dataset: " + dataset}; |
|
} |
|
|
|
RetVal<MString> CopernicusCatalog::AssetURL(const MString& prod, const MString& dataset, const MString& asset) const |
|
{ |
|
static const MString pref = "CopernicusCatalog::AssetURL"; |
|
|
|
MString url; |
|
{ |
|
auto ret = DatasetURL(prod, dataset); |
|
if(!ret) return ret.Add(pref, "Can't get url for the dataset " + dataset); |
|
url = ret.Value(); |
|
} |
|
|
|
auto ret = GetJSON(url); |
|
if(!ret) return ret.Add(pref, "Can't download dataset " + dataset); |
|
|
|
const auto& href = ret.Value()["assets"][asset.Buf()]["href"]; |
|
if(!href || href.type() != Json::stringValue) return {pref, "href for the asset " + asset + " not found"}; |
|
return MString(href.asString().c_str()); |
|
} |
|
|
|
RetVal<Json::Value> CopernicusCatalog::GetJSON(const MString& url) const |
|
{ |
|
const static MString pref = "CopernicusCatalog::GetJSON"; |
|
|
|
Json::Reader reader; |
|
Json::Value obj; |
|
MString content; |
|
|
|
auto [val, suc] = cache->Get(url); |
|
if(suc) |
|
content = std::move(val); |
|
else |
|
{ |
|
michlib::message(url + " not found in cache, downloading"); |
|
auto [out, res] = GetUrl(chandle, url); |
|
if(res != CURLE_OK) return Error(pref, MString("can't download JSON: ") + chandle.Err()); |
|
cache->Put(url, out, 3600); |
|
content = std::move(out); |
|
} |
|
|
|
reader.parse(content.Buf(), content.Buf() + content.Len(), obj, false); |
|
|
|
return obj; |
|
}
|
|
|