LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/nas - ogrnasdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 143 113 79.0 %
Date: 2012-04-28 Functions: 10 6 60.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrnasdatasource.cpp 24105 2012-03-10 12:08:04Z rouault $
       3                 :  *
       4                 :  * Project:  OGR
       5                 :  * Purpose:  Implements OGRNASDataSource 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_nas.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogrnasdatasource.cpp 24105 2012-03-10 12:08:04Z rouault $");
      35                 : 
      36                 : static const char *apszURNNames[] = 
      37                 : { 
      38                 :     "DE_DHDN_3GK2_*", "EPSG:31466", 
      39                 :     "DE_DHDN_3GK3_*", "EPSG:31467", 
      40                 :     "ETRS89_UTM32", "EPSG:25832", 
      41                 :     NULL, NULL 
      42                 : };
      43                 : 
      44                 : /************************************************************************/
      45                 : /*                         OGRNASDataSource()                         */
      46                 : /************************************************************************/
      47                 : 
      48             710 : OGRNASDataSource::OGRNASDataSource()
      49                 : 
      50                 : {
      51             710 :     pszName = NULL;
      52             710 :     papoLayers = NULL;
      53             710 :     nLayers = 0;
      54                 : 
      55             710 :     poReader = NULL;
      56             710 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*                        ~OGRNASDataSource()                         */
      60                 : /************************************************************************/
      61                 : 
      62             710 : OGRNASDataSource::~OGRNASDataSource()
      63                 : 
      64                 : {
      65             710 :     CPLFree( pszName );
      66                 : 
      67             974 :     for( int i = 0; i < nLayers; i++ )
      68             264 :         delete papoLayers[i];
      69                 :     
      70             710 :     CPLFree( papoLayers );
      71                 : 
      72             710 :     if( poReader )
      73              10 :         delete poReader;
      74             710 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                                Open()                                */
      78                 : /************************************************************************/
      79                 : 
      80             710 : int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen )
      81                 : 
      82                 : {
      83                 :     FILE        *fp;
      84                 :     char        szHeader[8192];
      85                 : 
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Open the source file.                                           */
      88                 : /* -------------------------------------------------------------------- */
      89             710 :     fp = VSIFOpen( pszNewName, "r" );
      90             710 :     if( fp == NULL )
      91                 :     {
      92             220 :         if( !bTestOpen )
      93                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
      94                 :                       "Failed to open NAS file `%s'.", 
      95               0 :                       pszNewName );
      96                 : 
      97             220 :         return FALSE;
      98                 :     }
      99                 : 
     100                 : /* -------------------------------------------------------------------- */
     101                 : /*      If we aren't sure it is NAS, load a header chunk and check      */
     102                 : /*      for signs it is NAS                                             */
     103                 : /* -------------------------------------------------------------------- */
     104             490 :     if( bTestOpen )
     105                 :     {
     106             490 :         size_t nRead = VSIFRead( szHeader, 1, sizeof(szHeader), fp );
     107             490 :         if (nRead <= 0)
     108                 :         {
     109              16 :             VSIFClose( fp );
     110              16 :             return FALSE;
     111                 :         }
     112             474 :         szHeader[MIN(nRead, sizeof(szHeader))-1] = '\0';
     113                 : 
     114                 : /* -------------------------------------------------------------------- */
     115                 : /*      Check for a UTF-8 BOM and skip if found                         */
     116                 : /*                                                                      */
     117                 : /*      TODO: BOM is variable-lenght parameter and depends on encoding. */
     118                 : /*            Add BOM detection for other encodings.                    */
     119                 : /* -------------------------------------------------------------------- */
     120                 : 
     121                 :         // Used to skip to actual beginning of XML data
     122             474 :         char* szPtr = szHeader;
     123                 : 
     124             482 :         if( ( (unsigned char)szHeader[0] == 0xEF )
     125               4 :             && ( (unsigned char)szHeader[1] == 0xBB )
     126               4 :             && ( (unsigned char)szHeader[2] == 0xBF) )
     127                 :         {
     128               4 :             szPtr += 3;
     129                 :         }
     130                 : 
     131                 : /* -------------------------------------------------------------------- */
     132                 : /*      Here, we expect the opening chevrons of NAS tree root element   */
     133                 : /* -------------------------------------------------------------------- */
     134             474 :         if( szPtr[0] != '<' 
     135                 :             || strstr(szPtr,"opengis.net/gml") == NULL 
     136                 :             || strstr(szPtr,"NAS-Operationen.xsd") == NULL )
     137                 :         {
     138             464 :             VSIFClose( fp );
     139             464 :             return FALSE;
     140                 :         }
     141                 :     }
     142                 :     
     143                 : /* -------------------------------------------------------------------- */
     144                 : /*      We assume now that it is NAS.  Close and instantiate a          */
     145                 : /*      NASReader on it.                                                */
     146                 : /* -------------------------------------------------------------------- */
     147              10 :     VSIFClose( fp );
     148                 :     
     149              10 :     poReader = CreateNASReader();
     150              10 :     if( poReader == NULL )
     151                 :     {
     152                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     153                 :                   "File %s appears to be NAS but the NAS reader can't\n"
     154                 :                   "be instantiated, likely because Xerces support wasn't\n"
     155                 :                   "configured in.", 
     156               0 :                   pszNewName );
     157               0 :         return FALSE;
     158                 :     }
     159                 : 
     160              10 :     poReader->SetSourceFile( pszNewName );
     161                 :     
     162              10 :     pszName = CPLStrdup( pszNewName );
     163                 : 
     164                 : /* -------------------------------------------------------------------- */
     165                 : /*      Can we find a NAS Feature Schema (.gfs) for the input file?     */
     166                 : /* -------------------------------------------------------------------- */
     167                 :     const char *pszGFSFilename;
     168                 :     VSIStatBuf sGFSStatBuf, sNASStatBuf;
     169              10 :     int        bHaveSchema = FALSE;
     170                 : 
     171              10 :     pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
     172              10 :     if( CPLStat( pszGFSFilename, &sGFSStatBuf ) == 0 )
     173                 :     {
     174               4 :         CPLStat( pszNewName, &sNASStatBuf );
     175                 : 
     176               4 :         if( sNASStatBuf.st_mtime > sGFSStatBuf.st_mtime )
     177                 :         {
     178                 :             CPLDebug( "NAS", 
     179                 :                       "Found %s but ignoring because it appears\n"
     180                 :                       "be older than the associated NAS file.", 
     181               0 :                       pszGFSFilename );
     182                 :         }
     183                 :         else
     184                 :         {
     185               4 :             bHaveSchema = poReader->LoadClasses( pszGFSFilename );
     186                 :         }
     187                 :     }
     188                 : 
     189                 : /* -------------------------------------------------------------------- */
     190                 : /*      Force a first pass to establish the schema.  Eventually we      */
     191                 : /*      will have mechanisms for remembering the schema and related     */
     192                 : /*      information.                                                    */
     193                 : /* -------------------------------------------------------------------- */
     194              10 :     CPLErrorReset();
     195              16 :     if( !bHaveSchema 
     196               6 :         && !poReader->PrescanForSchema( TRUE ) 
     197                 :         && CPLGetLastErrorType() == CE_Failure )
     198                 :     {
     199                 :         // we assume an errors have been reported.
     200               0 :         return FALSE;
     201                 :     }
     202                 : 
     203                 : /* -------------------------------------------------------------------- */
     204                 : /*      Save the schema file if possible.  Don't make a fuss if we      */
     205                 : /*      can't ... could be read-only directory or something.            */
     206                 : /* -------------------------------------------------------------------- */
     207              10 :     if( !bHaveSchema && poReader->GetClassCount() > 0 )
     208                 :     {
     209               4 :         FILE    *fp = NULL;
     210                 : 
     211               4 :         pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
     212               4 :         if( CPLStat( pszGFSFilename, &sGFSStatBuf ) != 0 
     213                 :             && (fp = VSIFOpen( pszGFSFilename, "wt" )) != NULL )
     214                 :         {
     215               4 :             VSIFClose( fp );
     216               4 :             poReader->SaveClasses( pszGFSFilename );
     217                 :         }
     218                 :         else
     219                 :         {
     220                 :             CPLDebug("NAS", 
     221                 :                      "Not saving %s files already exists or can't be created.",
     222               0 :                      pszGFSFilename );
     223                 :         }
     224                 :     }
     225                 : 
     226                 : /* -------------------------------------------------------------------- */
     227                 : /*      Translate the NASFeatureClasses into layers.                    */
     228                 : /* -------------------------------------------------------------------- */
     229                 :     papoLayers = (OGRLayer **)
     230              10 :         CPLCalloc( sizeof(OGRNASLayer *), poReader->GetClassCount()+1 );
     231              10 :     nLayers = 0;
     232                 : 
     233             274 :     while( nLayers < poReader->GetClassCount() )
     234                 :     {
     235             254 :         papoLayers[nLayers] = TranslateNASSchema(poReader->GetClass(nLayers));
     236             254 :         nLayers++;
     237                 :     }
     238                 :     
     239              10 :     poRelationLayer = new OGRNASRelationLayer( this );
     240                 : 
     241                 :     // keep delete the last layer
     242              18 :     if( nLayers>0 && EQUAL( papoLayers[nLayers-1]->GetName(), "Delete" ) )
     243                 :     {
     244               4 :       papoLayers[nLayers]   = papoLayers[nLayers-1];
     245               4 :       papoLayers[nLayers-1] = poRelationLayer;
     246                 :     }
     247                 :     else
     248                 :     {
     249               6 :       papoLayers[nLayers] = poRelationLayer;
     250                 :     }
     251                 : 
     252              10 :     nLayers++;
     253                 :     
     254              10 :     return TRUE;
     255                 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : /*                         TranslateNASSchema()                         */
     259                 : /************************************************************************/
     260                 : 
     261             254 : OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
     262                 : 
     263                 : {
     264                 :     OGRNASLayer *poLayer;
     265                 :     OGRwkbGeometryType eGType 
     266             254 :         = (OGRwkbGeometryType) poClass->GetGeometryType();
     267                 : 
     268             254 :     if( poClass->GetFeatureCount() == 0 )
     269               0 :         eGType = wkbUnknown;
     270                 : 
     271                 : /* -------------------------------------------------------------------- */
     272                 : /*      Translate SRS.                                                  */
     273                 : /* -------------------------------------------------------------------- */
     274             254 :     const char* pszSRSName = poClass->GetSRSName();
     275             254 :     OGRSpatialReference* poSRS = NULL;
     276             254 :     if (pszSRSName)
     277                 :     {
     278                 :         int i;
     279                 : 
     280               0 :         poSRS = new OGRSpatialReference();
     281                 :         
     282               0 :         const char *pszHandle = strrchr( pszSRSName, ':' );
     283               0 :         if( pszHandle != NULL )
     284               0 :             pszHandle += 1;
     285                 : 
     286               0 :         for( i = 0; apszURNNames[i*2+0] != NULL; i++ )
     287                 :         {
     288               0 :             const char *pszTarget = apszURNNames[i*2+0];
     289               0 :             int nTLen = strlen(pszTarget);
     290                 : 
     291                 :             // Are we just looking for a prefix match?
     292               0 :             if( pszTarget[nTLen-1] == '*' )
     293                 :             {
     294               0 :                 if( EQUALN(pszTarget,pszHandle,nTLen-1) )
     295               0 :                     pszSRSName = apszURNNames[i*2+1];
     296                 :             }
     297                 :             else
     298                 :             {
     299               0 :                 if( EQUAL(pszTarget,pszHandle) )
     300               0 :                     pszSRSName = apszURNNames[i*2+1];
     301                 :             }
     302                 :         }
     303                 :         
     304               0 :         if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE)
     305                 :         {
     306                 :             CPLDebug( "NAS", "Failed to translate srsName='%s'", 
     307               0 :                       pszSRSName );
     308               0 :             delete poSRS;
     309               0 :             poSRS = NULL;
     310                 :         }
     311                 :     }
     312                 : 
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      Create an empty layer.                                          */
     315                 : /* -------------------------------------------------------------------- */
     316             254 :     poLayer = new OGRNASLayer( poClass->GetName(), poSRS, eGType, this );
     317             254 :     delete poSRS;
     318                 : 
     319                 : /* -------------------------------------------------------------------- */
     320                 : /*      Added attributes (properties).                                  */
     321                 : /* -------------------------------------------------------------------- */
     322            2190 :     for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
     323                 :     {
     324            1936 :         GMLPropertyDefn *poProperty = poClass->GetProperty( iField );
     325                 :         OGRFieldType eFType;
     326                 : 
     327            1936 :         if( poProperty->GetType() == GMLPT_Untyped )
     328              68 :             eFType = OFTString;
     329            1868 :         else if( poProperty->GetType() == GMLPT_String )
     330            1150 :             eFType = OFTString;
     331             718 :         else if( poProperty->GetType() == GMLPT_Integer )
     332             660 :             eFType = OFTInteger;
     333              58 :         else if( poProperty->GetType() == GMLPT_Real )
     334              24 :             eFType = OFTReal;
     335              34 :         else if( poProperty->GetType() == GMLPT_StringList )
     336              26 :             eFType = OFTStringList;
     337               8 :         else if( poProperty->GetType() == GMLPT_IntegerList )
     338               8 :             eFType = OFTIntegerList;
     339               0 :         else if( poProperty->GetType() == GMLPT_RealList )
     340               0 :             eFType = OFTRealList;
     341                 :         else
     342               0 :             eFType = OFTString;
     343                 :         
     344            1936 :         OGRFieldDefn oField( poProperty->GetName(), eFType );
     345            1936 :         if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
     346               0 :           oField.SetName(poProperty->GetName()+4);
     347            1936 :         if( poProperty->GetWidth() > 0 )
     348            1150 :             oField.SetWidth( poProperty->GetWidth() );
     349                 : 
     350            1936 :         poLayer->GetLayerDefn()->AddFieldDefn( &oField );
     351                 :     }
     352                 : 
     353             254 :     return poLayer;
     354                 : }
     355                 : 
     356                 : /************************************************************************/
     357                 : /*                              GetLayer()                              */
     358                 : /************************************************************************/
     359                 : 
     360             236 : OGRLayer *OGRNASDataSource::GetLayer( int iLayer )
     361                 : 
     362                 : {
     363             236 :     if( iLayer < 0 || iLayer >= nLayers )
     364               0 :         return NULL;
     365                 :     else
     366             236 :         return papoLayers[iLayer];
     367                 : }
     368                 : 
     369                 : /************************************************************************/
     370                 : /*                           TestCapability()                           */
     371                 : /************************************************************************/
     372                 : 
     373               0 : int OGRNASDataSource::TestCapability( const char * pszCap )
     374                 : 
     375                 : {
     376               0 :     return FALSE;
     377                 : }
     378                 : 
     379                 : /************************************************************************/
     380                 : /*                         PopulateRelations()                          */
     381                 : /************************************************************************/
     382                 : 
     383               2 : void OGRNASDataSource::PopulateRelations()
     384                 : 
     385                 : {
     386                 :     GMLFeature  *poFeature;
     387                 : 
     388               2 :     poReader->ResetReading();
     389           16788 :     while( (poFeature = poReader->NextFeature()) != NULL )
     390                 :     {
     391           16784 :         char **papszOBProperties = poFeature->GetOBProperties();
     392                 :         int i;
     393                 : 
     394           20456 :         for( i = 0; papszOBProperties != NULL && papszOBProperties[i] != NULL;
     395                 :              i++ )
     396                 :         {
     397            3672 :             int nGMLIdIndex = poFeature->GetClass()->GetPropertyIndex( "gml_id" );
     398            3672 :             const GMLProperty *psGMLId = (nGMLIdIndex >= 0) ? poFeature->GetProperty(nGMLIdIndex ) : NULL;
     399            3672 :             char *pszName = NULL;
     400            3672 :             const char *pszValue = CPLParseNameValue( papszOBProperties[i], 
     401            7344 :                                                       &pszName );
     402                 : 
     403            3672 :             if( EQUALN(pszValue,"urn:adv:oid:",12) 
     404                 :                 && psGMLId != NULL && psGMLId->nSubProperties == 1 )
     405                 :             {
     406            3672 :                 poRelationLayer->AddRelation( psGMLId->papszSubProperties[0],
     407                 :                                               pszName, 
     408            7344 :                                               pszValue + 12 );
     409                 :             }
     410            3672 :             CPLFree( pszName );
     411                 :         }
     412                 :         
     413           16784 :         delete poFeature;
     414                 :     }
     415                 : 
     416               2 :     poRelationLayer->MarkRelationsPopulated();
     417               2 : }

Generated by: LCOV version 1.7