Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: WFS Translator
4 : * Purpose: Definition of classes for OGR WFS driver.
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef OGR_WFS_H_INCLUDED
14 : #define OGR_WFS_H_INCLUDED
15 :
16 : #include <vector>
17 : #include <set>
18 : #include <map>
19 :
20 : #include "cpl_minixml.h"
21 : #include "ogrsf_frmts.h"
22 : #include "gmlfeature.h"
23 : #include "cpl_http.h"
24 : #include "ogr_swq.h"
25 :
26 : const CPLXMLNode *WFSFindNode(const CPLXMLNode *psXML, const char *pszRootName);
27 :
28 : const char *FindSubStringInsensitive(const char *pszStr, const char *pszSubStr);
29 :
30 : CPLString WFS_EscapeURL(const char *pszURL);
31 : CPLString WFS_DecodeURL(const CPLString &osSrc);
32 :
33 : class OGRWFSSortDesc
34 : {
35 : public:
36 : CPLString osColumn;
37 : bool bAsc;
38 :
39 0 : OGRWFSSortDesc(const CPLString &osColumnIn, int bAscIn)
40 0 : : osColumn(osColumnIn), bAsc(CPL_TO_BOOL(bAscIn))
41 : {
42 0 : }
43 : };
44 :
45 : /************************************************************************/
46 : /* OGRWFSLayer */
47 : /************************************************************************/
48 :
49 : class OGRWFSDataSource;
50 :
51 : class OGRWFSLayer final : public OGRLayer
52 : {
53 : OGRWFSDataSource *poDS;
54 :
55 : OGRFeatureDefn *poFeatureDefn;
56 : bool bGotApproximateLayerDefn;
57 : GMLFeatureClass *poGMLFeatureClass;
58 :
59 : int bAxisOrderAlreadyInverted;
60 : OGRSpatialReference *m_poSRS;
61 : std::string m_osSRSName{};
62 :
63 : char *pszBaseURL;
64 : char *pszName;
65 : char *pszNS;
66 : char *pszNSVal;
67 :
68 : bool bStreamingDS;
69 : GDALDataset *poBaseDS;
70 : OGRLayer *poBaseLayer;
71 : bool bHasFetched;
72 : bool bReloadNeeded;
73 :
74 : CPLString osGeometryColumnName;
75 : OGRwkbGeometryType eGeomType;
76 : GIntBig nFeatures;
77 : GIntBig m_nNumberMatched = -1;
78 : bool m_bHasReadAtLeastOneFeatureInThisPage = false;
79 : bool bCountFeaturesInGetNextFeature;
80 :
81 : int CanRunGetFeatureCountAndGetExtentTogether();
82 :
83 : CPLString MakeGetFeatureURL(int nMaxFeatures, int bRequestHits);
84 : bool MustRetryIfNonCompliantServer(const char *pszServerAnswer);
85 : GDALDataset *FetchGetFeature(int nMaxFeatures);
86 : OGRFeatureDefn *DescribeFeatureType();
87 : GIntBig ExecuteGetFeatureResultTypeHits();
88 :
89 : OGREnvelope m_oWGS84Extents{};
90 : OGREnvelope m_oExtents{};
91 :
92 : OGRGeometry *poFetchedFilterGeom;
93 :
94 : CPLString osSQLWhere;
95 : CPLString osWFSWhere;
96 :
97 : CPLString osTargetNamespace;
98 : CPLString GetDescribeFeatureTypeURL(int bWithNS);
99 :
100 : int nExpectedInserts;
101 : CPLString osGlobalInsert;
102 : std::vector<CPLString> aosFIDList;
103 :
104 : bool bInTransaction;
105 :
106 : CPLString GetPostHeader();
107 :
108 : bool bUseFeatureIdAtLayerLevel;
109 :
110 : bool bPagingActive;
111 : int nPagingStartIndex;
112 : int nFeatureRead;
113 :
114 : OGRFeatureDefn *BuildLayerDefnFromFeatureClass(GMLFeatureClass *poClass);
115 :
116 : char *pszRequiredOutputFormat;
117 :
118 : std::vector<OGRWFSSortDesc> aoSortColumns;
119 :
120 : std::vector<std::string> m_aosSupportedCRSList{};
121 : OGRLayer::GetSupportedSRSListRetType m_apoSupportedCRSList{};
122 :
123 : std::string m_osTmpDir{};
124 :
125 : public:
126 : OGRWFSLayer(OGRWFSDataSource *poDS, OGRSpatialReference *poSRS,
127 : int bAxisOrderAlreadyInverted, const char *pszBaseURL,
128 : const char *pszName, const char *pszNS, const char *pszNSVal);
129 :
130 : virtual ~OGRWFSLayer();
131 :
132 : OGRWFSLayer *Clone();
133 :
134 1881 : const char *GetName() override
135 : {
136 1881 : return pszName;
137 : }
138 :
139 : virtual void ResetReading() override;
140 : virtual OGRFeature *GetNextFeature() override;
141 : virtual OGRFeature *GetFeature(GIntBig nFID) override;
142 :
143 : virtual OGRFeatureDefn *GetLayerDefn() override;
144 :
145 : virtual int TestCapability(const char *) override;
146 :
147 : OGRErr ISetSpatialFilter(int iGeomField,
148 : const OGRGeometry *poGeom) override;
149 :
150 : virtual OGRErr SetAttributeFilter(const char *) override;
151 :
152 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
153 :
154 : void SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
155 : void SetWGS84Extents(double dfMinX, double dfMinY, double dfMaxX,
156 : double dfMaxY);
157 : virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
158 : bool bForce) override;
159 :
160 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
161 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
162 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
163 :
164 : virtual OGRErr StartTransaction() override;
165 : virtual OGRErr CommitTransaction() override;
166 : virtual OGRErr RollbackTransaction() override;
167 :
168 : virtual OGRErr SetIgnoredFields(CSLConstList papszFields) override;
169 :
170 154 : int HasLayerDefn()
171 : {
172 154 : return poFeatureDefn != nullptr;
173 : }
174 :
175 : OGRFeatureDefn *ParseSchema(const CPLXMLNode *psSchema);
176 : OGRFeatureDefn *BuildLayerDefn(OGRFeatureDefn *poSrcFDefn = nullptr);
177 :
178 : OGRErr DeleteFromFilter(const std::string &osOGCFilter);
179 :
180 4 : const std::vector<CPLString> &GetLastInsertedFIDList()
181 : {
182 4 : return aosFIDList;
183 : }
184 :
185 : const char *GetShortName();
186 :
187 : void SetRequiredOutputFormat(const char *pszRequiredOutputFormatIn);
188 :
189 142 : const char *GetRequiredOutputFormat()
190 : {
191 142 : return pszRequiredOutputFormat;
192 : }
193 :
194 : void SetOrderBy(const std::vector<OGRWFSSortDesc> &aoSortColumnsIn);
195 :
196 0 : bool HasGotApproximateLayerDefn()
197 : {
198 0 : GetLayerDefn();
199 0 : return bGotApproximateLayerDefn;
200 : }
201 :
202 168 : const char *GetNamespacePrefix()
203 : {
204 168 : return pszNS;
205 : }
206 :
207 168 : const char *GetNamespaceName()
208 : {
209 168 : return pszNSVal;
210 : }
211 :
212 209 : void SetSupportedSRSList(
213 : std::vector<std::string> &&aosSupportedCRSList,
214 : OGRLayer::GetSupportedSRSListRetType &&apoSupportedCRSList)
215 : {
216 209 : m_aosSupportedCRSList = std::move(aosSupportedCRSList);
217 209 : m_apoSupportedCRSList = std::move(apoSupportedCRSList);
218 209 : }
219 :
220 : const OGRLayer::GetSupportedSRSListRetType &
221 1 : GetSupportedSRSList(int /*iGeomField*/) override
222 : {
223 1 : return m_apoSupportedCRSList;
224 : }
225 :
226 : OGRErr SetActiveSRS(int iGeomField,
227 : const OGRSpatialReference *poSRS) override;
228 :
229 56 : const std::string &GetTmpDir() const
230 : {
231 56 : return m_osTmpDir;
232 : }
233 : };
234 :
235 : /************************************************************************/
236 : /* OGRWFSJoinLayer */
237 : /************************************************************************/
238 :
239 : class OGRWFSJoinLayer final : public OGRLayer
240 : {
241 : OGRWFSDataSource *poDS;
242 : OGRFeatureDefn *poFeatureDefn;
243 :
244 : CPLString osGlobalFilter;
245 : CPLString osSortBy;
246 : int bDistinct;
247 : std::set<CPLString> aoSetMD5;
248 :
249 : std::vector<OGRWFSLayer *> apoLayers;
250 :
251 : GDALDataset *poBaseDS;
252 : OGRLayer *poBaseLayer;
253 : bool bReloadNeeded;
254 : bool bHasFetched;
255 :
256 : bool bPagingActive;
257 : int nPagingStartIndex;
258 : int nFeatureRead;
259 : int nFeatureCountRequested;
260 :
261 : std::vector<CPLString> aoSrcFieldNames;
262 : std::vector<CPLString> aoSrcGeomFieldNames;
263 :
264 : CPLString osFeatureTypes;
265 :
266 : std::string m_osTmpDir{};
267 :
268 : OGRWFSJoinLayer(OGRWFSDataSource *poDS, const swq_select *psSelectInfo,
269 : const CPLString &osGlobalFilter);
270 : CPLString MakeGetFeatureURL(int bRequestHits = FALSE);
271 : GDALDataset *FetchGetFeature();
272 : GIntBig ExecuteGetFeatureResultTypeHits();
273 :
274 : public:
275 : static OGRWFSJoinLayer *Build(OGRWFSDataSource *poDS,
276 : const swq_select *psSelectInfo);
277 : virtual ~OGRWFSJoinLayer();
278 :
279 : virtual void ResetReading() override;
280 : virtual OGRFeature *GetNextFeature() override;
281 :
282 : virtual OGRFeatureDefn *GetLayerDefn() override;
283 :
284 : virtual int TestCapability(const char *) override;
285 :
286 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
287 :
288 : OGRErr ISetSpatialFilter(int iGeomField,
289 : const OGRGeometry *poGeom) override;
290 :
291 : virtual OGRErr SetAttributeFilter(const char *) override;
292 : };
293 :
294 : /************************************************************************/
295 : /* OGRWFSDataSource */
296 : /************************************************************************/
297 :
298 : class OGRWFSDataSource final : public GDALDataset
299 : {
300 : bool bRewriteFile;
301 : CPLXMLNode *psFileXML;
302 :
303 : OGRWFSLayer **papoLayers;
304 : int nLayers;
305 : std::map<OGRLayer *, OGRLayer *> oMap;
306 :
307 : bool bUpdate;
308 :
309 : bool bGetFeatureSupportHits;
310 : CPLString osVersion;
311 : bool bNeedNAMESPACE;
312 : bool bHasMinOperators;
313 : bool bHasNullCheck;
314 : bool bPropertyIsNotEqualToSupported;
315 : bool bUseFeatureId;
316 : bool bGmlObjectIdNeedsGMLPrefix;
317 : bool bRequiresEnvelopeSpatialFilter;
318 : static bool DetectRequiresEnvelopeSpatialFilter(const CPLXMLNode *psRoot);
319 :
320 : bool bTransactionSupport;
321 : char **papszIdGenMethods;
322 : bool DetectTransactionSupport(const CPLXMLNode *psRoot);
323 :
324 : CPLString osBaseURL;
325 : CPLString osPostTransactionURL;
326 :
327 : CPLXMLNode *LoadFromFile(const char *pszFilename);
328 :
329 : bool bUseHttp10;
330 :
331 : char **papszHttpOptions;
332 :
333 : bool bPagingAllowed;
334 : int nPageSize;
335 : int nBaseStartIndex;
336 : bool DetectSupportPagingWFS2(const CPLXMLNode *psGetCapabilitiesResponse,
337 : const CPLXMLNode *psConfigurationRoot);
338 :
339 : bool bStandardJoinsWFS2;
340 : bool DetectSupportStandardJoinsWFS2(const CPLXMLNode *psRoot);
341 :
342 : bool bLoadMultipleLayerDefn;
343 : std::set<CPLString> aoSetAlreadyTriedLayers;
344 :
345 : CPLString osLayerMetadataCSV;
346 : CPLString osLayerMetadataTmpFileName;
347 : GDALDataset *poLayerMetadataDS;
348 : OGRLayer *poLayerMetadataLayer;
349 :
350 : CPLString osGetCapabilities;
351 : const char *apszGetCapabilities[2];
352 : GDALDataset *poLayerGetCapabilitiesDS;
353 : OGRLayer *poLayerGetCapabilitiesLayer;
354 :
355 : bool bKeepLayerNamePrefix;
356 :
357 : bool bEmptyAsNull;
358 :
359 : bool bInvertAxisOrderIfLatLong;
360 : CPLString osConsiderEPSGAsURN;
361 : bool bExposeGMLId;
362 :
363 : CPLHTTPResult *SendGetCapabilities(const char *pszBaseURL,
364 : CPLString &osTypeName);
365 :
366 : int GetLayerIndex(const char *pszName);
367 :
368 : public:
369 : OGRWFSDataSource();
370 : virtual ~OGRWFSDataSource();
371 :
372 : int Open(const char *pszFilename, int bUpdate,
373 : CSLConstList papszOpenOptions);
374 :
375 133 : virtual int GetLayerCount() override
376 : {
377 133 : return nLayers;
378 : }
379 :
380 : virtual OGRLayer *GetLayer(int) override;
381 : virtual OGRLayer *GetLayerByName(const char *pszLayerName) override;
382 :
383 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
384 : OGRGeometry *poSpatialFilter,
385 : const char *pszDialect) override;
386 : virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
387 :
388 128 : bool UpdateMode() const
389 : {
390 128 : return bUpdate;
391 : }
392 :
393 128 : bool SupportTransactions() const
394 : {
395 128 : return bTransactionSupport;
396 : }
397 :
398 1 : void DisableSupportHits()
399 : {
400 1 : bGetFeatureSupportHits = false;
401 1 : }
402 :
403 10 : bool GetFeatureSupportHits() const
404 : {
405 10 : return bGetFeatureSupportHits;
406 : }
407 :
408 959 : const char *GetVersion()
409 : {
410 959 : return osVersion.c_str();
411 : }
412 :
413 : bool IsOldDeegree(const char *pszErrorString);
414 :
415 6 : bool GetNeedNAMESPACE() const
416 : {
417 6 : return bNeedNAMESPACE;
418 : }
419 :
420 62 : bool HasMinOperators() const
421 : {
422 62 : return bHasMinOperators;
423 : }
424 :
425 2 : bool HasNullCheck() const
426 : {
427 2 : return bHasNullCheck;
428 : }
429 :
430 44 : bool UseFeatureId() const
431 : {
432 44 : return bUseFeatureId;
433 : }
434 :
435 5 : bool RequiresEnvelopeSpatialFilter() const
436 : {
437 5 : return bRequiresEnvelopeSpatialFilter;
438 : }
439 :
440 0 : void SetGmlObjectIdNeedsGMLPrefix()
441 : {
442 0 : bGmlObjectIdNeedsGMLPrefix = true;
443 0 : }
444 :
445 43 : int DoesGmlObjectIdNeedGMLPrefix() const
446 : {
447 43 : return bGmlObjectIdNeedsGMLPrefix;
448 : }
449 :
450 0 : void SetPropertyIsNotEqualToUnSupported()
451 : {
452 0 : bPropertyIsNotEqualToSupported = false;
453 0 : }
454 :
455 43 : bool PropertyIsNotEqualToSupported() const
456 : {
457 43 : return bPropertyIsNotEqualToSupported;
458 : }
459 :
460 : CPLString GetPostTransactionURL();
461 :
462 : void SaveLayerSchema(const char *pszLayerName, const CPLXMLNode *psSchema);
463 :
464 : CPLHTTPResult *HTTPFetch(const char *pszURL, char **papszOptions);
465 :
466 224 : bool IsPagingAllowed() const
467 : {
468 224 : return bPagingAllowed;
469 : }
470 :
471 90 : int GetPageSize() const
472 : {
473 90 : return nPageSize;
474 : }
475 :
476 88 : int GetBaseStartIndex() const
477 : {
478 88 : return nBaseStartIndex;
479 : }
480 :
481 : void LoadMultipleLayerDefn(const char *pszLayerName, char *pszNS,
482 : char *pszNSVal);
483 :
484 : bool GetKeepLayerNamePrefix() const
485 : {
486 : return bKeepLayerNamePrefix;
487 : }
488 :
489 84 : const CPLString &GetBaseURL()
490 : {
491 84 : return osBaseURL;
492 : }
493 :
494 605 : bool IsEmptyAsNull() const
495 : {
496 605 : return bEmptyAsNull;
497 : }
498 :
499 89 : bool InvertAxisOrderIfLatLong() const
500 : {
501 89 : return bInvertAxisOrderIfLatLong;
502 : }
503 :
504 89 : const CPLString &GetConsiderEPSGAsURN() const
505 : {
506 89 : return osConsiderEPSGAsURN;
507 : }
508 :
509 230 : bool ExposeGMLId() const
510 : {
511 230 : return bExposeGMLId;
512 : }
513 :
514 : virtual char **GetMetadataDomainList() override;
515 : virtual char **GetMetadata(const char *pszDomain = "") override;
516 : };
517 :
518 : #endif /* ndef OGR_WFS_H_INCLUDED */
|