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