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