LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - gmlreader.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 346
Code covered: 82.1 % Executed lines: 284

       1                 : /******************************************************************************
       2                 :  * $Id: gmlreader.cpp 20029 2010-07-11 18:38:23Z rouault $
       3                 :  *
       4                 :  * Project:  GML Reader
       5                 :  * Purpose:  Implementation of GMLReader 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                 : 
      34                 : #define SUPPORT_GEOMETRY
      35                 : 
      36                 : #ifdef SUPPORT_GEOMETRY
      37                 : #  include "ogr_geometry.h"
      38                 : #endif
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                            ~IGMLReader()                             */
      42                 : /************************************************************************/
      43                 : 
      44              21 : IGMLReader::~IGMLReader()
      45                 : 
      46                 : {
      47              21 : }
      48                 : 
      49                 : /************************************************************************/
      50                 : /* ==================================================================== */
      51                 : /*                  No XERCES or EXPAT Library                          */
      52                 : /* ==================================================================== */
      53                 : /************************************************************************/
      54                 : #if HAVE_XERCES == 0 && !defined(HAVE_EXPAT)
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                          CreateGMLReader()                           */
      58                 : /************************************************************************/
      59                 : 
      60                 : IGMLReader *CreateGMLReader()
      61                 : 
      62                 : {
      63                 :     CPLError( CE_Failure, CPLE_AppDefined,
      64                 :               "Unable to create Xerces C++ or Expat based GML reader, Xerces or Expat support\n"
      65                 :               "not configured into GDAL/OGR." );
      66                 :     return NULL;
      67                 : }
      68                 : 
      69                 : /************************************************************************/
      70                 : /* ==================================================================== */
      71                 : /*                  With XERCES or EXPAT Library                        */
      72                 : /* ==================================================================== */
      73                 : /************************************************************************/
      74                 : #else /* HAVE_XERCES == 1 or HAVE_EXPAT */
      75                 : 
      76                 : #include "gmlreaderp.h"
      77                 : #include "cpl_conv.h"
      78                 : 
      79                 : /************************************************************************/
      80                 : /*                          CreateGMLReader()                           */
      81                 : /************************************************************************/
      82                 : 
      83              20 : IGMLReader *CreateGMLReader()
      84                 : 
      85                 : {
      86              20 :     return new GMLReader();
      87                 : }
      88                 : 
      89                 : int GMLReader::m_bXercesInitialized = FALSE;
      90                 : int GMLReader::m_nInstanceCount = 0;
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                             GMLReader()                              */
      94                 : /************************************************************************/
      95                 : 
      96              20 : GMLReader::GMLReader()
      97                 : 
      98                 : {
      99              20 :     m_nInstanceCount++;
     100              20 :     m_nClassCount = 0;
     101              20 :     m_papoClass = NULL;
     102                 : 
     103              20 :     m_bClassListLocked = FALSE;
     104                 : 
     105              20 :     m_poGMLHandler = NULL;
     106                 : #if HAVE_XERCES == 1
     107              20 :     m_poSAXReader = NULL;
     108              20 :     m_poCompleteFeature = NULL;
     109              20 :     m_GMLInputSource = NULL;
     110                 : #else
     111                 :     oParser = NULL;
     112                 :     ppoFeatureTab = NULL;
     113                 :     nFeatureTabIndex = 0;
     114                 :     nFeatureTabLength = 0;
     115                 : #endif
     116              20 :     fpGML = NULL;
     117              20 :     m_bReadStarted = FALSE;
     118                 :     
     119              20 :     m_poState = NULL;
     120                 : 
     121              20 :     m_pszFilename = NULL;
     122                 : 
     123              20 :     m_bStopParsing = FALSE;
     124              20 : }
     125                 : 
     126                 : /************************************************************************/
     127                 : /*                             ~GMLReader()                             */
     128                 : /************************************************************************/
     129                 : 
     130              20 : GMLReader::~GMLReader()
     131                 : 
     132                 : {
     133              20 :     ClearClasses();
     134                 : 
     135              20 :     CPLFree( m_pszFilename );
     136                 : 
     137              20 :     CleanupParser();
     138                 : 
     139              20 :     --m_nInstanceCount;
     140                 : #if HAVE_XERCES == 1
     141              20 :     if( m_nInstanceCount == 0 && m_bXercesInitialized )
     142                 :     {
     143              16 :         XMLPlatformUtils::Terminate();
     144              16 :         m_bXercesInitialized = FALSE;
     145                 :     }
     146                 : #endif
     147                 : 
     148              20 :     if (fpGML)
     149              19 :         VSIFCloseL(fpGML);
     150              20 :     fpGML = NULL;
     151              20 : }
     152                 : 
     153                 : /************************************************************************/
     154                 : /*                          SetSourceFile()                             */
     155                 : /************************************************************************/
     156                 : 
     157              20 : void GMLReader::SetSourceFile( const char *pszFilename )
     158                 : 
     159                 : {
     160              20 :     CPLFree( m_pszFilename );
     161              20 :     m_pszFilename = CPLStrdup( pszFilename );
     162              20 : }
     163                 : 
     164                 : /************************************************************************/
     165                 : /*                       GetSourceFileName()                           */
     166                 : /************************************************************************/
     167                 : 
     168               1 : const char* GMLReader::GetSourceFileName()
     169                 : 
     170                 : {
     171               1 :     return m_pszFilename;
     172                 : }
     173                 : 
     174                 : #ifdef HAVE_EXPAT
     175                 : 
     176                 : static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
     177                 :                                     const char **ppszAttr)
     178                 : {
     179                 :     ((GMLHandler*)pUserData)->startElement(pszName, ppszAttr);
     180                 : }
     181                 : 
     182                 : static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
     183                 : {
     184                 :     ((GMLHandler*)pUserData)->endElement(pszName);
     185                 : }
     186                 : 
     187                 : static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
     188                 : {
     189                 :     ((GMLHandler*)pUserData)->dataHandler(data, nLen);
     190                 : }
     191                 : 
     192                 : #endif
     193                 : 
     194                 : /************************************************************************/
     195                 : /*                            SetupParser()                             */
     196                 : /************************************************************************/
     197                 : 
     198              27 : int GMLReader::SetupParser()
     199                 : 
     200                 : {
     201              27 :     if (fpGML == NULL)
     202              19 :         fpGML = VSIFOpenL(m_pszFilename, "rt");
     203              27 :     if (fpGML != NULL)
     204              27 :         VSIFSeekL( fpGML, 0, SEEK_SET );
     205                 : 
     206                 : #if HAVE_XERCES == 1
     207                 : 
     208              27 :     if( !m_bXercesInitialized )
     209                 :     {
     210                 :         try
     211                 :         {
     212              16 :             XMLPlatformUtils::Initialize();
     213                 :         }
     214                 :         
     215               0 :         catch (const XMLException& toCatch)
     216                 :         {
     217                 :             CPLError( CE_Warning, CPLE_AppDefined,
     218                 :                       "Exception initializing Xerces based GML reader.\n%s", 
     219               0 :                       tr_strdup(toCatch.getMessage()) );
     220               0 :             return FALSE;
     221                 :         }
     222              16 :         m_bXercesInitialized = TRUE;
     223                 :     }
     224                 : 
     225                 :     // Cleanup any old parser.
     226              27 :     if( m_poSAXReader != NULL )
     227               0 :         CleanupParser();
     228                 : 
     229                 :     // Create and initialize parser.
     230              27 :     XMLCh* xmlUriValid = NULL;
     231              27 :     XMLCh* xmlUriNS = NULL;
     232                 : 
     233                 :     try{
     234              27 :         m_poSAXReader = XMLReaderFactory::createXMLReader();
     235                 :     
     236              27 :         m_poGMLHandler = new GMLXercesHandler( this );
     237                 : 
     238              54 :         m_poSAXReader->setContentHandler( m_poGMLHandler );
     239              27 :         m_poSAXReader->setErrorHandler( m_poGMLHandler );
     240              27 :         m_poSAXReader->setLexicalHandler( m_poGMLHandler );
     241              27 :         m_poSAXReader->setEntityResolver( m_poGMLHandler );
     242              27 :         m_poSAXReader->setDTDHandler( m_poGMLHandler );
     243                 : 
     244              27 :         xmlUriValid = XMLString::transcode("http://xml.org/sax/features/validation");
     245              27 :         xmlUriNS = XMLString::transcode("http://xml.org/sax/features/namespaces");
     246                 : 
     247                 : #if (OGR_GML_VALIDATION)
     248                 :         m_poSAXReader->setFeature( xmlUriValid, true);
     249                 :         m_poSAXReader->setFeature( xmlUriNS, true);
     250                 : 
     251                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
     252                 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
     253                 : 
     254                 : //    m_poSAXReader->setDoSchema(true);
     255                 : //    m_poSAXReader->setValidationSchemaFullChecking(true);
     256                 : #else
     257              27 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreValidation, false);
     258                 : 
     259                 : #if XERCES_VERSION_MAJOR >= 3
     260                 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, false);
     261                 : #else
     262              27 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, false);
     263                 : #endif
     264                 : 
     265                 : #endif
     266              27 :         XMLString::release( &xmlUriValid );
     267              27 :         XMLString::release( &xmlUriNS );
     268                 :     }
     269               0 :     catch (...)
     270                 :     {
     271               0 :         XMLString::release( &xmlUriValid );
     272               0 :         XMLString::release( &xmlUriNS );
     273                 : 
     274                 :         CPLError( CE_Warning, CPLE_AppDefined,
     275               0 :                   "Exception initializing Xerces based GML reader.\n" );
     276               0 :         return FALSE;
     277                 :     }
     278                 : 
     279              54 :     if (m_GMLInputSource == NULL && fpGML != NULL)
     280              27 :         m_GMLInputSource = new GMLInputSource(fpGML);
     281                 : #else
     282                 :     // Cleanup any old parser.
     283                 :     if( oParser != NULL )
     284                 :         CleanupParser();
     285                 : 
     286                 :     oParser = OGRCreateExpatXMLParser();
     287                 :     m_poGMLHandler = new GMLExpatHandler( this, oParser );
     288                 : 
     289                 :     XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
     290                 :     XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
     291                 :     XML_SetUserData(oParser, m_poGMLHandler);
     292                 : #endif
     293                 : 
     294              27 :     m_bReadStarted = FALSE;
     295                 : 
     296                 :     // Push an empty state.
     297              27 :     PushState( new GMLReadState() );
     298                 : 
     299              27 :     return TRUE;
     300                 : }
     301                 : 
     302                 : /************************************************************************/
     303                 : /*                           CleanupParser()                            */
     304                 : /************************************************************************/
     305                 : 
     306              50 : void GMLReader::CleanupParser()
     307                 : 
     308                 : {
     309                 : #if HAVE_XERCES == 1
     310              50 :     if( m_poSAXReader == NULL )
     311              23 :         return;
     312                 : #else
     313                 :     if (oParser == NULL )
     314                 :         return;
     315                 : #endif
     316                 : 
     317              81 :     while( m_poState )
     318              27 :         PopState();
     319                 : 
     320                 : #if HAVE_XERCES == 1
     321              27 :     delete m_poSAXReader;
     322              27 :     m_poSAXReader = NULL;
     323              27 :     delete m_GMLInputSource;
     324              27 :     m_GMLInputSource = NULL;
     325                 : #else
     326                 :     if (oParser)
     327                 :         XML_ParserFree(oParser);
     328                 :     oParser = NULL;
     329                 : 
     330                 :     int i;
     331                 :     for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
     332                 :         delete ppoFeatureTab[i];
     333                 :     CPLFree(ppoFeatureTab);
     334                 :     nFeatureTabIndex = 0;
     335                 :     nFeatureTabLength = 0;
     336                 :     ppoFeatureTab = NULL;
     337                 : 
     338                 : #endif
     339                 : 
     340              27 :     delete m_poGMLHandler;
     341              27 :     m_poGMLHandler = NULL;
     342                 : 
     343              27 :     m_bReadStarted = FALSE;
     344                 : }
     345                 : 
     346                 : #if HAVE_XERCES == 1
     347                 : 
     348              27 : GMLBinInputStream::GMLBinInputStream(FILE* fp)
     349                 : {
     350              27 :     this->fp = fp;
     351              27 :     emptyString = 0;
     352              27 : }
     353                 : 
     354              27 : GMLBinInputStream::~ GMLBinInputStream()
     355                 : {
     356              27 : }
     357                 : 
     358                 : #if XERCES_VERSION_MAJOR >= 3
     359                 : XMLFilePos GMLBinInputStream::curPos() const
     360                 : {
     361                 :     return (XMLFilePos)VSIFTellL(fp);
     362                 : }
     363                 : 
     364                 : XMLSize_t GMLBinInputStream::readBytes(XMLByte* const toFill, const XMLSize_t maxToRead)
     365                 : {
     366                 :     return (XMLSize_t)VSIFReadL(toFill, 1, maxToRead, fp);
     367                 : }
     368                 : 
     369                 : const XMLCh* GMLBinInputStream::getContentType() const
     370                 : {
     371                 :     return &emptyString;
     372                 : }
     373                 : #else
     374               0 : unsigned int GMLBinInputStream::curPos() const
     375                 : {
     376               0 :     return (unsigned int)VSIFTellL(fp);
     377                 : }
     378                 : 
     379              48 : unsigned int GMLBinInputStream::readBytes(XMLByte* const toFill, const unsigned int maxToRead)
     380                 : {
     381              48 :     return (unsigned int)VSIFReadL(toFill, 1, maxToRead, fp);
     382                 : }
     383                 : #endif
     384                 : 
     385              27 : GMLInputSource::GMLInputSource(FILE* fp, MemoryManager* const manager) : InputSource(manager)
     386                 : {
     387              27 :     binInputStream = new GMLBinInputStream(fp);
     388              27 : }
     389                 : 
     390              27 : GMLInputSource::~GMLInputSource()
     391                 : {
     392              27 : }
     393                 : 
     394              27 : BinInputStream* GMLInputSource::makeStream() const
     395                 : {
     396              27 :     return binInputStream;
     397                 : }
     398                 : 
     399                 : #endif
     400                 : 
     401                 : /************************************************************************/
     402                 : /*                            NextFeature()                             */
     403                 : /************************************************************************/
     404                 : 
     405                 : #if HAVE_XERCES == 1
     406              81 : GMLFeature *GMLReader::NextFeature()
     407                 : 
     408                 : {
     409              81 :     GMLFeature *poReturn = NULL;
     410                 : 
     411                 :     try
     412                 :     {
     413              81 :         if( !m_bReadStarted )
     414                 :         {
     415              27 :             if( m_poSAXReader == NULL )
     416              15 :                 SetupParser();
     417                 : 
     418              27 :             m_bReadStarted = TRUE;
     419                 : 
     420              27 :             if (m_GMLInputSource == NULL)
     421               0 :                 return NULL;
     422                 : 
     423              27 :             if( !m_poSAXReader->parseFirst( *m_GMLInputSource, m_oToFill ) )
     424               0 :                 return NULL;
     425                 :         }
     426                 : 
     427            3154 :         while( m_poCompleteFeature == NULL 
     428                 :                && !m_bStopParsing
     429                 :                && m_poSAXReader->parseNext( m_oToFill ) ) {}
     430                 : 
     431              81 :         poReturn = m_poCompleteFeature;
     432              81 :         m_poCompleteFeature = NULL;
     433                 : 
     434                 :     }
     435               0 :     catch (const XMLException& toCatch)
     436                 :     {
     437               0 :         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
     438                 :         CPLDebug( "GML", 
     439                 :                   "Error during NextFeature()! Message:\n%s", 
     440               0 :                   pszErrorMessage );
     441               0 :         CPLFree(pszErrorMessage);
     442               0 :         m_bStopParsing = TRUE;
     443                 :     }
     444               0 :     catch (const SAXException& toCatch)
     445                 :     {
     446               0 :         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
     447               0 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMessage);
     448               0 :         CPLFree(pszErrorMessage);
     449               0 :         m_bStopParsing = TRUE;
     450                 :     }
     451                 : 
     452              81 :     return poReturn;
     453                 : }
     454                 : #else
     455                 : GMLFeature *GMLReader::NextFeature()
     456                 : 
     457                 : {
     458                 :     if (!m_bReadStarted)
     459                 :     {
     460                 :         if (oParser == NULL)
     461                 :             SetupParser();
     462                 : 
     463                 :         m_bReadStarted = TRUE;
     464                 :     }
     465                 : 
     466                 :     if (fpGML == NULL || m_bStopParsing)
     467                 :         return NULL;
     468                 : 
     469                 :     if (nFeatureTabIndex < nFeatureTabLength)
     470                 :     {
     471                 :         return ppoFeatureTab[nFeatureTabIndex++];
     472                 :     }
     473                 : 
     474                 :     if (VSIFEofL(fpGML))
     475                 :         return NULL;
     476                 : 
     477                 :     char aBuf[BUFSIZ];
     478                 : 
     479                 :     CPLFree(ppoFeatureTab);
     480                 :     ppoFeatureTab = NULL;
     481                 :     nFeatureTabLength = 0;
     482                 :     nFeatureTabIndex = 0;
     483                 : 
     484                 :     int nDone;
     485                 :     do
     486                 :     {
     487                 :         m_poGMLHandler->ResetDataHandlerCounter();
     488                 : 
     489                 :         unsigned int nLen =
     490                 :                 (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGML );
     491                 :         nDone = VSIFEofL(fpGML);
     492                 :         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     493                 :         {
     494                 :             CPLError(CE_Failure, CPLE_AppDefined,
     495                 :                      "XML parsing of GML file failed : %s "
     496                 :                      "at line %d, column %d",
     497                 :                      XML_ErrorString(XML_GetErrorCode(oParser)),
     498                 :                      (int)XML_GetCurrentLineNumber(oParser),
     499                 :                      (int)XML_GetCurrentColumnNumber(oParser));
     500                 :             m_bStopParsing = TRUE;
     501                 :         }
     502                 :         if (!m_bStopParsing)
     503                 :             m_bStopParsing = m_poGMLHandler->HasStoppedParsing();
     504                 : 
     505                 :     } while (!nDone && !m_bStopParsing && nFeatureTabLength == 0);
     506                 : 
     507                 :     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
     508                 : }
     509                 : #endif
     510                 : 
     511                 : /************************************************************************/
     512                 : /*                            PushFeature()                             */
     513                 : /*                                                                      */
     514                 : /*      Create a feature based on the named element.  If the            */
     515                 : /*      corresponding feature class doesn't exist yet, then create      */
     516                 : /*      it now.  A new GMLReadState will be created for the feature,    */
     517                 : /*      and it will be placed within that state.  The state is          */
     518                 : /*      pushed onto the readstate stack.                                */
     519                 : /************************************************************************/
     520                 : 
     521                 : void GMLReader::PushFeature( const char *pszElement, 
     522              60 :                              const char *pszFID )
     523                 : 
     524                 : {
     525                 :     int iClass;
     526                 : 
     527                 : /* -------------------------------------------------------------------- */
     528                 : /*      Find the class of this element.                                 */
     529                 : /* -------------------------------------------------------------------- */
     530              62 :     for( iClass = 0; iClass < GetClassCount(); iClass++ )
     531                 :     {
     532              53 :         if( EQUAL(pszElement,GetClass(iClass)->GetElementName()) )
     533              51 :             break;
     534                 :     }
     535                 : 
     536                 : /* -------------------------------------------------------------------- */
     537                 : /*      Create a new feature class for this element, if there is no     */
     538                 : /*      existing class for it.                                          */
     539                 : /* -------------------------------------------------------------------- */
     540              60 :     if( iClass == GetClassCount() )
     541                 :     {
     542               9 :         CPLAssert( !IsClassListLocked() );
     543                 : 
     544               9 :         GMLFeatureClass *poNewClass = new GMLFeatureClass( pszElement );
     545                 : 
     546               9 :         AddClass( poNewClass );
     547                 :     }
     548                 : 
     549                 : /* -------------------------------------------------------------------- */
     550                 : /*      Create a feature of this feature class.  Try to set the fid     */
     551                 : /*      if available.                                                   */
     552                 : /* -------------------------------------------------------------------- */
     553              60 :     GMLFeature *poFeature = new GMLFeature( GetClass( iClass ) );
     554              60 :     if( pszFID != NULL )
     555                 :     {
     556              54 :         poFeature->SetFID( pszFID );
     557                 :     }
     558                 : 
     559                 : /* -------------------------------------------------------------------- */
     560                 : /*      Create and push a new read state.                               */
     561                 : /* -------------------------------------------------------------------- */
     562                 :     GMLReadState *poState;
     563                 : 
     564              60 :     poState = new GMLReadState();
     565              60 :     poState->m_poFeature = poFeature;
     566              60 :     PushState( poState );
     567              60 : }
     568                 : 
     569                 : /************************************************************************/
     570                 : /*                          IsFeatureElement()                          */
     571                 : /*                                                                      */
     572                 : /*      Based on context and the element name, is this element a new    */
     573                 : /*      GML feature element?                                            */
     574                 : /************************************************************************/
     575                 : 
     576             343 : int GMLReader::IsFeatureElement( const char *pszElement )
     577                 : 
     578                 : {
     579             343 :     CPLAssert( m_poState != NULL );
     580                 : 
     581             343 :     const char *pszLast = m_poState->GetLastComponent();
     582             343 :     int        nLen = strlen(pszLast);
     583                 : 
     584             343 :     if (strcmp(pszLast, "dane") == 0)
     585                 :     {
     586                 :          /* Polish TBD GML */
     587                 :     }
     588             343 :     else if( nLen < 6 || !(EQUAL(pszLast+nLen-6,"member") ||
     589                 :                       EQUAL(pszLast+nLen-7,"members")) )
     590             283 :         return FALSE;
     591                 : 
     592                 :     // If the class list isn't locked, any element that is a featureMember
     593                 :     // will do. 
     594              60 :     if( !IsClassListLocked() )
     595              49 :         return TRUE;
     596                 : 
     597                 :     // otherwise, find a class with the desired element name.
     598              11 :     for( int i = 0; i < GetClassCount(); i++ )
     599                 :     {
     600              11 :         if( EQUAL(pszElement,GetClass(i)->GetElementName()) )
     601              11 :             return TRUE;
     602                 :     }
     603                 : 
     604               0 :     return FALSE;
     605                 : }
     606                 : 
     607                 : /************************************************************************/
     608                 : /*                         IsAttributeElement()                         */
     609                 : /************************************************************************/
     610                 : 
     611             574 : int GMLReader::IsAttributeElement( const char *pszElement )
     612                 : 
     613                 : {
     614             574 :     if( m_poState->m_poFeature == NULL )
     615             283 :         return FALSE;
     616                 : 
     617             291 :     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
     618                 : 
     619                 :     // If the schema is not yet locked, then any simple element
     620                 :     // is potentially an attribute.
     621             291 :     if( !poClass->IsSchemaLocked() )
     622             240 :         return TRUE;
     623                 : 
     624                 :     // Otherwise build the path to this element into a single string
     625                 :     // and compare against known attributes.
     626              51 :     CPLString osElemPath;
     627                 : 
     628              51 :     if( m_poState->m_nPathLength == 0 )
     629              45 :         osElemPath = pszElement;
     630                 :     else
     631                 :     {
     632               6 :         osElemPath = m_poState->m_pszPath;
     633               6 :         osElemPath += "|";
     634               6 :         osElemPath += pszElement;
     635                 :     }
     636                 : 
     637             150 :     for( int i = 0; i < poClass->GetPropertyCount(); i++ )
     638             133 :         if( EQUAL(poClass->GetProperty(i)->GetSrcElement(),osElemPath) )
     639              85 :             return TRUE;
     640                 : 
     641              17 :     return FALSE;
     642                 : }
     643                 : 
     644                 : /************************************************************************/
     645                 : /*                              PopState()                              */
     646                 : /************************************************************************/
     647                 : 
     648              87 : void GMLReader::PopState()
     649                 : 
     650                 : {
     651              87 :     if( m_poState != NULL )
     652                 :     {
     653                 : #if HAVE_XERCES == 1
     654              87 :         if( m_poState->m_poFeature != NULL && m_poCompleteFeature == NULL )
     655                 :         {
     656              60 :             m_poCompleteFeature = m_poState->m_poFeature;
     657              60 :             m_poState->m_poFeature = NULL;
     658                 :         }
     659                 : #else
     660                 :         if ( m_poState->m_poFeature != NULL )
     661                 :         {
     662                 :             ppoFeatureTab = (GMLFeature**)
     663                 :                     CPLRealloc(ppoFeatureTab,
     664                 :                                 sizeof(GMLFeature*) * (nFeatureTabLength + 1));
     665                 :             ppoFeatureTab[nFeatureTabLength] = m_poState->m_poFeature;
     666                 :             nFeatureTabLength++;
     667                 : 
     668                 :             m_poState->m_poFeature = NULL;
     669                 :         }
     670                 : #endif
     671                 : 
     672                 :         GMLReadState *poParent;
     673                 : 
     674              87 :         poParent = m_poState->m_poParentState;
     675                 :         
     676              87 :         delete m_poState;
     677              87 :         m_poState = poParent;
     678                 :     }
     679              87 : }
     680                 : 
     681                 : /************************************************************************/
     682                 : /*                             PushState()                              */
     683                 : /************************************************************************/
     684                 : 
     685              87 : void GMLReader::PushState( GMLReadState *poState )
     686                 : 
     687                 : {
     688              87 :     poState->m_poParentState = m_poState;
     689              87 :     m_poState = poState;
     690              87 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                              GetClass()                              */
     694                 : /************************************************************************/
     695                 : 
     696             186 : GMLFeatureClass *GMLReader::GetClass( int iClass ) const
     697                 : 
     698                 : {
     699             186 :     if( iClass < 0 || iClass >= m_nClassCount )
     700               0 :         return NULL;
     701                 :     else
     702             186 :         return m_papoClass[iClass];
     703                 : }
     704                 : 
     705                 : /************************************************************************/
     706                 : /*                              GetClass()                              */
     707                 : /************************************************************************/
     708                 : 
     709              34 : GMLFeatureClass *GMLReader::GetClass( const char *pszName ) const
     710                 : 
     711                 : {
     712              36 :     for( int iClass = 0; iClass < m_nClassCount; iClass++ )
     713                 :     {
     714              19 :         if( EQUAL(GetClass(iClass)->GetName(),pszName) )
     715              17 :             return GetClass(iClass);
     716                 :     }
     717                 : 
     718              17 :     return NULL;
     719                 : }
     720                 : 
     721                 : /************************************************************************/
     722                 : /*                              AddClass()                              */
     723                 : /************************************************************************/
     724                 : 
     725              17 : int GMLReader::AddClass( GMLFeatureClass *poNewClass )
     726                 : 
     727                 : {
     728              17 :     CPLAssert( GetClass( poNewClass->GetName() ) == NULL );
     729                 : 
     730              17 :     m_nClassCount++;
     731                 :     m_papoClass = (GMLFeatureClass **) 
     732              17 :         CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
     733              17 :     m_papoClass[m_nClassCount-1] = poNewClass;
     734                 : 
     735              17 :     return m_nClassCount-1;
     736                 : }
     737                 : 
     738                 : /************************************************************************/
     739                 : /*                            ClearClasses()                            */
     740                 : /************************************************************************/
     741                 : 
     742              32 : void GMLReader::ClearClasses()
     743                 : 
     744                 : {
     745              49 :     for( int i = 0; i < m_nClassCount; i++ )
     746              17 :         delete m_papoClass[i];
     747              32 :     CPLFree( m_papoClass );
     748                 : 
     749              32 :     m_nClassCount = 0;
     750              32 :     m_papoClass = NULL;
     751              32 : }
     752                 : 
     753                 : /************************************************************************/
     754                 : /*                         SetFeatureProperty()                         */
     755                 : /*                                                                      */
     756                 : /*      Set the property value on the current feature, adding the       */
     757                 : /*      property name to the GMLFeatureClass if required.               */
     758                 : /*      Eventually this function may also "refine" the property         */
     759                 : /*      type based on what is encountered.                              */
     760                 : /************************************************************************/
     761                 : 
     762                 : void GMLReader::SetFeatureProperty( const char *pszElement, 
     763             218 :                                     const char *pszValue )
     764                 : 
     765                 : {
     766             218 :     GMLFeature *poFeature = GetState()->m_poFeature;
     767                 : 
     768             218 :     CPLAssert( poFeature  != NULL );
     769                 : 
     770                 : /* -------------------------------------------------------------------- */
     771                 : /*      Does this property exist in the feature class?  If not, add     */
     772                 : /*      it.                                                             */
     773                 : /* -------------------------------------------------------------------- */
     774             218 :     GMLFeatureClass *poClass = poFeature->GetClass();
     775                 :     int      iProperty;
     776                 : 
     777             706 :     for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
     778                 :     {
     779             672 :         if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(),
     780                 :                   pszElement ) )
     781             184 :             break;
     782                 :     }
     783                 :     
     784             218 :     if( iProperty == poClass->GetPropertyCount() )
     785                 :     {
     786              34 :         if( poClass->IsSchemaLocked() )
     787                 :         {
     788               0 :             CPLDebug("GML","Encountered property missing from class schema.");
     789               0 :             return;
     790                 :         }
     791                 : 
     792              34 :         CPLString osFieldName;
     793                 :         
     794              34 :         if( strchr(pszElement,'|') == NULL )
     795              30 :             osFieldName = pszElement;
     796                 :         else
     797                 :         {
     798               4 :             osFieldName = strrchr(pszElement,'|') + 1;
     799               4 :             if( poClass->GetPropertyIndex(osFieldName) != -1 )
     800               0 :                 osFieldName = pszElement;
     801                 :         }
     802                 : 
     803                 :         // Does this conflict with an existing property name? 
     804              68 :         while( poClass->GetProperty(osFieldName) != NULL )
     805                 :         {
     806               0 :             osFieldName += "_";
     807                 :         }
     808                 : 
     809              34 :         GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);
     810                 : 
     811              68 :         if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
     812               0 :             poPDefn->SetType( GMLPT_String );
     813                 : 
     814              34 :         poClass->AddProperty( poPDefn );
     815                 :     }
     816                 : 
     817                 : /* -------------------------------------------------------------------- */
     818                 : /*      Do we need to update the property type?                         */
     819                 : /* -------------------------------------------------------------------- */
     820             218 :     if( !poClass->IsSchemaLocked() )
     821                 :     {
     822                 :         poClass->GetProperty(iProperty)->AnalysePropertyValue(
     823                 :                              pszValue, 
     824             184 :                              poFeature->GetProperty(iProperty));
     825                 :     }
     826                 : 
     827                 : /* -------------------------------------------------------------------- */
     828                 : /*      Set the property                                                */
     829                 : /* -------------------------------------------------------------------- */
     830             218 :     switch( poClass->GetProperty( iProperty )->GetType() )
     831                 :     {
     832                 :       case GMLPT_StringList:
     833                 :       case GMLPT_IntegerList:
     834                 :       case GMLPT_RealList:
     835                 :       {
     836               0 :           if( poFeature->GetProperty( iProperty ) != NULL )
     837                 :           {
     838               0 :               CPLString osJoinedValue = poFeature->GetProperty( iProperty );
     839               0 :               osJoinedValue += ",";
     840               0 :               osJoinedValue += pszValue;
     841                 : 
     842               0 :               poFeature->SetProperty( iProperty, osJoinedValue );
     843                 :           }
     844                 :           else
     845               0 :               poFeature->SetProperty( iProperty, pszValue );
     846                 :       }
     847               0 :       break;
     848                 : 
     849                 :       default:
     850             218 :         poFeature->SetProperty( iProperty, pszValue );
     851                 :         break;
     852                 :     }
     853                 : 
     854                 : }
     855                 : 
     856                 : /************************************************************************/
     857                 : /*                            LoadClasses()                             */
     858                 : /************************************************************************/
     859                 : 
     860               5 : int GMLReader::LoadClasses( const char *pszFile )
     861                 : 
     862                 : {
     863                 :     // Add logic later to determine reasonable default schema file. 
     864               5 :     if( pszFile == NULL )
     865               0 :         return FALSE;
     866                 : 
     867                 : /* -------------------------------------------------------------------- */
     868                 : /*      Load the raw XML file.                                          */
     869                 : /* -------------------------------------------------------------------- */
     870                 :     FILE       *fp;
     871                 :     int         nLength;
     872                 :     char        *pszWholeText;
     873                 : 
     874               5 :     fp = VSIFOpenL( pszFile, "rb" );
     875                 : 
     876               5 :     if( fp == NULL )
     877                 :     {
     878                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     879               0 :                   "Failed to open file %s.", pszFile );
     880               0 :         return FALSE;
     881                 :     }
     882                 : 
     883               5 :     VSIFSeekL( fp, 0, SEEK_END );
     884               5 :     nLength = VSIFTellL( fp );
     885               5 :     VSIFSeekL( fp, 0, SEEK_SET );
     886                 : 
     887               5 :     pszWholeText = (char *) VSIMalloc(nLength+1);
     888               5 :     if( pszWholeText == NULL )
     889                 :     {
     890                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     891                 :                   "Failed to allocate %d byte buffer for %s,\n"
     892                 :                   "is this really a GMLFeatureClassList file?",
     893               0 :                   nLength, pszFile );
     894               0 :         VSIFCloseL( fp );
     895               0 :         return FALSE;
     896                 :     }
     897                 :     
     898               5 :     if( VSIFReadL( pszWholeText, nLength, 1, fp ) != 1 )
     899                 :     {
     900               0 :         VSIFree( pszWholeText );
     901               0 :         VSIFCloseL( fp );
     902                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     903               0 :                   "Read failed on %s.", pszFile );
     904               0 :         return FALSE;
     905                 :     }
     906               5 :     pszWholeText[nLength] = '\0';
     907                 : 
     908               5 :     VSIFCloseL( fp );
     909                 : 
     910               5 :     if( strstr( pszWholeText, "<GMLFeatureClassList>" ) == NULL )
     911                 :     {
     912               0 :         VSIFree( pszWholeText );
     913                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     914                 :                   "File %s does not contain a GMLFeatureClassList tree.",
     915               0 :                   pszFile );
     916               0 :         return FALSE;
     917                 :     }
     918                 : 
     919                 : /* -------------------------------------------------------------------- */
     920                 : /*      Convert to XML parse tree.                                      */
     921                 : /* -------------------------------------------------------------------- */
     922                 :     CPLXMLNode *psRoot;
     923                 : 
     924               5 :     psRoot = CPLParseXMLString( pszWholeText );
     925               5 :     VSIFree( pszWholeText );
     926                 : 
     927                 :     // We assume parser will report errors via CPL.
     928               5 :     if( psRoot == NULL )
     929               0 :         return FALSE;
     930                 : 
     931               5 :     if( psRoot->eType != CXT_Element 
     932                 :         || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
     933                 :     {
     934               0 :         CPLDestroyXMLNode(psRoot);
     935                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     936                 :                   "File %s is not a GMLFeatureClassList document.",
     937               0 :                   pszFile );
     938               0 :         return FALSE;
     939                 :     }
     940                 : 
     941                 : /* -------------------------------------------------------------------- */
     942                 : /*      Extract feature classes for all definitions found.              */
     943                 : /* -------------------------------------------------------------------- */
     944                 :     CPLXMLNode *psThis;
     945                 : 
     946              10 :     for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     947                 :     {
     948               5 :         if( psThis->eType == CXT_Element 
     949                 :             && EQUAL(psThis->pszValue,"GMLFeatureClass") )
     950                 :         {
     951                 :             GMLFeatureClass   *poClass;
     952                 : 
     953               5 :             poClass = new GMLFeatureClass();
     954                 : 
     955               5 :             if( !poClass->InitializeFromXML( psThis ) )
     956                 :             {
     957               0 :                 delete poClass;
     958               0 :                 CPLDestroyXMLNode( psRoot );
     959               0 :                 return FALSE;
     960                 :             }
     961                 : 
     962               5 :             poClass->SetSchemaLocked( TRUE );
     963                 : 
     964               5 :             AddClass( poClass );
     965                 :         }
     966                 :     }
     967                 : 
     968               5 :     CPLDestroyXMLNode( psRoot );
     969                 :     
     970               5 :     SetClassListLocked( TRUE );
     971                 : 
     972               5 :     return TRUE;
     973                 : }
     974                 : 
     975                 : /************************************************************************/
     976                 : /*                            SaveClasses()                             */
     977                 : /************************************************************************/
     978                 : 
     979               8 : int GMLReader::SaveClasses( const char *pszFile )
     980                 : 
     981                 : {
     982                 :     // Add logic later to determine reasonable default schema file. 
     983               8 :     if( pszFile == NULL )
     984               0 :         return FALSE;
     985                 : 
     986                 : /* -------------------------------------------------------------------- */
     987                 : /*      Create in memory schema tree.                                   */
     988                 : /* -------------------------------------------------------------------- */
     989                 :     CPLXMLNode *psRoot;
     990                 : 
     991               8 :     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
     992                 : 
     993              17 :     for( int iClass = 0; iClass < GetClassCount(); iClass++ )
     994                 :     {
     995               9 :         GMLFeatureClass *poClass = GetClass( iClass );
     996                 :         
     997               9 :         CPLAddXMLChild( psRoot, poClass->SerializeToXML() );
     998                 :     }
     999                 : 
    1000                 : /* -------------------------------------------------------------------- */
    1001                 : /*      Serialize to disk.                                              */
    1002                 : /* -------------------------------------------------------------------- */
    1003                 :     FILE        *fp;
    1004               8 :     int         bSuccess = TRUE;
    1005               8 :     char        *pszWholeText = CPLSerializeXMLTree( psRoot );
    1006                 :     
    1007               8 :     CPLDestroyXMLNode( psRoot );
    1008                 :  
    1009               8 :     fp = VSIFOpenL( pszFile, "wb" );
    1010                 :     
    1011               8 :     if( fp == NULL )
    1012               0 :         bSuccess = FALSE;
    1013               8 :     else if( VSIFWriteL( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
    1014               0 :         bSuccess = FALSE;
    1015                 :     else
    1016               8 :         VSIFCloseL( fp );
    1017                 : 
    1018               8 :     CPLFree( pszWholeText );
    1019                 : 
    1020               8 :     return bSuccess;
    1021                 : }
    1022                 : 
    1023                 : /************************************************************************/
    1024                 : /*                          PrescanForSchema()                          */
    1025                 : /*                                                                      */
    1026                 : /*      For now we use a pretty dumb approach of just doing a normal    */
    1027                 : /*      scan of the whole file, building up the schema information.     */
    1028                 : /*      Eventually we hope to do a more efficient scan when just        */
    1029                 : /*      looking for schema information.                                 */
    1030                 : /************************************************************************/
    1031                 : 
    1032              12 : int GMLReader::PrescanForSchema( int bGetExtents )
    1033                 : 
    1034                 : {
    1035                 :     GMLFeature  *poFeature;
    1036                 : 
    1037              12 :     if( m_pszFilename == NULL )
    1038               0 :         return FALSE;
    1039                 : 
    1040              12 :     SetClassListLocked( FALSE );
    1041                 : 
    1042              12 :     ClearClasses();
    1043              12 :     if( !SetupParser() )
    1044               0 :         return FALSE;
    1045                 : 
    1046              49 :     while( (poFeature = NextFeature()) != NULL )
    1047                 :     {
    1048              25 :         GMLFeatureClass *poClass = poFeature->GetClass();
    1049                 : 
    1050              25 :         if( poClass->GetFeatureCount() == -1 )
    1051               9 :             poClass->SetFeatureCount( 1 );
    1052                 :         else
    1053              16 :             poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
    1054                 : 
    1055                 : #ifdef SUPPORT_GEOMETRY
    1056              25 :         if( bGetExtents )
    1057                 :         {
    1058              25 :             OGRGeometry *poGeometry = NULL;
    1059                 : 
    1060              25 :             if( poFeature->GetGeometry() != NULL 
    1061                 :                 && strlen(poFeature->GetGeometry()) != 0 )
    1062                 :             {
    1063                 :                 poGeometry = OGRGeometryFactory::createFromGML( 
    1064              25 :                     poFeature->GetGeometry() );
    1065                 :             }
    1066                 : 
    1067              25 :             if( poGeometry != NULL )
    1068                 :             {
    1069                 :                 double  dfXMin, dfXMax, dfYMin, dfYMax;
    1070              25 :                 OGREnvelope sEnvelope;
    1071                 :                 OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
    1072              25 :                     poClass->GetGeometryType();
    1073                 : 
    1074                 :                 // Merge geometry type into layer.
    1075              25 :                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
    1076               9 :                     eGType = wkbNone;
    1077                 : 
    1078                 :                 poClass->SetGeometryType( 
    1079                 :                     (int) OGRMergeGeometryTypes(
    1080              25 :                         eGType, poGeometry->getGeometryType() ) );
    1081                 : 
    1082                 :                 // merge extents.
    1083              25 :                 if (!poGeometry->IsEmpty())
    1084                 :                 {
    1085              25 :                     poGeometry->getEnvelope( &sEnvelope );
    1086              25 :                     if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
    1087                 :                     {
    1088              16 :                         dfXMin = MIN(dfXMin,sEnvelope.MinX);
    1089              16 :                         dfXMax = MAX(dfXMax,sEnvelope.MaxX);
    1090              16 :                         dfYMin = MIN(dfYMin,sEnvelope.MinY);
    1091              16 :                         dfYMax = MAX(dfYMax,sEnvelope.MaxY);
    1092                 :                     }
    1093                 :                     else
    1094                 :                     {
    1095               9 :                         dfXMin = sEnvelope.MinX;
    1096               9 :                         dfXMax = sEnvelope.MaxX;
    1097               9 :                         dfYMin = sEnvelope.MinY;
    1098               9 :                         dfYMax = sEnvelope.MaxY;
    1099                 :                     }
    1100                 : 
    1101              25 :                     poClass->SetExtents( dfXMin, dfXMax, dfYMin, dfYMax );
    1102                 :                 }
    1103              25 :                 delete poGeometry;
    1104                 : 
    1105                 :             }
    1106                 : #endif /* def SUPPORT_GEOMETRY */
    1107                 :         }
    1108                 :         
    1109              25 :         delete poFeature;
    1110                 :     }
    1111                 : 
    1112              12 :     CleanupParser();
    1113                 : 
    1114              12 :     return GetClassCount() > 0;
    1115                 : }
    1116                 : 
    1117                 : /************************************************************************/
    1118                 : /*                            ResetReading()                            */
    1119                 : /************************************************************************/
    1120                 : 
    1121              18 : void GMLReader::ResetReading()
    1122                 : 
    1123                 : {
    1124              18 :     CleanupParser();
    1125              18 : }
    1126                 : 
    1127                 : #endif /* HAVE_XERCES == 1 or HAVE_EXPAT */
    1128                 : 

Generated by: LTP GCOV extension version 1.5