LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - ogrgmllayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 178 127 71.3 %
Date: 2010-01-09 Functions: 11 8 72.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgmllayer.cpp 18077 2009-11-22 19:15:34Z rouault $
       3                 :  *
       4                 :  * Project:  OGR
       5                 :  * Purpose:  Implements OGRGMLLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR 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 "ogr_gml.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_port.h"
      33                 : #include "cpl_string.h"
      34                 : #include "ogr_p.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ogrgmllayer.cpp 18077 2009-11-22 19:15:34Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                           OGRGMLLayer()                              */
      40                 : /************************************************************************/
      41                 : 
      42              17 : OGRGMLLayer::OGRGMLLayer( const char * pszName,
      43                 :                           OGRSpatialReference *poSRSIn, int bWriterIn,
      44                 :                           OGRwkbGeometryType eReqType,
      45              17 :                           OGRGMLDataSource *poDSIn )
      46                 : 
      47                 : {
      48              17 :     if( poSRSIn == NULL )
      49              17 :         poSRS = NULL;
      50                 :     else
      51               0 :         poSRS = poSRSIn->Clone();
      52                 :     
      53              17 :     iNextGMLId = 0;
      54              17 :     nTotalGMLCount = -1;
      55              17 :     bInvalidFIDFound = FALSE;
      56              17 :     pszFIDPrefix = NULL;
      57                 :         
      58              17 :     poDS = poDSIn;
      59                 : 
      60              17 :     if ( EQUALN(pszName, "ogr:", 4) )
      61               0 :       poFeatureDefn = new OGRFeatureDefn( pszName+4 );
      62                 :     else
      63              17 :       poFeatureDefn = new OGRFeatureDefn( pszName );
      64              17 :     poFeatureDefn->Reference();
      65              17 :     poFeatureDefn->SetGeomType( eReqType );
      66                 : 
      67              17 :     bWriter = bWriterIn;
      68                 : 
      69                 : /* -------------------------------------------------------------------- */
      70                 : /*      Reader's should get the corresponding GMLFeatureClass and       */
      71                 : /*      cache it.                                                       */
      72                 : /* -------------------------------------------------------------------- */
      73              17 :     if( !bWriter )
      74              15 :         poFClass = poDS->GetReader()->GetClass( pszName );
      75                 :     else
      76               2 :         poFClass = NULL;
      77              17 : }
      78                 : 
      79                 : /************************************************************************/
      80                 : /*                           ~OGRGMLLayer()                           */
      81                 : /************************************************************************/
      82                 : 
      83              34 : OGRGMLLayer::~OGRGMLLayer()
      84                 : 
      85                 : {
      86              17 :     CPLFree(pszFIDPrefix);
      87                 : 
      88              17 :     if( poFeatureDefn )
      89              17 :         poFeatureDefn->Release();
      90                 : 
      91              17 :     if( poSRS != NULL )
      92               0 :         poSRS->Release();
      93              34 : }
      94                 : 
      95                 : /************************************************************************/
      96                 : /*                            ResetReading()                            */
      97                 : /************************************************************************/
      98                 : 
      99              16 : void OGRGMLLayer::ResetReading()
     100                 : 
     101                 : {
     102              16 :     iNextGMLId = 0;
     103              16 :     poDS->GetReader()->ResetReading();
     104              16 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                           GetNextFeature()                           */
     108                 : /************************************************************************/
     109                 : 
     110              40 : OGRFeature *OGRGMLLayer::GetNextFeature()
     111                 : 
     112                 : {
     113              40 :     GMLFeature  *poGMLFeature = NULL;
     114              40 :     OGRGeometry *poGeom = NULL;
     115                 : 
     116              40 :     if (bWriter)
     117                 :     {
     118                 :         CPLError(CE_Failure, CPLE_NotSupported,
     119               0 :                  "Cannot read features when writing a GML file");
     120               0 :         return NULL;
     121                 :     }
     122                 : 
     123              40 :     if( iNextGMLId == 0 )
     124              13 :         ResetReading();
     125                 : 
     126                 : /* ==================================================================== */
     127                 : /*      Loop till we find and translate a feature meeting all our       */
     128                 : /*      requirements.                                                   */
     129                 : /* ==================================================================== */
     130               2 :     while( TRUE )
     131                 :     {
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      Cleanup last feature, and get a new raw gml feature.            */
     134                 : /* -------------------------------------------------------------------- */
     135              42 :         if( poGMLFeature != NULL )
     136               2 :             delete poGMLFeature;
     137                 : 
     138              42 :         if( poGeom != NULL )
     139                 :         {
     140               1 :             delete poGeom;
     141               1 :             poGeom = NULL;
     142                 :         }
     143                 : 
     144              42 :         poGMLFeature = poDS->GetReader()->NextFeature();
     145              42 :         if( poGMLFeature == NULL )
     146               9 :             return NULL;
     147                 : 
     148                 : /* -------------------------------------------------------------------- */
     149                 : /*      Is it of the proper feature class?                              */
     150                 : /* -------------------------------------------------------------------- */
     151                 : 
     152                 :         // We count reading low level GML features as a feature read for
     153                 :         // work checking purposes, though at least we didn't necessary
     154                 :         // have to turn it into an OGRFeature.
     155              33 :         m_nFeaturesRead++;
     156                 : 
     157              33 :         if( poGMLFeature->GetClass() != poFClass )
     158               1 :             continue;
     159                 : 
     160                 : /* -------------------------------------------------------------------- */
     161                 : /*      Extract the fid:                                                */
     162                 : /*      -Assumes the fids are non-negative integers with an optional    */
     163                 : /*       prefix                                                         */
     164                 : /*      -If a prefix differs from the prefix of the first feature from  */
     165                 : /*       the poDS then the fids from the poDS are ignored and are       */
     166                 : /*       assigned serially thereafter                                   */
     167                 : /* -------------------------------------------------------------------- */
     168                 :         int nFID;
     169              32 :         const char * pszGML_FID = poGMLFeature->GetFID();
     170              32 :         if( bInvalidFIDFound )
     171                 :         {
     172               6 :             nFID = iNextGMLId++;
     173                 :         }
     174              26 :         else if( pszGML_FID == NULL )
     175                 :         {
     176               1 :             bInvalidFIDFound = TRUE;
     177               1 :             nFID = iNextGMLId++;
     178                 :         }
     179              25 :         else if( iNextGMLId == 0 )
     180                 :         {
     181              12 :             int i = strlen( pszGML_FID )-1, j = 0;
     182             108 :             while( i >= 0 && pszGML_FID[i] >= '0'
     183              47 :                           && pszGML_FID[i] <= '9' && j<8)
     184              37 :                 i--, j++;
     185                 :             /* i points the last character of the fid */
     186              12 :             if( i >= 0 && j < 8 && pszFIDPrefix == NULL)
     187                 :             {
     188               9 :                 pszFIDPrefix = (char *) CPLMalloc(i+2);
     189               9 :                 pszFIDPrefix[i+1] = '\0';
     190               9 :                 strncpy(pszFIDPrefix, pszGML_FID, i+1);
     191                 :             }
     192                 :             /* pszFIDPrefix now contains the prefix or NULL if no prefix is found */
     193              12 :             if( j < 8 && sscanf(pszGML_FID+i+1, "%d", &nFID)==1)
     194                 :             {
     195              10 :                 if( iNextGMLId <= nFID )
     196              10 :                     iNextGMLId = nFID + 1;
     197                 :             }
     198                 :             else
     199                 :             {
     200               2 :                 bInvalidFIDFound = TRUE;
     201               2 :                 nFID = iNextGMLId++;
     202                 :             }
     203                 :         }
     204              13 :         else if( iNextGMLId != 0 )
     205                 :         {
     206              13 :             const char* pszFIDPrefix_notnull = pszFIDPrefix;
     207              13 :             if (pszFIDPrefix_notnull == NULL) pszFIDPrefix_notnull = "";
     208              13 :             int nLenPrefix = strlen(pszFIDPrefix_notnull);
     209                 : 
     210              13 :             if(  strncmp(pszGML_FID, pszFIDPrefix_notnull, nLenPrefix) == 0 &&
     211                 :                  strlen(pszGML_FID+nLenPrefix) <= 9 &&
     212                 :                  sscanf(pszGML_FID+nLenPrefix, "%d", &nFID) == 1 )
     213                 :             { /* fid with the prefix. Using its numerical part */
     214              11 :                 if( iNextGMLId < nFID )
     215               5 :                     iNextGMLId = nFID + 1;
     216                 :             }
     217                 :             else
     218                 :             { /* fid without the aforementioned prefix or a valid numerical part */
     219               2 :                 bInvalidFIDFound = TRUE;
     220               2 :                 nFID = iNextGMLId++;
     221                 :             }
     222                 :         }
     223                 : 
     224                 : /* -------------------------------------------------------------------- */
     225                 : /*      Does it satisfy the spatial query, if there is one?             */
     226                 : /* -------------------------------------------------------------------- */
     227                 : 
     228              32 :         if( poGMLFeature->GetGeometry() != NULL )
     229                 :         {
     230              30 :             poGeom = OGRGeometryFactory::createFromGML( poGMLFeature->GetGeometry() );
     231                 :             // We assume the createFromGML() function would have already
     232                 :             // reported the error. 
     233              30 :             if( poGeom == NULL )
     234                 :             {
     235               0 :                 delete poGMLFeature;
     236               0 :                 return NULL;
     237                 :             }
     238                 :             
     239              30 :             if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
     240               0 :                 continue;
     241                 :         }
     242                 :         
     243                 : /* -------------------------------------------------------------------- */
     244                 : /*      Convert the whole feature into an OGRFeature.                   */
     245                 : /* -------------------------------------------------------------------- */
     246                 :         int iField;
     247              32 :         OGRFeature *poOGRFeature = new OGRFeature( GetLayerDefn() );
     248                 : 
     249              32 :         poOGRFeature->SetFID( nFID );
     250                 : 
     251             141 :         for( iField = 0; iField < poFClass->GetPropertyCount(); iField++ )
     252                 :         {
     253             109 :             const char *pszProperty = poGMLFeature->GetProperty( iField );
     254                 :             
     255             109 :             if( pszProperty != NULL )
     256             106 :                 poOGRFeature->SetField( iField, pszProperty );
     257                 :         }
     258                 : 
     259                 : /* -------------------------------------------------------------------- */
     260                 : /*      Test against the attribute query.                               */
     261                 : /* -------------------------------------------------------------------- */
     262              32 :         if( m_poAttrQuery != NULL
     263                 :             && !m_poAttrQuery->Evaluate( poOGRFeature ) )
     264                 :         {
     265               1 :             delete poOGRFeature;
     266               1 :             continue;
     267                 :         }
     268                 : 
     269                 : /* -------------------------------------------------------------------- */
     270                 : /*      Wow, we got our desired feature. Return it.                     */
     271                 : /* -------------------------------------------------------------------- */
     272              31 :         delete poGMLFeature;
     273                 : 
     274              31 :         poOGRFeature->SetGeometryDirectly( poGeom );
     275                 : 
     276              31 :         return poOGRFeature;
     277                 :     }
     278                 : 
     279                 :     return NULL;
     280                 : }
     281                 : 
     282                 : /************************************************************************/
     283                 : /*                          GetFeatureCount()                           */
     284                 : /************************************************************************/
     285                 : 
     286               2 : int OGRGMLLayer::GetFeatureCount( int bForce )
     287                 : 
     288                 : {
     289               2 :     if( poFClass == NULL )
     290               0 :         return 0;
     291                 : 
     292               2 :     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
     293               0 :         return OGRLayer::GetFeatureCount( bForce );
     294                 :     else
     295                 :     {
     296                 :         /* If the schema is read from a .xsd file, we haven't read */
     297                 :         /* the feature count, so compute it now */
     298               2 :         int nFeatureCount = poFClass->GetFeatureCount();
     299               2 :         if (nFeatureCount < 0)
     300                 :         {
     301               1 :             nFeatureCount = OGRLayer::GetFeatureCount(bForce);
     302               1 :             poFClass->SetFeatureCount(nFeatureCount);
     303                 :         }
     304               2 :         return nFeatureCount;
     305                 :     }
     306                 : }
     307                 : 
     308                 : /************************************************************************/
     309                 : /*                             GetExtent()                              */
     310                 : /************************************************************************/
     311                 : 
     312               0 : OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
     313                 : 
     314                 : {
     315                 :     double dfXMin, dfXMax, dfYMin, dfYMax;
     316                 : 
     317               0 :     if( poFClass != NULL && 
     318                 :         poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
     319                 :     {
     320               0 :         psExtent->MinX = dfXMin;
     321               0 :         psExtent->MaxX = dfXMax;
     322               0 :         psExtent->MinY = dfYMin;
     323               0 :         psExtent->MaxY = dfYMax;
     324                 : 
     325               0 :         return OGRERR_NONE;
     326                 :     }
     327                 :     else 
     328               0 :         return OGRLayer::GetExtent( psExtent, bForce );
     329                 : }
     330                 : 
     331                 : /************************************************************************/
     332                 : /*                           CreateFeature()                            */
     333                 : /************************************************************************/
     334                 : 
     335               2 : OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
     336                 : 
     337                 : {
     338               2 :     FILE        *fp = poDS->GetOutputFP();
     339                 : 
     340               2 :     if( !bWriter )
     341               0 :         return OGRERR_FAILURE;
     342                 : 
     343               2 :     VSIFPrintf( fp, "  <gml:featureMember>\n" );
     344                 : 
     345               2 :     if( poFeature->GetFID() == OGRNullFID )
     346               2 :         poFeature->SetFID( iNextGMLId++ );
     347                 : 
     348                 :     VSIFPrintf( fp, "    <ogr:%s fid=\"F%ld\">\n", 
     349                 :                 poFeatureDefn->GetName(),
     350               2 :                 poFeature->GetFID() );
     351                 : 
     352                 :     // Write out Geometry - for now it isn't indented properly.
     353               2 :     if( poFeature->GetGeometryRef() != NULL )
     354                 :     {
     355                 :         char    *pszGeometry;
     356               0 :         OGREnvelope sGeomBounds;
     357                 : 
     358               0 :         pszGeometry = poFeature->GetGeometryRef()->exportToGML();
     359                 :         VSIFPrintf( fp, "      <ogr:geometryProperty>%s</ogr:geometryProperty>\n",
     360               0 :                     pszGeometry );
     361               0 :         CPLFree( pszGeometry );
     362                 : 
     363               0 :         poFeature->GetGeometryRef()->getEnvelope( &sGeomBounds );
     364               0 :         poDS->GrowExtents( &sGeomBounds );
     365                 :     }
     366                 : 
     367                 :     // Write all "set" fields. 
     368               8 :     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     369                 :     {
     370                 :         
     371               6 :         OGRFieldDefn *poField = poFeatureDefn->GetFieldDefn( iField );
     372                 : 
     373               6 :         if( poFeature->IsFieldSet( iField ) )
     374                 :         {
     375               6 :             const char *pszRaw = poFeature->GetFieldAsString( iField );
     376                 : 
     377              12 :             while( *pszRaw == ' ' )
     378               0 :                 pszRaw++;
     379                 : 
     380               6 :             char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
     381                 :             VSIFPrintf( fp, "      <ogr:%s>%s</ogr:%s>\n", 
     382                 :                         poField->GetNameRef(), pszEscaped, 
     383               6 :                         poField->GetNameRef() );
     384               6 :             CPLFree( pszEscaped );
     385                 :         }
     386                 :     }
     387                 : 
     388               2 :     VSIFPrintf( fp, "    </ogr:%s>\n", poFeatureDefn->GetName() );
     389               2 :     VSIFPrintf( fp, "  </gml:featureMember>\n" );
     390                 : 
     391               2 :     return OGRERR_NONE;
     392                 : }
     393                 : 
     394                 : /************************************************************************/
     395                 : /*                           TestCapability()                           */
     396                 : /************************************************************************/
     397                 : 
     398               0 : int OGRGMLLayer::TestCapability( const char * pszCap )
     399                 : 
     400                 : {
     401               0 :     if( EQUAL(pszCap,OLCSequentialWrite) )
     402               0 :         return bWriter;
     403                 : 
     404               0 :     else if( EQUAL(pszCap,OLCCreateField) )
     405               0 :         return bWriter && iNextGMLId == 0;
     406                 : 
     407               0 :     else if( EQUAL(pszCap,OLCFastGetExtent) )
     408                 :     {
     409                 :         double  dfXMin, dfXMax, dfYMin, dfYMax;
     410                 : 
     411               0 :         if( poFClass == NULL )
     412               0 :             return FALSE;
     413                 : 
     414               0 :         return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax );
     415                 :     }
     416                 : 
     417               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     418                 :     {
     419               0 :         if( poFClass == NULL 
     420                 :             || m_poFilterGeom != NULL 
     421                 :             || m_poAttrQuery != NULL )
     422               0 :             return FALSE;
     423                 : 
     424               0 :         return poFClass->GetFeatureCount() != -1;
     425                 :     }
     426                 : 
     427               0 :     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
     428               0 :         return TRUE;
     429                 : 
     430                 :     else 
     431               0 :         return FALSE;
     432                 : }
     433                 : 
     434                 : /************************************************************************/
     435                 : /*                            CreateField()                             */
     436                 : /************************************************************************/
     437                 : 
     438               6 : OGRErr OGRGMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
     439                 : 
     440                 : {
     441               6 :     if( !bWriter || iNextGMLId != 0 )
     442               0 :         return OGRERR_FAILURE;
     443                 : 
     444                 : /* -------------------------------------------------------------------- */
     445                 : /*      Enforce XML naming semantics on element name.                   */
     446                 : /* -------------------------------------------------------------------- */
     447               6 :     OGRFieldDefn oCleanCopy( poField );
     448               6 :     char *pszName = CPLStrdup( poField->GetNameRef() );
     449               6 :     CPLCleanXMLElementName( pszName );
     450                 :     
     451               6 :     if( strcmp(pszName,poField->GetNameRef()) != 0 )
     452                 :     {
     453               0 :         if( !bApproxOK )
     454                 :         {
     455               0 :             CPLFree( pszName );
     456                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     457                 :                       "Unable to create field with name '%s', it would not\n"
     458                 :                       "be valid as an XML element name.",
     459               0 :                       poField->GetNameRef() );
     460               0 :             return OGRERR_FAILURE;
     461                 :         }
     462                 : 
     463               0 :         oCleanCopy.SetName( pszName );
     464                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     465                 :                   "Field name '%s' adjusted to '%s' to be a valid\n"
     466                 :                   "XML element name.",
     467               0 :                   poField->GetNameRef(), pszName );
     468                 :     }
     469                 : 
     470               6 :     CPLFree( pszName );
     471                 : 
     472                 :     
     473               6 :     poFeatureDefn->AddFieldDefn( &oCleanCopy );
     474                 : 
     475               6 :     return OGRERR_NONE;
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                           GetSpatialRef()                            */
     480                 : /************************************************************************/
     481                 : 
     482               0 : OGRSpatialReference *OGRGMLLayer::GetSpatialRef()
     483                 : 
     484                 : {
     485               0 :     return poSRS;
     486                 : }
     487                 : 

Generated by: LCOV version 1.7