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