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 : class OGRNGWCodedFieldDomain
135 : {
136 : public:
137 0 : explicit OGRNGWCodedFieldDomain() = default;
138 : explicit OGRNGWCodedFieldDomain(const CPLJSONObject &oResourceJsonObject);
139 0 : virtual ~OGRNGWCodedFieldDomain() = default;
140 : const OGRFieldDomain *ToFieldDomain(OGRFieldType eFieldType) const;
141 : GIntBig GetID() const;
142 : std::string GetDomainsNames() const;
143 : bool HasDomainName(const std::string &osName) const;
144 :
145 : private:
146 : GIntBig nResourceID = 0;
147 : GIntBig nResourceParentID = 0;
148 : std::string osCreationDate;
149 : std::string osDisplayName;
150 : std::string osKeyName;
151 : std::string osDescription;
152 : std::array<std::shared_ptr<OGRCodedFieldDomain>, 3> apDomains;
153 : };
154 :
155 : class OGRNGWDataset;
156 :
157 : class OGRNGWLayer final : public OGRLayer
158 : {
159 : std::string osResourceId;
160 : OGRNGWDataset *poDS;
161 : NGWAPI::Permissions stPermissions;
162 : bool bFetchedPermissions;
163 : OGRFeatureDefn *poFeatureDefn;
164 : GIntBig nFeatureCount;
165 : OGREnvelope stExtent;
166 : std::map<GIntBig, OGRFeature *> moFeatures;
167 : std::map<GIntBig, OGRFeature *>::const_iterator oNextPos;
168 : GIntBig nPageStart;
169 : bool bNeedSyncData, bNeedSyncStructure;
170 : std::set<GIntBig> soChangedIds;
171 : std::set<GIntBig> soDeletedFieldsIds;
172 : std::string osFields;
173 : std::string osWhere;
174 : std::string osSpatialFilter;
175 : bool bClientSideAttributeFilter;
176 :
177 : explicit OGRNGWLayer(const std::string &osResourceIdIn,
178 : OGRNGWDataset *poDSIn,
179 : const NGWAPI::Permissions &stPermissionsIn,
180 : OGRFeatureDefn *poFeatureDefnIn,
181 : GIntBig nFeatureCountIn,
182 : const OGREnvelope &stExtentIn);
183 :
184 : public:
185 : explicit OGRNGWLayer(OGRNGWDataset *poDSIn,
186 : const CPLJSONObject &oResourceJsonObject);
187 : explicit OGRNGWLayer(OGRNGWDataset *poDSIn, const std::string &osNameIn,
188 : OGRSpatialReference *poSpatialRef,
189 : OGRwkbGeometryType eGType, const std::string &osKeyIn,
190 : const std::string &osDescIn);
191 : virtual ~OGRNGWLayer();
192 :
193 : bool Delete();
194 : virtual OGRErr Rename(const char *pszNewName) override;
195 : std::string GetResourceId() const;
196 :
197 : /* OGRLayer */
198 : virtual void ResetReading() override;
199 : virtual OGRFeature *GetNextFeature() override;
200 : virtual OGRErr SetNextByIndex(GIntBig nIndex) override;
201 : virtual OGRFeature *GetFeature(GIntBig nFID) override;
202 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
203 : virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
204 : bool bForce) override;
205 : virtual OGRFeatureDefn *GetLayerDefn() override;
206 : virtual int TestCapability(const char *) override;
207 :
208 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
209 : int bApproxOK = TRUE) override;
210 : virtual OGRErr DeleteField(int iField) override;
211 : virtual OGRErr ReorderFields(int *panMap) override;
212 : virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
213 : int nFlags) override;
214 :
215 : virtual OGRErr SyncToDisk() override;
216 :
217 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
218 : OGRErr DeleteFeatures(const std::vector<GIntBig> &vFeaturesID);
219 : bool DeleteAllFeatures();
220 :
221 : virtual CPLErr SetMetadata(char **papszMetadata,
222 : const char *pszDomain = "") override;
223 : virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
224 : const char *pszDomain = "") override;
225 :
226 : virtual OGRErr SetIgnoredFields(CSLConstList papszFields) override;
227 : virtual OGRErr SetAttributeFilter(const char *pszQuery) override;
228 : virtual OGRErr ISetSpatialFilter(int iGeomField,
229 : const OGRGeometry *poGeom) override;
230 :
231 : OGRErr SetSelectedFields(const std::set<std::string> &aosFields);
232 : OGRNGWLayer *Clone() const;
233 :
234 : public:
235 : static std::string TranslateSQLToFilter(swq_expr_node *poNode);
236 :
237 : protected:
238 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
239 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
240 :
241 : private:
242 : void Fill(const CPLJSONObject &oRootObject);
243 : void FillMetadata(const CPLJSONObject &oRootObject);
244 : void FillFields(const CPLJSONArray &oFields,
245 : const CPLStringList &soIgnoredFieldNames);
246 : void FetchPermissions();
247 : void FreeFeaturesCache(bool bForce = false);
248 : std::string CreateNGWResourceJson();
249 : OGRErr SyncFeatures();
250 : GIntBig GetMaxFeatureCount(bool bForce);
251 : bool FillFeatures(const std::string &osUrl);
252 : GIntBig GetNewFeaturesCount() const;
253 : CPLJSONObject LoadUrl(const std::string &osUrl) const;
254 : };
255 :
256 : using OGRNGWLayerPtr = std::shared_ptr<OGRNGWLayer>;
257 :
258 : class OGRNGWDataset final : public GDALDataset
259 : {
260 : friend class OGRNGWLayer;
261 : int nBatchSize;
262 : int nPageSize;
263 : NGWAPI::Permissions stPermissions;
264 : bool bFetchedPermissions;
265 : bool bHasFeaturePaging;
266 : std::string osUserPwd;
267 : std::string osUrl;
268 : std::string osResourceId;
269 : std::string osName;
270 : bool bExtInNativeData;
271 : bool bMetadataDerty;
272 : // http options
273 : std::string osConnectTimeout;
274 : std::string osTimeout;
275 : std::string osRetryCount;
276 : std::string osRetryDelay;
277 :
278 : // vector
279 : std::vector<OGRNGWLayerPtr> aoLayers;
280 :
281 : // raster
282 : GDALDataset *poRasterDS;
283 : OGREnvelope stPixelExtent;
284 : int nRasters;
285 : int nCacheExpires, nCacheMaxSize;
286 :
287 : // json
288 : std::string osJsonDepth;
289 : std::string osExtensions;
290 :
291 : // domain
292 : std::map<GIntBig, OGRNGWCodedFieldDomain> moDomains;
293 :
294 : public:
295 : OGRNGWDataset();
296 : virtual ~OGRNGWDataset();
297 :
298 : bool Open(const char *pszFilename, char **papszOpenOptionsIn,
299 : bool bUpdateIn, int nOpenFlagsIn);
300 : bool Open(const std::string &osUrlIn, const std::string &osResourceIdIn,
301 : char **papszOpenOptionsIn, bool bUpdateIn, int nOpenFlagsIn);
302 : std::string Extensions() const;
303 :
304 : /* GDALDataset */
305 0 : virtual int GetLayerCount() override
306 : {
307 0 : return static_cast<int>(aoLayers.size());
308 : }
309 :
310 : virtual OGRLayer *GetLayer(int) override;
311 : virtual int TestCapability(const char *) override;
312 : virtual OGRLayer *ICreateLayer(const char *pszName,
313 : const OGRGeomFieldDefn *poGeomFieldDefn,
314 : CSLConstList papszOptions) override;
315 : virtual OGRErr DeleteLayer(int) override;
316 : virtual CPLErr SetMetadata(char **papszMetadata,
317 : const char *pszDomain = "") override;
318 : virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
319 : const char *pszDomain = "") override;
320 : virtual CPLErr FlushCache(bool bAtClosing) override;
321 : virtual OGRLayer *ExecuteSQL(const char *pszStatement,
322 : OGRGeometry *poSpatialFilter,
323 : const char *pszDialect) override;
324 :
325 : virtual const OGRSpatialReference *GetSpatialRef() const override;
326 : virtual CPLErr GetGeoTransform(double *padfTransform) override;
327 : virtual CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
328 : int nXSize, int nYSize, void *pData, int nBufXSize,
329 : int nBufYSize, GDALDataType eBufType,
330 : int nBandCount, BANDMAP_TYPE panBandMap,
331 : GSpacing nPixelSpace, GSpacing nLineSpace,
332 : GSpacing nBandSpace,
333 : GDALRasterIOExtraArg *psExtraArg) override;
334 : std::vector<std::string>
335 : GetFieldDomainNames(CSLConstList papszOptions = nullptr) const override;
336 : const OGRFieldDomain *
337 : GetFieldDomain(const std::string &name) const override;
338 : bool AddFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
339 : std::string &failureReason) override;
340 : bool DeleteFieldDomain(const std::string &name,
341 : std::string &failureReason) override;
342 : bool UpdateFieldDomain(std::unique_ptr<OGRFieldDomain> &&domain,
343 : std::string &failureReason) override;
344 :
345 : private:
346 : CPLStringList GetHeaders(bool bSkipRetry = true) const;
347 :
348 0 : std::string GetUrl() const
349 : {
350 0 : return osUrl;
351 : }
352 :
353 0 : std::string GetResourceId() const
354 : {
355 0 : return osResourceId;
356 : }
357 :
358 : void FillMetadata(const CPLJSONObject &oRootObject);
359 : bool FillResources(const CPLStringList &aosHTTPOptions, int nOpenFlagsIn);
360 : void AddLayer(const CPLJSONObject &oResourceJsonObject,
361 : const CPLStringList &aosHTTPOptions, int nOpenFlagsIn);
362 : void AddRaster(const CPLJSONObject &oResourceJsonObject);
363 : void SetupRasterDSWrapper(const OGREnvelope &stExtent);
364 : bool Init(int nOpenFlagsIn);
365 : bool FlushMetadata(char **papszMetadata);
366 :
367 0 : inline bool IsUpdateMode() const
368 : {
369 0 : return eAccess == GA_Update;
370 : }
371 :
372 0 : bool IsBatchMode() const
373 : {
374 0 : return nBatchSize >= 0;
375 : }
376 :
377 0 : bool HasFeaturePaging() const
378 : {
379 0 : return bHasFeaturePaging;
380 : }
381 :
382 0 : int GetPageSize() const
383 : {
384 0 : return bHasFeaturePaging ? nPageSize : -1;
385 : }
386 :
387 0 : int GetBatchSize() const
388 : {
389 0 : return nBatchSize;
390 : }
391 :
392 0 : bool IsExtInNativeData() const
393 : {
394 0 : return bExtInNativeData;
395 : }
396 :
397 : void FetchPermissions();
398 : void FillCapabilities(const CPLStringList &aosHTTPOptions);
399 :
400 : OGRNGWCodedFieldDomain GetDomainByID(GIntBig id) const;
401 : GIntBig GetDomainIdByName(const std::string &osDomainName) const;
402 :
403 : private:
404 : CPL_DISALLOW_COPY_ASSIGN(OGRNGWDataset)
405 : };
406 :
407 : #endif // OGR_NGW_H_INCLUDED
|