LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/gmlas - ogr_gmlas.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 323 323 100.0 %
Date: 2024-05-06 18:28:20 Functions: 135 136 99.3 %

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

Generated by: LCOV version 1.14