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 1835 : const char *GetName() override
135 : {
136 1835 : 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 : virtual void SetSpatialFilter(OGRGeometry *) override;
148 :
149 12 : virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override
150 : {
151 12 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
152 12 : }
153 :
154 : virtual OGRErr SetAttributeFilter(const char *) override;
155 :
156 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
157 :
158 : void SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
159 : void SetWGS84Extents(double dfMinX, double dfMinY, double dfMaxX,
160 : double dfMaxY);
161 : virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
162 :
163 15 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
164 : int bForce) override
165 : {
166 15 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
167 : }
168 :
169 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
170 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
171 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
172 :
173 : virtual OGRErr StartTransaction() override;
174 : virtual OGRErr CommitTransaction() override;
175 : virtual OGRErr RollbackTransaction() override;
176 :
177 : virtual OGRErr SetIgnoredFields(CSLConstList papszFields) override;
178 :
179 138 : int HasLayerDefn()
180 : {
181 138 : return poFeatureDefn != nullptr;
182 : }
183 :
184 : OGRFeatureDefn *ParseSchema(const CPLXMLNode *psSchema);
185 : OGRFeatureDefn *BuildLayerDefn(OGRFeatureDefn *poSrcFDefn = nullptr);
186 :
187 : OGRErr DeleteFromFilter(const std::string &osOGCFilter);
188 :
189 4 : const std::vector<CPLString> &GetLastInsertedFIDList()
190 : {
191 4 : return aosFIDList;
192 : }
193 :
194 : const char *GetShortName();
195 :
196 : void SetRequiredOutputFormat(const char *pszRequiredOutputFormatIn);
197 :
198 122 : const char *GetRequiredOutputFormat()
199 : {
200 122 : return pszRequiredOutputFormat;
201 : }
202 :
203 : void SetOrderBy(const std::vector<OGRWFSSortDesc> &aoSortColumnsIn);
204 :
205 0 : bool HasGotApproximateLayerDefn()
206 : {
207 0 : GetLayerDefn();
208 0 : return bGotApproximateLayerDefn;
209 : }
210 :
211 168 : const char *GetNamespacePrefix()
212 : {
213 168 : return pszNS;
214 : }
215 :
216 168 : const char *GetNamespaceName()
217 : {
218 168 : return pszNSVal;
219 : }
220 :
221 209 : void SetSupportedSRSList(
222 : std::vector<std::string> &&aosSupportedCRSList,
223 : OGRLayer::GetSupportedSRSListRetType &&apoSupportedCRSList)
224 : {
225 209 : m_aosSupportedCRSList = std::move(aosSupportedCRSList);
226 209 : m_apoSupportedCRSList = std::move(apoSupportedCRSList);
227 209 : }
228 :
229 : const OGRLayer::GetSupportedSRSListRetType &
230 1 : GetSupportedSRSList(int /*iGeomField*/) override
231 : {
232 1 : return m_apoSupportedCRSList;
233 : }
234 :
235 : OGRErr SetActiveSRS(int iGeomField,
236 : const OGRSpatialReference *poSRS) override;
237 :
238 56 : const std::string &GetTmpDir() const
239 : {
240 56 : return m_osTmpDir;
241 : }
242 : };
243 :
244 : /************************************************************************/
245 : /* OGRWFSJoinLayer */
246 : /************************************************************************/
247 :
248 : class OGRWFSJoinLayer final : public OGRLayer
249 : {
250 : OGRWFSDataSource *poDS;
251 : OGRFeatureDefn *poFeatureDefn;
252 :
253 : CPLString osGlobalFilter;
254 : CPLString osSortBy;
255 : int bDistinct;
256 : std::set<CPLString> aoSetMD5;
257 :
258 : std::vector<OGRWFSLayer *> apoLayers;
259 :
260 : GDALDataset *poBaseDS;
261 : OGRLayer *poBaseLayer;
262 : bool bReloadNeeded;
263 : bool bHasFetched;
264 :
265 : bool bPagingActive;
266 : int nPagingStartIndex;
267 : int nFeatureRead;
268 : int nFeatureCountRequested;
269 :
270 : std::vector<CPLString> aoSrcFieldNames;
271 : std::vector<CPLString> aoSrcGeomFieldNames;
272 :
273 : CPLString osFeatureTypes;
274 :
275 : std::string m_osTmpDir{};
276 :
277 : OGRWFSJoinLayer(OGRWFSDataSource *poDS, const swq_select *psSelectInfo,
278 : const CPLString &osGlobalFilter);
279 : CPLString MakeGetFeatureURL(int bRequestHits = FALSE);
280 : GDALDataset *FetchGetFeature();
281 : GIntBig ExecuteGetFeatureResultTypeHits();
282 :
283 : public:
284 : static OGRWFSJoinLayer *Build(OGRWFSDataSource *poDS,
285 : const swq_select *psSelectInfo);
286 : virtual ~OGRWFSJoinLayer();
287 :
288 : virtual void ResetReading() override;
289 : virtual OGRFeature *GetNextFeature() override;
290 :
291 : virtual OGRFeatureDefn *GetLayerDefn() override;
292 :
293 : virtual int TestCapability(const char *) override;
294 :
295 : virtual GIntBig GetFeatureCount(int bForce = TRUE) override;
296 :
297 : virtual void SetSpatialFilter(OGRGeometry *) override;
298 :
299 0 : virtual void SetSpatialFilter(int iGeomField, OGRGeometry *poGeom) override
300 : {
301 0 : OGRLayer::SetSpatialFilter(iGeomField, poGeom);
302 0 : }
303 :
304 : virtual OGRErr SetAttributeFilter(const char *) override;
305 : };
306 :
307 : /************************************************************************/
308 : /* OGRWFSDataSource */
309 : /************************************************************************/
310 :
311 : class OGRWFSDataSource final : public GDALDataset
312 : {
313 : bool bRewriteFile;
314 : CPLXMLNode *psFileXML;
315 :
316 : OGRWFSLayer **papoLayers;
317 : int nLayers;
318 : std::map<OGRLayer *, OGRLayer *> oMap;
319 :
320 : bool bUpdate;
321 :
322 : bool bGetFeatureSupportHits;
323 : CPLString osVersion;
324 : bool bNeedNAMESPACE;
325 : bool bHasMinOperators;
326 : bool bHasNullCheck;
327 : bool bPropertyIsNotEqualToSupported;
328 : bool bUseFeatureId;
329 : bool bGmlObjectIdNeedsGMLPrefix;
330 : bool bRequiresEnvelopeSpatialFilter;
331 : static bool DetectRequiresEnvelopeSpatialFilter(const CPLXMLNode *psRoot);
332 :
333 : bool bTransactionSupport;
334 : char **papszIdGenMethods;
335 : bool DetectTransactionSupport(const CPLXMLNode *psRoot);
336 :
337 : CPLString osBaseURL;
338 : CPLString osPostTransactionURL;
339 :
340 : CPLXMLNode *LoadFromFile(const char *pszFilename);
341 :
342 : bool bUseHttp10;
343 :
344 : char **papszHttpOptions;
345 :
346 : bool bPagingAllowed;
347 : int nPageSize;
348 : int nBaseStartIndex;
349 : bool DetectSupportPagingWFS2(const CPLXMLNode *psGetCapabilitiesResponse,
350 : const CPLXMLNode *psConfigurationRoot);
351 :
352 : bool bStandardJoinsWFS2;
353 : bool DetectSupportStandardJoinsWFS2(const CPLXMLNode *psRoot);
354 :
355 : bool bLoadMultipleLayerDefn;
356 : std::set<CPLString> aoSetAlreadyTriedLayers;
357 :
358 : CPLString osLayerMetadataCSV;
359 : CPLString osLayerMetadataTmpFileName;
360 : GDALDataset *poLayerMetadataDS;
361 : OGRLayer *poLayerMetadataLayer;
362 :
363 : CPLString osGetCapabilities;
364 : const char *apszGetCapabilities[2];
365 : GDALDataset *poLayerGetCapabilitiesDS;
366 : OGRLayer *poLayerGetCapabilitiesLayer;
367 :
368 : bool bKeepLayerNamePrefix;
369 :
370 : bool bEmptyAsNull;
371 :
372 : bool bInvertAxisOrderIfLatLong;
373 : CPLString osConsiderEPSGAsURN;
374 : bool bExposeGMLId;
375 :
376 : CPLHTTPResult *SendGetCapabilities(const char *pszBaseURL,
377 : CPLString &osTypeName);
378 :
379 : int GetLayerIndex(const char *pszName);
380 :
381 : public:
382 : OGRWFSDataSource();
383 : virtual ~OGRWFSDataSource();
384 :
385 : int Open(const char *pszFilename, int bUpdate,
386 : CSLConstList papszOpenOptions);
387 :
388 127 : virtual int GetLayerCount() override
389 : {
390 127 : return nLayers;
391 : }
392 :
393 : virtual OGRLayer *GetLayer(int) override;
394 : virtual OGRLayer *GetLayerByName(const char *pszLayerName) override;
395 :
396 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
397 : OGRGeometry *poSpatialFilter,
398 : const char *pszDialect) override;
399 : virtual void ReleaseResultSet(OGRLayer *poResultsSet) override;
400 :
401 128 : bool UpdateMode() const
402 : {
403 128 : return bUpdate;
404 : }
405 :
406 128 : bool SupportTransactions() const
407 : {
408 128 : return bTransactionSupport;
409 : }
410 :
411 1 : void DisableSupportHits()
412 : {
413 1 : bGetFeatureSupportHits = false;
414 1 : }
415 :
416 10 : bool GetFeatureSupportHits() const
417 : {
418 10 : return bGetFeatureSupportHits;
419 : }
420 :
421 937 : const char *GetVersion()
422 : {
423 937 : return osVersion.c_str();
424 : }
425 :
426 : bool IsOldDeegree(const char *pszErrorString);
427 :
428 6 : bool GetNeedNAMESPACE() const
429 : {
430 6 : return bNeedNAMESPACE;
431 : }
432 :
433 62 : bool HasMinOperators() const
434 : {
435 62 : return bHasMinOperators;
436 : }
437 :
438 2 : bool HasNullCheck() const
439 : {
440 2 : return bHasNullCheck;
441 : }
442 :
443 44 : bool UseFeatureId() const
444 : {
445 44 : return bUseFeatureId;
446 : }
447 :
448 5 : bool RequiresEnvelopeSpatialFilter() const
449 : {
450 5 : return bRequiresEnvelopeSpatialFilter;
451 : }
452 :
453 0 : void SetGmlObjectIdNeedsGMLPrefix()
454 : {
455 0 : bGmlObjectIdNeedsGMLPrefix = true;
456 0 : }
457 :
458 43 : int DoesGmlObjectIdNeedGMLPrefix() const
459 : {
460 43 : return bGmlObjectIdNeedsGMLPrefix;
461 : }
462 :
463 0 : void SetPropertyIsNotEqualToUnSupported()
464 : {
465 0 : bPropertyIsNotEqualToSupported = false;
466 0 : }
467 :
468 43 : bool PropertyIsNotEqualToSupported() const
469 : {
470 43 : return bPropertyIsNotEqualToSupported;
471 : }
472 :
473 : CPLString GetPostTransactionURL();
474 :
475 : void SaveLayerSchema(const char *pszLayerName, const CPLXMLNode *psSchema);
476 :
477 : CPLHTTPResult *HTTPFetch(const char *pszURL, char **papszOptions);
478 :
479 220 : bool IsPagingAllowed() const
480 : {
481 220 : return bPagingAllowed;
482 : }
483 :
484 90 : int GetPageSize() const
485 : {
486 90 : return nPageSize;
487 : }
488 :
489 88 : int GetBaseStartIndex() const
490 : {
491 88 : return nBaseStartIndex;
492 : }
493 :
494 : void LoadMultipleLayerDefn(const char *pszLayerName, char *pszNS,
495 : char *pszNSVal);
496 :
497 : bool GetKeepLayerNamePrefix() const
498 : {
499 : return bKeepLayerNamePrefix;
500 : }
501 :
502 84 : const CPLString &GetBaseURL()
503 : {
504 84 : return osBaseURL;
505 : }
506 :
507 591 : bool IsEmptyAsNull() const
508 : {
509 591 : return bEmptyAsNull;
510 : }
511 :
512 90 : bool InvertAxisOrderIfLatLong() const
513 : {
514 90 : return bInvertAxisOrderIfLatLong;
515 : }
516 :
517 90 : const CPLString &GetConsiderEPSGAsURN() const
518 : {
519 90 : return osConsiderEPSGAsURN;
520 : }
521 :
522 229 : bool ExposeGMLId() const
523 : {
524 229 : return bExposeGMLId;
525 : }
526 :
527 : virtual char **GetMetadataDomainList() override;
528 : virtual char **GetMetadata(const char *pszDomain = "") override;
529 : };
530 :
531 : #endif /* ndef OGR_WFS_H_INCLUDED */
|