Cogs.Core
OGC3DTilesAssetsParser.cpp
1#include "OGC3DTilesAssetsParser.h"
2
3#include "Context.h"
4#include "Engine.h"
5
6#include <Foundation/Logging/Logger.h>
7
8#include <Serialization/JsonParser.h>
9
10#include <algorithm> // for copy() and assign()
11
12namespace {
13 Cogs::Logging::Log logger = Cogs::Logging::getLogger("OGC3DTilesAssetsParser");
14}
15
16using namespace Cogs::Core;
17
18// FIXME: We should rather return a BOOL for status and provide the TilesAssets object as a pre-allocated parameter.
20parseJSON(std::string_view json) {
21 Document doc = parseJson(json, JsonParseFlags::None);
23
24 if (doc.HasMember("type")) {
25 asset->type = std::string(doc["type"].GetString());
26 }
27 else {
28 LOG_ERROR(logger, "No TYPE in asset structure");
29 return asset;
30 }
31
32 if (doc.HasMember("url")) {
33 asset->url = std::string(doc["url"].GetString());
34 }
35 else if (doc.HasMember("options")) {
36 GenericObject options = doc["options"].GetObject();
37 if (options.HasMember("url")) {
38 asset->url = std::string(options["url"].GetString());
39 }
40 else {
41 LOG_ERROR(logger, "No URL:OPTIONS in asset structure");
42 return asset;
43 }
44 }
45 else {
46 LOG_ERROR(logger, "No URL in asset structure");
47 return asset;
48 }
49
50 if (doc.HasMember("accessToken")) {
51 // Using the name 'bearerToken' to avoid confusion with 'accessToken' in OGC3DTilesComponent
52 asset->bearerToken = std::string(doc["accessToken"].GetString());
53 }
54 else {
55 LOG_WARNING(logger, "Tiles assets file does not contain an 'accessToken' property.");
56 }
57
58 // Parse the "attribution" section later, if needed.
59 return asset;
60}
61
69Cogs::Core::DataFetcherManager::FetchId
70OGC3DTilesAssetsParser::fetch(Context* context, const std::string& baseURL, const std::string& accessToken, int assetId, OGC3DTilesAssetsParser::FetchCallback callback)
71{
72 if (assetId < 0) { // Is this a dataset which does not have an asset file?
73 callback(nullptr);
74 return Cogs::Core::DataFetcherManager::NoFetchId;
75 }
76
77 const std::string url = baseURL + "/v1/assets/" + std::to_string(assetId) + "/endpoint?access_token=" + accessToken;
78
79 Cogs::Core::DataFetcherManager::FetchId fetchId = DataFetcherManager::fetchAsync(context, url,
80 [context, url, callback](std::unique_ptr<Cogs::FileContents> data) {
82 if (data) {
83 // Data is available in worker thread. Create a data parsing task lambda
84 Cogs::Memory::MemoryBuffer contentsBuff = data->take();
85 std::string_view jsonStr = std::string_view(static_cast<const char*>(contentsBuff.data()), contentsBuff.size());
86 asset = parseJSON(jsonStr);
87 }
88 else {
89 LOG_ERROR(logger, "Could not fetch assets file '%s'", url.c_str());
90 }
91
92 auto finishTask = [callback, asset]() {
93 callback(asset);
94 };
95
96#if defined(EMSCRIPTEN)
97 // Cogs.js support - no threading
98 (void)context; // Silence unused capture warning.
99 finishTask();
100#else
101 context->engine->runTaskInMainThread(std::move(finishTask));
102#endif
103 });
104
105 return fetchId;
106}
107
108std::string
109OGC3DTilesAssetsParser::getAssetHostname(const OGC3DTilesAssetsParser::TilesAsset* asset)
110{
111 const size_t start = asset->url.find_first_of("://");
112 const size_t end = asset->url.find("/", start + 4);
113 if (start == std::string::npos || end == std::string::npos) {
114 return asset->url;
115 }
116 return asset->url.substr(0, end);
117}
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< class Engine > engine
Engine instance.
Definition: Context.h:222
Log implementation class.
Definition: LogManager.h:139
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180