Line data Source code
1 : /*******************************************************************************
2 : * Project: NextGIS Web Driver
3 : * Purpose: Implements NextGIS Web Driver
4 : * Author: Dmitry Baryshnikov, dmitry.baryshnikov@nextgis.com
5 : * Language: C++
6 : *******************************************************************************
7 : * The MIT License (MIT)
8 : *
9 : * Copyright (c) 2018-2025, NextGIS
10 : *
11 : * SPDX-License-Identifier: MIT
12 : *******************************************************************************/
13 : #ifndef OGR_NGW_H_INCLUDED
14 : #define OGR_NGW_H_INCLUDED
15 :
16 : // gdal headers
17 : #include "ogrsf_frmts.h"
18 : #include "ogr_swq.h"
19 :
20 : #include <array>
21 : #include <map>
22 : #include <set>
23 :
24 : namespace NGWAPI
25 : {
26 : std::string GetPermissionsURL(const std::string &osUrl,
27 : const std::string &osResourceId);
28 : std::string GetResourceURL(const std::string &osUrl,
29 : const std::string &osResourceId);
30 : std::string GetChildrenURL(const std::string &osUrl,
31 : const std::string &osResourceId);
32 : std::string GetFeatureURL(const std::string &osUrl,
33 : const std::string &osResourceId);
34 : std::string GetTMSURL(const std::string &osUrl,
35 : const std::string &osResourceId);
36 : std::string GetFeaturePageURL(const std::string &osUrl,
37 : const std::string &osResourceId, GIntBig nStart,
38 : int nCount = 0, const std::string &osFields = "",
39 : const std::string &osWhere = "",
40 : const std::string &osSpatialWhere = "",
41 : const std::string &osExtensions = "",
42 : bool IsGeometryIgnored = false);
43 : std::string GetRouteURL(const std::string &osUrl);
44 : std::string GetUploadURL(const std::string &osUrl);
45 : std::string GetVersionURL(const std::string &osUrl);
46 : std::string GetCOGURL(const std::string &osUrl,
47 : const std::string &osResourceId);
48 : std::string GetSearchURL(const std::string &osUrl, const std::string &osKey,
49 : const std::string &osValue);
50 :
51 : bool CheckVersion(const std::string &osVersion, int nMajor, int nMinor = 0,
52 : int nPatch = 0);
53 : bool CheckRequestResult(bool bResult, const CPLJSONObject &oRoot,
54 : const std::string &osErrorMessage);
55 : bool CheckSupportedType(bool bIsRaster, const std::string &osType);
56 :
57 : struct Uri
58 : {
59 : std::string osPrefix;
60 : std::string osAddress;
61 : std::string osResourceId;
62 : std::string osNewResourceName;
63 : };
64 :
65 : // C++11 allow defaults
66 : struct Permissions
67 : {
68 : bool bResourceCanRead = false;
69 : bool bResourceCanCreate = false;
70 : bool bResourceCanUpdate = false;
71 : bool bResourceCanDelete = false;
72 : bool bDatastructCanRead = false;
73 : bool bDatastructCanWrite = false;
74 : bool bDataCanRead = false;
75 : bool bDataCanWrite = false;
76 : bool bMetadataCanRead = false;
77 : bool bMetadataCanWrite = false;
78 : };
79 :
80 : Uri ParseUri(const std::string &osUrl);
81 : Permissions CheckPermissions(const std::string &osUrl,
82 : const std::string &osResourceId,
83 : const CPLStringList &aosHTTPOptions,
84 : bool bReadWrite);
85 : bool DeleteResource(const std::string &osUrl, const std::string &osResourceId,
86 : const CPLStringList &aosHTTPOptions);
87 : bool RenameResource(const std::string &osUrl, const std::string &osResourceId,
88 : const std::string &osNewName,
89 : const CPLStringList &aosHTTPOptions);
90 : OGRwkbGeometryType NGWGeomTypeToOGRGeomType(const std::string &osGeomType);
91 : std::string OGRGeomTypeToNGWGeomType(OGRwkbGeometryType eType);
92 : OGRFieldType NGWFieldTypeToOGRFieldType(const std::string &osFieldType);
93 : std::string OGRFieldTypeToNGWFieldType(OGRFieldType eType);
94 : std::string GetFeatureCount(const std::string &osUrl,
95 : const std::string &osResourceId);
96 : std::string GetLayerExtent(const std::string &osUrl,
97 : const std::string &osResourceId);
98 : bool FlushMetadata(const std::string &osUrl, const std::string &osResourceId,
99 : char **papszMetadata, const CPLStringList &aosHTTPOptions);
100 : std::string CreateResource(const std::string &osUrl,
101 : const std::string &osPayload,
102 : const CPLStringList &aosHTTPOptions);
103 : bool UpdateResource(const std::string &osUrl, const std::string &osResourceId,
104 : const std::string &osPayload,
105 : const CPLStringList &aosHTTPOptions);
106 : void FillResmeta(const CPLJSONObject &oRoot, char **papszMetadata);
107 : std::string GetResmetaSuffix(CPLJSONObject::Type eType);
108 : bool DeleteFeature(const std::string &osUrl, const std::string &osResourceId,
109 : const std::string &osFeatureId,
110 : const CPLStringList &aosHTTPOptions);
111 : bool DeleteFeatures(const std::string &osUrl, const std::string &osResourceId,
112 : const std::string &osFeaturesIDJson,
113 : const CPLStringList &aosHTTPOptions);
114 : GIntBig CreateFeature(const std::string &osUrl, const std::string &osResourceId,
115 : const std::string &osFeatureJson,
116 : const CPLStringList &aosHTTPOptions);
117 : bool UpdateFeature(const std::string &osUrl, const std::string &osResourceId,
118 : const std::string &osFeatureId,
119 : const std::string &osFeatureJson,
120 : const CPLStringList &aosHTTPOptions);
121 : std::vector<GIntBig> PatchFeatures(const std::string &osUrl,
122 : const std::string &osResourceId,
123 : const std::string &osFeaturesJson,
124 : const CPLStringList &aosHTTPOptions);
125 : bool GetExtent(const std::string &osUrl, const std::string &osResourceId,
126 : const CPLStringList &aosHTTPOptions, int nEPSG,
127 : OGREnvelope &stExtent);
128 : CPLJSONObject UploadFile(const std::string &osUrl,
129 : const std::string &osFilePath,
130 : const CPLStringList &aosHTTPOptions,
131 : GDALProgressFunc pfnProgress, void *pProgressData);
132 : } // namespace NGWAPI
133 :
134 0 : class OGRNGWCodedFieldDomain
135 : {
136 : public:
137 0 : explicit OGRNGWCodedFieldDomain() = default;
138 : explicit OGRNGWCodedFieldDomain(const CPLJSONObject &oResourceJsonObject);
139 0 : OGRNGWCodedFieldDomain(const OGRNGWCodedFieldDomain &) = default;
140 : OGRNGWCodedFieldDomain &operator=(const OGRNGWCodedFieldDomain &) = default;
141 : OGRNGWCodedFieldDomain(OGRNGWCodedFieldDomain &&) = default;
142 : OGRNGWCodedFieldDomain &operator=(OGRNGWCodedFieldDomain &&) = default;
143 :
144 : const OGRFieldDomain *ToFieldDomain(OGRFieldType eFieldType) const;
145 : GIntBig GetID() const;
146 : std::string GetDomainsNames() const;
147 : bool HasDomainName(const std::string &osName) const;
148 :
149 : private:
150 : GIntBig nResourceID = 0;
151 : GIntBig nResourceParentID = 0;
152 : std::string osCreationDate;
153 : std::string osDisplayName;
154 : std::string osKeyName;
155 : std::string osDescription;
156 : std::array<std::shared_ptr<OGRCodedFieldDomain>, 3> apDomains;
157 : };
158 :
159 : class OGRNGWDataset;
160 :
161 : class OGRNGWLayer final : public OGRLayer
162 : {
163 : std::string osResourceId;
164 : OGRNGWDataset *poDS;
165 : NGWAPI::Permissions stPermissions;
166 : bool bFetchedPermissions;
167 : OGRFeatureDefn *poFeatureDefn;
168 : GIntBig nFeatureCount;
169 : OGREnvelope stExtent;
170 : std::map<GIntBig, OGRFeature *> moFeatures;
171 : std::map<GIntBig, OGRFeature *>::const_iterator oNextPos;
172 : GIntBig nPageStart;
173 : bool bNeedSyncData, bNeedSyncStructure;
174 : std::set<GIntBig> soChangedIds;
175 : std::set<GIntBig> soDeletedFieldsIds;
176 : std::string osFields;
177 : std::string osWhere;
178 : std::string osSpatialFilter;
179 : bool bClientSideAttributeFilter;
180 : bool m_bEOF = false;
181 :
182 : explicit OGRNGWLayer(const std::string &osResourceIdIn,
183 : OGRNGWDataset *poDSIn,
184 : const NGWAPI::Permissions &stPermissionsIn,
185 : OGRFeatureDefn *poFeatureDefnIn,
186 : GIntBig nFeatureCountIn,
187 : const OGREnvelope &stExtentIn);
188 :
189 : public:
190 : explicit OGRNGWLayer(OGRNGWDataset *poDSIn,
191 : const CPLJSONObject &oResourceJsonObject);
192 : explicit OGRNGWLayer(OGRNGWDataset *poDSIn, const std::string &osNameIn,
193 : OGRSpatialReference *poSpatialRef,
194 : OGRwkbGeometryType eGType, const std::string &osKeyIn,
195 : const std::string &osDescIn);
196 : ~OGRNGWLayer() override;
197 :
198 : bool Delete();
199 : OGRErr Rename(const char *pszNewName) override;
200 : std::string GetResourceId() const;
201 :
202 : /* OGRLayer */
203 : void ResetReading() override;
204 : OGRFeature *GetNextFeature() override;
205 : OGRErr SetNextByIndex(GIntBig nIndex) override;
206 : OGRFeature *GetFeature(GIntBig nFID) override;
207 : GIntBig GetFeatureCount(int bForce = TRUE) override;
208 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
209 : bool bForce) override;
210 : using OGRLayer::GetLayerDefn;
211 : const OGRFeatureDefn *GetLayerDefn() const override;
212 : int TestCapability(const char *) const override;
213 :
214 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
215 : int bApproxOK = TRUE) override;
216 : OGRErr DeleteField(int iField) override;
217 : OGRErr ReorderFields(int *panMap) override;
218 : virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
219 : int nFlags) override;
220 :
221 : OGRErr SyncToDisk() override;
222 :
223 : OGRErr DeleteFeature(GIntBig nFID) override;
224 : OGRErr DeleteFeatures(const std::vector<GIntBig> &vFeaturesID);
225 : bool DeleteAllFeatures();
226 :
227 : CPLErr SetMetadata(char **papszMetadata,
228 : const char *pszDomain = "") override;
229 : CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
230 : const char *pszDomain = "") override;
231 :
232 : OGRErr SetIgnoredFields(CSLConstList papszFields) override;
233 : OGRErr SetAttributeFilter(const char *pszQuery) override;
234 : virtual OGRErr ISetSpatialFilter(int iGeomField,
235 : const OGRGeometry *poGeom) override;
236 :
237 : OGRErr SetSelectedFields(const std::set<std::string> &aosFields);
238 : OGRNGWLayer *Clone() const;
239 :
240 : public:
241 : static std::string TranslateSQLToFilter(swq_expr_node *poNode);
242 :
243 : protected:
244 : OGRErr ISetFeature(OGRFeature *poFeature) override;
245 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
246 :
247 : private:
248 : void Fill(const CPLJSONObject &oRootObject);
249 : void FillMetadata(const CPLJSONObject &oRootObject);
250 : void FillFields(const CPLJSONArray &oFields,
251 : const CPLStringList &soIgnoredFieldNames);
252 : void FetchPermissions();
253 : void FreeFeaturesCache(bool bForce = false);
254 : std::string CreateNGWResourceJson();
255 : OGRErr SyncFeatures();
256 : GIntBig GetMaxFeatureCount(bool bForce);
257 : bool FillFeatures(const std::string &osUrl);
258 : GIntBig GetNewFeaturesCount() const;
259 : CPLJSONObject LoadUrl(const std::string &osUrl) const;
260 : };
261 :
262 : using OGRNGWLayerPtr = std::shared_ptr<OGRNGWLayer>;
263 :
264 : class OGRNGWDataset final : public GDALDataset
265 : {
266 : friend class OGRNGWLayer;
267 : int nBatchSize;
268 : int nPageSize;
269 : NGWAPI::Permissions stPermissions;
270 : bool bFetchedPermissions;
271 : bool bHasFeaturePaging;
272 : std::string osUserPwd;
273 : std::string osUrl;
274 : std::string osResourceId;
275 : std::string osName;
276 : bool bExtInNativeData;
277 : bool bMetadataDerty;
278 : // http options
279 : std::string osConnectTimeout;
280 : std::string osTimeout;
281 : std::string osRetryCount;
282 : std::string osRetryDelay;
283 :
284 : // vector
285 : std::vector<OGRNGWLayerPtr> aoLayers;
286 :
287 : // raster
288 : GDALDataset *poRasterDS;
289 : OGREnvelope stPixelExtent;
290 : int nRasters;
291 : int nCacheExpires, nCacheMaxSize;
292 :
293 : // json
294 : std::string osJsonDepth;
295 : std::string osExtensions;
296 :
297 : // domain
298 : std::map<GIntBig, OGRNGWCodedFieldDomain> moDomains;
299 :
300 : public:
301 : OGRNGWDataset();
302 : ~OGRNGWDataset() override;
303 :
304 : bool Open(const char *pszFilename, char **papszOpenOptionsIn,
305 : bool bUpdateIn, int nOpenFlagsIn);
306 : bool Open(const std::string &osUrlIn, const std::string &osResourceIdIn,
307 : char **papszOpenOptionsIn, bool bUpdateIn, int nOpenFlagsIn);
308 : std::string Extensions() const;
309 :
310 : /* GDALDataset */
311 0 : int GetLayerCount() const override
312 : {
313 0 : return static_cast<int>(aoLayers.size());
314 : }
315 :
316 : const OGRLayer *GetLayer(int) const override;
317 : int TestCapability(const char *) const override;
318 : virtual OGRLayer *ICreateLayer(const char *pszName,
319 : const OGRGeomFieldDefn *poGeomFieldDefn,
320 : CSLConstList papszOptions) override;
321 : OGRErr DeleteLayer(int) override;
322 : CPLErr SetMetadata(char **papszMetadata,
323 : const char *pszDomain = "") override;
324 : CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
325 : const char *pszDomain = "") override;
326 : CPLErr FlushCache(bool bAtClosing) override;
327 : OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
328 : const char *pszDialect) override;
329 :
330 : const OGRSpatialReference *GetSpatialRef() const override;
331 : CPLErr GetGeoTransform(GDALGeoTransform >) const override;
332 : CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
333 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
334 : GDALDataType eBufType, int nBandCount,
335 : BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
336 : GSpacing nLineSpace, GSpacing nBandSpace,
337 : GDALRasterIOExtraArg *psExtraArg) override;
338 : std::vector<std::string>
339 : GetFieldDomainNames(CSLConstList papszOptions = nullptr) const override;
340 : const OGRFieldDomain *
341 : GetFieldDomain(const std::string &name) const override;
342 : bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
343 : std::string &failureReason) override;
344 : bool DeleteFieldDomain(const std::string &name,
345 : std::string &failureReason) override;
346 : bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
347 : std::string &failureReason) override;
348 :
349 : private:
350 : CPLStringList GetHeaders(bool bSkipRetry = true) const;
351 :
352 0 : std::string GetUrl() const
353 : {
354 0 : return osUrl;
355 : }
356 :
357 0 : std::string GetResourceId() const
358 : {
359 0 : return osResourceId;
360 : }
361 :
362 : void FillMetadata(const CPLJSONObject &oRootObject);
363 : bool FillResources(const CPLStringList &aosHTTPOptions, int nOpenFlagsIn);
364 : void AddLayer(const CPLJSONObject &oResourceJsonObject,
365 : const CPLStringList &aosHTTPOptions, int nOpenFlagsIn);
366 : void AddRaster(const CPLJSONObject &oResourceJsonObject);
367 : void SetupRasterDSWrapper(const OGREnvelope &stExtent);
368 : bool Init(int nOpenFlagsIn);
369 : bool FlushMetadata(char **papszMetadata);
370 :
371 0 : inline bool IsUpdateMode() const
372 : {
373 0 : return eAccess == GA_Update;
374 : }
375 :
376 0 : bool IsBatchMode() const
377 : {
378 0 : return nBatchSize >= 0;
379 : }
380 :
381 0 : bool HasFeaturePaging() const
382 : {
383 0 : return bHasFeaturePaging;
384 : }
385 :
386 0 : int GetPageSize() const
387 : {
388 0 : return bHasFeaturePaging ? nPageSize : -1;
389 : }
390 :
391 0 : int GetBatchSize() const
392 : {
393 0 : return nBatchSize;
394 : }
395 :
396 0 : bool IsExtInNativeData() const
397 : {
398 0 : return bExtInNativeData;
399 : }
400 :
401 : void FetchPermissions();
402 : void FillCapabilities(const CPLStringList &aosHTTPOptions);
403 :
404 : OGRNGWCodedFieldDomain GetDomainByID(GIntBig id) const;
405 : GIntBig GetDomainIdByName(const std::string &osDomainName) const;
406 :
407 : private:
408 : CPL_DISALLOW_COPY_ASSIGN(OGRNGWDataset)
409 : };
410 :
411 : #endif // OGR_NGW_H_INCLUDED
|