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