LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/nas - nasreader.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 346
Code covered: 57.5 % Executed lines: 199

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

Generated by: LTP GCOV extension version 1.5