Line data Source code
1 : /******************************************************************************
2 : * Project: OGR
3 : * Purpose: OGRGMLASDriver implementation
4 : * Author: Even Rouault, <even dot rouault at spatialys dot com>
5 : *
6 : * Initial development funded by the European Earth observation programme
7 : * Copernicus
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #ifndef OGR_GMLAS_INCLUDED
16 : #define OGR_GMLAS_INCLUDED
17 :
18 : #include "xercesc_headers.h"
19 : #include "ogr_xerces.h"
20 :
21 : #include "cpl_vsi_virtual.h"
22 : #include "gdal_priv.h"
23 : #include "ogrsf_frmts.h"
24 :
25 : #include "ogr_gmlas_consts.h"
26 :
27 : #include <list>
28 : #include <set>
29 : #include <map>
30 : #include <vector>
31 :
32 : typedef std::pair<CPLString, CPLString> PairURIFilename;
33 :
34 : typedef enum
35 : {
36 : GMLAS_SWAP_AUTO,
37 : GMLAS_SWAP_YES,
38 : GMLAS_SWAP_NO,
39 : } GMLASSwapCoordinatesEnum;
40 :
41 : GDALDataset *OGRGMLASDriverCreateCopy(const char *pszFilename,
42 : GDALDataset *poSrcDS, int /*bStrict*/,
43 : char **papszOptions,
44 : GDALProgressFunc pfnProgress,
45 : void *pProgressData);
46 :
47 : /************************************************************************/
48 : /* IGMLASInputSourceClosing */
49 : /************************************************************************/
50 :
51 240 : class IGMLASInputSourceClosing
52 : {
53 : public:
54 : virtual ~IGMLASInputSourceClosing();
55 :
56 : virtual void notifyClosing(const CPLString &osFilename) = 0;
57 : };
58 :
59 : /************************************************************************/
60 : /* GMLASResourceCache */
61 : /************************************************************************/
62 :
63 : class GMLASResourceCache
64 : {
65 : protected:
66 : bool m_bHasCheckedCacheDirectory = false;
67 : std::string m_osCacheDirectory{};
68 : bool m_bRefresh = false;
69 : bool m_bAllowDownload = false;
70 : std::set<std::string> m_aoSetRefreshedFiles{};
71 :
72 : static bool
73 : RecursivelyCreateDirectoryIfNeeded(const std::string &osDirname);
74 : bool RecursivelyCreateDirectoryIfNeeded();
75 :
76 : std::string GetCachedFilename(const std::string &osResource);
77 :
78 : public:
79 : void SetCacheDirectory(const std::string &osCacheDirectory);
80 :
81 371 : void SetRefreshMode(bool bRefresh)
82 : {
83 371 : m_bRefresh = bRefresh;
84 371 : }
85 :
86 193 : void SetAllowDownload(bool bVal)
87 : {
88 193 : m_bAllowDownload = bVal;
89 193 : }
90 : };
91 :
92 : /************************************************************************/
93 : /* GMLASXSDCache */
94 : /************************************************************************/
95 :
96 : class GMLASXSDCache final : public GMLASResourceCache
97 : {
98 : bool CacheAllGML321();
99 : bool CacheAllISO20070417();
100 :
101 : public:
102 : VSILFILE *Open(const std::string &osResource, const std::string &osBasePath,
103 : std::string &osOutFilename);
104 : };
105 :
106 : /************************************************************************/
107 : /* GMLASBaseEntityResolver */
108 : /************************************************************************/
109 :
110 : class GMLASBaseEntityResolver : public EntityResolver,
111 : public IGMLASInputSourceClosing
112 : {
113 : protected:
114 : std::vector<CPLString> m_aosPathStack{};
115 : GMLASXSDCache &m_oCache;
116 : CPLString m_osGMLVersionFound{};
117 : std::set<CPLString> m_oSetSchemaURLs{};
118 : bool m_bFoundNonOfficialGMLSchemaLocation = false;
119 : bool m_bSubstituteWithOGCSchemaLocation = false;
120 :
121 : public:
122 : GMLASBaseEntityResolver(const CPLString &osBasePath, GMLASXSDCache &oCache);
123 : virtual ~GMLASBaseEntityResolver();
124 :
125 : void SetBasePath(const CPLString &osBasePath);
126 :
127 179 : const CPLString &GetGMLVersionFound() const
128 : {
129 179 : return m_osGMLVersionFound;
130 : }
131 :
132 179 : const std::set<CPLString> &GetSchemaURLS() const
133 : {
134 179 : return m_oSetSchemaURLs;
135 : }
136 :
137 2 : void SetSubstituteWithOGCSchemaLocation(bool b)
138 : {
139 2 : m_bSubstituteWithOGCSchemaLocation = b;
140 2 : }
141 :
142 2 : bool GetFoundNonOfficialGMLSchemaLocation() const
143 : {
144 2 : return m_bFoundNonOfficialGMLSchemaLocation;
145 : }
146 :
147 : virtual void notifyClosing(const CPLString &osFilename) override;
148 : virtual InputSource *resolveEntity(const XMLCh *const publicId,
149 : const XMLCh *const systemId) override;
150 :
151 : virtual void
152 : DoExtraSchemaProcessing(const CPLString &osFilename,
153 : const std::shared_ptr<VSIVirtualHandle> &fp);
154 : };
155 :
156 : /************************************************************************/
157 : /* GMLASInputSource */
158 : /************************************************************************/
159 :
160 : class GMLASInputSource final : public InputSource
161 : {
162 : std::shared_ptr<VSIVirtualHandle> m_fp{};
163 : int m_nCounter = 0;
164 : int *m_pnCounter = nullptr;
165 : CPLString m_osFilename{};
166 : IGMLASInputSourceClosing *m_cbk = nullptr;
167 :
168 : CPL_DISALLOW_COPY_ASSIGN(GMLASInputSource)
169 :
170 : public:
171 : GMLASInputSource(
172 : const char *pszFilename, const std::shared_ptr<VSIVirtualHandle> &fp,
173 : MemoryManager *const manager = XMLPlatformUtils::fgMemoryManager);
174 : virtual ~GMLASInputSource();
175 :
176 : virtual BinInputStream *makeStream() const override;
177 :
178 : void SetClosingCallback(IGMLASInputSourceClosing *cbk);
179 : };
180 :
181 : /************************************************************************/
182 : /* GMLASErrorHandler */
183 : /************************************************************************/
184 :
185 : class GMLASErrorHandler : public ErrorHandler
186 : {
187 : public:
188 2963 : GMLASErrorHandler() = default;
189 :
190 1673 : void SetSchemaFullCheckingEnabled(bool b)
191 : {
192 1673 : m_bSchemaFullChecking = b;
193 1673 : }
194 :
195 1673 : void SetHandleMultipleImportsEnabled(bool b)
196 : {
197 1673 : m_bHandleMultipleImports = b;
198 1673 : }
199 :
200 279 : void SetHideGMLTypeNotFound(bool b)
201 : {
202 279 : m_bHideGMLTypeNotFound = b;
203 279 : }
204 :
205 6 : const std::string &GetGMLTypeNotFoundError() const
206 : {
207 6 : return m_osGMLTypeNotFoundError;
208 : }
209 :
210 278 : bool hasFailed() const
211 : {
212 278 : return m_bFailed;
213 : }
214 :
215 : virtual void warning(const SAXParseException &e) override;
216 : virtual void error(const SAXParseException &e) override;
217 : virtual void fatalError(const SAXParseException &e) override;
218 :
219 2529 : virtual void resetErrors() override
220 : {
221 2529 : m_bFailed = false;
222 2529 : }
223 :
224 : private:
225 : bool m_bFailed = false;
226 : bool m_bSchemaFullChecking = false;
227 : bool m_bHandleMultipleImports = false;
228 : bool m_bHideGMLTypeNotFound = false;
229 : std::string m_osGMLTypeNotFoundError{};
230 :
231 : void handle(const SAXParseException &e, CPLErr eErr);
232 : };
233 :
234 : /************************************************************************/
235 : /* GMLASXLinkResolutionConf */
236 : /************************************************************************/
237 :
238 : class GMLASXLinkResolutionConf
239 : {
240 : public:
241 : /* See data/gmlasconf.xsd for docomentation of the fields */
242 :
243 : typedef enum
244 : {
245 : RawContent,
246 : FieldsFromXPath
247 : } ResolutionMode;
248 :
249 : int m_nTimeOut = 0;
250 :
251 : int m_nMaxFileSize = MAX_FILE_SIZE_DEFAULT;
252 :
253 : int m_nMaxGlobalResolutionTime = 0;
254 :
255 : CPLString m_osProxyServerPort{};
256 :
257 : CPLString m_osProxyUserPassword{};
258 :
259 : CPLString m_osProxyAuth{};
260 :
261 : CPLString m_osCacheDirectory{};
262 :
263 : bool m_bDefaultResolutionEnabled = DEFAULT_RESOLUTION_ENABLED_DEFAULT;
264 :
265 : bool m_bDefaultAllowRemoteDownload = ALLOW_REMOTE_DOWNLOAD_DEFAULT;
266 :
267 : ResolutionMode m_eDefaultResolutionMode = RawContent;
268 :
269 : int m_nDefaultResolutionDepth = 1;
270 :
271 : bool m_bDefaultCacheResults = CACHE_RESULTS_DEFAULT;
272 :
273 : bool m_bResolveInternalXLinks = INTERNAL_XLINK_RESOLUTION_DEFAULT;
274 :
275 : struct URLSpecificResolution
276 : {
277 : CPLString m_osURLPrefix{};
278 :
279 : std::vector<std::pair<CPLString, CPLString>>
280 : m_aosNameValueHTTPHeaders{};
281 :
282 : bool m_bAllowRemoteDownload = false;
283 :
284 : ResolutionMode m_eResolutionMode = RawContent;
285 :
286 : int m_nResolutionDepth = 1;
287 :
288 : bool m_bCacheResults = false;
289 :
290 : struct XPathDerivedField
291 : {
292 : CPLString m_osName{};
293 :
294 : CPLString m_osType{};
295 :
296 : CPLString m_osXPath{};
297 : };
298 :
299 : std::vector<XPathDerivedField> m_aoFields{};
300 : };
301 :
302 : std::vector<URLSpecificResolution> m_aoURLSpecificRules{};
303 :
304 : GMLASXLinkResolutionConf() = default;
305 :
306 : bool LoadFromXML(CPLXMLNode *psRoot);
307 : };
308 :
309 : /************************************************************************/
310 : /* GMLASConfiguration */
311 : /************************************************************************/
312 :
313 : class GMLASConfiguration
314 : {
315 : public:
316 : /** Whether remote schemas are allowed to be download. */
317 : bool m_bAllowRemoteSchemaDownload = ALLOW_REMOTE_SCHEMA_DOWNLOAD_DEFAULT;
318 :
319 : /** Whether a ogr_pkid attribute should always be generated. */
320 : bool m_bAlwaysGenerateOGRId = ALWAYS_GENERATE_OGR_ID_DEFAULT;
321 :
322 : /** Whether to remove layers found to be unused in initial scan pass */
323 : bool m_bRemoveUnusedLayers = REMOVE_UNUSED_LAYERS_DEFAULT;
324 :
325 : /** Whether to remove fields found to be unused in initial scan pass */
326 : bool m_bRemoveUnusedFields = REMOVE_UNUSED_FIELDS_DEFAULT;
327 :
328 : /** Whether repeated strings, integers, reals should be in corresponding
329 : OGR array types. */
330 : bool m_bUseArrays = USE_ARRAYS_DEFAULT;
331 :
332 : /** Whether OGR field null state should be used. */
333 : bool m_bUseNullState = USE_NULL_STATE_DEFAULT;
334 :
335 : /** Whether geometries should be stored as XML in a OGR string field. */
336 : bool m_bIncludeGeometryXML = INCLUDE_GEOMETRY_XML_DEFAULT;
337 :
338 : /** Whether, when dealing with schemas that import the
339 : GML namespace, and that at least one of them has
340 : elements that derive from gml:_Feature or
341 : gml:AbstractFeatureonly, only such elements should be
342 : instantiated as OGR layers, during the first pass that
343 : iterates over top level elements of the imported
344 : schemas. */
345 : bool m_bInstantiateGMLFeaturesOnly = INSTANTIATE_GML_FEATURES_ONLY_DEFAULT;
346 :
347 : /** Maximum length of layer and field identifiers*/
348 : int m_nIdentifierMaxLength = 0;
349 :
350 : /** Whether case insensitive comparison should be used for identifier
351 : * equality testing */
352 : bool m_bCaseInsensitiveIdentifier = CASE_INSENSITIVE_IDENTIFIER_DEFAULT;
353 :
354 : /** Whether to launder identifiers like postgresql does */
355 : bool m_bPGIdentifierLaundering = PG_IDENTIFIER_LAUNDERING_DEFAULT;
356 :
357 : /* Maximum number of fields in an element considered for flattening. */
358 : int m_nMaximumFieldsForFlattening = MAXIMUM_FIELDS_FLATTENING_DEFAULT;
359 :
360 : /** Whether remote XSD schemas should be locally cached. */
361 : bool m_bAllowXSDCache = ALLOW_XSD_CACHE_DEFAULT;
362 :
363 : /** Cache directory for cached XSD schemas. */
364 : CPLString m_osXSDCacheDirectory{};
365 :
366 : /** Whether to enable schema full checking. */
367 : bool m_bSchemaFullChecking = SCHEMA_FULL_CHECKING_DEFAULT;
368 :
369 : /** Whether to allow multiple imports of the same namespace. */
370 : bool m_bHandleMultipleImports = HANDLE_MULTIPLE_IMPORTS_DEFAULT;
371 :
372 : /** Whether validation of document against schema should be done. */
373 : bool m_bValidate = VALIDATE_DEFAULT;
374 :
375 : /** Whether a validation error should prevent dataset opening. */
376 : bool m_bFailIfValidationError = FAIL_IF_VALIDATION_ERROR_DEFAULT;
377 :
378 : /** Whether technical layers should be exposed. */
379 : bool m_bExposeMetadataLayers = WARN_IF_EXCLUDED_XPATH_FOUND_DEFAULT;
380 :
381 : /** For flatening rules, map prefix namespace to its URI */
382 : std::map<CPLString, CPLString> m_oMapPrefixToURIFlatteningRules{};
383 :
384 : std::vector<CPLString> m_osForcedFlattenedXPath{};
385 :
386 : std::vector<CPLString> m_osDisabledFlattenedXPath{};
387 :
388 : enum SWEActivationMode
389 : {
390 : SWE_ACTIVATE_IF_NAMESPACE_FOUND,
391 : SWE_ACTIVATE_TRUE,
392 : SWE_ACTIVATE_FALSE
393 : };
394 :
395 : /** If and when activate SWE special processings */
396 : SWEActivationMode m_eSWEActivationMode = SWE_ACTIVATE_IF_NAMESPACE_FOUND;
397 :
398 : /** If enabling swe:DataRecord parsing */
399 : bool m_bSWEProcessDataRecord = SWE_PROCESS_DATA_RECORD_DEFAULT;
400 :
401 : /** If enabling swe:DataArray parsing */
402 : bool m_bSWEProcessDataArray = SWE_PROCESS_DATA_ARRAY_DEFAULT;
403 :
404 : /** For ignored xpaths, map prefix namespace to its URI */
405 : std::map<CPLString, CPLString> m_oMapPrefixToURIIgnoredXPaths{};
406 :
407 : /** Ignored xpaths */
408 : std::vector<CPLString> m_aosIgnoredXPaths{};
409 :
410 : /** For type constraints, map prefix namespace to its URI */
411 : std::map<CPLString, CPLString> m_oMapPrefixToURITypeConstraints{};
412 :
413 : /** Map an XPath to a list of potential types for its children */
414 : std::map<CPLString, std::vector<CPLString>>
415 : m_oMapChildrenElementsConstraints{};
416 :
417 : /* Beginning of Writer config */
418 :
419 : /** Number of spaces for indentation */
420 : int m_nIndentSize = INDENT_SIZE_DEFAULT;
421 :
422 : CPLString m_osComment{};
423 :
424 : /** End of line format: "CRLF" or "LR" */
425 : CPLString m_osLineFormat{};
426 :
427 : /** "SHORT", "OGC_URN" or "OGC_URL" */
428 : CPLString m_osSRSNameFormat = szSRSNAME_DEFAULT;
429 :
430 : /** "WFS2_FEATURECOLLECTION" or "GMLAS_FEATURECOLLECTION" */
431 : CPLString m_osWrapping = szWFS2_FEATURECOLLECTION;
432 :
433 : /** XML datetime or empty for current time */
434 : CPLString m_osTimestamp{};
435 :
436 : /** Path or URL to OGC WFS 2.0 schema. */
437 : CPLString m_osWFS20SchemaLocation = szWFS20_SCHEMALOCATION;
438 :
439 : /* End of Writer config */
440 :
441 : /** Whether a warning should be emitted when an element or attribute is
442 : found in the document parsed, but ignored because of the ignored
443 : XPath defined. */
444 : std::map<CPLString, bool> m_oMapIgnoredXPathToWarn{};
445 :
446 : GMLASXLinkResolutionConf m_oXLinkResolution{};
447 :
448 : GMLASConfiguration() = default;
449 :
450 : bool Load(const char *pszFilename);
451 : void Finalize();
452 :
453 : static std::string GetDefaultConfFile(bool &bUnlinkAfterUse);
454 : };
455 :
456 : /************************************************************************/
457 : /* GMLASXLinkResolver */
458 : /************************************************************************/
459 :
460 : class GMLASXLinkResolver final : public GMLASResourceCache
461 : {
462 : GMLASXLinkResolutionConf m_oConf{};
463 : int m_nGlobalResolutionTime = 0;
464 :
465 : std::map<CPLString, CPLString> m_oMapURLToContent{};
466 : std::map<size_t, std::vector<CPLString>> m_oMapFileSizeToURLs{};
467 : size_t m_nMaxRAMCacheSize = 0;
468 : size_t m_nCurrentRAMCacheSize = 0;
469 :
470 : CPLString FetchRawContent(const CPLString &osURL, const char *pszHeaders);
471 :
472 : CPLString GetRawContent(const CPLString &osURL, const char *pszHeaders,
473 : bool bAllowRemoteDownload, bool bCacheResults);
474 :
475 : public:
476 : GMLASXLinkResolver();
477 :
478 : void SetConf(const GMLASXLinkResolutionConf &oConf);
479 :
480 19559 : const GMLASXLinkResolutionConf &GetConf() const
481 : {
482 19559 : return m_oConf;
483 : }
484 :
485 : bool IsRawContentResolutionEnabled() const;
486 : int GetMatchingResolutionRule(const CPLString &osURL) const;
487 : CPLString GetRawContent(const CPLString &osURL);
488 : CPLString GetRawContentForRule(const CPLString &osURL, int nIdxRule);
489 : };
490 :
491 : /************************************************************************/
492 : /* GMLASXPathMatcher */
493 : /************************************************************************/
494 :
495 : /** Object to compares a user provided XPath against a set of test XPaths */
496 : class GMLASXPathMatcher
497 : {
498 : struct XPathComponent
499 : {
500 : CPLString m_osValue{};
501 : bool m_bDirectChild = false;
502 : };
503 :
504 : /** For reference xpaths, map prefix namespace to its URI */
505 : std::map<CPLString, CPLString> m_oMapPrefixToURIReferenceXPaths{};
506 :
507 : /** Reference xpaths */
508 : std::vector<CPLString> m_aosReferenceXPathsUncompiled{};
509 :
510 : /** Reference xpaths "compiled" */
511 : std::vector<std::vector<XPathComponent>> m_aosReferenceXPaths{};
512 :
513 : static bool MatchesRefXPath(const CPLString &osXPath,
514 : const std::vector<XPathComponent> &oRefXPath);
515 :
516 : public:
517 : void SetRefXPaths(
518 : const std::map<CPLString, CPLString> &oMapPrefixToURIReferenceXPaths,
519 : const std::vector<CPLString> &aosReferenceXPaths);
520 :
521 : void SetDocumentMapURIToPrefix(
522 : const std::map<CPLString, CPLString> &oMapURIToPrefix);
523 :
524 : /** Return true if osXPath matches one of the XPath of
525 : m_aosReferenceXPaths */
526 : bool MatchesRefXPath(const CPLString &osXPath,
527 : CPLString &osOutMatchedXPath) const;
528 :
529 6 : const std::map<CPLString, CPLString> &GetMapPrefixToURI() const
530 : {
531 6 : return m_oMapPrefixToURIReferenceXPaths;
532 : }
533 : };
534 :
535 : /************************************************************************/
536 : /* GMLASFieldType */
537 : /************************************************************************/
538 :
539 : /** Enumeration for XML primitive types */
540 : typedef enum
541 : {
542 : GMLAS_FT_STRING,
543 : GMLAS_FT_ID,
544 : GMLAS_FT_BOOLEAN,
545 : GMLAS_FT_SHORT,
546 : GMLAS_FT_INT32,
547 : GMLAS_FT_INT64,
548 : GMLAS_FT_FLOAT,
549 : GMLAS_FT_DOUBLE,
550 : GMLAS_FT_DECIMAL,
551 : GMLAS_FT_DATE,
552 : GMLAS_FT_GYEAR,
553 : GMLAS_FT_GYEAR_MONTH,
554 : GMLAS_FT_TIME,
555 : GMLAS_FT_DATETIME,
556 : GMLAS_FT_BASE64BINARY,
557 : GMLAS_FT_HEXBINARY,
558 : GMLAS_FT_ANYURI,
559 : GMLAS_FT_ANYTYPE,
560 : GMLAS_FT_ANYSIMPLETYPE,
561 : GMLAS_FT_GEOMETRY, // this one isn't a XML primitive type.
562 : } GMLASFieldType;
563 :
564 : /************************************************************************/
565 : /* GMLASField */
566 : /************************************************************************/
567 :
568 : class GMLASField
569 : {
570 : public:
571 : typedef enum
572 : {
573 : /** Field that is going to be instantiated as a OGR field */
574 : REGULAR,
575 :
576 : /** Non-instanciable field. The corresponding element to the XPath
577 : is stored in a child layer that will reference back to the
578 : main layer. */
579 : PATH_TO_CHILD_ELEMENT_NO_LINK,
580 :
581 : /** Field that will store the PKID of a child element */
582 : PATH_TO_CHILD_ELEMENT_WITH_LINK,
583 :
584 : /** Non-instanciable field. The corresponding element to the XPath
585 : is stored in a child layer. And the link between both will be
586 : done through a junction table. */
587 : PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE,
588 :
589 : /** Non-instanciable field. Corresponds to a group of an element. */
590 : GROUP
591 : } Category;
592 :
593 : private:
594 : CPLString m_osName{}; /**< Field name */
595 : GMLASFieldType m_eType = GMLAS_FT_STRING; /**< Field type */
596 : OGRwkbGeometryType m_eGeomType = wkbNone; /**< Field geometry type */
597 : CPLString m_osTypeName{}; /**< Original XSD type */
598 : int m_nWidth = 0; /**< Field width */
599 : bool m_bNotNullable = false; /**< If the field is not nullable */
600 :
601 : /** If the field is an array (from OGR types point of view) */
602 : bool m_bArray = false;
603 : bool m_bList = false; /**< If the field is a list (a xs:list) */
604 :
605 : /** Category of the field. */
606 : Category m_eCategory = REGULAR;
607 :
608 : /** XPath of the field. */
609 : CPLString m_osXPath{};
610 :
611 : /** Set of XPath that are linked to this field.
612 : This is used for cases where a gml:AbstractGeometry element is
613 : referenced. In which case all possible realizations of this
614 : element are listed. Will be used with eType == GMLAS_FT_ANYTYPE
615 : to store XML blob on parsing. */
616 : std::vector<CPLString> m_aosXPath{};
617 :
618 : CPLString m_osFixedValue{}; /**< Value of fixed='' attribute */
619 : CPLString m_osDefaultValue{}; /**< Value of default='' attribute */
620 :
621 : /** Minimum number of occurrences. Might be -1 if unset */
622 : int m_nMinOccurs = -1;
623 :
624 : /** Maximum number of occurrences, or MAXOCCURS_UNLIMITED. Might be
625 : -1 if unset. */
626 : int m_nMaxOccurs = -1;
627 :
628 : /** For a PATH_TO_CHILD_ELEMENT_NO_LINK, whether maxOccurs>1 is on the
629 : sequence rather than on the element */
630 : bool m_bRepetitionOnSequence = false;
631 :
632 : /** In case of m_eType == GMLAS_FT_ANYTYPE whether the current element
633 : must be stored in the XML blob (if false, only its children) */
634 : bool m_bIncludeThisEltInBlob = false;
635 :
636 : /** Only used for PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE. The XPath
637 : of the abstract element (the concrete XPath is in m_osXPath).
638 : e.g myns:mainElt/myns:subEltAbstract whereas the concrete XPath
639 : is myns:mainElt/myns:subEltRealization */
640 : CPLString m_osAbstractElementXPath{};
641 :
642 : /** Only used for PATH_TO_CHILD_ELEMENT_WITH_LINK and
643 : PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE (and also for
644 : PATH_TO_CHILD_ELEMENT_NO_LINK and GROUP but for metadata layers only).
645 : The XPath of the child element. */
646 : CPLString m_osRelatedClassXPath{};
647 :
648 : /** Only use for PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE. Name of
649 : the junction layer to consult for this field. Only used by
650 : writer code. */
651 : CPLString m_osJunctionLayer{};
652 :
653 : /** Dirty hack to register attributes with fixed values, despite being
654 : in the XPath ignored list. Needed to avoid warning when doing validation
655 : */
656 : bool m_bIgnored = false;
657 :
658 : /** Documentation from schema */
659 : CPLString m_osDoc{};
660 :
661 : /** For elements within xs:choice */
662 : bool m_bMayAppearOutOfOrder = false;
663 :
664 : public:
665 231519 : GMLASField() = default;
666 :
667 819392 : void SetName(const CPLString &osName)
668 : {
669 819392 : m_osName = osName;
670 819392 : }
671 :
672 : void SetType(GMLASFieldType eType, const char *pszTypeName);
673 :
674 739 : void SetGeomType(OGRwkbGeometryType eGeomType)
675 : {
676 739 : m_eGeomType = eGeomType;
677 739 : }
678 :
679 200972 : void SetWidth(int nWidth)
680 : {
681 200972 : m_nWidth = nWidth;
682 200972 : }
683 :
684 174697 : void SetNotNullable(bool bNotNullable)
685 : {
686 174697 : m_bNotNullable = bNotNullable;
687 174697 : }
688 :
689 4250 : void SetArray(bool bArray)
690 : {
691 4250 : m_bArray = bArray;
692 4250 : }
693 :
694 2504 : void SetList(bool bList)
695 : {
696 2504 : m_bList = bList;
697 2504 : }
698 :
699 230717 : void SetXPath(const CPLString &osXPath)
700 : {
701 230717 : m_osXPath = osXPath;
702 230717 : }
703 :
704 1780 : void AddAlternateXPath(const CPLString &osXPath)
705 : {
706 1780 : m_aosXPath.push_back(osXPath);
707 1780 : }
708 :
709 1105 : void SetFixedValue(const CPLString &osFixedValue)
710 : {
711 1105 : m_osFixedValue = osFixedValue;
712 1105 : }
713 :
714 922 : void SetDefaultValue(const CPLString &osDefaultValue)
715 : {
716 922 : m_osDefaultValue = osDefaultValue;
717 922 : }
718 :
719 29712 : void SetCategory(Category eCategory)
720 : {
721 29712 : m_eCategory = eCategory;
722 29712 : }
723 :
724 336809 : void SetMinOccurs(int nMinOccurs)
725 : {
726 336809 : m_nMinOccurs = nMinOccurs;
727 336809 : }
728 :
729 230593 : void SetMaxOccurs(int nMaxOccurs)
730 : {
731 230593 : m_nMaxOccurs = nMaxOccurs;
732 230593 : }
733 :
734 818 : void SetRepetitionOnSequence(bool b)
735 : {
736 818 : m_bRepetitionOnSequence = b;
737 818 : }
738 :
739 321 : void SetIncludeThisEltInBlob(bool b)
740 : {
741 321 : m_bIncludeThisEltInBlob = b;
742 321 : }
743 :
744 9857 : void SetAbstractElementXPath(const CPLString &osName)
745 : {
746 9857 : m_osAbstractElementXPath = osName;
747 9857 : }
748 :
749 29144 : void SetRelatedClassXPath(const CPLString &osName)
750 : {
751 29144 : m_osRelatedClassXPath = osName;
752 29144 : }
753 :
754 16 : void SetJunctionLayer(const CPLString &osName)
755 : {
756 16 : m_osJunctionLayer = osName;
757 16 : }
758 :
759 451 : void SetIgnored()
760 : {
761 451 : m_bIgnored = true;
762 451 : }
763 :
764 200833 : void SetDocumentation(const CPLString &osDoc)
765 : {
766 200833 : m_osDoc = osDoc;
767 200833 : }
768 :
769 149490 : void SetMayAppearOutOfOrder(bool b)
770 : {
771 149490 : m_bMayAppearOutOfOrder = b;
772 149490 : }
773 :
774 : static CPLString
775 22 : MakePKIDFieldXPathFromXLinkHrefXPath(const CPLString &osBaseXPath)
776 : {
777 44 : return "{" + osBaseXPath + "}_pkid";
778 : }
779 :
780 25 : static CPLString MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(
781 : const CPLString &osBaseXPath)
782 : {
783 50 : return "{" + osBaseXPath + "}_rawcontent";
784 : }
785 :
786 : static CPLString
787 40 : MakeXLinkDerivedFieldXPathFromXLinkHrefXPath(const CPLString &osBaseXPath,
788 : const CPLString &osName)
789 : {
790 80 : return "{" + osBaseXPath + "}_derived_" + osName;
791 : }
792 :
793 1767320 : const CPLString &GetName() const
794 : {
795 1767320 : return m_osName;
796 : }
797 :
798 6560560 : const CPLString &GetXPath() const
799 : {
800 6560560 : return m_osXPath;
801 : }
802 :
803 200459 : const std::vector<CPLString> &GetAlternateXPaths() const
804 : {
805 200459 : return m_aosXPath;
806 : }
807 :
808 694478 : GMLASFieldType GetType() const
809 : {
810 694478 : return m_eType;
811 : }
812 :
813 737 : OGRwkbGeometryType GetGeomType() const
814 : {
815 737 : return m_eGeomType;
816 : }
817 :
818 386333 : const CPLString &GetTypeName() const
819 : {
820 386333 : return m_osTypeName;
821 : }
822 :
823 183842 : int GetWidth() const
824 : {
825 183842 : return m_nWidth;
826 : }
827 :
828 235352 : bool IsNotNullable() const
829 : {
830 235352 : return m_bNotNullable;
831 : }
832 :
833 351012 : bool IsArray() const
834 : {
835 351012 : return m_bArray;
836 : }
837 :
838 235266 : bool IsList() const
839 : {
840 235266 : return m_bList;
841 : }
842 :
843 2013780 : const CPLString &GetFixedValue() const
844 : {
845 2013780 : return m_osFixedValue;
846 : }
847 :
848 1869310 : const CPLString &GetDefaultValue() const
849 : {
850 1869310 : return m_osDefaultValue;
851 : }
852 :
853 2400050 : Category GetCategory() const
854 : {
855 2400050 : return m_eCategory;
856 : }
857 :
858 400830 : int GetMinOccurs() const
859 : {
860 400830 : return m_nMinOccurs;
861 : }
862 :
863 955178 : int GetMaxOccurs() const
864 : {
865 955178 : return m_nMaxOccurs;
866 : }
867 :
868 15895 : bool GetRepetitionOnSequence() const
869 : {
870 15895 : return m_bRepetitionOnSequence;
871 : }
872 :
873 5788 : bool GetIncludeThisEltInBlob() const
874 : {
875 5788 : return m_bIncludeThisEltInBlob;
876 : }
877 :
878 14423 : const CPLString &GetAbstractElementXPath() const
879 : {
880 14423 : return m_osAbstractElementXPath;
881 : }
882 :
883 24 : const CPLString &GetJunctionLayer() const
884 : {
885 24 : return m_osJunctionLayer;
886 : }
887 :
888 250502 : const CPLString &GetRelatedClassXPath() const
889 : {
890 250502 : return m_osRelatedClassXPath;
891 : }
892 :
893 199977 : bool IsIgnored() const
894 : {
895 199977 : return m_bIgnored;
896 : }
897 :
898 342899 : const CPLString &GetDocumentation() const
899 : {
900 342899 : return m_osDoc;
901 : }
902 :
903 4 : bool MayAppearOutOfOrder() const
904 : {
905 4 : return m_bMayAppearOutOfOrder;
906 : }
907 :
908 : static GMLASFieldType GetTypeFromString(const CPLString &osType);
909 : };
910 :
911 : /************************************************************************/
912 : /* GMLASFeatureClass */
913 : /************************************************************************/
914 :
915 : class GMLASFeatureClass
916 : {
917 : /** User facing name */
918 : CPLString m_osName{};
919 :
920 : /** XPath to the main element of the feature class */
921 : CPLString m_osXPath{};
922 :
923 : /** List of fields */
924 : std::vector<GMLASField> m_aoFields{};
925 :
926 : /** Child nested classes */
927 : std::vector<GMLASFeatureClass> m_aoNestedClasses{};
928 :
929 : /** Whether this layer corresponds to a (multiple instantiated) xs:group
930 : or a repeated sequence */
931 : bool m_bIsRepeatedSequence = false;
932 :
933 : /** Whether this is a repeated group. Should be set together with
934 : * m_bIsRepeatedSequence */
935 : bool m_bIsGroup = false;
936 :
937 : /** Only used for junction tables. The XPath to the parent table */
938 : CPLString m_osParentXPath{};
939 :
940 : /** Only used for junction tables. The XPath to the child table */
941 : CPLString m_osChildXPath{};
942 :
943 : /** Whether this corresponds to a top-level XSD element in the schema */
944 : bool m_bIsTopLevelElt = false;
945 :
946 : /** Documentation from schema */
947 : CPLString m_osDoc{};
948 :
949 : public:
950 44357 : GMLASFeatureClass() = default;
951 :
952 : void SetName(const CPLString &osName);
953 : void SetXPath(const CPLString &osXPath);
954 : void AddField(const GMLASField &oField);
955 : void PrependFields(const std::vector<GMLASField> &aoFields);
956 : void AppendFields(const std::vector<GMLASField> &aoFields);
957 : void AddNestedClass(const GMLASFeatureClass &oNestedClass);
958 :
959 4292 : void SetIsRepeatedSequence(bool bIsRepeatedSequence)
960 : {
961 4292 : m_bIsRepeatedSequence = bIsRepeatedSequence;
962 4292 : }
963 :
964 215 : void SetIsGroup(bool bIsGroup)
965 : {
966 215 : m_bIsGroup = bIsGroup;
967 215 : }
968 :
969 9857 : void SetParentXPath(const CPLString &osXPath)
970 : {
971 9857 : m_osParentXPath = osXPath;
972 9857 : }
973 :
974 9857 : void SetChildXPath(const CPLString &osXPath)
975 : {
976 9857 : m_osChildXPath = osXPath;
977 9857 : }
978 :
979 3322 : void SetIsTopLevelElt(bool bIsTopLevelElt)
980 : {
981 3322 : m_bIsTopLevelElt = bIsTopLevelElt;
982 3322 : }
983 :
984 31356 : void SetDocumentation(const CPLString &osDoc)
985 : {
986 31356 : m_osDoc = osDoc;
987 31356 : }
988 :
989 94154 : const CPLString &GetName() const
990 : {
991 94154 : return m_osName;
992 : }
993 :
994 7903870 : const CPLString &GetXPath() const
995 : {
996 7903870 : return m_osXPath;
997 : }
998 :
999 327878 : const std::vector<GMLASField> &GetFields() const
1000 : {
1001 327878 : return m_aoFields;
1002 : }
1003 :
1004 66385 : std::vector<GMLASField> &GetFields()
1005 : {
1006 66385 : return m_aoFields;
1007 : }
1008 :
1009 16958 : const std::vector<GMLASFeatureClass> &GetNestedClasses() const
1010 : {
1011 16958 : return m_aoNestedClasses;
1012 : }
1013 :
1014 50727 : std::vector<GMLASFeatureClass> &GetNestedClasses()
1015 : {
1016 50727 : return m_aoNestedClasses;
1017 : }
1018 :
1019 189133 : bool IsRepeatedSequence() const
1020 : {
1021 189133 : return m_bIsRepeatedSequence;
1022 : }
1023 :
1024 64261 : bool IsGroup() const
1025 : {
1026 64261 : return m_bIsGroup;
1027 : }
1028 :
1029 77230 : const CPLString &GetParentXPath() const
1030 : {
1031 77230 : return m_osParentXPath;
1032 : }
1033 :
1034 : const CPLString &GetChildXPath() const
1035 : {
1036 : return m_osChildXPath;
1037 : }
1038 :
1039 7101 : bool IsTopLevelElt() const
1040 : {
1041 7101 : return m_bIsTopLevelElt;
1042 : }
1043 :
1044 12844 : const CPLString &GetDocumentation() const
1045 : {
1046 12844 : return m_osDoc;
1047 : }
1048 : };
1049 :
1050 : /************************************************************************/
1051 : /* GMLASSchemaAnalyzer */
1052 : /************************************************************************/
1053 :
1054 : class GMLASSchemaAnalyzer
1055 : {
1056 : GMLASXPathMatcher &m_oIgnoredXPathMatcher;
1057 :
1058 : GMLASXPathMatcher &m_oChildrenElementsConstraintsXPathMatcher;
1059 :
1060 : GMLASXPathMatcher &m_oForcedFlattenedXPathMatcher;
1061 :
1062 : GMLASXPathMatcher &m_oDisabledFlattenedXPathMatcher;
1063 :
1064 : std::map<CPLString, std::vector<CPLString>>
1065 : m_oMapChildrenElementsConstraints{};
1066 :
1067 : /** Whether repeated strings, integers, reals should be in corresponding
1068 : OGR array types. */
1069 : bool m_bUseArrays = true;
1070 :
1071 : /** Whether OGR field null state should be used. */
1072 : bool m_bUseNullState = false;
1073 :
1074 : /** Whether, when dealing with schemas that import the
1075 : GML namespace, and that at least one of them has
1076 : elements that derive from gml:_Feature or
1077 : gml:AbstractFeatureonly, only such elements should be
1078 : instantiated as OGR layers, during the first pass that
1079 : iterates over top level elements of the imported
1080 : schemas. */
1081 : bool m_bInstantiateGMLFeaturesOnly = true;
1082 :
1083 : /** Vector of feature classes */
1084 : std::vector<GMLASFeatureClass> m_aoClasses{};
1085 :
1086 : /** Map from a namespace URI to the corresponding prefix */
1087 : std::map<CPLString, CPLString> m_oMapURIToPrefix{};
1088 :
1089 : /** Map element XPath to its XSElementDeclaration* */
1090 : std::map<CPLString, XSElementDeclaration *> m_oMapXPathToEltDecl{};
1091 :
1092 : typedef std::map<XSElementDeclaration *,
1093 : std::vector<XSElementDeclaration *>>
1094 : tMapParentEltToChildElt;
1095 : /** Map from a base/parent element to a vector of derived/children
1096 : elements that are substitutionGroup of it. The map only
1097 : addresses the direct derived types, and not the 2nd level or more
1098 : derived ones. For that recursion in the map must be used.*/
1099 : tMapParentEltToChildElt m_oMapParentEltToChildElt{};
1100 :
1101 : /** Map from a XSModelGroup* object to the name of its group definition. */
1102 : std::map<XSModelGroup *, XSModelGroupDefinition *> m_oMapModelGroupToMGD{};
1103 :
1104 : /** Map from (non namespace prefixed) element names to the number of
1105 : elements that share the same namespace (in different namespaces) */
1106 : std::map<CPLString, int> m_oMapEltNamesToInstanceCount{};
1107 :
1108 : /** Set of elements that match a OGR layer */
1109 : std::set<XSElementDeclaration *> m_oSetEltsForTopClass{};
1110 :
1111 : /** Set of elements that are simple enough to be inlined whenever they
1112 : are referenced with cardinality 1. The use case if base:identifier
1113 : used by Inspire schemas. */
1114 : std::set<XSElementDeclaration *> m_oSetSimpleEnoughElts{};
1115 :
1116 : /** Maximum length of layer and field identifiers*/
1117 : int m_nIdentifierMaxLength = 0;
1118 :
1119 : /** Whether case insensitive comparison should be used for identifier
1120 : * equality testing */
1121 : bool m_bCaseInsensitiveIdentifier = CASE_INSENSITIVE_IDENTIFIER_DEFAULT;
1122 :
1123 : /** Whether to launder identifiers like postgresql does */
1124 : bool m_bPGIdentifierLaundering = PG_IDENTIFIER_LAUNDERING_DEFAULT;
1125 :
1126 : /* Maximum number of fields in an element considered for flattening. */
1127 : int m_nMaximumFieldsForFlattening = MAXIMUM_FIELDS_FLATTENING_DEFAULT;
1128 :
1129 : /** GML version found: 2.1.1, 3.1.1 or 3.2.1 or empty*/
1130 : CPLString m_osGMLVersionFound{};
1131 :
1132 : /** Set of schemas opened */
1133 : std::set<CPLString> m_oSetSchemaURLs{};
1134 :
1135 : /** Map from namespace URI to namespace prefix coming from the
1136 : * examination of xmlns:foo=bar attributes of the top element of the
1137 : * GML document */
1138 : std::map<CPLString, CPLString> m_oMapDocNSURIToPrefix{};
1139 :
1140 : bool m_bAlwaysGenerateOGRId = ALWAYS_GENERATE_OGR_ID_DEFAULT;
1141 :
1142 : static bool IsSame(const XSModelGroup *poModelGroup1,
1143 : const XSModelGroup *poModelGroup2);
1144 : XSModelGroupDefinition *
1145 : GetGroupDefinition(const XSModelGroup *poModelGroup);
1146 : bool SetFieldFromAttribute(GMLASField &oField, XSAttributeUse *poAttr,
1147 : const CPLString &osXPathPrefix,
1148 : const CPLString &osNamePrefix = CPLString());
1149 : void GetConcreteImplementationTypes(
1150 : XSElementDeclaration *poParentElt,
1151 : std::vector<XSElementDeclaration *> &apoImplEltList);
1152 : std::vector<XSElementDeclaration *>
1153 : GetConstraintChildrenElements(const CPLString &osFullXPath);
1154 : bool FindElementsWithMustBeToLevel(
1155 : const CPLString &osParentXPath, XSModelGroup *poModelGroup,
1156 : int nRecursionCounter,
1157 : std::set<XSElementDeclaration *> &oSetVisitedEltDecl,
1158 : std::set<XSModelGroup *> &oSetVisitedModelGroups,
1159 : std::vector<XSElementDeclaration *> &oVectorEltsForTopClass,
1160 : std::set<CPLString> &aoSetXPathEltsForTopClass, XSModel *poModel,
1161 : bool &bSimpleEnoughOut, int &nCountSubEltsOut);
1162 : static void BuildMapCountOccurrencesOfSameName(
1163 : XSModelGroup *poModelGroup,
1164 : std::map<CPLString, int> &oMapCountOccurrencesOfSameName);
1165 : bool ExploreModelGroup(
1166 : XSModelGroup *psMainModelGroup, XSAttributeUseList *poMainAttrList,
1167 : GMLASFeatureClass &oClass, int nRecursionCounter,
1168 : std::set<XSModelGroup *> &oSetVisitedModelGroups, XSModel *poModel,
1169 : const std::map<CPLString, int> &oMapCountOccurrencesOfSameName);
1170 : void SetFieldTypeAndWidthFromDefinition(XSSimpleTypeDefinition *poST,
1171 : GMLASField &oField);
1172 : CPLString GetPrefix(const CPLString &osNamespaceURI);
1173 : CPLString MakeXPath(const CPLString &osNamespace, const CPLString &osName);
1174 : bool LaunderFieldNames(GMLASFeatureClass &oClass);
1175 : void LaunderClassNames();
1176 :
1177 : XSElementDeclaration *
1178 : GetTopElementDeclarationFromXPath(const CPLString &osXPath,
1179 : XSModel *poModel);
1180 :
1181 : bool InstantiateClassFromEltDeclaration(XSElementDeclaration *poEltDecl,
1182 : XSModel *poModel, bool &bError);
1183 : void CreateNonNestedRelationship(
1184 : XSElementDeclaration *poElt,
1185 : std::vector<XSElementDeclaration *> &apoSubEltList,
1186 : GMLASFeatureClass &oClass, int nMaxOccurs, bool bEltNameWillNeedPrefix,
1187 : bool bForceJunctionTable, bool bCaseOfConstraintChildren);
1188 :
1189 : bool IsGMLNamespace(const CPLString &osURI);
1190 :
1191 : bool DerivesFromGMLFeature(XSElementDeclaration *poEltDecl);
1192 :
1193 : bool IsIgnoredXPath(const CPLString &osXPath);
1194 :
1195 : static void
1196 : CollectClassesReferences(GMLASFeatureClass &oClass,
1197 : std::vector<GMLASFeatureClass *> &aoClasses);
1198 :
1199 : CPL_DISALLOW_COPY_ASSIGN(GMLASSchemaAnalyzer)
1200 :
1201 : public:
1202 : GMLASSchemaAnalyzer(
1203 : GMLASXPathMatcher &oIgnoredXPathMatcher,
1204 : GMLASXPathMatcher &oChildrenElementsConstraintsXPathMatcher,
1205 : const std::map<CPLString, std::vector<CPLString>>
1206 : &oMapChildrenElementsConstraints,
1207 : GMLASXPathMatcher &oForcedFlattenedXPathMatcher,
1208 : GMLASXPathMatcher &oDisabledFlattenedXPathMatcher);
1209 :
1210 193 : void SetUseArrays(bool b)
1211 : {
1212 193 : m_bUseArrays = b;
1213 193 : }
1214 :
1215 193 : void SetUseNullState(bool b)
1216 : {
1217 193 : m_bUseNullState = b;
1218 193 : }
1219 :
1220 193 : void SetInstantiateGMLFeaturesOnly(bool b)
1221 : {
1222 193 : m_bInstantiateGMLFeaturesOnly = b;
1223 193 : }
1224 :
1225 193 : void SetIdentifierMaxLength(int nLength)
1226 : {
1227 193 : m_nIdentifierMaxLength = nLength;
1228 193 : }
1229 :
1230 193 : void SetCaseInsensitiveIdentifier(bool b)
1231 : {
1232 193 : m_bCaseInsensitiveIdentifier = b;
1233 193 : }
1234 :
1235 193 : void SetPGIdentifierLaundering(bool b)
1236 : {
1237 193 : m_bPGIdentifierLaundering = b;
1238 193 : }
1239 :
1240 193 : void SetMaximumFieldsForFlattening(int n)
1241 : {
1242 193 : m_nMaximumFieldsForFlattening = n;
1243 193 : }
1244 :
1245 158 : void SetMapDocNSURIToPrefix(const std::map<CPLString, CPLString> &oMap)
1246 : {
1247 158 : m_oMapDocNSURIToPrefix = oMap;
1248 158 : }
1249 :
1250 193 : void SetAlwaysGenerateOGRId(bool b)
1251 : {
1252 193 : m_bAlwaysGenerateOGRId = b;
1253 193 : }
1254 :
1255 : bool Analyze(GMLASXSDCache &oCache, const CPLString &osBaseDirname,
1256 : std::vector<PairURIFilename> &aoXSDs, bool bSchemaFullChecking,
1257 : bool bHandleMultipleImports);
1258 :
1259 178 : const std::vector<GMLASFeatureClass> &GetClasses() const
1260 : {
1261 178 : return m_aoClasses;
1262 : }
1263 :
1264 178 : const std::map<CPLString, CPLString> &GetMapURIToPrefix() const
1265 : {
1266 178 : return m_oMapURIToPrefix;
1267 : }
1268 :
1269 178 : const CPLString &GetGMLVersionFound() const
1270 : {
1271 178 : return m_osGMLVersionFound;
1272 : }
1273 :
1274 178 : const std::set<CPLString> &GetSchemaURLS() const
1275 : {
1276 178 : return m_oSetSchemaURLs;
1277 : }
1278 :
1279 14453 : static CPLString BuildJunctionTableXPath(const CPLString &osEltXPath,
1280 : const CPLString &osSubEltXPath)
1281 : {
1282 28906 : return osEltXPath + "|" + osSubEltXPath;
1283 : }
1284 : };
1285 :
1286 : /************************************************************************/
1287 : /* OGRGMLASDataSource */
1288 : /************************************************************************/
1289 :
1290 : class OGRGMLASLayer;
1291 : class GMLASReader;
1292 :
1293 : class OGRGMLASDataSource final : public GDALDataset
1294 : {
1295 : struct XercesInitializer
1296 : {
1297 : XercesInitializer();
1298 : ~XercesInitializer();
1299 : };
1300 :
1301 : // MUST be first member, to get destroyed last after we have cleaned up
1302 : // all other Xerces dependent objects.
1303 : XercesInitializer m_oXercesInitializer{};
1304 :
1305 : std::vector<std::unique_ptr<OGRGMLASLayer>> m_apoLayers{};
1306 : std::map<CPLString, CPLString> m_oMapURIToPrefix{};
1307 : CPLString m_osGMLFilename{};
1308 : std::unique_ptr<OGRLayer> m_poFieldsMetadataLayer{};
1309 : std::unique_ptr<OGRLayer> m_poLayersMetadataLayer{};
1310 : std::unique_ptr<OGRLayer> m_poRelationshipsLayer{};
1311 : std::unique_ptr<OGRLayer> m_poOtherMetadataLayer{};
1312 : std::vector<OGRLayer *> m_apoRequestedMetadataLayers{};
1313 : std::shared_ptr<VSIVirtualHandle> m_fpGML{};
1314 : std::shared_ptr<VSIVirtualHandle> m_fpGMLParser{};
1315 : bool m_bLayerInitFinished = false;
1316 : bool m_bSchemaFullChecking = false;
1317 : bool m_bHandleMultipleImports = false;
1318 : bool m_bValidate = false;
1319 : bool m_bRemoveUnusedLayers = false;
1320 : bool m_bRemoveUnusedFields = false;
1321 : bool m_bFirstPassDone = false;
1322 : /** Map from a SRS name to a boolean indicating if its coordinate
1323 : order is inverted. */
1324 : std::map<CPLString, bool> m_oMapSRSNameToInvertedAxis{};
1325 :
1326 : /** Map from geometry field definition to its expected SRSName */
1327 : std::map<OGRGeomFieldDefn *, CPLString> m_oMapGeomFieldDefnToSRSName{};
1328 :
1329 : /* map the ID attribute to its belonging layer, e.g foo.1 -> layer Foo */
1330 : std::map<CPLString, OGRGMLASLayer *> m_oMapElementIdToLayer{};
1331 :
1332 : /* map the ID attribute to the feature PKID (when different from itself) */
1333 : std::map<CPLString, CPLString> m_oMapElementIdToPKID{};
1334 :
1335 : std::vector<PairURIFilename> m_aoXSDsManuallyPassed{};
1336 :
1337 : /** Default value for srsDimension attribute. */
1338 : int m_nDefaultSrsDimension = 0;
1339 :
1340 : GMLASConfiguration m_oConf{};
1341 :
1342 : /** Schema cache */
1343 : GMLASXSDCache m_oCache{};
1344 :
1345 : GMLASXPathMatcher m_oIgnoredXPathMatcher{};
1346 :
1347 : GMLASXPathMatcher m_oChildrenElementsConstraintsXPathMatcher{};
1348 :
1349 : GMLASXPathMatcher m_oForcedFlattenedXPathMatcher{};
1350 :
1351 : GMLASXPathMatcher m_oDisabledFlattenedXPathMatcher{};
1352 :
1353 : GMLASSwapCoordinatesEnum m_eSwapCoordinates = GMLAS_SWAP_AUTO;
1354 :
1355 : /** Base unique identifier */
1356 : CPLString m_osHash{};
1357 :
1358 : vsi_l_offset m_nFileSize = 0;
1359 :
1360 : std::unique_ptr<GMLASReader> m_poReader{};
1361 :
1362 : bool m_bEndOfReaderLayers = false;
1363 :
1364 : int m_nCurMetadataLayerIdx = -1;
1365 :
1366 : GMLASXLinkResolver m_oXLinkResolver{};
1367 :
1368 : CPLString m_osGMLVersionFound{};
1369 :
1370 : bool m_bFoundSWE = false;
1371 :
1372 : // Pointers are also included in m_apoLayers
1373 : std::vector<OGRGMLASLayer *> m_apoSWEDataArrayLayersRef{};
1374 :
1375 : // Path to gmlasconf.xml. It is a /vsimem temporary file if
1376 : // m_bUnlinkConfigFileAfterUse is set.
1377 : std::string m_osConfigFile{};
1378 :
1379 : // Whether m_osConfigFile should be removed at closing.
1380 : bool m_bUnlinkConfigFileAfterUse = false;
1381 :
1382 : void TranslateClasses(OGRGMLASLayer *poParentLayer,
1383 : const GMLASFeatureClass &oFC);
1384 :
1385 : bool RunFirstPassIfNeeded(GMLASReader *poReader,
1386 : GDALProgressFunc pfnProgress,
1387 : void *pProgressData);
1388 :
1389 : void FillOtherMetadataLayer(GDALOpenInfo *poOpenInfo,
1390 : const CPLString &osConfigFile,
1391 : const std::vector<PairURIFilename> &aoXSDs,
1392 : const std::set<CPLString> &oSetSchemaURLs);
1393 :
1394 : static std::vector<PairURIFilename>
1395 : BuildXSDVector(const CPLString &osXSDFilenames);
1396 :
1397 : void InitReaderWithFirstPassElements(GMLASReader *poReader);
1398 :
1399 : public:
1400 : OGRGMLASDataSource();
1401 :
1402 : ~OGRGMLASDataSource();
1403 :
1404 : virtual int GetLayerCount() override;
1405 : virtual OGRLayer *GetLayer(int) override;
1406 : virtual OGRLayer *GetLayerByName(const char *pszName) override;
1407 :
1408 : virtual void ResetReading() override;
1409 : virtual OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
1410 : double *pdfProgressPct,
1411 : GDALProgressFunc pfnProgress,
1412 : void *pProgressData) override;
1413 : virtual int TestCapability(const char *) override;
1414 :
1415 : bool Open(GDALOpenInfo *poOpenInfo);
1416 :
1417 1392 : std::vector<std::unique_ptr<OGRGMLASLayer>> &GetLayers()
1418 : {
1419 1392 : return m_apoLayers;
1420 : }
1421 :
1422 1392 : const std::map<CPLString, CPLString> &GetMapURIToPrefix() const
1423 : {
1424 1392 : return m_oMapURIToPrefix;
1425 : }
1426 :
1427 1475 : const CPLString &GetGMLFilename() const
1428 : {
1429 1475 : return m_osGMLFilename;
1430 : }
1431 :
1432 : const CPLString &GetGMLVersionFound() const
1433 : {
1434 : return m_osGMLVersionFound;
1435 : }
1436 :
1437 16987 : OGRLayer *GetFieldsMetadataLayer()
1438 : {
1439 16987 : return m_poFieldsMetadataLayer.get();
1440 : }
1441 :
1442 16958 : OGRLayer *GetLayersMetadataLayer()
1443 : {
1444 16958 : return m_poLayersMetadataLayer.get();
1445 : }
1446 :
1447 16961 : OGRLayer *GetRelationshipsLayer()
1448 : {
1449 16961 : return m_poRelationshipsLayer.get();
1450 : }
1451 :
1452 : OGRGMLASLayer *GetLayerByXPath(const CPLString &osXPath);
1453 :
1454 : GMLASReader *CreateReader(std::shared_ptr<VSIVirtualHandle> &fpGML,
1455 : GDALProgressFunc pfnProgress = nullptr,
1456 : void *pProgressData = nullptr);
1457 :
1458 1280 : GMLASXSDCache &GetCache()
1459 : {
1460 1280 : return m_oCache;
1461 : }
1462 :
1463 : void PushUnusedGMLFilePointer(std::shared_ptr<VSIVirtualHandle> &fpGML);
1464 : std::shared_ptr<VSIVirtualHandle> PopUnusedGMLFilePointer();
1465 :
1466 61587 : bool IsLayerInitFinished() const
1467 : {
1468 61587 : return m_bLayerInitFinished;
1469 : }
1470 :
1471 1280 : GMLASSwapCoordinatesEnum GetSwapCoordinates() const
1472 : {
1473 1280 : return m_eSwapCoordinates;
1474 : }
1475 :
1476 1280 : const std::map<CPLString, bool> &GetMapIgnoredXPathToWarn() const
1477 : {
1478 1280 : return m_oConf.m_oMapIgnoredXPathToWarn;
1479 : }
1480 :
1481 1280 : const GMLASXPathMatcher &GetIgnoredXPathMatcher() const
1482 : {
1483 1280 : return m_oIgnoredXPathMatcher;
1484 : }
1485 :
1486 982 : const GMLASConfiguration &GetConf() const
1487 : {
1488 982 : return m_oConf;
1489 : }
1490 :
1491 : const std::vector<PairURIFilename> &GetXSDsManuallyPassed() const
1492 : {
1493 : return m_aoXSDsManuallyPassed;
1494 : }
1495 : };
1496 :
1497 : /************************************************************************/
1498 : /* OGRGMLASLayer */
1499 : /************************************************************************/
1500 :
1501 : class OGRGMLASLayer final : public OGRLayer
1502 : {
1503 : friend class OGRGMLASDataSource;
1504 :
1505 : OGRGMLASDataSource *m_poDS = nullptr;
1506 : GMLASFeatureClass m_oFC{};
1507 : bool m_bLayerDefnFinalized = false;
1508 : int m_nMaxFieldIndex = 0;
1509 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
1510 :
1511 : /** Map from XPath to corresponding field index in OGR layer
1512 : definition */
1513 : std::map<CPLString, int> m_oMapFieldXPathToOGRFieldIdx{};
1514 :
1515 : /** Map from XPath to corresponding geometry field index in OGR layer
1516 : definition */
1517 : std::map<CPLString, int> m_oMapFieldXPathToOGRGeomFieldIdx{};
1518 :
1519 : /** Map from a OGR field index to the corresponding field index in
1520 : m_oFC.GetFields() */
1521 : std::map<int, int> m_oMapOGRFieldIdxtoFCFieldIdx{};
1522 : std::map<int, int> m_oMapOGRGeomFieldIdxtoFCFieldIdx{};
1523 :
1524 : /** Map from XPath to corresponding field index in m_oFC.GetFields() */
1525 : std::map<CPLString, int> m_oMapFieldXPathToFCFieldIdx{};
1526 :
1527 : bool m_bEOF = false;
1528 : std::unique_ptr<GMLASReader> m_poReader{};
1529 : std::shared_ptr<VSIVirtualHandle> m_fpGML{};
1530 : /** OGR field index of the ID field */
1531 : int m_nIDFieldIdx = -1;
1532 : /** Whether the ID field is generated, or comes from the XML content */
1533 : bool m_bIDFieldIsGenerated = false;
1534 : /** Pointer to parent layer */
1535 : OGRGMLASLayer *m_poParentLayer = nullptr;
1536 : /** OGR field index of the field that points to the parent ID */
1537 : int m_nParentIDFieldIdx = -1;
1538 :
1539 : std::map<CPLString, CPLString> m_oMapSWEFieldToOGRFieldName{};
1540 :
1541 : OGRFeature *GetNextRawFeature();
1542 :
1543 : bool InitReader();
1544 :
1545 14212 : void SetLayerDefnFinalized(bool bVal)
1546 : {
1547 14212 : m_bLayerDefnFinalized = bVal;
1548 14212 : }
1549 :
1550 : CPLString LaunderFieldName(const CPLString &osFieldName);
1551 :
1552 : CPLString GetXPathFromOGRFieldIndex(int nIdx) const;
1553 :
1554 : CPL_DISALLOW_COPY_ASSIGN(OGRGMLASLayer)
1555 :
1556 : public:
1557 : OGRGMLASLayer(OGRGMLASDataSource *poDS, const GMLASFeatureClass &oFC,
1558 : OGRGMLASLayer *poParentLayer, bool bAlwaysGenerateOGRPKId);
1559 : explicit OGRGMLASLayer(const char *pszLayerName);
1560 : virtual ~OGRGMLASLayer();
1561 :
1562 352967 : virtual const char *GetName() override
1563 : {
1564 352967 : return GetDescription();
1565 : }
1566 :
1567 : virtual OGRFeatureDefn *GetLayerDefn() override;
1568 : virtual void ResetReading() override;
1569 : virtual OGRFeature *GetNextFeature() override;
1570 :
1571 919 : virtual int TestCapability(const char *) override
1572 : {
1573 919 : return FALSE;
1574 : }
1575 :
1576 3 : void SetDataSource(OGRGMLASDataSource *poDS)
1577 : {
1578 3 : m_poDS = poDS;
1579 3 : }
1580 :
1581 : void PostInit(bool bIncludeGeometryXML);
1582 : void
1583 : ProcessDataRecordCreateFields(CPLXMLNode *psDataRecord,
1584 : const std::vector<OGRFeature *> &apoFeatures,
1585 : OGRLayer *poFieldsMetadataLayer);
1586 : void ProcessDataRecordFillFeature(CPLXMLNode *psDataRecord,
1587 : OGRFeature *poFeature);
1588 : void
1589 : ProcessDataRecordOfDataArrayCreateFields(OGRGMLASLayer *poParentLayer,
1590 : CPLXMLNode *psDataRecord,
1591 : OGRLayer *poFieldsMetadataLayer);
1592 : void CreateCompoundFoldedMappings();
1593 :
1594 8154920 : const GMLASFeatureClass &GetFeatureClass() const
1595 : {
1596 8154920 : return m_oFC;
1597 : }
1598 :
1599 : int GetOGRFieldIndexFromXPath(const CPLString &osXPath) const;
1600 : int GetOGRGeomFieldIndexFromXPath(const CPLString &osXPath) const;
1601 :
1602 207980 : int GetIDFieldIdx() const
1603 : {
1604 207980 : return m_nIDFieldIdx;
1605 : }
1606 :
1607 52467 : bool IsGeneratedIDField() const
1608 : {
1609 52467 : return m_bIDFieldIsGenerated;
1610 : }
1611 :
1612 109449 : OGRGMLASLayer *GetParent()
1613 : {
1614 109449 : return m_poParentLayer;
1615 : }
1616 :
1617 90567 : int GetParentIDFieldIdx() const
1618 : {
1619 90567 : return m_nParentIDFieldIdx;
1620 : }
1621 :
1622 : int GetFCFieldIndexFromOGRFieldIdx(int iOGRFieldIdx) const;
1623 : int GetFCFieldIndexFromOGRGeomFieldIdx(int iOGRGeomFieldIdx) const;
1624 : int GetFCFieldIndexFromXPath(const CPLString &osXPath) const;
1625 :
1626 : bool EvaluateFilter(OGRFeature *poFeature);
1627 :
1628 : bool RemoveField(int nIdx);
1629 : void InsertNewField(int nInsertPos, const OGRFieldDefn &oFieldDefn,
1630 : const CPLString &osXPath);
1631 :
1632 : CPLString
1633 : GetXPathOfFieldLinkForAttrToOtherLayer(const CPLString &osFieldName,
1634 : const CPLString &osTargetLayerXPath);
1635 : CPLString
1636 : CreateLinkForAttrToOtherLayer(const CPLString &osFieldName,
1637 : const CPLString &osTargetLayerXPath);
1638 :
1639 2237 : const std::map<CPLString, int> &GetMapFieldXPathToOGRFieldIdx() const
1640 : {
1641 2237 : return m_oMapFieldXPathToOGRFieldIdx;
1642 : }
1643 : };
1644 :
1645 : /************************************************************************/
1646 : /* GMLASReader */
1647 : /************************************************************************/
1648 :
1649 : class GMLASReader final : public DefaultHandler
1650 : {
1651 : /** Schema cache */
1652 : GMLASXSDCache &m_oCache;
1653 :
1654 : /** Object to tell if a XPath must be ignored */
1655 : const GMLASXPathMatcher &m_oIgnoredXPathMatcher;
1656 :
1657 : /** XLink resolver */
1658 : GMLASXLinkResolver &m_oXLinkResolver;
1659 :
1660 : /** Whether we should stop parsing */
1661 : bool m_bParsingError = false;
1662 :
1663 : /** Xerces reader object */
1664 : std::unique_ptr<SAX2XMLReader> m_poSAXReader{};
1665 :
1666 : /** Token for Xerces */
1667 : XMLPScanToken m_oToFill{};
1668 :
1669 : /** File descriptor */
1670 : std::shared_ptr<VSIVirtualHandle> m_fp{};
1671 :
1672 : /** Input source */
1673 : std::unique_ptr<GMLASInputSource> m_GMLInputSource{};
1674 :
1675 : /** Whether we are at the first iteration */
1676 : bool m_bFirstIteration = true;
1677 :
1678 : /** Whether we have reached end of file (or an error) */
1679 : bool m_bEOF = false;
1680 :
1681 : /** Whether GetNextFeature() has been user interrupted (progress cbk) */
1682 : bool m_bInterrupted = false;
1683 :
1684 : /** Error handler (for Xerces reader) */
1685 : GMLASErrorHandler m_oErrorHandler{};
1686 :
1687 : /** Map URI namespaces to their prefix */
1688 : std::map<CPLString, CPLString> m_oMapURIToPrefix{};
1689 :
1690 : /** List of OGR layers */
1691 : std::vector<std::unique_ptr<OGRGMLASLayer>> *m_apoLayers = nullptr;
1692 :
1693 : /** Vector of features ready for consumption */
1694 : std::list<std::pair<std::unique_ptr<OGRFeature>, OGRGMLASLayer *>>
1695 : m_aoFeaturesReady{};
1696 :
1697 : /** OGR field index of the current field */
1698 : int m_nCurFieldIdx = -1;
1699 :
1700 : /** OGR geometry field index of the current field */
1701 : int m_nCurGeomFieldIdx = -1;
1702 :
1703 : /** XML nested level of current field */
1704 : int m_nCurFieldLevel = 0;
1705 :
1706 : /** Whether we should store all content of the current field as XML */
1707 : bool m_bIsXMLBlob = false;
1708 : bool m_bIsXMLBlobIncludeUpper = false;
1709 :
1710 : /** Content of the current field */
1711 : CPLString m_osTextContent{};
1712 :
1713 : /** For list field types, list of content */
1714 : CPLStringList m_osTextContentList{};
1715 : /** Estimated memory footprint of m_osTextContentList */
1716 : size_t m_nTextContentListEstimatedSize = 0;
1717 :
1718 : /** Which layer is of interest for the reader, or NULL for all */
1719 : OGRGMLASLayer *m_poLayerOfInterest = nullptr;
1720 :
1721 : /** Stack of length of split XPath components */
1722 : std::vector<size_t> m_anStackXPathLength{};
1723 :
1724 : /** Current absolute XPath */
1725 : CPLString m_osCurXPath{};
1726 :
1727 : /** Current XPath, relative to top-level feature */
1728 : CPLString m_osCurSubXPath{};
1729 :
1730 : /** Current XML nesting level */
1731 : int m_nLevel = 0;
1732 :
1733 : /** Whether we are in a gml:boundedBy element at level 1 */
1734 : bool m_bInGMLBoundedByLevel1 = false;
1735 :
1736 : /** Default value for srsDimension attribute. */
1737 : int m_nDefaultSrsDimension = 0;
1738 :
1739 : /** Map layer to global FID */
1740 : std::map<OGRLayer *, int> m_oMapGlobalCounter{};
1741 :
1742 : /** Parsing context */
1743 : struct Context
1744 : {
1745 : /** XML nesting level */
1746 : int m_nLevel = 0;
1747 :
1748 : /** Current feature */
1749 : OGRFeature *m_poFeature = nullptr;
1750 :
1751 : /** Layer of m_poFeature */
1752 : OGRGMLASLayer *m_poLayer = nullptr;
1753 :
1754 : /** Current layer in a repeated group */
1755 : OGRGMLASLayer *m_poGroupLayer = nullptr;
1756 :
1757 : /** Nesting level of m_poCurGroupLayer */
1758 : int m_nGroupLayerLevel = -1;
1759 :
1760 : /** Index of the last processed OGR field in m_poCurGroupLayer */
1761 : int m_nLastFieldIdxGroupLayer = -1;
1762 :
1763 : /** Map layer to local FID */
1764 : std::map<OGRLayer *, int> m_oMapCounter{};
1765 :
1766 : /** Current XPath, relative to (current) top-level feature */
1767 : CPLString m_osCurSubXPath{};
1768 :
1769 : void Dump() const;
1770 : };
1771 :
1772 : /** Current context */
1773 : Context m_oCurCtxt{};
1774 :
1775 : /** Stack of saved contexts */
1776 : std::vector<Context> m_aoStackContext{};
1777 :
1778 : /** Context used in m_apsXMLNodeStack */
1779 : struct NodeLastChild
1780 : {
1781 : /** Current node */
1782 : CPLXMLNode *psNode = nullptr;
1783 :
1784 : /** Last child of psNode (for fast append operations) */
1785 : CPLXMLNode *psLastChild = nullptr;
1786 : };
1787 :
1788 : /** Stack of contexts to build XML tree of GML Geometry */
1789 : std::vector<NodeLastChild> m_apsXMLNodeStack{};
1790 :
1791 : /** Counter used to prevent XML billion laugh attacks */
1792 : int m_nEntityCounter = 0;
1793 :
1794 : /** Maximum allowed number of XML nesting level */
1795 : int m_nMaxLevel = 100;
1796 :
1797 : /** Maximum allowed size of XML content in byte */
1798 : size_t m_nMaxContentSize = 512000000;
1799 :
1800 : /** Map from a SRS name to a boolean indicating if its coordinate
1801 : order is inverted. */
1802 : std::map<CPLString, bool> m_oMapSRSNameToInvertedAxis{};
1803 :
1804 : /** Set of geometry fields with unknown SRS */
1805 : std::set<OGRGeomFieldDefn *> m_oSetGeomFieldsWithUnknownSRS{};
1806 :
1807 : /** Map from geometry field definition to its expected SRSName.
1808 : This is used to know if reprojection must be done */
1809 : std::map<OGRGeomFieldDefn *, CPLString> m_oMapGeomFieldDefnToSRSName{};
1810 :
1811 : /** Whether this parsing involves schema validation */
1812 : bool m_bValidate = false;
1813 :
1814 : /** Entity resolver used during schema validation */
1815 : std::unique_ptr<GMLASBaseEntityResolver> m_poEntityResolver{};
1816 :
1817 : /** First level from which warnings about ignored XPath should be
1818 : silent. */
1819 : int m_nLevelSilentIgnoredXPath = -1;
1820 :
1821 : /** Whether a warning should be emitted when an element or attribute is
1822 : found in the document parsed, but ignored because of the ignored
1823 : XPath defined. */
1824 : std::map<CPLString, bool> m_oMapIgnoredXPathToWarn{};
1825 :
1826 : /** Policy to decide when to invert coordinates */
1827 : GMLASSwapCoordinatesEnum m_eSwapCoordinates = GMLAS_SWAP_AUTO;
1828 :
1829 : /** Initial pass to guess SRS, etc... */
1830 : bool m_bInitialPass = false;
1831 :
1832 : /** Whether to process swe:DataArray in a special way */
1833 : bool m_bProcessSWEDataArray = false;
1834 :
1835 : /** Whether to process swe:DataArray in a special way */
1836 : bool m_bProcessSWEDataRecord = false;
1837 :
1838 : /** Depth level of the swe:DataArray element */
1839 : int m_nSWEDataArrayLevel = -1;
1840 :
1841 : /** Field name to which the DataArray belongs to */
1842 : CPLString m_osSWEDataArrayParentField{};
1843 :
1844 : /** Depth level of the swe:DataRecord element */
1845 : int m_nSWEDataRecordLevel = -1;
1846 :
1847 : OGRLayer *m_poFieldsMetadataLayer = nullptr;
1848 : OGRLayer *m_poLayersMetadataLayer = nullptr;
1849 : OGRLayer *m_poRelationshipsLayer = nullptr;
1850 :
1851 : /** Base unique identifier */
1852 : CPLString m_osHash{};
1853 :
1854 : vsi_l_offset m_nFileSize = 0;
1855 :
1856 : bool m_bWarnUnexpected = false;
1857 :
1858 : /** Map from layer to a map of field XPath to a set of matching
1859 : URL specific resolution rule index */
1860 : std::map<OGRGMLASLayer *, std::map<CPLString, std::set<int>>>
1861 : m_oMapXLinkFields{};
1862 :
1863 : /** Variables that could be local but more efficient to have same
1864 : persistent, so as to save many memory allocations/deallocations */
1865 : CPLString m_osLocalname{};
1866 : CPLString m_osNSUri{};
1867 : CPLString m_osNSPrefix{};
1868 : CPLString m_osXPath{};
1869 : CPLString m_osLayerXPath{};
1870 : CPLString m_osAttrNSUri{};
1871 : CPLString m_osAttrNSPrefix{};
1872 : CPLString m_osAttrLocalName{};
1873 : CPLString m_osAttrXPath{};
1874 : CPLString m_osAttrValue{};
1875 : CPLString m_osText{};
1876 :
1877 : std::vector<OGRGMLASLayer *> m_apoSWEDataArrayLayersRef{};
1878 : std::vector<std::unique_ptr<OGRGMLASLayer>> m_apoSWEDataArrayLayersOwned{};
1879 :
1880 : int m_nSWEDataArrayLayerIdx = 0;
1881 :
1882 : /* Set of 3 maps used for xlink:href="#xxxx" internal links resolution */
1883 : /* 1) map the ID attribute to its belonging layer, e.g foo.1 -> layer Foo */
1884 : std::map<CPLString, OGRGMLASLayer *> m_oMapElementIdToLayer{};
1885 : /* 2) map the ID attribute to the feature PKID (when different from itself)
1886 : */
1887 : std::map<CPLString, CPLString> m_oMapElementIdToPKID{};
1888 : /* 3) map each (layer, field_xpath) to the list of ID it refers to */
1889 : /* e.g (layer Bar, field_xpath) -> [foo.1, foo.2] */
1890 : std::map<std::pair<OGRGMLASLayer *, CPLString>, std::vector<CPLString>>
1891 : m_oMapFieldXPathToLinkValue{};
1892 :
1893 : /* Map layer's XPath to layer (for layers that are not group) */
1894 : std::map<CPLString, OGRGMLASLayer *> m_oMapXPathToLayer{};
1895 :
1896 : /* Map OGR field XPath to layer (for layers that are group) */
1897 : std::map<CPLString, OGRGMLASLayer *> m_oMapFieldXPathToGroupLayer{};
1898 :
1899 : /* Map layer's XPath to layer (for layers that are repeated sequences) */
1900 : std::map<CPLString, std::vector<OGRGMLASLayer *>>
1901 : m_oMapXPathToLayerRepeadedSequence{};
1902 :
1903 : void SetField(OGRFeature *poFeature, OGRGMLASLayer *poLayer, int nAttrIdx,
1904 : const CPLString &osAttrValue);
1905 :
1906 : void CreateNewFeature(const CPLString &osLocalname);
1907 :
1908 : void PushFeatureReady(std::unique_ptr<OGRFeature> &&,
1909 : OGRGMLASLayer *poLayer);
1910 :
1911 : void PushContext(const Context &oContext);
1912 : void PopContext();
1913 :
1914 : void BuildXMLBlobStartElement(const CPLString &osXPath,
1915 : const Attributes &attrs);
1916 :
1917 : OGRGMLASLayer *GetLayerByXPath(const CPLString &osXPath);
1918 :
1919 : void AttachAsLastChild(CPLXMLNode *psNode);
1920 :
1921 : void ProcessSWEDataArray(CPLXMLNode *psRoot);
1922 : void ProcessSWEDataRecord(CPLXMLNode *psRoot);
1923 : void ProcessGeometry(CPLXMLNode *psRoot);
1924 :
1925 : void ProcessAttributes(const Attributes &attrs);
1926 : void ProcessXLinkHref(int nAttrIdx, const CPLString &osAttrXPath,
1927 : const CPLString &osAttrValue);
1928 : void
1929 : ExploreXMLDoc(const CPLString &osAttrXPath,
1930 : const GMLASXLinkResolutionConf::URLSpecificResolution &oRule,
1931 : CPLXMLNode *psNode, const CPLString &osParentXPath,
1932 : const GMLASXPathMatcher &oMatcher,
1933 : const std::map<CPLString, size_t> &oMapFieldXPathToIdx);
1934 :
1935 : void CreateFieldsForURLSpecificRules();
1936 : void CreateFieldsForURLSpecificRule(
1937 : OGRGMLASLayer *poLayer, int nFieldIdx, const CPLString &osFieldXPath,
1938 : int &nInsertFieldIdx,
1939 : const GMLASXLinkResolutionConf::URLSpecificResolution &oRule);
1940 :
1941 321265 : bool FillTextContent() const
1942 : {
1943 321265 : return !m_bInitialPass && m_nCurFieldIdx >= 0;
1944 : }
1945 :
1946 : void ProcessInternalXLinkFirstPass(
1947 : bool bRemoveUnusedFields,
1948 : std::map<OGRGMLASLayer *, std::set<CPLString>> &oMapUnusedFields);
1949 :
1950 : CPL_DISALLOW_COPY_ASSIGN(GMLASReader)
1951 :
1952 : public:
1953 : GMLASReader(GMLASXSDCache &oCache,
1954 : const GMLASXPathMatcher &oIgnoredXPathMatcher,
1955 : GMLASXLinkResolver &oXLinkResolver);
1956 : ~GMLASReader();
1957 :
1958 : bool Init(const char *pszFilename,
1959 : const std::shared_ptr<VSIVirtualHandle> &fp,
1960 : const std::map<CPLString, CPLString> &oMapURIToPrefix,
1961 : std::vector<std::unique_ptr<OGRGMLASLayer>> &apoLayers,
1962 : bool bValidate, const std::vector<PairURIFilename> &aoXSDs,
1963 : bool bSchemaFullChecking, bool bHandleMultipleImports);
1964 :
1965 : void SetLayerOfInterest(OGRGMLASLayer *poLayer);
1966 :
1967 1392 : void SetMapIgnoredXPathToWarn(const std::map<CPLString, bool> &oMap)
1968 : {
1969 1392 : m_oMapIgnoredXPathToWarn = oMap;
1970 1392 : }
1971 :
1972 1280 : void SetSwapCoordinates(GMLASSwapCoordinatesEnum eVal)
1973 : {
1974 1280 : m_eSwapCoordinates = eVal;
1975 1280 : }
1976 :
1977 43 : const std::shared_ptr<VSIVirtualHandle> &GetFP() const
1978 : {
1979 43 : return m_fp;
1980 : }
1981 :
1982 112 : const std::map<CPLString, bool> &GetMapSRSNameToInvertedAxis() const
1983 : {
1984 112 : return m_oMapSRSNameToInvertedAxis;
1985 : }
1986 :
1987 1267 : void SetMapSRSNameToInvertedAxis(const std::map<CPLString, bool> &oMap)
1988 : {
1989 1267 : m_oMapSRSNameToInvertedAxis = oMap;
1990 1267 : }
1991 :
1992 : const std::map<OGRGeomFieldDefn *, CPLString> &
1993 112 : GetMapGeomFieldDefnToSRSName() const
1994 : {
1995 112 : return m_oMapGeomFieldDefnToSRSName;
1996 : }
1997 :
1998 1267 : void SetMapGeomFieldDefnToSRSName(
1999 : const std::map<OGRGeomFieldDefn *, CPLString> &oMap)
2000 : {
2001 1267 : m_oMapGeomFieldDefnToSRSName = oMap;
2002 1267 : }
2003 :
2004 112 : const std::map<CPLString, OGRGMLASLayer *> &GetMapElementIdToLayer() const
2005 : {
2006 112 : return m_oMapElementIdToLayer;
2007 : }
2008 :
2009 : void
2010 1267 : SetMapElementIdToLayer(const std::map<CPLString, OGRGMLASLayer *> &oMap)
2011 : {
2012 1267 : m_oMapElementIdToLayer = oMap;
2013 1267 : }
2014 :
2015 112 : const std::map<CPLString, CPLString> &GetMapElementIdToPKID() const
2016 : {
2017 112 : return m_oMapElementIdToPKID;
2018 : }
2019 :
2020 1267 : void SetMapElementIdToPKID(const std::map<CPLString, CPLString> &oMap)
2021 : {
2022 1267 : m_oMapElementIdToPKID = oMap;
2023 1267 : }
2024 :
2025 112 : int GetDefaultSrsDimension() const
2026 : {
2027 112 : return m_nDefaultSrsDimension;
2028 : }
2029 :
2030 1267 : void SetDefaultSrsDimension(int nDim)
2031 : {
2032 1267 : m_nDefaultSrsDimension = nDim;
2033 1267 : }
2034 :
2035 1392 : void SetHash(const CPLString &osHash)
2036 : {
2037 1392 : m_osHash = osHash;
2038 1392 : }
2039 :
2040 1392 : void SetFileSize(vsi_l_offset nFileSize)
2041 : {
2042 1392 : m_nFileSize = nFileSize;
2043 1392 : }
2044 :
2045 : OGRFeature *GetNextFeature(OGRGMLASLayer **ppoBelongingLayer = nullptr,
2046 : GDALProgressFunc pfnProgress = nullptr,
2047 : void *pProgressData = nullptr);
2048 :
2049 : virtual void startElement(const XMLCh *const uri,
2050 : const XMLCh *const localname,
2051 : const XMLCh *const qname,
2052 : const Attributes &attrs) override;
2053 : virtual void endElement(const XMLCh *const uri,
2054 : const XMLCh *const localname,
2055 : const XMLCh *const qname) override;
2056 :
2057 : virtual void characters(const XMLCh *const chars,
2058 : const XMLSize_t length) override;
2059 :
2060 : void startEntity(const XMLCh *const name) override;
2061 :
2062 : bool RunFirstPass(GDALProgressFunc pfnProgress, void *pProgressData,
2063 : bool bRemoveUnusedLayers, bool bRemoveUnusedFields,
2064 : bool bProcessSWEDataArray,
2065 : OGRLayer *poFieldsMetadataLayer,
2066 : OGRLayer *poLayersMetadataLayer,
2067 : OGRLayer *poRelationshipsLayer,
2068 : std::set<CPLString> &aoSetRemovedLayerNames);
2069 :
2070 : static bool LoadXSDInParser(SAX2XMLReader *poParser, GMLASXSDCache &oCache,
2071 : GMLASBaseEntityResolver &oXSDEntityResolver,
2072 : const CPLString &osBaseDirname,
2073 : const CPLString &osXSDFilename,
2074 : Grammar **ppoGrammar, bool bSchemaFullChecking,
2075 : bool bHandleMultipleImports);
2076 :
2077 : void SetSWEDataArrayLayersRef(const std::vector<OGRGMLASLayer *> &ar);
2078 :
2079 1379 : void SetProcessDataRecord(bool b)
2080 : {
2081 1379 : m_bProcessSWEDataRecord = b;
2082 1379 : }
2083 :
2084 112 : std::vector<std::unique_ptr<OGRGMLASLayer>> StealSWEDataArrayLayersOwned()
2085 : {
2086 112 : return std::move(m_apoSWEDataArrayLayersOwned);
2087 : }
2088 : };
2089 :
2090 : CPLString OGRGMLASTruncateIdentifier(const CPLString &osName,
2091 : int nIdentMaxLength);
2092 :
2093 : CPLString OGRGMLASAddSerialNumber(const CPLString &osNameIn, int iOccurrence,
2094 : size_t nOccurrences, int nIdentMaxLength);
2095 :
2096 : #endif // OGR_GMLAS_INCLUDED
|