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-2020, NextGIS
10  *
11  *  Permission is hereby granted, free of charge, to any person obtaining a copy
12  *  of this software and associated documentation files (the "Software"), to deal
13  *  in the Software without restriction, including without limitation the rights
14  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  *  copies of the Software, and to permit persons to whom the Software is
16  *  furnished to do so, subject to the following conditions:
17  *
18  *  The above copyright notice and this permission notice shall be included in all
19  *  copies or substantial portions of the Software.
20  *
21  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  *  SOFTWARE.
28  *******************************************************************************/
29 #ifndef OGR_NGW_H_INCLUDED
30 #define OGR_NGW_H_INCLUDED
31 
32 // gdal headers
33 #include "ogrsf_frmts.h"
34 #include "ogr_swq.h"
35 
36 #include <map>
37 #include <set>
38 
39 namespace NGWAPI {
40     std::string GetPermissions(const std::string &osUrl, const std::string &osResourceId);
41     std::string GetResource(const std::string &osUrl, const std::string &osResourceId);
42     std::string GetChildren(const std::string &osUrl, const std::string &osResourceId);
43     std::string GetFeature(const std::string &osUrl, const std::string &osResourceId);
44     std::string GetTMS(const std::string &osUrl, const std::string &osResourceId);
45     std::string GetFeaturePage(const std::string &osUrl, const std::string &osResourceId,
46         GIntBig nStart, int nCount = 0, const std::string &osFields = "",
47         const std::string &osWhere = "", const std::string &osSpatialWhere = "",
48         const std::string &osExtensions = "", bool IsGeometryIgnored = false);
49     std::string GetRoute(const std::string &osUrl);
50     std::string GetUpload(const std::string &osUrl);
51     std::string GetVersion(const std::string &osUrl);
52     bool CheckVersion(const std::string &osVersion, int nMajor, int nMinor = 0,
53         int nPatch = 0);
54 
55     struct Uri {
56         std::string osPrefix;
57         std::string osAddress;
58         std::string osResourceId;
59         std::string osNewResourceName;
60     };
61 
62     // C++11 allow defaults
63     struct Permissions {
64         bool bResourceCanRead = false;
65         bool bResourceCanCreate = false;
66         bool bResourceCanUpdate = false;
67         bool bResourceCanDelete = false;
68         bool bDatastructCanRead = false;
69         bool bDatastructCanWrite = false;
70         bool bDataCanRead = false;
71         bool bDataCanWrite = false;
72         bool bMetadataCanRead = false;
73         bool bMetadataCanWrite = false;
74     };
75 
76     Uri ParseUri(const std::string &osUrl);
77     Permissions CheckPermissions(const std::string &osUrl,
78         const std::string &osResourceId, char **papszHTTPOptions, bool bReadWrite);
79     bool DeleteResource(const std::string &osUrl, const std::string &osResourceId,
80         char **papszHTTPOptions);
81     bool RenameResource(const std::string &osUrl, const std::string &osResourceId,
82         const std::string &osNewName, char **papszHTTPOptions);
83     OGRwkbGeometryType NGWGeomTypeToOGRGeomType(const std::string &osGeomType);
84     std::string OGRGeomTypeToNGWGeomType(OGRwkbGeometryType eType);
85     OGRFieldType NGWFieldTypeToOGRFieldType(const std::string &osFieldType);
86     std::string OGRFieldTypeToNGWFieldType(OGRFieldType eType);
87     std::string GetFeatureCount(const std::string &osUrl,
88         const std::string &osResourceId);
89     std::string GetLayerExtent(const std::string &osUrl,
90         const std::string &osResourceId);
91     bool FlushMetadata(const std::string &osUrl, const std::string &osResourceId,
92         char **papszMetadata, char **papszHTTPOptions );
93     std::string CreateResource(const std::string &osUrl, const std::string &osPayload,
94         char **papszHTTPOptions);
95     bool UpdateResource(const std::string &osUrl, const std::string &osResourceId,
96         const std::string &osPayload, char **papszHTTPOptions);
97     void FillResmeta(CPLJSONObject &oRoot, char **papszMetadata);
98     std::string GetResmetaSuffix(CPLJSONObject::Type eType);
99     bool DeleteFeature(const std::string &osUrl, const std::string &osResourceId,
100         const std::string &osFeatureId, char **papszHTTPOptions);
101     GIntBig CreateFeature(const std::string &osUrl, const std::string &osResourceId,
102         const std::string &osFeatureJson, char **papszHTTPOptions);
103     bool UpdateFeature(const std::string &osUrl, const std::string &osResourceId,
104         const std::string &osFeatureId, const std::string &osFeatureJson,
105         char **papszHTTPOptions);
106     std::vector<GIntBig> PatchFeatures(const std::string &osUrl, const std::string &osResourceId,
107         const std::string &osFeaturesJson, char **papszHTTPOptions);
108     bool GetExtent(const std::string &osUrl, const std::string &osResourceId,
109         char **papszHTTPOptions, int nEPSG, OGREnvelope &stExtent);
110     CPLJSONObject UploadFile(const std::string &osUrl, const std::string &osFilePath,
111         char **papszHTTPOptions, GDALProgressFunc pfnProgress, void *pProgressData);
112 } // namespace NGWAPI
113 
114 class OGRNGWDataset;
115 
116 class OGRNGWLayer final: public OGRLayer
117 {
118     std::string osResourceId;
119     OGRNGWDataset *poDS;
120     NGWAPI::Permissions stPermissions;
121     bool bFetchedPermissions;
122     OGRFeatureDefn *poFeatureDefn;
123     GIntBig nFeatureCount;
124     OGREnvelope stExtent;
125     std::map<GIntBig, OGRFeature*> moFeatures;
126     std::map<GIntBig, OGRFeature*>::const_iterator oNextPos;
127     GIntBig nPageStart;
128     bool bNeedSyncData, bNeedSyncStructure;
129     std::set<GIntBig> soChangedIds;
130     std::string osFields;
131     std::string osWhere;
132     std::string osSpatialFilter;
133     bool bClientSideAttributeFilter;
134 
135     explicit OGRNGWLayer( const std::string &osResourceIdIn, OGRNGWDataset *poDSIn,
136         const NGWAPI::Permissions &stPermissionsIn, OGRFeatureDefn *poFeatureDefnIn,
137         GIntBig nFeatureCountIn, const OGREnvelope &stExtentIn );
138 
139 public:
140     explicit OGRNGWLayer( OGRNGWDataset *poDSIn, const CPLJSONObject &oResourceJsonObject );
141     explicit OGRNGWLayer( OGRNGWDataset *poDSIn, const std::string &osNameIn,
142         OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType,
143         const std::string &osKeyIn, const std::string &osDescIn );
144     virtual ~OGRNGWLayer();
145 
146     bool Delete();
147     bool Rename( const std::string &osNewName );
148     std::string GetResourceId() const;
149 
150     /* OGRLayer */
151     virtual void ResetReading() override;
152     virtual OGRFeature *GetNextFeature() override;
153     virtual OGRErr SetNextByIndex( GIntBig nIndex ) override;
154     virtual OGRFeature *GetFeature( GIntBig nFID ) override;
155     virtual GIntBig GetFeatureCount( int bForce = TRUE ) override;
156     virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
157     virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
158         int bForce = TRUE) override;
159     virtual OGRFeatureDefn *GetLayerDefn() override;
160     virtual int TestCapability( const char * ) override;
161 
162     virtual OGRErr CreateField( OGRFieldDefn *poField,
163         int bApproxOK = TRUE ) override;
164     virtual OGRErr DeleteField( int iField ) override;
165     virtual OGRErr ReorderFields( int *panMap ) override;
166     virtual OGRErr AlterFieldDefn( int iField, OGRFieldDefn *poNewFieldDefn,
167         int nFlagsIn ) override;
168 
169     virtual OGRErr SyncToDisk() override;
170 
171     virtual OGRErr DeleteFeature(GIntBig nFID) override;
172     bool DeleteAllFeatures();
173 
174     virtual CPLErr SetMetadata( char **papszMetadata,
175         const char *pszDomain = "" ) override;
176     virtual CPLErr SetMetadataItem( const char *pszName, const char *pszValue,
177         const char *pszDomain = "" ) override;
178 
179     virtual OGRErr SetIgnoredFields( const char **papszFields ) override;
180     virtual OGRErr SetAttributeFilter( const char *pszQuery ) override;
181     virtual void SetSpatialFilter( OGRGeometry *poGeom ) override;
182     virtual void SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
183 
184     OGRErr SetSelectedFields(const std::set<std::string> &aosFields);
185     OGRNGWLayer *Clone() const;
186 
187 public:
188     static std::string TranslateSQLToFilter( swq_expr_node *poNode );
189 
190 protected:
191     virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
192     virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
193 
194 private:
195     void FillMetadata( const CPLJSONObject &oRootObject );
196     void FillFields( const CPLJSONArray &oFields );
197     void FetchPermissions();
198     void FreeFeaturesCache( bool bForce = false );
199     std::string CreateNGWResourceJson();
200     OGRErr SyncFeatures();
201     GIntBig GetMaxFeatureCount( bool bForce );
202     bool FillFeatures(const std::string &osUrl);
203     GIntBig GetNewFeaturesCount() const;
204 };
205 
206 class OGRNGWDataset final : public GDALDataset
207 {
208     friend class OGRNGWLayer;
209     int nBatchSize;
210     int nPageSize;
211     NGWAPI::Permissions stPermissions;
212     bool bFetchedPermissions;
213     bool bHasFeaturePaging;
214     std::string osUserPwd;
215     std::string osUrl;
216     std::string osResourceId;
217     std::string osName;
218     bool bExtInNativeData;
219     bool bMetadataDerty;
220 
221     // vector
222     OGRNGWLayer **papoLayers;
223     int nLayers;
224 
225     // raster
226     GDALDataset *poRasterDS;
227     OGREnvelope stPixelExtent;
228     int nRasters;
229     int nCacheExpires, nCacheMaxSize;
230 
231     // json
232     std::string osJsonDepth;
233     std::string osExtensions;
234 
235 public:
236     OGRNGWDataset();
237     virtual ~OGRNGWDataset();
238 
239     bool Open( const char *pszFilename, char **papszOpenOptionsIn,
240         bool bUpdateIn, int nOpenFlagsIn );
241     bool Open( const std::string &osUrlIn, const std::string &osResourceIdIn,
242         char **papszOpenOptionsIn, bool bUpdateIn, int nOpenFlagsIn );
243     std::string Extensions() const;
244 
245     /* GDALDataset */
GetLayerCount()246     virtual int GetLayerCount() override { return nLayers; }
247     virtual OGRLayer *GetLayer( int ) override;
248     virtual int TestCapability( const char * ) override;
249     virtual OGRLayer  *ICreateLayer( const char *pszName,
250         OGRSpatialReference *poSpatialRef = nullptr,
251         OGRwkbGeometryType eGType = wkbUnknown,
252         char **papszOptions = nullptr ) override;
253     virtual OGRErr DeleteLayer( int ) override;
254     virtual CPLErr SetMetadata( char **papszMetadata,
255         const char *pszDomain = "" ) override;
256     virtual CPLErr SetMetadataItem( const char *pszName, const char *pszValue,
257         const char *pszDomain = "" ) override;
258     virtual void FlushCache() override;
259     virtual OGRLayer *ExecuteSQL( const char *pszStatement,
260         OGRGeometry *poSpatialFilter, const char *pszDialect ) override;
261 
262     virtual const OGRSpatialReference *GetSpatialRef() const override;
263     virtual CPLErr GetGeoTransform( double *padfTransform ) override;
264     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff,
265         int nXSize, int nYSize, void *pData, int nBufXSize, int nBufYSize,
266         GDALDataType eBufType, int nBandCount, int *panBandMap,
267         GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
268         GDALRasterIOExtraArg* psExtraArg ) override;
269 
270 private:
271     char **GetHeaders() const;
GetUrl()272     std::string GetUrl() const { return osUrl; }
GetResourceId()273     std::string GetResourceId() const { return osResourceId; }
274     void FillMetadata( const CPLJSONObject &oRootObject );
275     bool FillResources( char **papszOptions, int nOpenFlagsIn );
276     void AddLayer( const CPLJSONObject &oResourceJsonObject,  char **papszOptions,
277         int nOpenFlagsIn );
278     void AddRaster( const CPLJSONObject &oResourceJsonObject,  char **papszOptions );
279     bool Init(int nOpenFlagsIn);
280     bool FlushMetadata( char **papszMetadata );
IsUpdateMode()281     inline bool IsUpdateMode() const { return eAccess == GA_Update; }
IsBatchMode()282     bool IsBatchMode() const { return nBatchSize >= 0; }
HasFeaturePaging()283     bool HasFeaturePaging() const { return bHasFeaturePaging; }
GetPageSize()284     int GetPageSize() const { return bHasFeaturePaging ? nPageSize : -1; }
GetBatchSize()285     int GetBatchSize() const { return nBatchSize; }
IsExtInNativeData()286     bool IsExtInNativeData() const { return bExtInNativeData; }
287     void FetchPermissions();
288     void FillCapabilities( char **papszOptions );
289 private:
290     CPL_DISALLOW_COPY_ASSIGN(OGRNGWDataset)
291 };
292 
293 #endif // OGR_NGW_H_INCLUDED
294