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 = nullptr;
54 :
55 : OGRFeatureDefn *poFeatureDefn = nullptr;
56 : bool bGotApproximateLayerDefn = false;
57 : GMLFeatureClass *poGMLFeatureClass = nullptr;
58 :
59 : int bAxisOrderAlreadyInverted = false;
60 : OGRSpatialReference *m_poSRS = nullptr;
61 : std::string m_osSRSName{};
62 :
63 : char *pszBaseURL = nullptr;
64 : char *pszName = nullptr;
65 : char *pszNS = nullptr;
66 : char *pszNSVal = nullptr;
67 :
68 : bool bStreamingDS = false;
69 : GDALDataset *poBaseDS = nullptr;
70 : OGRLayer *poBaseLayer = nullptr;
71 : bool bHasFetched = false;
72 : bool bReloadNeeded = false;
73 :
74 : CPLString osGeometryColumnName{};
75 : OGRwkbGeometryType eGeomType = wkbUnknown;
76 : GIntBig nFeatures = -1;
77 : GIntBig m_nNumberMatched = -1;
78 : bool m_bHasReadAtLeastOneFeatureInThisPage = false;
79 : bool bCountFeaturesInGetNextFeature = false;
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 = nullptr;
93 :
94 : CPLString osSQLWhere{};
95 : CPLString osWFSWhere{};
96 :
97 : CPLString osTargetNamespace{};
98 : CPLString GetDescribeFeatureTypeURL(int bWithNS);
99 :
100 : int nExpectedInserts = 0;
101 : CPLString osGlobalInsert{};
102 : std::vector<CPLString> aosFIDList{};
103 :
104 : bool bInTransaction = false;
105 :
106 : CPLString GetPostHeader();
107 :
108 : bool bUseFeatureIdAtLayerLevel = false;
109 :
110 : bool bPagingActive = false;
111 : int nPagingStartIndex = 0;
112 : int nFeatureRead = 0;
113 :
114 : OGRFeatureDefn *BuildLayerDefnFromFeatureClass(GMLFeatureClass *poClass);
115 :
116 : char *pszRequiredOutputFormat = nullptr;
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 : void BuildLayerDefn();
126 :
127 : CPL_DISALLOW_COPY_ASSIGN(OGRWFSLayer)
128 :
129 : public:
130 : OGRWFSLayer(OGRWFSDataSource *poDS, OGRSpatialReference *poSRS,
131 : int bAxisOrderAlreadyInverted, const char *pszBaseURL,
132 : const char *pszName, const char *pszNS, const char *pszNSVal);
133 :
134 : ~OGRWFSLayer() override;
135 :
136 : OGRWFSLayer *Clone();
137 :
138 1881 : const char *GetName() const override
139 : {
140 1881 : return pszName;
141 : }
142 :
143 : void ResetReading() override;
144 : OGRFeature *GetNextFeature() override;
145 : OGRFeature *GetFeature(GIntBig nFID) override;
146 :
147 : const OGRFeatureDefn *GetLayerDefn() const override;
148 :
149 : int TestCapability(const char *) const override;
150 :
151 : OGRErr ISetSpatialFilter(int iGeomField,
152 : const OGRGeometry *poGeom) override;
153 :
154 : OGRErr SetAttributeFilter(const char *) override;
155 :
156 : 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 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
162 : bool bForce) override;
163 :
164 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
165 : OGRErr ISetFeature(OGRFeature *poFeature) override;
166 : OGRErr DeleteFeature(GIntBig nFID) override;
167 :
168 : OGRErr StartTransaction() override;
169 : OGRErr CommitTransaction() override;
170 : OGRErr RollbackTransaction() override;
171 :
172 : OGRErr SetIgnoredFields(CSLConstList papszFields) override;
173 :
174 154 : int HasLayerDefn()
175 : {
176 154 : return poFeatureDefn != nullptr;
177 : }
178 :
179 : OGRFeatureDefn *ParseSchema(const CPLXMLNode *psSchema);
180 : OGRFeatureDefn *BuildLayerDefn(OGRFeatureDefn *poSrcFDefn);
181 :
182 : OGRErr DeleteFromFilter(const std::string &osOGCFilter);
183 :
184 4 : const std::vector<CPLString> &GetLastInsertedFIDList()
185 : {
186 4 : return aosFIDList;
187 : }
188 :
189 : const char *GetShortName();
190 :
191 : void SetRequiredOutputFormat(const char *pszRequiredOutputFormatIn);
192 :
193 142 : const char *GetRequiredOutputFormat()
194 : {
195 142 : return pszRequiredOutputFormat;
196 : }
197 :
198 : void SetOrderBy(const std::vector<OGRWFSSortDesc> &aoSortColumnsIn);
199 :
200 0 : bool HasGotApproximateLayerDefn()
201 : {
202 0 : GetLayerDefn();
203 0 : return bGotApproximateLayerDefn;
204 : }
205 :
206 168 : const char *GetNamespacePrefix()
207 : {
208 168 : return pszNS;
209 : }
210 :
211 168 : const char *GetNamespaceName()
212 : {
213 168 : return pszNSVal;
214 : }
215 :
216 211 : void SetSupportedSRSList(
217 : std::vector<std::string> &&aosSupportedCRSList,
218 : OGRLayer::GetSupportedSRSListRetType &&apoSupportedCRSList)
219 : {
220 211 : m_aosSupportedCRSList = std::move(aosSupportedCRSList);
221 211 : m_apoSupportedCRSList = std::move(apoSupportedCRSList);
222 211 : }
223 :
224 : const OGRLayer::GetSupportedSRSListRetType &
225 1 : GetSupportedSRSList(int /*iGeomField*/) override
226 : {
227 1 : return m_apoSupportedCRSList;
228 : }
229 :
230 : OGRErr SetActiveSRS(int iGeomField,
231 : const OGRSpatialReference *poSRS) override;
232 :
233 56 : const std::string &GetTmpDir() const
234 : {
235 56 : return m_osTmpDir;
236 : }
237 : };
238 :
239 : /************************************************************************/
240 : /* OGRWFSJoinLayer */
241 : /************************************************************************/
242 :
243 : class OGRWFSJoinLayer final : public OGRLayer
244 : {
245 : OGRWFSDataSource *poDS = nullptr;
246 : OGRFeatureDefn *poFeatureDefn = nullptr;
247 :
248 : CPLString osGlobalFilter{};
249 : CPLString osSortBy{};
250 : bool bDistinct = false;
251 : std::set<CPLString> aoSetMD5{};
252 :
253 : std::vector<OGRWFSLayer *> apoLayers{};
254 :
255 : GDALDataset *poBaseDS = nullptr;
256 : OGRLayer *poBaseLayer = nullptr;
257 : bool bReloadNeeded = false;
258 : bool bHasFetched = false;
259 :
260 : bool bPagingActive = false;
261 : int nPagingStartIndex = 0;
262 : int nFeatureRead = 0;
263 : int nFeatureCountRequested = 0;
264 :
265 : std::vector<CPLString> aoSrcFieldNames{};
266 : std::vector<CPLString> aoSrcGeomFieldNames{};
267 :
268 : CPLString osFeatureTypes{};
269 :
270 : std::string m_osTmpDir{};
271 :
272 : OGRWFSJoinLayer(OGRWFSDataSource *poDS, const swq_select *psSelectInfo,
273 : const CPLString &osGlobalFilter);
274 : CPLString MakeGetFeatureURL(int bRequestHits = FALSE);
275 : GDALDataset *FetchGetFeature();
276 : GIntBig ExecuteGetFeatureResultTypeHits();
277 :
278 : CPL_DISALLOW_COPY_ASSIGN(OGRWFSJoinLayer)
279 :
280 : public:
281 : static OGRWFSJoinLayer *Build(OGRWFSDataSource *poDS,
282 : const swq_select *psSelectInfo);
283 : ~OGRWFSJoinLayer() override;
284 :
285 : void ResetReading() override;
286 : OGRFeature *GetNextFeature() override;
287 :
288 : const OGRFeatureDefn *GetLayerDefn() const override;
289 :
290 : int TestCapability(const char *) const override;
291 :
292 : GIntBig GetFeatureCount(int bForce = TRUE) override;
293 :
294 : OGRErr ISetSpatialFilter(int iGeomField,
295 : const OGRGeometry *poGeom) override;
296 :
297 : OGRErr SetAttributeFilter(const char *) override;
298 : };
299 :
300 : /************************************************************************/
301 : /* OGRWFSDataSource */
302 : /************************************************************************/
303 :
304 : class OGRWFSDataSource final : public GDALDataset
305 : {
306 : static constexpr int DEFAULT_BASE_START_INDEX = 0;
307 : static constexpr int DEFAULT_PAGE_SIZE = 100;
308 :
309 : bool bRewriteFile = false;
310 : CPLXMLNode *psFileXML = nullptr;
311 :
312 : OGRWFSLayer **papoLayers = nullptr;
313 : int nLayers = 0;
314 : std::map<OGRLayer *, OGRLayer *> oMap{};
315 :
316 : bool bUpdate = false;
317 :
318 : bool bGetFeatureSupportHits = false;
319 : CPLString osVersion{};
320 : bool bNeedNAMESPACE = false;
321 : bool bHasMinOperators = false;
322 : bool bHasNullCheck = false;
323 : // Advertized by deegree but not implemented.
324 : bool bPropertyIsNotEqualToSupported = true;
325 : // CubeWerx doesn't like GmlObjectId.
326 : bool bUseFeatureId = false;
327 : bool bGmlObjectIdNeedsGMLPrefix = false;
328 : bool bRequiresEnvelopeSpatialFilter = false;
329 : static bool DetectRequiresEnvelopeSpatialFilter(const CPLXMLNode *psRoot);
330 :
331 : bool bTransactionSupport = false;
332 : char **papszIdGenMethods = nullptr;
333 : bool DetectTransactionSupport(const CPLXMLNode *psRoot);
334 :
335 : CPLString osBaseURL{};
336 : CPLString osPostTransactionURL{};
337 :
338 : CPLXMLNode *LoadFromFile(const char *pszFilename);
339 :
340 : bool bUseHttp10 = false;
341 :
342 : char **papszHttpOptions = nullptr;
343 :
344 : bool bPagingAllowed = false;
345 : int nPageSize = DEFAULT_PAGE_SIZE;
346 : int nBaseStartIndex = DEFAULT_BASE_START_INDEX;
347 : bool DetectSupportPagingWFS2(const CPLXMLNode *psGetCapabilitiesResponse,
348 : const CPLXMLNode *psConfigurationRoot);
349 :
350 : bool bStandardJoinsWFS2 = false;
351 : bool DetectSupportStandardJoinsWFS2(const CPLXMLNode *psRoot);
352 :
353 : bool bLoadMultipleLayerDefn = false;
354 : std::set<CPLString> aoSetAlreadyTriedLayers{};
355 :
356 : CPLString osLayerMetadataCSV{};
357 : CPLString osLayerMetadataTmpFileName{};
358 : GDALDataset *poLayerMetadataDS = nullptr;
359 : OGRLayer *poLayerMetadataLayer = nullptr;
360 :
361 : CPLString osGetCapabilities{};
362 : const char *apszGetCapabilities[2] = {nullptr, nullptr};
363 : GDALDataset *poLayerGetCapabilitiesDS = nullptr;
364 : OGRLayer *poLayerGetCapabilitiesLayer = nullptr;
365 :
366 : bool bKeepLayerNamePrefix = false;
367 :
368 : bool bEmptyAsNull = true;
369 :
370 : bool bInvertAxisOrderIfLatLong = true;
371 : CPLString osConsiderEPSGAsURN{};
372 : bool bExposeGMLId = true;
373 :
374 : CPLHTTPResult *SendGetCapabilities(const char *pszBaseURL,
375 : CPLString &osTypeName);
376 :
377 : int GetLayerIndex(const char *pszName);
378 :
379 : CPL_DISALLOW_COPY_ASSIGN(OGRWFSDataSource)
380 :
381 : public:
382 : OGRWFSDataSource();
383 : ~OGRWFSDataSource() override;
384 :
385 : int Open(const char *pszFilename, int bUpdate,
386 : CSLConstList papszOpenOptions);
387 :
388 135 : int GetLayerCount() const override
389 : {
390 135 : return nLayers;
391 : }
392 :
393 : const OGRLayer *GetLayer(int) const override;
394 : OGRLayer *GetLayerByName(const char *pszLayerName) override;
395 :
396 : OGRLayer *ExecuteSQL(const char *pszSQLCommand,
397 : OGRGeometry *poSpatialFilter,
398 : const char *pszDialect) override;
399 : 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 972 : const char *GetVersion()
422 : {
423 972 : 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 64 : bool HasMinOperators() const
434 : {
435 64 : 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 229 : bool IsPagingAllowed() const
480 : {
481 229 : 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 612 : bool IsEmptyAsNull() const
508 : {
509 612 : return bEmptyAsNull;
510 : }
511 :
512 91 : bool InvertAxisOrderIfLatLong() const
513 : {
514 91 : return bInvertAxisOrderIfLatLong;
515 : }
516 :
517 91 : const CPLString &GetConsiderEPSGAsURN() const
518 : {
519 91 : return osConsiderEPSGAsURN;
520 : }
521 :
522 233 : bool ExposeGMLId() const
523 : {
524 233 : return bExposeGMLId;
525 : }
526 :
527 : char **GetMetadataDomainList() override;
528 : char **GetMetadata(const char *pszDomain = "") override;
529 : };
530 :
531 : #endif /* ndef OGR_WFS_H_INCLUDED */
|