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 :
181 : explicit OGRNGWLayer(const std::string &osResourceIdIn,
182 : OGRNGWDataset *poDSIn,
183 : const NGWAPI::Permissions &stPermissionsIn,
184 : OGRFeatureDefn *poFeatureDefnIn,
185 : GIntBig nFeatureCountIn,
186 : const OGREnvelope &stExtentIn);
187 :
188 : public:
189 : explicit OGRNGWLayer(OGRNGWDataset *poDSIn,
190 : const CPLJSONObject &oResourceJsonObject);
191 : explicit OGRNGWLayer(OGRNGWDataset *poDSIn, const std::string &osNameIn,
192 : OGRSpatialReference *poSpatialRef,
193 : OGRwkbGeometryType eGType, const std::string &osKeyIn,
194 : const std::string &osDescIn);
195 : virtual ~OGRNGWLayer();
196 :
197 : bool Delete();
198 : virtual OGRErr Rename(const char *pszNewName) override;
199 : std::string GetResourceId() const;
200 :
201 : /* OGRLayer */
202 : virtual void ResetReading() override;
203 : virtual OGRFeature *GetNextFeature() override;
204 : virtual OGRErr SetNextByIndex(GIntBig nIndex) override;
205 : virtual OGRFeature *GetFeature(GIntBig nFID) override;
206 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
207 : virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
208 : bool bForce) override;
209 : virtual OGRFeatureDefn *GetLayerDefn() override;
210 : virtual int TestCapability(const char *) override;
211 :
212 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
213 : int bApproxOK = TRUE) override;
214 : virtual OGRErr DeleteField(int iField) override;
215 : virtual OGRErr ReorderFields(int *panMap) override;
216 : virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
217 : int nFlags) override;
218 :
219 : virtual OGRErr SyncToDisk() override;
220 :
221 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
222 : OGRErr DeleteFeatures(const std::vector<GIntBig> &vFeaturesID);
223 : bool DeleteAllFeatures();
224 :
225 : virtual CPLErr SetMetadata(char **papszMetadata,
226 : const char *pszDomain = "") override;
227 : virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
228 : const char *pszDomain = "") override;
229 :
230 : virtual OGRErr SetIgnoredFields(CSLConstList papszFields) override;
231 : virtual OGRErr SetAttributeFilter(const char *pszQuery) override;
232 : virtual OGRErr ISetSpatialFilter(int iGeomField,
233 : const OGRGeometry *poGeom) override;
234 :
235 : OGRErr SetSelectedFields(const std::set<std::string> &aosFields);
236 : OGRNGWLayer *Clone() const;
237 :
238 : public:
239 : static std::string TranslateSQLToFilter(swq_expr_node *poNode);
240 :
241 : protected:
242 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
243 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
244 :
245 : private:
246 : void Fill(const CPLJSONObject &oRootObject);
247 : void FillMetadata(const CPLJSONObject &oRootObject);
248 : void FillFields(const CPLJSONArray &oFields,
249 : const CPLStringList &soIgnoredFieldNames);
250 : void FetchPermissions();
251 : void FreeFeaturesCache(bool bForce = false);
252 : std::string CreateNGWResourceJson();
253 : OGRErr SyncFeatures();
254 : GIntBig GetMaxFeatureCount(bool bForce);
255 : bool FillFeatures(const std::string &osUrl);
256 : GIntBig GetNewFeaturesCount() const;
257 : CPLJSONObject LoadUrl(const std::string &osUrl) const;
258 : };
259 :
260 : using OGRNGWLayerPtr = std::shared_ptr<OGRNGWLayer>;
261 :
262 : class OGRNGWDataset final : public GDALDataset
263 : {
264 : friend class OGRNGWLayer;
265 : int nBatchSize;
266 : int nPageSize;
267 : NGWAPI::Permissions stPermissions;
268 : bool bFetchedPermissions;
269 : bool bHasFeaturePaging;
270 : std::string osUserPwd;
271 : std::string osUrl;
272 : std::string osResourceId;
273 : std::string osName;
274 : bool bExtInNativeData;
275 : bool bMetadataDerty;
276 : // http options
277 : std::string osConnectTimeout;
278 : std::string osTimeout;
279 : std::string osRetryCount;
280 : std::string osRetryDelay;
281 :
282 : // vector
283 : std::vector<OGRNGWLayerPtr> aoLayers;
284 :
285 : // raster
286 : GDALDataset *poRasterDS;
287 : OGREnvelope stPixelExtent;
288 : int nRasters;
289 : int nCacheExpires, nCacheMaxSize;
290 :
291 : // json
292 : std::string osJsonDepth;
293 : std::string osExtensions;
294 :
295 : // domain
296 : std::map<GIntBig, OGRNGWCodedFieldDomain> moDomains;
297 :
298 : public:
299 : OGRNGWDataset();
300 : virtual ~OGRNGWDataset();
301 :
302 : bool Open(const char *pszFilename, char **papszOpenOptionsIn,
303 : bool bUpdateIn, int nOpenFlagsIn);
304 : bool Open(const std::string &osUrlIn, const std::string &osResourceIdIn,
305 : char **papszOpenOptionsIn, bool bUpdateIn, int nOpenFlagsIn);
306 : std::string Extensions() const;
307 :
308 : /* GDALDataset */
309 0 : virtual int GetLayerCount() override
310 : {
311 0 : return static_cast<int>(aoLayers.size());
312 : }
313 :
314 : virtual OGRLayer *GetLayer(int) override;
315 : virtual int TestCapability(const char *) override;
316 : virtual OGRLayer *ICreateLayer(const char *pszName,
317 : const OGRGeomFieldDefn *poGeomFieldDefn,
318 : CSLConstList papszOptions) override;
319 : virtual OGRErr DeleteLayer(int) override;
320 : virtual CPLErr SetMetadata(char **papszMetadata,
321 : const char *pszDomain = "") override;
322 : virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
323 : const char *pszDomain = "") override;
324 : virtual CPLErr FlushCache(bool bAtClosing) override;
325 : virtual OGRLayer *ExecuteSQL(const char *pszStatement,
326 : OGRGeometry *poSpatialFilter,
327 : const char *pszDialect) override;
328 :
329 : virtual const OGRSpatialReference *GetSpatialRef() const override;
330 : virtual CPLErr GetGeoTransform(GDALGeoTransform >) const override;
331 : virtual CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
332 : int nXSize, int nYSize, void *pData, int nBufXSize,
333 : int nBufYSize, GDALDataType eBufType,
334 : int nBandCount, BANDMAP_TYPE panBandMap,
335 : GSpacing nPixelSpace, GSpacing nLineSpace,
336 : 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
|