LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/nas - nashandler.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 162 145 89.5 %
Date: 2011-12-18 Functions: 11 7 63.6 %

       1                 : /**********************************************************************
       2                 :  * $Id: gmlhandler.cpp 13760 2008-02-11 17:48:30Z warmerdam $
       3                 :  *
       4                 :  * Project:  GML Reader
       5                 :  * Purpose:  Implementation of NASHandler class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  **********************************************************************
       9                 :  * Copyright (c) 2002, Frank Warmerdam
      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                 : 
      35                 : #define MAX_TOKEN_SIZE  1000
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                             NASHandler()                             */
      39                 : /************************************************************************/
      40                 : 
      41               9 : NASHandler::NASHandler( NASReader *poReader )
      42                 : 
      43                 : {
      44               9 :     m_poReader = poReader;
      45               9 :     m_pszCurField = NULL;
      46               9 :     m_pszGeometry = NULL;
      47               9 :     m_nGeomAlloc = m_nGeomLen = 0;
      48               9 :     m_nDepthFeature = m_nDepth = 0;
      49               9 :     m_bIgnoreFeature = FALSE;
      50               9 : }
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                            ~NASHandler()                             */
      54                 : /************************************************************************/
      55                 : 
      56               9 : NASHandler::~NASHandler()
      57                 : 
      58                 : {
      59               9 :     CPLFree( m_pszCurField );
      60               9 :     CPLFree( m_pszGeometry );
      61               9 : }
      62                 : 
      63                 : /************************************************************************/
      64                 : /*                        GetAttributes()                               */
      65                 : /************************************************************************/
      66                 : 
      67          449744 : CPLString NASHandler::GetAttributes(const Attributes* attrs)
      68                 : {
      69          449744 :     CPLString osRes;
      70                 :     char *pszString;
      71                 : 
      72          459649 :     for(unsigned int i=0; i < attrs->getLength(); i++)
      73                 :     {
      74            9905 :         osRes += " ";
      75            9905 :         pszString = tr_strdup(attrs->getQName(i));
      76            9905 :         osRes += pszString;
      77            9905 :         CPLFree( pszString );
      78            9905 :         osRes += "=\"";
      79            9905 :         pszString = tr_strdup(attrs->getValue(i));
      80            9905 :         osRes += pszString;
      81            9905 :         CPLFree( pszString );
      82            9905 :         osRes += "\"";
      83                 :     }
      84               0 :     return osRes;
      85                 : }
      86                 : 
      87                 : 
      88                 : /************************************************************************/
      89                 : /*                            startElement()                            */
      90                 : /************************************************************************/
      91                 : 
      92         2235313 : void NASHandler::startElement(const XMLCh* const    uri,
      93                 :                               const XMLCh* const    localname,
      94                 :                               const XMLCh* const    qname,
      95                 :                               const Attributes& attrs )
      96                 : 
      97                 : {
      98                 :     char        szElementName[MAX_TOKEN_SIZE];
      99         2235313 :     GMLReadState *poState = m_poReader->GetState();
     100         2235313 :     const char *pszLast = NULL;
     101                 : 
     102         2235313 :     tr_strcpy( szElementName, localname );
     103                 : 
     104         2235313 :     if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
     105                 :     {
     106         1561936 :         m_nDepth ++;
     107         1561936 :         return;
     108                 :     }
     109                 : 
     110                 : /* -------------------------------------------------------------------- */
     111                 : /*      If we are in the midst of collecting a feature attribute        */
     112                 : /*      value, then this must be a complex attribute which we don't     */
     113                 : /*      try to collect for now, so just terminate the field             */
     114                 : /*      collection.                                                     */
     115                 : /* -------------------------------------------------------------------- */
     116          673377 :     if( m_pszCurField != NULL )
     117                 :     {
     118              50 :         CPLFree( m_pszCurField );
     119              50 :         m_pszCurField = NULL;
     120                 :     }
     121                 : 
     122                 : /* -------------------------------------------------------------------- */
     123                 : /*      If we are collecting geometry, or if we determine this is a     */
     124                 : /*      geometry element then append to the geometry info.              */
     125                 : /* -------------------------------------------------------------------- */
     126          673377 :     if( m_pszGeometry != NULL 
     127                 :         || IsGeometryElement( szElementName ) )
     128                 :     {
     129          449744 :         int nLNLen = tr_strlen( localname );
     130          449744 :         CPLString osAttributes = GetAttributes( &attrs );
     131                 : 
     132                 :         /* should save attributes too! */
     133                 : 
     134          449744 :         if( m_pszGeometry == NULL )
     135            6684 :             m_nGeometryDepth = poState->m_nPathLength;
     136                 :         
     137          449744 :         if( m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc )
     138                 :         {
     139            6684 :             m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + osAttributes.size() + 1000);
     140                 :             m_pszGeometry = (char *) 
     141            6684 :                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
     142                 :         }
     143                 : 
     144          449744 :         strcpy( m_pszGeometry+m_nGeomLen, "<" );
     145          449744 :         tr_strcpy( m_pszGeometry+m_nGeomLen+1, localname );
     146                 :         
     147          449744 :         if( osAttributes.size() > 0 )
     148                 :         {
     149            9572 :             strcat( m_pszGeometry+m_nGeomLen, " " );
     150            9572 :             strcat( m_pszGeometry+m_nGeomLen, osAttributes );
     151                 :         }
     152                 : 
     153          449744 :         strcat( m_pszGeometry+m_nGeomLen, ">" );
     154          449744 :         m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
     155                 :     }
     156                 :     
     157                 : /* -------------------------------------------------------------------- */
     158                 : /*      Is this the ogc:Filter element in a wfs:Delete operation?       */
     159                 : /*      If so we translate it as a specialized sort of feature.         */
     160                 : /* -------------------------------------------------------------------- */
     161          223633 :     else if( EQUAL(szElementName,"Filter") 
     162                 :              && (pszLast = m_poReader->GetState()->GetLastComponent()) != NULL
     163                 :              && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace")) )
     164                 :     {
     165               6 :         const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
     166               6 :         if ( pszFilteredClassName != NULL &&
     167                 :              strcmp("Delete", pszFilteredClassName) != 0 )
     168                 :         {
     169               0 :             m_bIgnoreFeature = TRUE;
     170               0 :             m_nDepthFeature = m_nDepth;
     171               0 :             m_nDepth ++;
     172                 : 
     173               0 :             return;
     174                 :         }
     175                 : 
     176               6 :         m_bIgnoreFeature = FALSE;
     177                 : 
     178               6 :         m_poReader->PushFeature( "Delete", attrs );
     179                 : 
     180               6 :         m_nDepthFeature = m_nDepth;
     181               6 :         m_nDepth ++;
     182                 :             
     183               6 :         m_poReader->SetFeaturePropertyDirectly( "typeName", CPLStrdup(m_osLastTypeName) );
     184               6 :         return;
     185                 :     }
     186                 : 
     187                 : /* -------------------------------------------------------------------- */
     188                 : /*      Is it a feature?  If so push a whole new state, and return.     */
     189                 : /* -------------------------------------------------------------------- */
     190          223627 :     else if( m_poReader->IsFeatureElement( szElementName ) )
     191                 :     {
     192           69646 :         m_osLastTypeName = szElementName;
     193                 : 
     194           69646 :         const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
     195                 : 
     196          130899 :         if ( pszFilteredClassName != NULL &&
     197                 :              strcmp(szElementName, pszFilteredClassName) != 0 )
     198                 :         {
     199           60918 :             m_bIgnoreFeature = TRUE;
     200           60918 :             m_nDepthFeature = m_nDepth;
     201           60918 :             m_nDepth ++;
     202                 : 
     203           60918 :             return;
     204                 :         }
     205                 : 
     206            8728 :         m_bIgnoreFeature = FALSE;
     207                 : 
     208            8728 :         m_poReader->PushFeature( szElementName, attrs );
     209                 : 
     210            8728 :         m_nDepthFeature = m_nDepth;
     211            8728 :         m_nDepth ++;
     212                 : 
     213            8728 :         return;
     214                 :     }
     215                 : 
     216                 : /* -------------------------------------------------------------------- */
     217                 : /*      If it is the wfs:Delete element, then remember the typeName     */
     218                 : /*      attribute so we can assign it to the feature that will be       */
     219                 : /*      produced when we process the Filter element.                    */
     220                 : /* -------------------------------------------------------------------- */
     221          153981 :     else if( EQUAL(szElementName,"Delete") )
     222                 :     {
     223                 :         int nIndex;
     224                 :         XMLCh  Name[100];
     225                 : 
     226               4 :         tr_strcpy( Name, "typeName" );
     227               4 :         nIndex = attrs.getIndex( Name );
     228                 :         
     229               4 :         if( nIndex != -1 )
     230                 :         {
     231               4 :             char *pszTypeName = tr_strdup( attrs.getValue( nIndex ) );
     232               4 :             m_osLastTypeName = pszTypeName;
     233               4 :             CPLFree( pszTypeName );
     234                 :         }
     235                 :     }
     236                 : 
     237                 : /* -------------------------------------------------------------------- */
     238                 : /*      If it is (or at least potentially is) a simple attribute,       */
     239                 : /*      then start collecting it.                                       */
     240                 : /* -------------------------------------------------------------------- */
     241          153977 :     else if( m_poReader->IsAttributeElement( szElementName ) )
     242                 :     {
     243           38579 :         CPLFree( m_pszCurField );
     244           38579 :         m_pszCurField = CPLStrdup("");
     245                 : 
     246                 :         // Capture href as OB property.
     247           38579 :         m_poReader->CheckForRelations( szElementName, attrs );
     248                 : 
     249                 :         // Capture "fid" attribute as part of the property value - 
     250                 :         // primarily this is for wfs:Delete operation's FeatureId attribute.
     251           38579 :         if( EQUAL(szElementName,"FeatureId") )
     252               6 :             m_poReader->CheckForFID( attrs, &m_pszCurField );
     253                 :     }
     254                 : 
     255                 : /* -------------------------------------------------------------------- */
     256                 : /*      Push the element onto the current state's path.                 */
     257                 : /* -------------------------------------------------------------------- */
     258          603725 :     poState->PushPath( szElementName );
     259                 : 
     260          603725 :     m_nDepth ++;
     261                 : }
     262                 : 
     263                 : /************************************************************************/
     264                 : /*                             endElement()                             */
     265                 : /************************************************************************/
     266         2235294 : void NASHandler::endElement(const   XMLCh* const    uri,
     267                 :                             const   XMLCh* const    localname,
     268                 :                             const   XMLCh* const    qname )
     269                 : 
     270                 : {
     271                 :     char        szElementName[MAX_TOKEN_SIZE];
     272         2235294 :     GMLReadState *poState = m_poReader->GetState();
     273                 : 
     274         2235294 :     tr_strcpy( szElementName, localname );
     275                 : 
     276                 : 
     277         2235294 :     m_nDepth --;
     278                 : 
     279         2235294 :     if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
     280                 :     {
     281         1622854 :         if (m_nDepth == m_nDepthFeature)
     282                 :         {
     283           60918 :              m_bIgnoreFeature = FALSE;
     284           60918 :              m_nDepthFeature = 0;
     285                 :         }
     286         1622854 :         return;
     287                 :     }
     288                 : 
     289                 : /* -------------------------------------------------------------------- */
     290                 : /*      Is this closing off an attribute value?  We assume so if        */
     291                 : /*      we are collecting an attribute value and got to this point.     */
     292                 : /*      We don't bother validating that the closing tag matches the     */
     293                 : /*      opening tag.                                                    */
     294                 : /* -------------------------------------------------------------------- */
     295          612440 :     if( m_pszCurField != NULL )
     296                 :     {
     297           38529 :         CPLAssert( poState->m_poFeature != NULL );
     298                 :         
     299           38529 :         m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(), m_pszCurField );
     300           38529 :         m_pszCurField = NULL;
     301                 :     }
     302                 : 
     303                 : /* -------------------------------------------------------------------- */
     304                 : /*      If we are collecting Geometry than store it, and consider if    */
     305                 : /*      this is the end of the geometry.                                */
     306                 : /* -------------------------------------------------------------------- */
     307          612440 :     if( m_pszGeometry != NULL )
     308                 :     {
     309          449744 :         int nLNLen = tr_strlen( localname );
     310                 : 
     311                 :         /* should save attributes too! */
     312                 : 
     313          449744 :         if( m_nGeomLen + nLNLen + 4 > m_nGeomAlloc )
     314                 :         {
     315               0 :             m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + 1000);
     316                 :             m_pszGeometry = (char *) 
     317               0 :                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
     318                 :         }
     319                 : 
     320          449744 :         strcat( m_pszGeometry+m_nGeomLen, "</" );
     321          449744 :         tr_strcpy( m_pszGeometry+m_nGeomLen+2, localname );
     322          449744 :         strcat( m_pszGeometry+m_nGeomLen+nLNLen+2, ">" );
     323          449744 :         m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
     324                 : 
     325          449744 :         if( poState->m_nPathLength == m_nGeometryDepth+1 )
     326                 :         {
     327            6684 :             if( poState->m_poFeature != NULL )
     328                 :             {
     329            6684 :                 CPLXMLNode* psNode = CPLParseXMLString(m_pszGeometry);
     330            6684 :                 if (psNode)
     331            6684 :                     poState->m_poFeature->SetGeometryDirectly( psNode );
     332                 :             }
     333                 : 
     334            6684 :             CPLFree( m_pszGeometry );
     335            6684 :             m_pszGeometry = NULL;
     336            6684 :             m_nGeomAlloc = m_nGeomLen = 0;
     337                 :         }
     338                 :     }
     339                 : 
     340                 : /* -------------------------------------------------------------------- */
     341                 : /*      If we are collecting a feature, and this element tag matches    */
     342                 : /*      element name for the class, then we have finished the           */
     343                 : /*      feature, and we pop the feature read state.                     */
     344                 : /* -------------------------------------------------------------------- */
     345          612440 :     if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
     346                 :         && EQUAL(szElementName,
     347                 :                  poState->m_poFeature->GetClass()->GetElementName()) )
     348                 :     {
     349            8728 :         m_nDepthFeature = 0;
     350            8728 :         m_poReader->PopState();
     351                 :     }
     352                 : 
     353                 : /* -------------------------------------------------------------------- */
     354                 : /*      Ends of a wfs:Delete should be triggered on the close of the    */
     355                 : /*      <Filter> element.                                               */
     356                 : /* -------------------------------------------------------------------- */
     357          603712 :     else if( m_nDepth == m_nDepthFeature 
     358                 :              && poState->m_poFeature != NULL
     359                 :              && EQUAL(szElementName,"Filter") 
     360                 :              && EQUAL(poState->m_poFeature->GetClass()->GetElementName(),
     361                 :                       "Delete") )
     362                 :     {
     363               6 :         m_nDepthFeature = 0;
     364               6 :         m_poReader->PopState();
     365                 :     }
     366                 : 
     367                 : /* -------------------------------------------------------------------- */
     368                 : /*      Otherwise, we just pop the element off the local read states    */
     369                 : /*      element stack.                                                  */
     370                 : /* -------------------------------------------------------------------- */
     371                 :     else
     372                 :     {
     373          603706 :         if( EQUAL(szElementName,poState->GetLastComponent()) )
     374          603706 :             poState->PopPath();
     375                 :         else
     376                 :         {
     377               0 :             CPLAssert( FALSE );
     378                 :         }
     379                 :     }
     380                 : }
     381                 : 
     382                 : /************************************************************************/
     383                 : /*                             characters()                             */
     384                 : /************************************************************************/
     385                 : 
     386                 : #if XERCES_VERSION_MAJOR >= 3
     387         4417187 : void NASHandler::characters( const XMLCh *const chars_in,
     388                 :                              const XMLSize_t length )
     389                 : #else
     390                 : void NASHandler::characters(const XMLCh* const chars_in,
     391                 :                             const unsigned int length )
     392                 : #endif
     393                 : 
     394                 : {
     395         4417187 :     const XMLCh *chars = chars_in;
     396                 : 
     397         4417187 :     if( m_pszCurField != NULL )
     398                 :     {
     399           36065 :         int     nCurFieldLength = strlen(m_pszCurField);
     400                 : 
     401           36065 :         if (nCurFieldLength == 0)
     402                 :         {
     403                 :             // Ignore white space
     404           72528 :             while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
     405             398 :                 chars++;
     406                 :         }
     407                 : 
     408           36065 :         char *pszTranslated = tr_strdup(chars);
     409                 :         
     410           36065 :         if( m_pszCurField == NULL )
     411                 :         {
     412               0 :             m_pszCurField = pszTranslated;
     413               0 :             nCurFieldLength = strlen(m_pszCurField);
     414                 :         }
     415                 :         else
     416                 :         {
     417                 :             m_pszCurField = (char *) 
     418                 :                 CPLRealloc( m_pszCurField, 
     419           36065 :                             nCurFieldLength+strlen(pszTranslated)+1 );
     420           36065 :             strcpy( m_pszCurField + nCurFieldLength, pszTranslated );
     421           36065 :             CPLFree( pszTranslated );
     422                 :         }
     423                 :     }
     424         4381122 :     else if( m_pszGeometry != NULL )
     425                 :     {
     426          892804 :         if (m_nGeomLen == 0)
     427                 :         {
     428                 :             // Ignore white space
     429               0 :             while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
     430               0 :                 chars++;
     431                 :         }
     432                 :         
     433          892804 :         int nCharsLen = tr_strlen(chars);
     434                 : 
     435          892804 :         if( m_nGeomLen + nCharsLen*4 + 4 > m_nGeomAlloc )
     436                 :         {
     437           11966 :             m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nCharsLen*4 + 1000);
     438                 :             m_pszGeometry = (char *) 
     439           11966 :                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
     440                 :         }
     441                 : 
     442          892804 :         tr_strcpy( m_pszGeometry+m_nGeomLen, chars );
     443          892804 :         m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
     444                 :     }
     445         4417187 : }
     446                 : 
     447                 : /************************************************************************/
     448                 : /*                             fatalError()                             */
     449                 : /************************************************************************/
     450                 : 
     451               0 : void NASHandler::fatalError( const SAXParseException &exception)
     452                 : 
     453                 : {
     454                 :     char *pszErrorMessage;
     455                 : 
     456               0 :     pszErrorMessage = tr_strdup( exception.getMessage() );
     457                 :     CPLError( CE_Failure, CPLE_AppDefined, 
     458                 :               "XML Parsing Error: %s\n", 
     459               0 :               pszErrorMessage );
     460                 : 
     461               0 :     CPLFree( pszErrorMessage );
     462               0 : }
     463                 : 
     464                 : /************************************************************************/
     465                 : /*                         IsGeometryElement()                          */
     466                 : /************************************************************************/
     467                 : 
     468          230317 : int NASHandler::IsGeometryElement( const char *pszElement )
     469                 : 
     470                 : {
     471                 :     return strcmp(pszElement,"Polygon") == 0
     472                 :         || strcmp(pszElement,"MultiPolygon") == 0 
     473                 :         || strcmp(pszElement,"MultiPoint") == 0 
     474                 :         || strcmp(pszElement,"MultiLineString") == 0 
     475                 :         || strcmp(pszElement,"MultiSurface") == 0 
     476                 :         || strcmp(pszElement,"GeometryCollection") == 0
     477                 :         || strcmp(pszElement,"Point") == 0 
     478                 :         || strcmp(pszElement,"Curve") == 0 
     479                 :         || strcmp(pszElement,"Surface") == 0 
     480                 :         || strcmp(pszElement,"PolygonPatch") == 0 
     481          230317 :         || strcmp(pszElement,"LineString") == 0;
     482                 : }

Generated by: LCOV version 1.7