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: 2013-03-30 Functions: 10 6 60.0 %

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

Generated by: LCOV version 1.7