LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/nas - nashandler.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 210 322 65.2 %
Date: 2024-05-03 15:49:35 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  * Project:  NAS Reader
       4             :  * Purpose:  Implementation of NASHandler class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  **********************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam
       9             :  * Copyright (c) 2010-2012, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include <ctype.h>
      31             : #include "nasreaderp.h"
      32             : #include "cpl_conv.h"
      33             : #include "cpl_string.h"
      34             : #include "ogr_xerces.h"
      35             : 
      36             : #define NASDebug(fmt, ...)                                                     \
      37             :     CPLDebugOnly("NAS", "%s:%d %s " fmt, __FILE__, __LINE__, __FUNCTION__,     \
      38             :                  __VA_ARGS__)
      39             : 
      40             : /*
      41             :   Update modes:
      42             : 
      43             : GID<7
      44             :     <wfs:Transaction version="1.0.0" service="WFS">
      45             :         <wfs:Delete typeName="AX_BesondereFlurstuecksgrenze">
      46             :             <ogc:Filter>
      47             :                 <ogc:FeatureId fid="DENW18AL0000nANA20120117T130819Z" />
      48             :             </ogc:Filter>
      49             :         </wfs:Delete>
      50             :         <wfsext:Replace vendorId="AdV" safeToIgnore="false">
      51             :             <AP_PTO gml:id="DENW18AL0000pewY20131011T071138Z">
      52             :                 [...]
      53             :             </AP_PTO>
      54             :             <ogc:Filter>
      55             :                 <ogc:FeatureId fid="DENW18AL0000pewY20120117T143330Z" />
      56             :             </ogc:Filter>
      57             :         </wfsext:Replace>
      58             :         <wfs:Update typeName="AX_KommunalesGebiet">
      59             :             <wfs:Property>
      60             :                 <wfs:Name>adv:lebenszeitintervall/adv:AA_Lebenszeitintervall/adv:endet</wfs:Name>
      61             :                 <wfs:Value>2012-08-14T12:32:30Z</wfs:Value>
      62             :             </wfs:Property>
      63             :             <wfs:Property>
      64             :                 <wfs:Name>adv:anlass</wfs:Name>
      65             :                 <wfs:Value>000000</wfs:Value>
      66             :             </wfs:Property>
      67             :             <wfs:Property>
      68             :                 <wfs:Name>adv:anlass</wfs:Name>
      69             :                 <wfs:Value>010102</wfs:Value>
      70             :             </wfs:Property>
      71             :             <ogc:Filter>
      72             :                 <ogc:FeatureId fid="DENW11AL000062WD20111016T122010Z" />
      73             :             </ogc:Filter>
      74             :         </wfs:Update>
      75             :     </wfs:Transaction>
      76             : 
      77             : GID>=7
      78             :     <wfs:Transaction>
      79             :         <wfs:Insert>
      80             :             <AX_Flurstueck gml:id="DEBY0000F0000001">
      81             :                 …
      82             :             </AX_Flurstueck>
      83             :             <AX_Gebaeude gml:id="DEBY0000G0000001">
      84             :                 …
      85             :             </AX_Gebaeude>
      86             :         </wfs:Insert>
      87             :         <wfs:Replace>
      88             :             <AX_Flurstueck gml:id="DEBY0000F0000002">
      89             :                 …
      90             :             </AX_Flurstueck>
      91             :             <fes:Filter>
      92             :                 <fes:ResourceId rid="DEBY0000F000000220010101T000000Z"/>
      93             :             </fes:Filter>
      94             :         </wfs:Replace>
      95             :         <wfs:Delete typeNames=“AX_Buchungsstelle”>
      96             :             <fes:Filter>
      97             :                 <fes:ResourceId rid="DEBY0000B000000320010101T000000Z"/>
      98             :                 <fes:ResourceId rid="DEBY0000B000000420010101T000000Z"/>
      99             :                 …
     100             :             </fes:Filter>
     101             :         </wfs:Delete>
     102             :         <wfs:Update typeNames="adv:AX_Flurstueck">
     103             :             <wfs:Property>
     104             :                 <wfs:ValueReference>adv:lebenszeitintervall/adv:AA_Lebenszeitintervall/adv:endet</wfs:ValueReference>
     105             :                     <wfs:Value>2007-11-13T12:00:00Z</wfs:Value>
     106             :                 </wfs:Property>
     107             :             <wfs:Property>
     108             :             <wfs:ValueReference>adv:anlass</wfs:ValueReference>
     109             :                  <wfs:Value>000000</wfs:Value>
     110             :             </wfs:Property>
     111             :             <wfs:Property>
     112             :                  <wfs:ValueReference>adv:anlass</wfs:ValueReference>
     113             :                  <wfs:Value>010102</wfs:Value>
     114             :             </wfs:Property>
     115             :             <wfs:Filter>
     116             :                  <fes:ResourceId rid="DEBY123412345678"/>
     117             :             </wfs:Filter>
     118             :         </wfs:Update>
     119             :     </wfs:Transaction>
     120             : */
     121             : 
     122             : /************************************************************************/
     123             : /*                             NASHandler()                             */
     124             : /************************************************************************/
     125             : 
     126           6 : NASHandler::NASHandler(NASReader *poReader)
     127             :     : m_poReader(poReader), m_pszCurField(nullptr), m_pszGeometry(nullptr),
     128             :       m_nGeomAlloc(0), m_nGeomLen(0), m_nGeometryDepth(0),
     129             :       m_nGeometryPropertyIndex(-1), m_nDepth(0), m_nDepthFeature(0),
     130           6 :       m_bIgnoreFeature(false), m_Locator(nullptr)
     131             : {
     132           6 : }
     133             : 
     134             : /************************************************************************/
     135             : /*                            ~NASHandler()                             */
     136             : /************************************************************************/
     137             : 
     138          12 : NASHandler::~NASHandler()
     139             : 
     140             : {
     141           6 :     CPLFree(m_pszCurField);
     142           6 :     CPLFree(m_pszGeometry);
     143          12 : }
     144             : 
     145             : /************************************************************************/
     146             : /*                        GetAttributes()                               */
     147             : /************************************************************************/
     148             : 
     149          80 : CPLString NASHandler::GetAttributes(const Attributes *attrs)
     150             : {
     151          80 :     CPLString osRes;
     152             : 
     153          96 :     for (unsigned int i = 0; i < attrs->getLength(); i++)
     154             :     {
     155          16 :         osRes += " ";
     156          16 :         osRes += transcode(attrs->getQName(i));
     157          16 :         osRes += "=\"";
     158          16 :         osRes += transcode(attrs->getValue(i));
     159          16 :         osRes += "\"";
     160             :     }
     161          80 :     return osRes;
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                   setDocumentLocator()                               */
     166             : /************************************************************************/
     167             : 
     168           6 : void NASHandler::setDocumentLocator(const Locator *locator)
     169             : {
     170           6 :     m_Locator = locator;
     171           6 :     return DefaultHandler::setDocumentLocator(locator);
     172             : }
     173             : 
     174             : /************************************************************************/
     175             : /*                            startElement()                            */
     176             : /************************************************************************/
     177             : 
     178         443 : void NASHandler::startElement(const XMLCh *const /* uri */,
     179             :                               const XMLCh *const localname,
     180             :                               const XMLCh *const /* qname */,
     181             :                               const Attributes &attrs)
     182             : 
     183             : {
     184         443 :     GMLReadState *poState = m_poReader->GetState();
     185             : 
     186         443 :     transcode(localname, m_osElementName);
     187             : 
     188         443 :     NASDebug("element=%s poState=%s m_nDepth=%d m_nDepthFeature=%d context=%s",
     189             :              m_osElementName.c_str(), poState ? "(state)" : "(no state)",
     190             :              m_nDepth, m_nDepthFeature, m_osDeleteContext.c_str());
     191             : 
     192         443 :     m_nDepth++;
     193         443 :     if (m_bIgnoreFeature && m_nDepth > m_nDepthFeature)
     194          93 :         return;
     195             : 
     196         350 :     if (m_nDepthFeature == 0)
     197             :     {
     198         164 :         if (m_osElementName == "Replace")
     199             :         {
     200           3 :             const XMLCh achSafeToIgnore[] = {'s', 'a', 'f', 'e', 'T', 'o', 'I',
     201             :                                              'g', 'n', 'o', 'r', 'e', 0};
     202           3 :             int nIndex = attrs.getIndex(achSafeToIgnore);
     203           3 :             if (nIndex != -1)
     204           3 :                 transcode(attrs.getValue(nIndex), m_osSafeToIgnore);
     205             :             else
     206           0 :                 m_osSafeToIgnore = "true";
     207           3 :             m_osReplacingFID = "";
     208             : 
     209           3 :             CPLAssert(m_osDeleteContext == "");
     210           3 :             m_osDeleteContext = m_osElementName;
     211             :         }
     212         161 :         else if (m_osElementName == "Update" || m_osElementName == "Delete")
     213             :         {
     214           4 :             const XMLCh achTypeNames[] = {'t', 'y', 'p', 'e', 'N',
     215             :                                           'a', 'm', 'e', 's', 0};
     216           4 :             const XMLCh achTypeName[] = {'t', 'y', 'p', 'e', 'N',
     217             :                                          'a', 'm', 'e', 0};
     218           4 :             int nIndex = attrs.getIndex(achTypeNames);
     219           4 :             if (nIndex == -1)
     220           4 :                 nIndex = attrs.getIndex(achTypeName);
     221             : 
     222           4 :             if (nIndex == -1)
     223             :             {
     224           0 :                 CPLError(CE_Failure, CPLE_AssertionFailed,
     225             :                          "NAS: expected type name missing at %s:%d:%d",
     226           0 :                          m_poReader->GetSourceFileName(),
     227           0 :                          static_cast<int>(m_Locator->getLineNumber()),
     228           0 :                          static_cast<int>(m_Locator->getColumnNumber()));
     229           0 :                 return;
     230             :             }
     231             : 
     232           4 :             transcode(attrs.getValue(nIndex), m_osTypeName);
     233             : 
     234           4 :             const char *pszTypeName = strchr(m_osTypeName.c_str(), ':');
     235           4 :             pszTypeName = pszTypeName ? pszTypeName + 1 : m_osTypeName.c_str();
     236           4 :             m_osTypeName = pszTypeName;
     237             : 
     238           4 :             CPLAssert(m_osDeleteContext == "");
     239           4 :             m_osDeleteContext = m_osElementName;
     240             :         }
     241         157 :         else if (m_osDeleteContext == "Update" &&
     242           0 :                  (m_osElementName == "Name" ||
     243           0 :                   m_osElementName == "ValueReference" ||
     244           0 :                   m_osElementName == "Value"))
     245             :         {
     246             :             // fetch value
     247           0 :             CPLFree(m_pszCurField);
     248           0 :             m_pszCurField = CPLStrdup("");
     249             :         }
     250         172 :         else if (m_osDeleteContext != "" && (m_osElementName == "ResourceId" ||
     251          15 :                                              m_osElementName == "FeatureId"))
     252             :         {
     253             :             const char *pszFilteredClassName =
     254           6 :                 m_poReader->GetFilteredClassName();
     255           6 :             if (!pszFilteredClassName || EQUAL(pszFilteredClassName, "Delete"))
     256             :             {
     257           6 :                 const XMLCh achRid[] = {'r', 'i', 'd', 0};
     258           6 :                 const XMLCh achFid[] = {'f', 'i', 'd', 0};
     259           6 :                 if (m_osTypeName == "")
     260             :                 {
     261           0 :                     CPLError(CE_Failure, CPLE_AssertionFailed,
     262             :                              "NAS: type name(s) missing at %s:%d:%d",
     263           0 :                              m_poReader->GetSourceFileName(),
     264           0 :                              static_cast<int>(m_Locator->getLineNumber()),
     265           0 :                              static_cast<int>(m_Locator->getColumnNumber()));
     266           0 :                     return;
     267             :                 }
     268             : 
     269           6 :                 int nIndex = attrs.getIndex(
     270           6 :                     m_osElementName == "ResourceId" ? achRid : achFid);
     271           6 :                 if (nIndex == -1)
     272             :                 {
     273           0 :                     CPLError(CE_Failure, CPLE_AssertionFailed,
     274             :                              "NAS: expected feature id missing at %s,%d:%d",
     275           0 :                              m_poReader->GetSourceFileName(),
     276           0 :                              static_cast<int>(m_Locator->getLineNumber()),
     277           0 :                              static_cast<int>(m_Locator->getColumnNumber()));
     278           0 :                     return;
     279             :                 }
     280             : 
     281          12 :                 CPLString osFeatureId;
     282           6 :                 transcode(attrs.getValue(nIndex), osFeatureId);
     283             : 
     284           6 :                 m_poReader->PushFeature("Delete", attrs);
     285           6 :                 m_poReader->SetFeaturePropertyDirectly("typeName",
     286             :                                                        CPLStrdup(m_osTypeName));
     287           6 :                 m_poReader->SetFeaturePropertyDirectly(
     288             :                     "context", CPLStrdup(m_osDeleteContext));
     289           6 :                 m_poReader->SetFeaturePropertyDirectly("FeatureId",
     290             :                                                        CPLStrdup(osFeatureId));
     291             : 
     292           6 :                 if (m_osDeleteContext == "Replace")
     293             :                 {
     294           2 :                     if (m_osReplacingFID == "")
     295             :                     {
     296           0 :                         CPLError(
     297             :                             CE_Failure, CPLE_AssertionFailed,
     298             :                             "NAS: replacing feature id not set at %s:%d:%d",
     299           0 :                             m_poReader->GetSourceFileName(),
     300           0 :                             static_cast<int>(m_Locator->getLineNumber()),
     301           0 :                             static_cast<int>(m_Locator->getColumnNumber()));
     302           0 :                         return;
     303             :                     }
     304             : 
     305           2 :                     m_poReader->SetFeaturePropertyDirectly(
     306             :                         "replacedBy", CPLStrdup(m_osReplacingFID));
     307           2 :                     m_poReader->SetFeaturePropertyDirectly(
     308             :                         "safeToIgnore", CPLStrdup(m_osSafeToIgnore));
     309           2 :                     m_osReplacingFID = "";
     310           2 :                     m_osSafeToIgnore = "";
     311             :                 }
     312           4 :                 else if (m_osDeleteContext == "Update")
     313             :                 {
     314           0 :                     m_poReader->SetFeaturePropertyDirectly(
     315             :                         "endet", CPLStrdup(m_osUpdateEnds));
     316           0 :                     for (std::list<CPLString>::iterator it =
     317           0 :                              m_UpdateOccasions.begin();
     318           0 :                          it != m_UpdateOccasions.end(); ++it)
     319             :                     {
     320           0 :                         m_poReader->SetFeaturePropertyDirectly("anlass",
     321           0 :                                                                CPLStrdup(*it));
     322             :                     }
     323             : 
     324           0 :                     m_osUpdateEnds = "";
     325           0 :                     m_UpdateOccasions.clear();
     326             :                 }
     327             : 
     328           6 :                 return;
     329             :             }
     330             :             else
     331             :             {
     332             :                 // we don't issue Delete features
     333           0 :                 m_osDeleteContext = "";
     334             :             }
     335             :         }
     336         151 :         else if (m_poReader->IsFeatureElement(m_osElementName))
     337             :         {
     338           3 :             m_nDepthFeature = m_nDepth - 1;
     339             : 
     340             :             // record id of replacing feature
     341           3 :             if (m_osDeleteContext == "Replace")
     342             :             {
     343           3 :                 const XMLCh achGmlId[] = {'g', 'm', 'l', ':', 'i', 'd', 0};
     344           3 :                 int nIndex = attrs.getIndex(achGmlId);
     345           3 :                 if (nIndex == -1)
     346             :                 {
     347           0 :                     CPLError(CE_Failure, CPLE_AssertionFailed,
     348             :                              "NAS: id of replacing feature not set at %s:%d:%d",
     349           0 :                              m_poReader->GetSourceFileName(),
     350           0 :                              static_cast<int>(m_Locator->getLineNumber()),
     351           0 :                              static_cast<int>(m_Locator->getColumnNumber()));
     352           0 :                     m_bIgnoreFeature = true;
     353           0 :                     return;
     354             :                 }
     355             : 
     356           3 :                 CPLAssert(m_osReplacingFID == "");
     357           3 :                 transcode(attrs.getValue(nIndex), m_osReplacingFID);
     358             :             }
     359             : 
     360           3 :             m_osTypeName = m_osElementName;
     361             : 
     362             :             const char *pszFilteredClassName =
     363           3 :                 m_poReader->GetFilteredClassName();
     364           5 :             m_bIgnoreFeature = pszFilteredClassName &&
     365           2 :                                !EQUAL(m_osElementName, pszFilteredClassName);
     366             : 
     367           3 :             if (!m_bIgnoreFeature)
     368           2 :                 m_poReader->PushFeature(m_osElementName, attrs);
     369             : 
     370           3 :             return;
     371             :         }
     372             :     }
     373         186 :     else if (m_pszGeometry != nullptr || IsGeometryElement(m_osElementName))
     374             :     {
     375         160 :         if (m_nGeometryPropertyIndex == -1 && poState->m_poFeature &&
     376          80 :             poState->m_poFeature->GetClass())
     377             :         {
     378          80 :             GMLFeatureClass *poClass = poState->m_poFeature->GetClass();
     379          80 :             m_nGeometryPropertyIndex =
     380          80 :                 poClass->GetGeometryPropertyIndexBySrcElement(
     381             :                     poState->osPath.c_str());
     382             :         }
     383             : 
     384          80 :         const int nLNLen = static_cast<int>(m_osElementName.size());
     385          80 :         CPLString osAttributes = GetAttributes(&attrs);
     386             : 
     387             :         /* should save attributes too! */
     388             : 
     389          80 :         if (m_pszGeometry == nullptr)
     390           2 :             m_nGeometryDepth = poState->m_nPathLength;
     391             : 
     392         158 :         if (m_pszGeometry == nullptr ||
     393          78 :             m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc)
     394             :         {
     395           2 :             m_nGeomAlloc =
     396           2 :                 (int)(m_nGeomAlloc * 1.3 + nLNLen + osAttributes.size() + 1000);
     397           2 :             m_pszGeometry = (char *)CPLRealloc(m_pszGeometry, m_nGeomAlloc);
     398             :         }
     399             : 
     400          80 :         strcpy(m_pszGeometry + m_nGeomLen, "<");
     401          80 :         strcpy(m_pszGeometry + m_nGeomLen + 1, m_osElementName);
     402             : 
     403          80 :         if (!osAttributes.empty())
     404             :         {
     405          16 :             strcat(m_pszGeometry + m_nGeomLen, " ");
     406          16 :             strcat(m_pszGeometry + m_nGeomLen, osAttributes);
     407             :         }
     408             : 
     409          80 :         strcat(m_pszGeometry + m_nGeomLen, ">");
     410          80 :         m_nGeomLen += static_cast<int>(strlen(m_pszGeometry + m_nGeomLen));
     411             :     }
     412         106 :     else if (m_poReader->IsAttributeElement(m_osElementName, attrs))
     413             :     {
     414         106 :         m_poReader->DealWithAttributes(
     415         106 :             m_osElementName, static_cast<int>(m_osElementName.length()), attrs);
     416         106 :         CPLFree(m_pszCurField);
     417         106 :         m_pszCurField = CPLStrdup("");
     418             :     }
     419             : 
     420         341 :     poState->PushPath(m_osElementName);
     421             : 
     422         341 :     if (poState->osPath.size() > 512)
     423             :     {
     424           0 :         CPLError(CE_Failure, CPLE_AssertionFailed,
     425             :                  "NAS: Too long path. Stop parsing at %s:%d:%d",
     426           0 :                  m_poReader->GetSourceFileName(),
     427           0 :                  static_cast<int>(m_Locator->getLineNumber()),
     428           0 :                  static_cast<int>(m_Locator->getColumnNumber()));
     429           0 :         m_poReader->StopParsing();
     430             :     }
     431             : }
     432             : 
     433             : /************************************************************************/
     434             : /*                             endElement()                             */
     435             : /************************************************************************/
     436         429 : void NASHandler::endElement(const XMLCh *const /* uri */,
     437             :                             const XMLCh *const localname,
     438             :                             const XMLCh *const /* qname */)
     439             : 
     440             : {
     441         429 :     GMLReadState *poState = m_poReader->GetState();
     442             : 
     443         429 :     transcode(localname, m_osElementName);
     444             : 
     445         429 :     NASDebug("element=%s poState=%s m_nDepth=%d m_nDepthFeature=%d context=%s",
     446             :              m_osElementName.c_str(), poState ? "(state)" : "(no state)",
     447             :              m_nDepth, m_nDepthFeature, m_osDeleteContext.c_str());
     448             : 
     449         429 :     m_nDepth--;
     450         429 :     if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
     451             :     {
     452          94 :         if (m_nDepth == m_nDepthFeature)
     453             :         {
     454           1 :             m_bIgnoreFeature = false;
     455           1 :             m_nDepthFeature = 0;
     456             :         }
     457          94 :         return;
     458             :     }
     459             : 
     460         335 :     if (m_osDeleteContext == "Update")
     461             :     {
     462           0 :         if (m_osElementName == "Name" || m_osElementName == "ValueReference")
     463             :         {
     464             :             const char *pszName;
     465           0 :             pszName = strrchr(m_pszCurField, '/');
     466           0 :             pszName = pszName ? pszName + 1 : m_pszCurField;
     467           0 :             pszName = strrchr(pszName, ':');
     468           0 :             pszName = pszName ? pszName + 1 : m_pszCurField;
     469             : 
     470           0 :             CPLAssert(m_osUpdatePropertyName == "");
     471           0 :             m_osUpdatePropertyName = pszName;
     472           0 :             CPLFree(m_pszCurField);
     473           0 :             m_pszCurField = nullptr;
     474             : 
     475           0 :             if (m_osUpdatePropertyName != "endet" &&
     476           0 :                 m_osUpdatePropertyName != "anlass")
     477             :             {
     478           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     479             :                          "NAS: Unexpected property name %s at %s:%d:%d",
     480             :                          m_osUpdatePropertyName.c_str(),
     481           0 :                          m_poReader->GetSourceFileName(),
     482           0 :                          static_cast<int>(m_Locator->getLineNumber()),
     483           0 :                          static_cast<int>(m_Locator->getColumnNumber()));
     484           0 :                 m_osUpdatePropertyName = "";
     485             :             }
     486             :         }
     487           0 :         else if (m_osElementName == "Value")
     488             :         {
     489           0 :             CPLAssert(m_osUpdatePropertyName != "");
     490           0 :             if (m_osUpdatePropertyName == "endet")
     491           0 :                 m_osUpdateEnds = m_pszCurField;
     492           0 :             else if (m_osUpdatePropertyName == "anlass")
     493           0 :                 m_UpdateOccasions.push_back(m_pszCurField);
     494           0 :             m_osUpdatePropertyName = "";
     495           0 :             CPLFree(m_pszCurField);
     496           0 :             m_pszCurField = nullptr;
     497             :         }
     498             :     }
     499         335 :     else if (m_pszCurField != nullptr && poState->m_poFeature != nullptr)
     500             :     {
     501          58 :         m_poReader->SetFeaturePropertyDirectly(poState->osPath.c_str(),
     502             :                                                m_pszCurField);
     503          58 :         m_pszCurField = nullptr;
     504             :     }
     505             : 
     506             :     /* -------------------------------------------------------------------- */
     507             :     /*      If we are collecting Geometry than store it, and consider if    */
     508             :     /*      this is the end of the geometry.                                */
     509             :     /* -------------------------------------------------------------------- */
     510         335 :     if (m_pszGeometry != nullptr)
     511             :     {
     512          80 :         int nLNLen = static_cast<int>(m_osElementName.size());
     513             : 
     514             :         /* should save attributes too! */
     515             : 
     516          80 :         if (m_nGeomLen + nLNLen + 4 > m_nGeomAlloc)
     517             :         {
     518           0 :             m_nGeomAlloc = (int)(m_nGeomAlloc * 1.3 + nLNLen + 1000);
     519           0 :             m_pszGeometry = (char *)CPLRealloc(m_pszGeometry, m_nGeomAlloc);
     520             :         }
     521             : 
     522          80 :         strcat(m_pszGeometry + m_nGeomLen, "</");
     523          80 :         strcpy(m_pszGeometry + m_nGeomLen + 2, m_osElementName);
     524          80 :         strcat(m_pszGeometry + m_nGeomLen + nLNLen + 2, ">");
     525          80 :         m_nGeomLen += static_cast<int>(strlen(m_pszGeometry + m_nGeomLen));
     526             : 
     527          80 :         if (poState->m_nPathLength == m_nGeometryDepth + 1)
     528             :         {
     529           2 :             if (poState->m_poFeature != nullptr)
     530             :             {
     531           2 :                 CPLXMLNode *psNode = CPLParseXMLString(m_pszGeometry);
     532           2 :                 if (psNode)
     533             :                 {
     534             :                     /* workaround for common malformed gml:pos with just a
     535             :                      * elevation value instead of a full 3D coordinate:
     536             :                      *
     537             :                      * <gml:Point gml:id="BII2H">
     538             :                      *    <gml:pos
     539             :                      * srsName="urn:adv:crs:ETRS89_h">41.394</gml:pos>
     540             :                      * </gml:Point>
     541             :                      *
     542             :                      */
     543             :                     const char *pszPos =
     544           2 :                         CPLGetXMLValue(psNode, "=Point.pos", nullptr);
     545           2 :                     if (pszPos != nullptr && strstr(pszPos, " ") == nullptr)
     546             :                     {
     547           0 :                         CPLSetXMLValue(psNode, "pos",
     548             :                                        CPLSPrintf("0 0 %s", pszPos));
     549             :                     }
     550             : 
     551           0 :                     if (m_nGeometryPropertyIndex >= 0 &&
     552           0 :                         m_nGeometryPropertyIndex <
     553           2 :                             poState->m_poFeature->GetGeometryCount() &&
     554           0 :                         poState->m_poFeature
     555           0 :                             ->GetGeometryList()[m_nGeometryPropertyIndex])
     556             :                     {
     557             :                         int iId =
     558           0 :                             poState->m_poFeature->GetClass()->GetPropertyIndex(
     559             :                                 "gml_id");
     560             :                         const GMLProperty *poIdProp =
     561           0 :                             poState->m_poFeature->GetProperty(iId);
     562             : #ifdef DEBUG_VERBOSE
     563             :                         char *pszOldGeom = CPLSerializeXMLTree(
     564             :                             poState->m_poFeature
     565             :                                 ->GetGeometryList()[m_nGeometryPropertyIndex]);
     566             : 
     567             :                         NASDebug(
     568             :                             "Overwriting other geometry (%s; replace:%s; "
     569             :                             "with:%s) at %s:%d:%d",
     570             :                             poIdProp && poIdProp->nSubProperties > 0 &&
     571             :                                     poIdProp->papszSubProperties[0]
     572             :                                 ? poIdProp->papszSubProperties[0]
     573             :                                 : "(null)",
     574             :                             m_pszGeometry, pszOldGeom,
     575             :                             m_poReader->GetSourceFileName(),
     576             :                             static_cast<int>(m_Locator->getLineNumber()),
     577             :                             static_cast<int>(m_Locator->getColumnNumber()));
     578             : 
     579             :                         CPLFree(pszOldGeom);
     580             : #else
     581           0 :                         CPLError(
     582             :                             CE_Warning, CPLE_AppDefined,
     583             :                             "NAS: Overwriting other geometry (%s) at %s:%d:%d",
     584           0 :                             poIdProp && poIdProp->nSubProperties > 0 &&
     585           0 :                                     poIdProp->papszSubProperties[0]
     586           0 :                                 ? poIdProp->papszSubProperties[0]
     587             :                                 : "(null)",
     588           0 :                             m_poReader->GetSourceFileName(),
     589           0 :                             static_cast<int>(m_Locator->getLineNumber()),
     590           0 :                             static_cast<int>(m_Locator->getColumnNumber()));
     591             : #endif
     592             :                     }
     593             : 
     594           2 :                     if (m_nGeometryPropertyIndex >= 0)
     595           0 :                         poState->m_poFeature->SetGeometryDirectly(
     596             :                             m_nGeometryPropertyIndex, psNode);
     597             : 
     598             :                     // no geometry property or property without element path
     599           4 :                     else if (poState->m_poFeature->GetClass()
     600           4 :                                      ->GetGeometryPropertyCount() == 0 ||
     601           1 :                              (poState->m_poFeature->GetClass()
     602           2 :                                       ->GetGeometryPropertyCount() == 1 &&
     603           1 :                               poState->m_poFeature->GetClass()
     604             :                                   ->GetGeometryProperty(0)
     605           1 :                                   ->GetSrcElement() &&
     606           1 :                               *poState->m_poFeature->GetClass()
     607             :                                       ->GetGeometryProperty(0)
     608           1 :                                       ->GetSrcElement() == 0))
     609           2 :                         poState->m_poFeature->SetGeometryDirectly(psNode);
     610             : 
     611             :                     else
     612             :                     {
     613           0 :                         CPLError(
     614             :                             CE_Warning, CPLE_AssertionFailed,
     615             :                             "NAS: Unexpected geometry skipped (class:%s "
     616             :                             "path:%s geom:%s) at %s:%d:%d",
     617           0 :                             poState->m_poFeature->GetClass()->GetName(),
     618             :                             poState->osPath.c_str(), m_pszGeometry,
     619           0 :                             m_poReader->GetSourceFileName(),
     620           0 :                             static_cast<int>(m_Locator->getLineNumber()),
     621           0 :                             static_cast<int>(m_Locator->getColumnNumber()));
     622           0 :                         CPLDestroyXMLNode(psNode);
     623             :                     }
     624             :                 }
     625             :                 else
     626           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     627             :                              "NAS: Invalid geometry skipped at %s:%d:%d",
     628           0 :                              m_poReader->GetSourceFileName(),
     629           0 :                              static_cast<int>(m_Locator->getLineNumber()),
     630           0 :                              static_cast<int>(m_Locator->getColumnNumber()));
     631             :             }
     632             :             else
     633           0 :                 CPLError(CE_Warning, CPLE_AppDefined,
     634             :                          "NAS: Skipping geometry without feature at %s:%d:%d",
     635           0 :                          m_poReader->GetSourceFileName(),
     636           0 :                          static_cast<int>(m_Locator->getLineNumber()),
     637           0 :                          static_cast<int>(m_Locator->getColumnNumber()));
     638             : 
     639           2 :             CPLFree(m_pszGeometry);
     640           2 :             m_pszGeometry = nullptr;
     641           2 :             m_nGeomAlloc = m_nGeomLen = 0;
     642           2 :             m_nGeometryPropertyIndex = -1;
     643             :         }
     644             :     }
     645             : 
     646             :     // Finished actual feature or ResourceId/FeatureId of Delete/Replace/Update operation
     647           5 :     if ((m_nDepth == m_nDepthFeature && poState->m_poFeature != nullptr &&
     648           2 :          EQUAL(m_osElementName,
     649         870 :                poState->m_poFeature->GetClass()->GetElementName())) ||
     650         533 :         (m_osDeleteContext != "" &&
     651         400 :          (m_osElementName == "ResourceId" || m_osElementName == "FeatureId")))
     652             :     {
     653           8 :         m_nDepthFeature = 0;
     654           8 :         m_poReader->PopState();
     655             :     }
     656             :     else
     657         327 :         poState->PopPath();
     658             : 
     659         335 :     if (m_osDeleteContext == m_osElementName)
     660             :     {
     661           4 :         m_osDeleteContext = "";
     662             :     }
     663             : }
     664             : 
     665             : /************************************************************************/
     666             : /*                             characters()                             */
     667             : /************************************************************************/
     668             : 
     669         914 : void NASHandler::characters(const XMLCh *const chars, const XMLSize_t length)
     670             : {
     671         914 :     if (m_pszCurField != nullptr)
     672             :     {
     673         120 :         const int nCurFieldLength = static_cast<int>(strlen(m_pszCurField));
     674             : 
     675         120 :         int nSkipped = 0;
     676         120 :         if (nCurFieldLength == 0)
     677             :         {
     678             :             // Ignore white space
     679         734 :             while (chars[nSkipped] == ' ' || chars[nSkipped] == 10 ||
     680        1400 :                    chars[nSkipped] == 13 || chars[nSkipped] == '\t')
     681         614 :                 nSkipped++;
     682             :         }
     683             : 
     684         120 :         transcode(chars + nSkipped, m_osCharacters,
     685         120 :                   static_cast<int>(length) - nSkipped);
     686             : 
     687         240 :         m_pszCurField = static_cast<char *>(CPLRealloc(
     688         120 :             m_pszCurField, nCurFieldLength + m_osCharacters.size() + 1));
     689         120 :         memcpy(m_pszCurField + nCurFieldLength, m_osCharacters.c_str(),
     690         120 :                m_osCharacters.size() + 1);
     691             :     }
     692             : 
     693         914 :     if (m_pszGeometry != nullptr)
     694             :     {
     695         158 :         int nSkipped = 0;
     696         158 :         if (m_nGeomLen == 0)
     697             :         {
     698             :             // Ignore white space
     699           0 :             while (chars[nSkipped] == ' ' || chars[nSkipped] == 10 ||
     700           0 :                    chars[nSkipped] == 13 || chars[nSkipped] == '\t')
     701           0 :                 nSkipped++;
     702             :         }
     703             : 
     704         158 :         transcode(chars + nSkipped, m_osCharacters,
     705         158 :                   static_cast<int>(length) - nSkipped);
     706             : 
     707         158 :         const int nCharsLen = static_cast<int>(m_osCharacters.size());
     708             : 
     709         158 :         if (m_nGeomLen + nCharsLen * 4 + 4 > m_nGeomAlloc)
     710             :         {
     711           2 :             m_nGeomAlloc = (int)(m_nGeomAlloc * 1.3 + nCharsLen * 4 + 1000);
     712           2 :             m_pszGeometry = (char *)CPLRealloc(m_pszGeometry, m_nGeomAlloc);
     713             :         }
     714             : 
     715         158 :         memcpy(m_pszGeometry + m_nGeomLen, m_osCharacters.c_str(),
     716         158 :                m_osCharacters.size() + 1);
     717         158 :         m_nGeomLen += static_cast<int>(strlen(m_pszGeometry + m_nGeomLen));
     718             :     }
     719         914 : }
     720             : 
     721             : /************************************************************************/
     722             : /*                             fatalError()                             */
     723             : /************************************************************************/
     724             : 
     725           0 : void NASHandler::fatalError(const SAXParseException &exception)
     726             : 
     727             : {
     728           0 :     CPLString osErrMsg;
     729           0 :     transcode(exception.getMessage(), osErrMsg);
     730           0 :     CPLError(CE_Failure, CPLE_AppDefined,
     731             :              "NAS: XML Parsing Error: %s at line %d, column %d\n",
     732           0 :              osErrMsg.c_str(), static_cast<int>(exception.getLineNumber()),
     733           0 :              static_cast<int>(exception.getColumnNumber()));
     734           0 : }
     735             : 
     736             : /************************************************************************/
     737             : /*                         IsGeometryElement()                          */
     738             : /************************************************************************/
     739             : 
     740         108 : bool NASHandler::IsGeometryElement(const char *pszElement)
     741             : 
     742             : {
     743         216 :     return strcmp(pszElement, "Polygon") == 0 ||
     744         108 :            strcmp(pszElement, "MultiPolygon") == 0 ||
     745         108 :            strcmp(pszElement, "MultiPoint") == 0 ||
     746         108 :            strcmp(pszElement, "MultiLineString") == 0 ||
     747         108 :            strcmp(pszElement, "MultiSurface") == 0 ||
     748         108 :            strcmp(pszElement, "GeometryCollection") == 0 ||
     749         108 :            strcmp(pszElement, "Point") == 0 ||
     750         108 :            strcmp(pszElement, "Curve") == 0 ||
     751         108 :            strcmp(pszElement, "MultiCurve") == 0 ||
     752         108 :            strcmp(pszElement, "CompositeCurve") == 0 ||
     753         108 :            strcmp(pszElement, "Surface") == 0 ||
     754         322 :            strcmp(pszElement, "PolygonPatch") == 0 ||
     755         214 :            strcmp(pszElement, "LineString") == 0;
     756             : }
     757             : 
     758             : // vim: set sw=4 expandtab ai :

Generated by: LCOV version 1.14