LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/nas - nasreader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 357 288 80.7 %
Date: 2011-12-18 Functions: 31 24 77.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: gmlreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $
       3                 :  *
       4                 :  * Project:  NAS Reader
       5                 :  * Purpose:  Implementation of NASReader 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 "gmlreader.h"
      31                 : #include "cpl_error.h"
      32                 : #include "cpl_string.h"
      33                 : #include "gmlutils.h"
      34                 : 
      35                 : #define SUPPORT_GEOMETRY
      36                 : 
      37                 : #ifdef SUPPORT_GEOMETRY
      38                 : #  include "ogr_geometry.h"
      39                 : #endif
      40                 : 
      41                 : /************************************************************************/
      42                 : /* ==================================================================== */
      43                 : /*                  With XERCES Library                                 */
      44                 : /* ==================================================================== */
      45                 : /************************************************************************/
      46                 : 
      47                 : #include "nasreaderp.h"
      48                 : #include "cpl_conv.h"
      49                 : 
      50                 : /************************************************************************/
      51                 : /*                          CreateGMLReader()                           */
      52                 : /************************************************************************/
      53                 : 
      54               5 : IGMLReader *CreateNASReader()
      55                 : 
      56                 : {
      57               5 :     return new NASReader();
      58                 : }
      59                 : 
      60                 : /************************************************************************/
      61                 : /*                             GMLReader()                              */
      62                 : /************************************************************************/
      63                 : 
      64               5 : NASReader::NASReader()
      65                 : 
      66                 : {
      67               5 :     m_nClassCount = 0;
      68               5 :     m_papoClass = NULL;
      69                 : 
      70               5 :     m_bClassListLocked = FALSE;
      71                 : 
      72               5 :     m_poNASHandler = NULL;
      73               5 :     m_poSAXReader = NULL;
      74               5 :     m_bReadStarted = FALSE;
      75                 :     
      76               5 :     m_poState = NULL;
      77               5 :     m_poCompleteFeature = NULL;
      78                 : 
      79               5 :     m_pszFilename = NULL;
      80               5 :     m_pszFilteredClassName = NULL;
      81               5 : }
      82                 : 
      83                 : /************************************************************************/
      84                 : /*                             ~NASReader()                             */
      85                 : /************************************************************************/
      86                 : 
      87               5 : NASReader::~NASReader()
      88                 : 
      89                 : {
      90               5 :     ClearClasses();
      91                 : 
      92               5 :     CPLFree( m_pszFilename );
      93                 : 
      94               5 :     CleanupParser();
      95                 : 
      96               5 :     if (CSLTestBoolean(CPLGetConfigOption("NAS_XERCES_TERMINATE", "FALSE")))
      97               0 :         XMLPlatformUtils::Terminate();
      98                 : 
      99               5 :     CPLFree( m_pszFilteredClassName );
     100               5 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                          SetSourceFile()                             */
     104                 : /************************************************************************/
     105                 : 
     106               5 : void NASReader::SetSourceFile( const char *pszFilename )
     107                 : 
     108                 : {
     109               5 :     CPLFree( m_pszFilename );
     110               5 :     m_pszFilename = CPLStrdup( pszFilename );
     111               5 : }
     112                 : 
     113                 : /************************************************************************/
     114                 : /*                       GetSourceFileName()                            */
     115                 : /************************************************************************/
     116                 : 
     117               0 : const char* NASReader::GetSourceFileName()
     118                 : 
     119                 : {
     120               0 :     return m_pszFilename;
     121                 : }
     122                 : 
     123                 : /************************************************************************/
     124                 : /*                            SetupParser()                             */
     125                 : /************************************************************************/
     126                 : 
     127               9 : int NASReader::SetupParser()
     128                 : 
     129                 : {
     130                 :     static int bXercesInitialized = FALSE;
     131                 : 
     132               9 :     if( !bXercesInitialized )
     133                 :     {
     134                 :         try
     135                 :         {
     136               1 :             XMLPlatformUtils::Initialize();
     137                 :         }
     138                 :         
     139               0 :         catch (const XMLException& toCatch)
     140                 :         {
     141                 :             CPLError( CE_Warning, CPLE_AppDefined,
     142                 :                       "Exception initializing Xerces based GML reader.\n%s", 
     143               0 :                       tr_strdup(toCatch.getMessage()) );
     144               0 :             return FALSE;
     145                 :         }
     146               1 :         bXercesInitialized = TRUE;
     147                 :     }
     148                 : 
     149                 :     // Cleanup any old parser.
     150               9 :     if( m_poSAXReader != NULL )
     151               0 :         CleanupParser();
     152                 : 
     153                 :     // Create and initialize parser.
     154               9 :     XMLCh* xmlUriValid = NULL;
     155               9 :     XMLCh* xmlUriNS = NULL;
     156                 : 
     157                 :     try{
     158               9 :         m_poSAXReader = XMLReaderFactory::createXMLReader();
     159                 :     
     160               9 :         m_poNASHandler = new NASHandler( this );
     161                 : 
     162              18 :         m_poSAXReader->setContentHandler( m_poNASHandler );
     163               9 :         m_poSAXReader->setErrorHandler( m_poNASHandler );
     164               9 :         m_poSAXReader->setLexicalHandler( m_poNASHandler );
     165               9 :         m_poSAXReader->setEntityResolver( m_poNASHandler );
     166               9 :         m_poSAXReader->setDTDHandler( m_poNASHandler );
     167                 : 
     168               9 :         xmlUriValid = XMLString::transcode("http://xml.org/sax/features/validation");
     169               9 :         xmlUriNS = XMLString::transcode("http://xml.org/sax/features/namespaces");
     170                 : 
     171                 : #if (OGR_GML_VALIDATION)
     172                 :         m_poSAXReader->setFeature( xmlUriValid, true);
     173                 :         m_poSAXReader->setFeature( xmlUriNS, true);
     174                 : 
     175                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
     176                 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
     177                 : 
     178                 : //    m_poSAXReader->setDoSchema(true);
     179                 : //    m_poSAXReader->setValidationSchemaFullChecking(true);
     180                 : #else
     181               9 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreValidation, false);
     182                 : 
     183                 : #if XERCES_VERSION_MAJOR >= 3
     184               9 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, false);
     185                 : #else
     186                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, false);
     187                 : #endif
     188                 : 
     189                 : #endif
     190               9 :         XMLString::release( &xmlUriValid );
     191               9 :         XMLString::release( &xmlUriNS );
     192                 :     }
     193               0 :     catch (...)
     194                 :     {
     195               0 :         XMLString::release( &xmlUriValid );
     196               0 :         XMLString::release( &xmlUriNS );
     197                 : 
     198                 :         CPLError( CE_Warning, CPLE_AppDefined,
     199               0 :                   "Exception initializing Xerces based GML reader.\n" );
     200               0 :         return FALSE;
     201                 :     }
     202                 : 
     203               9 :     m_bReadStarted = FALSE;
     204                 : 
     205                 :     // Push an empty state.
     206              18 :     PushState( new GMLReadState() );
     207                 : 
     208               9 :     return TRUE;
     209                 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /*                           CleanupParser()                            */
     213                 : /************************************************************************/
     214                 : 
     215              17 : void NASReader::CleanupParser()
     216                 : 
     217                 : {
     218              17 :     if( m_poSAXReader == NULL )
     219               8 :         return;
     220                 : 
     221              27 :     while( m_poState )
     222               9 :         PopState();
     223                 : 
     224               9 :     delete m_poSAXReader;
     225               9 :     m_poSAXReader = NULL;
     226                 : 
     227               9 :     delete m_poNASHandler;
     228               9 :     m_poNASHandler = NULL;
     229                 : 
     230               9 :     delete m_poCompleteFeature;
     231               9 :     m_poCompleteFeature = NULL;
     232                 : 
     233               9 :     m_bReadStarted = FALSE;
     234                 : }
     235                 : 
     236                 : /************************************************************************/
     237                 : /*                            NextFeature()                             */
     238                 : /************************************************************************/
     239                 : 
     240            8738 : GMLFeature *NASReader::NextFeature()
     241                 : 
     242                 : {
     243            8738 :     GMLFeature *poReturn = NULL;
     244                 : 
     245                 :     try
     246                 :     {
     247            8738 :         if( !m_bReadStarted )
     248                 :         {
     249               9 :             if( m_poSAXReader == NULL )
     250               6 :                 SetupParser();
     251                 : 
     252               9 :             if( !m_poSAXReader->parseFirst( m_pszFilename, m_oToFill ) )
     253               0 :                 return NULL;
     254               9 :             m_bReadStarted = TRUE;
     255                 :         }
     256                 : 
     257        17661102 :         while( m_poCompleteFeature == NULL 
     258         8826184 :                && m_poSAXReader->parseNext( m_oToFill ) ) {}
     259                 : 
     260            8738 :         poReturn = m_poCompleteFeature;
     261            8738 :         m_poCompleteFeature = NULL;
     262                 : 
     263                 :     }
     264               0 :     catch (const XMLException& toCatch)
     265                 :     {
     266                 :         CPLDebug( "GML", 
     267                 :                   "Error during NextFeature()! Message:\n%s", 
     268               0 :                   tr_strdup( toCatch.getMessage() ) );
     269                 :     }
     270                 : 
     271            8738 :     return poReturn;
     272                 : }
     273                 : 
     274                 : /************************************************************************/
     275                 : /*                            PushFeature()                             */
     276                 : /*                                                                      */
     277                 : /*      Create a feature based on the named element.  If the            */
     278                 : /*      corresponding feature class doesn't exist yet, then create      */
     279                 : /*      it now.  A new GMLReadState will be created for the feature,    */
     280                 : /*      and it will be placed within that state.  The state is          */
     281                 : /*      pushed onto the readstate stack.                                */
     282                 : /************************************************************************/
     283                 : 
     284            8734 : void NASReader::PushFeature( const char *pszElement, 
     285                 :                              const Attributes &attrs )
     286                 : 
     287                 : {
     288                 :     int iClass;
     289                 : 
     290                 : /* -------------------------------------------------------------------- */
     291                 : /*      Find the class of this element.                                 */
     292                 : /* -------------------------------------------------------------------- */
     293          150035 :     for( iClass = 0; iClass < GetClassCount(); iClass++ )
     294                 :     {
     295          150032 :         if( EQUAL(pszElement,GetClass(iClass)->GetElementName()) )
     296            8731 :             break;
     297                 :     }
     298                 : 
     299                 : /* -------------------------------------------------------------------- */
     300                 : /*      Create a new feature class for this element, if there is no     */
     301                 : /*      existing class for it.                                          */
     302                 : /* -------------------------------------------------------------------- */
     303            8734 :     if( iClass == GetClassCount() )
     304                 :     {
     305               3 :         CPLAssert( !IsClassListLocked() );
     306                 : 
     307               3 :         GMLFeatureClass *poNewClass = new GMLFeatureClass( pszElement );
     308                 : 
     309               3 :         AddClass( poNewClass );
     310                 :     }
     311                 : 
     312                 : /* -------------------------------------------------------------------- */
     313                 : /*      Create a feature of this feature class.                         */
     314                 : /* -------------------------------------------------------------------- */
     315            8734 :     GMLFeature *poFeature = new GMLFeature( GetClass( iClass ) );
     316                 : 
     317                 : /* -------------------------------------------------------------------- */
     318                 : /*      Create and push a new read state.                               */
     319                 : /* -------------------------------------------------------------------- */
     320                 :     GMLReadState *poState;
     321                 : 
     322           17468 :     poState = new GMLReadState();
     323            8734 :     poState->m_poFeature = poFeature;
     324            8734 :     PushState( poState );
     325                 : 
     326                 : /* -------------------------------------------------------------------- */
     327                 : /*      Check for gml:id, and if found push it as an attribute named    */
     328                 : /*      gml_id.                                                         */
     329                 : /* -------------------------------------------------------------------- */
     330                 :     int nFIDIndex;
     331                 :     XMLCh   anFID[100];
     332                 : 
     333            8734 :     tr_strcpy( anFID, "gml:id" );
     334            8734 :     nFIDIndex = attrs.getIndex( anFID );
     335            8734 :     if( nFIDIndex != -1 )
     336                 :     {
     337            8728 :         char *pszFID = tr_strdup( attrs.getValue( nFIDIndex ) );
     338            8728 :         SetFeaturePropertyDirectly( "gml_id", pszFID );
     339                 :     }
     340                 : 
     341            8734 : }
     342                 : 
     343                 : /************************************************************************/
     344                 : /*                          IsFeatureElement()                          */
     345                 : /*                                                                      */
     346                 : /*      Based on context and the element name, is this element a new    */
     347                 : /*      GML feature element?                                            */
     348                 : /************************************************************************/
     349                 : 
     350          223627 : int NASReader::IsFeatureElement( const char *pszElement )
     351                 : 
     352                 : {
     353          223627 :     CPLAssert( m_poState != NULL );
     354                 : 
     355          223627 :     const char *pszLast = m_poState->GetLastComponent();
     356          223627 :     int        nLen = strlen(pszLast);
     357                 : 
     358                 :     // There seem to be two major NAS classes of feature identifiers 
     359                 :     // -- either a wfs:Insert or a gml:featureMember. 
     360                 : 
     361          223627 :     if( (nLen < 6 || !EQUAL(pszLast+nLen-6,"Insert")) 
     362                 :         && (nLen < 13 || !EQUAL(pszLast+nLen-13,"featureMember"))
     363                 :         && (nLen < 6 || !EQUAL(pszLast+nLen-7,"Replace")) )
     364          153981 :         return FALSE;
     365                 : 
     366                 :     // If the class list isn't locked, any element that is a featureMember
     367                 :     // will do. 
     368           69646 :     if( !IsClassListLocked() )
     369               3 :         return TRUE;
     370                 : 
     371                 :     // otherwise, find a class with the desired element name.
     372         1090803 :     for( int i = 0; i < GetClassCount(); i++ )
     373                 :     {
     374         1090803 :         if( EQUAL(pszElement,GetClass(i)->GetElementName()) )
     375           69643 :             return TRUE;
     376                 :     }
     377                 : 
     378               0 :     return FALSE;
     379                 : }
     380                 : 
     381                 : /************************************************************************/
     382                 : /*                         IsAttributeElement()                         */
     383                 : /************************************************************************/
     384                 : 
     385          153977 : int NASReader::IsAttributeElement( const char *pszElement )
     386                 : 
     387                 : {
     388          153977 :     if( m_poState->m_poFeature == NULL )
     389           69852 :         return FALSE;
     390                 : 
     391           84125 :     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
     392                 : 
     393                 :     // If the schema is not yet locked, then any simple element
     394                 :     // is potentially an attribute.
     395           84125 :     if( !poClass->IsSchemaLocked() )
     396             112 :         return TRUE;
     397                 : 
     398                 :     // Otherwise build the path to this element into a single string
     399                 :     // and compare against known attributes.
     400           84013 :     CPLString osElemPath;
     401                 : 
     402           84013 :     if( m_poState->m_nPathLength == 0 )
     403           42220 :         osElemPath = pszElement;
     404                 :     else
     405                 :     {
     406           41793 :         osElemPath = m_poState->osPath;
     407           41793 :         osElemPath += "|";
     408           41793 :         osElemPath += pszElement;
     409                 :     }
     410                 : 
     411          603772 :     for( int i = 0; i < poClass->GetPropertyCount(); i++ )
     412          558226 :         if( EQUAL(poClass->GetProperty(i)->GetSrcElement(),osElemPath) )
     413           38467 :             return TRUE;
     414                 : 
     415           45546 :     return FALSE;
     416                 : }
     417                 : 
     418                 : /************************************************************************/
     419                 : /*                              PopState()                              */
     420                 : /************************************************************************/
     421                 : 
     422            8743 : void NASReader::PopState()
     423                 : 
     424                 : {
     425            8743 :     if( m_poState != NULL )
     426                 :     {
     427            8743 :         if( m_poState->m_poFeature != NULL && m_poCompleteFeature == NULL )
     428                 :         {
     429            8734 :             m_poCompleteFeature = m_poState->m_poFeature;
     430            8734 :             m_poState->m_poFeature = NULL;
     431                 :         }
     432                 : 
     433                 :         GMLReadState *poParent;
     434                 : 
     435            8743 :         poParent = m_poState->m_poParentState;
     436                 :         
     437            8743 :         delete m_poState;
     438            8743 :         m_poState = poParent;
     439                 :     }
     440            8743 : }
     441                 : 
     442                 : /************************************************************************/
     443                 : /*                             PushState()                              */
     444                 : /************************************************************************/
     445                 : 
     446            8743 : void NASReader::PushState( GMLReadState *poState )
     447                 : 
     448                 : {
     449            8743 :     poState->m_poParentState = m_poState;
     450            8743 :     m_poState = poState;
     451            8743 : }
     452                 : 
     453                 : /************************************************************************/
     454                 : /*                              GetClass()                              */
     455                 : /************************************************************************/
     456                 : 
     457         1258487 : GMLFeatureClass *NASReader::GetClass( int iClass ) const
     458                 : 
     459                 : {
     460         1258487 :     if( iClass < 0 || iClass >= m_nClassCount )
     461               0 :         return NULL;
     462                 :     else
     463         1258487 :         return m_papoClass[iClass];
     464                 : }
     465                 : 
     466                 : /************************************************************************/
     467                 : /*                              GetClass()                              */
     468                 : /************************************************************************/
     469                 : 
     470             254 : GMLFeatureClass *NASReader::GetClass( const char *pszName ) const
     471                 : 
     472                 : {
     473            8788 :     for( int iClass = 0; iClass < m_nClassCount; iClass++ )
     474                 :     {
     475            8661 :         if( EQUAL(GetClass(iClass)->GetName(),pszName) )
     476             127 :             return GetClass(iClass);
     477                 :     }
     478                 : 
     479             127 :     return NULL;
     480                 : }
     481                 : 
     482                 : /************************************************************************/
     483                 : /*                              AddClass()                              */
     484                 : /************************************************************************/
     485                 : 
     486             127 : int NASReader::AddClass( GMLFeatureClass *poNewClass )
     487                 : 
     488                 : {
     489             127 :     CPLAssert( GetClass( poNewClass->GetName() ) == NULL );
     490                 : 
     491             127 :     m_nClassCount++;
     492                 :     m_papoClass = (GMLFeatureClass **) 
     493             127 :         CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
     494             127 :     m_papoClass[m_nClassCount-1] = poNewClass;
     495                 : 
     496             127 :     return m_nClassCount-1;
     497                 : }
     498                 : 
     499                 : /************************************************************************/
     500                 : /*                            ClearClasses()                            */
     501                 : /************************************************************************/
     502                 : 
     503               8 : void NASReader::ClearClasses()
     504                 : 
     505                 : {
     506             135 :     for( int i = 0; i < m_nClassCount; i++ )
     507             127 :         delete m_papoClass[i];
     508               8 :     CPLFree( m_papoClass );
     509                 : 
     510               8 :     m_nClassCount = 0;
     511               8 :     m_papoClass = NULL;
     512               8 : }
     513                 : 
     514                 : /************************************************************************/
     515                 : /*                         SetFeatureProperty()                         */
     516                 : /*                                                                      */
     517                 : /*      Set the property value on the current feature, adding the       */
     518                 : /*      property name to the GMLFeatureClass if required.               */
     519                 : /*      The pszValue ownership is passed to this function.              */
     520                 : /************************************************************************/
     521                 : 
     522           47263 : void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
     523                 :                                             char *pszValue )
     524                 : 
     525                 : {
     526           47263 :     GMLFeature *poFeature = GetState()->m_poFeature;
     527                 : 
     528           47263 :     CPLAssert( poFeature  != NULL );
     529                 : 
     530                 : /* -------------------------------------------------------------------- */
     531                 : /*      Does this property exist in the feature class?  If not, add     */
     532                 : /*      it.                                                             */
     533                 : /* -------------------------------------------------------------------- */
     534           47263 :     GMLFeatureClass *poClass = poFeature->GetClass();
     535                 :     int      iProperty;
     536                 : 
     537          201822 :     for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
     538                 :     {
     539          201793 :         if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(),
     540                 :                   pszElement ) )
     541           47234 :             break;
     542                 :     }
     543                 :     
     544           47263 :     if( iProperty == poClass->GetPropertyCount() )
     545                 :     {
     546              29 :         if( poClass->IsSchemaLocked() )
     547                 :         {
     548               0 :             CPLDebug("GML","Encountered property missing from class schema.");
     549               0 :             CPLFree(pszValue);
     550               0 :             return;
     551                 :         }
     552                 : 
     553              29 :         CPLString osFieldName;
     554                 :         
     555              29 :         if( strchr(pszElement,'|') == NULL )
     556              15 :             osFieldName = pszElement;
     557                 :         else
     558                 :         {
     559              14 :             osFieldName = strrchr(pszElement,'|') + 1;
     560              14 :             if( poClass->GetPropertyIndex(osFieldName) != -1 )
     561               2 :                 osFieldName = pszElement;
     562                 :         }
     563                 : 
     564                 :         // Does this conflict with an existing property name? 
     565              58 :         while( poClass->GetProperty(osFieldName) != NULL )
     566                 :         {
     567               0 :             osFieldName += "_";
     568                 :         }
     569                 : 
     570              29 :         GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);
     571                 : 
     572              58 :         if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
     573               0 :             poPDefn->SetType( GMLPT_String );
     574                 : 
     575              29 :         poClass->AddProperty( poPDefn );
     576                 :     }
     577                 : 
     578                 : /* -------------------------------------------------------------------- */
     579                 : /*      We want to handle <lage> specially to ensure it is zero         */
     580                 : /*      filled, and treated as a string depspite the numeric            */
     581                 : /*      content. https://trac.wheregroup.com/PostNAS/ticket/9           */
     582                 : /* -------------------------------------------------------------------- */
     583           47263 :     if( strcmp(poClass->GetProperty(iProperty)->GetName(),"lage") == 0 )
     584                 :     {
     585             315 :         if( strlen(pszValue) < 5 )
     586                 :         {
     587               0 :             CPLString osValue = "00000";
     588               0 :             osValue += pszValue;
     589               0 :             poFeature->SetPropertyDirectly( iProperty, CPLStrdup(osValue + osValue.size() - 5) );
     590               0 :             CPLFree(pszValue);
     591                 :         }
     592                 :         else
     593             315 :             poFeature->SetPropertyDirectly( iProperty, pszValue );
     594                 : 
     595                 :         
     596             315 :         if( !poClass->IsSchemaLocked() )
     597                 :         {
     598               0 :             poClass->GetProperty(iProperty)->SetWidth( 5 );
     599               0 :             poClass->GetProperty(iProperty)->SetType( GMLPT_String );
     600                 :         }
     601             315 :         return;
     602                 :     }
     603                 : 
     604                 : /* -------------------------------------------------------------------- */
     605                 : /*      Set the property                                                */
     606                 : /* -------------------------------------------------------------------- */
     607           46948 :     poFeature->SetPropertyDirectly( iProperty, pszValue );
     608                 : 
     609                 : /* -------------------------------------------------------------------- */
     610                 : /*      Do we need to update the property type?                         */
     611                 : /* -------------------------------------------------------------------- */
     612           46948 :     if( !poClass->IsSchemaLocked() )
     613                 :     {
     614                 :         // Special handling for punktkennung per NAS #12
     615              70 :         if( strcmp(poClass->GetProperty(iProperty)->GetName(),
     616                 :                    "punktkennung") == 0)
     617                 :         {
     618               0 :             poClass->GetProperty(iProperty)->SetWidth( 15 );
     619               0 :             poClass->GetProperty(iProperty)->SetType( GMLPT_String );
     620                 :         }
     621                 :         // Special handling for artDerFlurstuecksgrenze per http://trac.osgeo.org/gdal/ticket/4255
     622              70 :         else if( strcmp(poClass->GetProperty(iProperty)->GetName(),
     623                 :                    "artDerFlurstuecksgrenze") == 0)
     624                 :         {
     625               0 :             poClass->GetProperty(iProperty)->SetType( GMLPT_IntegerList );
     626                 :         }
     627                 :         else
     628                 :             poClass->GetProperty(iProperty)->AnalysePropertyValue(
     629              70 :                 poFeature->GetProperty(iProperty));
     630                 :     }
     631                 : }
     632                 : 
     633                 : /************************************************************************/
     634                 : /*                            LoadClasses()                             */
     635                 : /************************************************************************/
     636                 : 
     637               2 : int NASReader::LoadClasses( const char *pszFile )
     638                 : 
     639                 : {
     640                 :     // Add logic later to determine reasonable default schema file. 
     641               2 :     if( pszFile == NULL )
     642               0 :         return FALSE;
     643                 : 
     644                 : /* -------------------------------------------------------------------- */
     645                 : /*      Load the raw XML file.                                          */
     646                 : /* -------------------------------------------------------------------- */
     647                 :     FILE       *fp;
     648                 :     int         nLength;
     649                 :     char        *pszWholeText;
     650                 : 
     651               2 :     fp = VSIFOpen( pszFile, "rb" );
     652                 : 
     653               2 :     if( fp == NULL )
     654                 :     {
     655                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     656               0 :                   "Failed to open file %s.", pszFile );
     657               0 :         return FALSE;
     658                 :     }
     659                 : 
     660               2 :     VSIFSeek( fp, 0, SEEK_END );
     661               2 :     nLength = VSIFTell( fp );
     662               2 :     VSIFSeek( fp, 0, SEEK_SET );
     663                 : 
     664               2 :     pszWholeText = (char *) VSIMalloc(nLength+1);
     665               2 :     if( pszWholeText == NULL )
     666                 :     {
     667                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     668                 :                   "Failed to allocate %d byte buffer for %s,\n"
     669                 :                   "is this really a GMLFeatureClassList file?",
     670               0 :                   nLength, pszFile );
     671               0 :         VSIFClose( fp );
     672               0 :         return FALSE;
     673                 :     }
     674                 :     
     675               2 :     if( VSIFRead( pszWholeText, nLength, 1, fp ) != 1 )
     676                 :     {
     677               0 :         VSIFree( pszWholeText );
     678               0 :         VSIFClose( fp );
     679                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     680               0 :                   "Read failed on %s.", pszFile );
     681               0 :         return FALSE;
     682                 :     }
     683               2 :     pszWholeText[nLength] = '\0';
     684                 : 
     685               2 :     VSIFClose( fp );
     686                 : 
     687               2 :     if( strstr( pszWholeText, "<GMLFeatureClassList>" ) == NULL )
     688                 :     {
     689               0 :         VSIFree( pszWholeText );
     690                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     691                 :                   "File %s does not contain a GMLFeatureClassList tree.",
     692               0 :                   pszFile );
     693               0 :         return FALSE;
     694                 :     }
     695                 : 
     696                 : /* -------------------------------------------------------------------- */
     697                 : /*      Convert to XML parse tree.                                      */
     698                 : /* -------------------------------------------------------------------- */
     699                 :     CPLXMLNode *psRoot;
     700                 : 
     701               2 :     psRoot = CPLParseXMLString( pszWholeText );
     702               2 :     VSIFree( pszWholeText );
     703                 : 
     704                 :     // We assume parser will report errors via CPL.
     705               2 :     if( psRoot == NULL )
     706               0 :         return FALSE;
     707                 : 
     708               2 :     if( psRoot->eType != CXT_Element 
     709                 :         || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
     710                 :     {
     711               0 :         CPLDestroyXMLNode(psRoot);
     712                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     713                 :                   "File %s is not a GMLFeatureClassList document.",
     714               0 :                   pszFile );
     715               0 :         return FALSE;
     716                 :     }
     717                 : 
     718                 : /* -------------------------------------------------------------------- */
     719                 : /*      Extract feature classes for all definitions found.              */
     720                 : /* -------------------------------------------------------------------- */
     721                 :     CPLXMLNode *psThis;
     722                 : 
     723             126 :     for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     724                 :     {
     725             124 :         if( psThis->eType == CXT_Element 
     726                 :             && EQUAL(psThis->pszValue,"GMLFeatureClass") )
     727                 :         {
     728                 :             GMLFeatureClass   *poClass;
     729                 : 
     730             124 :             poClass = new GMLFeatureClass();
     731                 : 
     732             124 :             if( !poClass->InitializeFromXML( psThis ) )
     733                 :             {
     734               0 :                 delete poClass;
     735               0 :                 CPLDestroyXMLNode( psRoot );
     736               0 :                 return FALSE;
     737                 :             }
     738                 : 
     739             124 :             poClass->SetSchemaLocked( TRUE );
     740                 : 
     741             124 :             AddClass( poClass );
     742                 :         }
     743                 :     }
     744                 : 
     745               2 :     CPLDestroyXMLNode( psRoot );
     746                 :     
     747               2 :     SetClassListLocked( TRUE );
     748                 : 
     749               2 :     return TRUE;
     750                 : }
     751                 : 
     752                 : /************************************************************************/
     753                 : /*                            SaveClasses()                             */
     754                 : /************************************************************************/
     755                 : 
     756               2 : int NASReader::SaveClasses( const char *pszFile )
     757                 : 
     758                 : {
     759                 :     // Add logic later to determine reasonable default schema file. 
     760               2 :     if( pszFile == NULL )
     761               0 :         return FALSE;
     762                 : 
     763                 : /* -------------------------------------------------------------------- */
     764                 : /*      Create in memory schema tree.                                   */
     765                 : /* -------------------------------------------------------------------- */
     766                 :     CPLXMLNode *psRoot;
     767                 : 
     768               2 :     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
     769                 : 
     770               5 :     for( int iClass = 0; iClass < GetClassCount(); iClass++ )
     771                 :     {
     772               3 :         GMLFeatureClass *poClass = GetClass( iClass );
     773                 :         
     774               3 :         CPLAddXMLChild( psRoot, poClass->SerializeToXML() );
     775                 :     }
     776                 : 
     777                 : /* -------------------------------------------------------------------- */
     778                 : /*      Serialize to disk.                                              */
     779                 : /* -------------------------------------------------------------------- */
     780                 :     FILE        *fp;
     781               2 :     int         bSuccess = TRUE;
     782               2 :     char        *pszWholeText = CPLSerializeXMLTree( psRoot );
     783                 :     
     784               2 :     CPLDestroyXMLNode( psRoot );
     785                 :  
     786               2 :     fp = VSIFOpen( pszFile, "wb" );
     787                 :     
     788               2 :     if( fp == NULL )
     789               0 :         bSuccess = FALSE;
     790               2 :     else if( VSIFWrite( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
     791               0 :         bSuccess = FALSE;
     792                 :     else
     793               2 :         VSIFClose( fp );
     794                 : 
     795               2 :     CPLFree( pszWholeText );
     796                 : 
     797               2 :     return bSuccess;
     798                 : }
     799                 : 
     800                 : /************************************************************************/
     801                 : /*                          PrescanForSchema()                          */
     802                 : /*                                                                      */
     803                 : /*      For now we use a pretty dumb approach of just doing a normal    */
     804                 : /*      scan of the whole file, building up the schema information.     */
     805                 : /*      Eventually we hope to do a more efficient scan when just        */
     806                 : /*      looking for schema information.                                 */
     807                 : /************************************************************************/
     808                 : 
     809               3 : int NASReader::PrescanForSchema( int bGetExtents )
     810                 : 
     811                 : {
     812                 :     GMLFeature  *poFeature;
     813                 : 
     814               3 :     if( m_pszFilename == NULL )
     815               0 :         return FALSE;
     816                 : 
     817               3 :     SetClassListLocked( FALSE );
     818                 : 
     819               3 :     ClearClasses();
     820               3 :     if( !SetupParser() )
     821               0 :         return FALSE;
     822                 : 
     823               3 :     std::string osWork;
     824                 : 
     825              11 :     while( (poFeature = NextFeature()) != NULL )
     826                 :     {
     827               5 :         GMLFeatureClass *poClass = poFeature->GetClass();
     828                 : 
     829               5 :         if( poClass->GetFeatureCount() == -1 )
     830               3 :             poClass->SetFeatureCount( 1 );
     831                 :         else
     832               2 :             poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
     833                 : 
     834                 : #ifdef SUPPORT_GEOMETRY
     835               5 :         if( bGetExtents )
     836                 :         {
     837               5 :             OGRGeometry *poGeometry = NULL;
     838                 : 
     839               5 :             const CPLXMLNode* const * papsGeometry = poFeature->GetGeometryList();
     840               5 :             if( papsGeometry[0] != NULL )
     841                 :             {
     842               1 :                 poGeometry = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[0]);
     843                 :             }
     844                 : 
     845               5 :             if( poGeometry != NULL )
     846                 :             {
     847                 :                 double  dfXMin, dfXMax, dfYMin, dfYMax;
     848               1 :                 OGREnvelope sEnvelope;
     849                 :                 OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
     850               1 :                     poClass->GetGeometryType();
     851                 : 
     852                 :                 // Merge SRSName into layer.
     853               1 :                 const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork, FALSE);
     854                 : //                if (pszSRSName != NULL)
     855                 : //                    m_bCanUseGlobalSRSName = FALSE;
     856               1 :                 poClass->MergeSRSName(pszSRSName);
     857                 : 
     858                 :                 // Merge geometry type into layer.
     859               1 :                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
     860               1 :                     eGType = wkbNone;
     861                 : 
     862                 :                 poClass->SetGeometryType( 
     863                 :                     (int) OGRMergeGeometryTypes(
     864               1 :                         eGType, poGeometry->getGeometryType() ) );
     865                 : 
     866                 :                 // merge extents.
     867               1 :                 poGeometry->getEnvelope( &sEnvelope );
     868               1 :                 delete poGeometry;
     869               1 :                 if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
     870                 :                 {
     871               0 :                     dfXMin = MIN(dfXMin,sEnvelope.MinX);
     872               0 :                     dfXMax = MAX(dfXMax,sEnvelope.MaxX);
     873               0 :                     dfYMin = MIN(dfYMin,sEnvelope.MinY);
     874               0 :                     dfYMax = MAX(dfYMax,sEnvelope.MaxY);
     875                 :                 }
     876                 :                 else
     877                 :                 {
     878               1 :                     dfXMin = sEnvelope.MinX;
     879               1 :                     dfXMax = sEnvelope.MaxX;
     880               1 :                     dfYMin = sEnvelope.MinY;
     881               1 :                     dfYMax = sEnvelope.MaxY;
     882                 :                 }
     883                 : 
     884               1 :                 poClass->SetExtents( dfXMin, dfXMax, dfYMin, dfYMax );
     885                 :             }
     886                 :             else 
     887                 :             {
     888               4 :                 if( poClass->GetGeometryType() == (int) wkbUnknown 
     889                 :                     && poClass->GetFeatureCount() == 1 )
     890               2 :                     poClass->SetGeometryType( wkbNone );
     891                 :             }
     892                 : #endif /* def SUPPORT_GEOMETRY */
     893                 :         }
     894                 :         
     895               5 :         delete poFeature;
     896                 :     }
     897                 : 
     898               3 :     CleanupParser();
     899                 : 
     900               3 :     return GetClassCount() > 0;
     901                 : }
     902                 : 
     903                 : /************************************************************************/
     904                 : /*                            ResetReading()                            */
     905                 : /************************************************************************/
     906                 : 
     907               9 : void NASReader::ResetReading()
     908                 : 
     909                 : {
     910               9 :     CleanupParser();
     911               9 :     SetFilteredClassName(NULL);
     912               9 : }
     913                 : 
     914                 : /************************************************************************/
     915                 : /*                            CheckForFID()                             */
     916                 : /*                                                                      */
     917                 : /*      Merge the fid attribute into the current field text.            */
     918                 : /************************************************************************/
     919                 : 
     920               6 : void NASReader::CheckForFID( const Attributes &attrs,
     921                 :                              char **ppszCurField )
     922                 : 
     923                 : {
     924                 :     int nIndex;
     925                 :     XMLCh  Name[100];
     926                 : 
     927               6 :     tr_strcpy( Name, "fid" );
     928               6 :     nIndex = attrs.getIndex( Name );
     929                 : 
     930               6 :     if( nIndex != -1 )
     931                 :     {
     932               6 :         char *pszFID = tr_strdup( attrs.getValue( nIndex ) );
     933               6 :         CPLString osCurField = *ppszCurField;
     934                 : 
     935               6 :         osCurField += pszFID;
     936               6 :         CPLFree( pszFID );
     937                 : 
     938               6 :         CPLFree( *ppszCurField );
     939               6 :         *ppszCurField = CPLStrdup(osCurField);
     940                 :     }
     941               6 : }
     942                 : 
     943                 : /************************************************************************/
     944                 : /*                         CheckForRelations()                          */
     945                 : /************************************************************************/
     946                 : 
     947           38579 : void NASReader::CheckForRelations( const char *pszElement, 
     948                 :                                    const Attributes &attrs )
     949                 : 
     950                 : {
     951           38579 :     GMLFeature *poFeature = GetState()->m_poFeature;
     952                 : 
     953           38579 :     CPLAssert( poFeature  != NULL );
     954                 : 
     955                 :     int nIndex;
     956                 :     XMLCh  Name[100];
     957                 : 
     958           38579 :     tr_strcpy( Name, "xlink:href" );
     959           38579 :     nIndex = attrs.getIndex( Name );
     960                 : 
     961           38579 :     if( nIndex != -1 )
     962                 :     {
     963            2508 :         char *pszHRef = tr_strdup( attrs.getValue( nIndex ) );
     964                 : 
     965            2508 :         if( EQUALN(pszHRef,"urn:adv:oid:", 12 ) )
     966            2508 :             poFeature->AddOBProperty( pszElement, pszHRef );
     967                 : 
     968            2508 :         CPLFree( pszHRef );
     969                 :     }
     970           38579 : }
     971                 : 
     972                 : /************************************************************************/
     973                 : /*                         HugeFileResolver()                           */
     974                 : /*      Returns TRUE for success                                        */
     975                 : /************************************************************************/
     976                 : 
     977               0 : int NASReader::HugeFileResolver( const char *pszFile,
     978                 :                               int bSqliteIsTempFile,
     979                 :                               int iSqliteCacheMB )
     980                 : 
     981                 : {
     982               0 :     CPLDebug( "NAS", "HugeFileResolver() not currently implemented for NAS." );
     983               0 :     return FALSE;
     984                 : }
     985                 : 
     986                 : /************************************************************************/
     987                 : /*                         PrescanForTemplate()                         */
     988                 : /*      Returns TRUE for success                                        */
     989                 : /************************************************************************/
     990                 : 
     991               0 : int NASReader::PrescanForTemplate( void )
     992                 : 
     993                 : {
     994               0 :     CPLDebug( "NAS", "PrescanForTemplate() not currently implemented for NAS." );
     995               0 :     return FALSE;
     996                 : }
     997                 : 
     998                 : /************************************************************************/
     999                 : /*                           ResolveXlinks()                            */
    1000                 : /*      Returns TRUE for success                                        */
    1001                 : /************************************************************************/
    1002                 : 
    1003               0 : int NASReader::ResolveXlinks( const char *pszFile,
    1004                 :                               int* pbOutIsTempFile,
    1005                 :                               char **papszSkip,
    1006                 :                               const int bStrict )
    1007                 : 
    1008                 : {
    1009               0 :     CPLDebug( "NAS", "ResolveXlinks() not currently implemented for NAS." );
    1010               0 :     return FALSE;
    1011                 : }
    1012                 : 
    1013                 : /************************************************************************/
    1014                 : /*                       SetFilteredClassName()                         */
    1015                 : /************************************************************************/
    1016                 : 
    1017              17 : int NASReader::SetFilteredClassName(const char* pszClassName)
    1018                 : {
    1019              17 :     CPLFree(m_pszFilteredClassName);
    1020              17 :     m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
    1021              17 :     return TRUE;
    1022                 : }

Generated by: LCOV version 1.7