LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/nas - ogrnasdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 139 109 78.4 %
Date: 2011-12-18 Functions: 10 6 60.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgmldatasource.cpp 12743 2007-11-13 13:59:37Z dron $
       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: ogrgmldatasource.cpp 12743 2007-11-13 13:59:37Z dron $");
      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             304 : OGRNASDataSource::OGRNASDataSource()
      49                 : 
      50                 : {
      51             304 :     pszName = NULL;
      52             304 :     papoLayers = NULL;
      53             304 :     nLayers = 0;
      54                 : 
      55             304 :     poReader = NULL;
      56             304 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*                        ~OGRNASDataSource()                         */
      60                 : /************************************************************************/
      61                 : 
      62             304 : OGRNASDataSource::~OGRNASDataSource()
      63                 : 
      64                 : {
      65             304 :     CPLFree( pszName );
      66                 : 
      67             436 :     for( int i = 0; i < nLayers; i++ )
      68             132 :         delete papoLayers[i];
      69                 :     
      70             304 :     CPLFree( papoLayers );
      71                 : 
      72             304 :     if( poReader )
      73               5 :         delete poReader;
      74             304 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                                Open()                                */
      78                 : /************************************************************************/
      79                 : 
      80             304 : 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             304 :     fp = VSIFOpen( pszNewName, "r" );
      90             304 :     if( fp == NULL )
      91                 :     {
      92             106 :         if( !bTestOpen )
      93                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
      94                 :                       "Failed to open NAS file `%s'.", 
      95               0 :                       pszNewName );
      96                 : 
      97             106 :         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             198 :     if( bTestOpen )
     105                 :     {
     106             198 :         size_t nRead = VSIFRead( szHeader, 1, sizeof(szHeader), fp );
     107             198 :         if (nRead <= 0)
     108                 :         {
     109               4 :             VSIFClose( fp );
     110               4 :             return FALSE;
     111                 :         }
     112             194 :         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             194 :         char* szPtr = szHeader;
     123                 : 
     124             198 :         if( ( (unsigned char)szHeader[0] == 0xEF )
     125               2 :             && ( (unsigned char)szHeader[1] == 0xBB )
     126               2 :             && ( (unsigned char)szHeader[2] == 0xBF) )
     127                 :         {
     128               2 :             szPtr += 3;
     129                 :         }
     130                 : 
     131                 : /* -------------------------------------------------------------------- */
     132                 : /*      Here, we expect the opening chevrons of NAS tree root element   */
     133                 : /* -------------------------------------------------------------------- */
     134             194 :         if( szPtr[0] != '<' 
     135                 :             || strstr(szPtr,"opengis.net/gml") == NULL 
     136                 :             || strstr(szPtr,"NAS-Operationen.xsd") == NULL )
     137                 :         {
     138             189 :             VSIFClose( fp );
     139             189 :             return FALSE;
     140                 :         }
     141                 :     }
     142                 :     
     143                 : /* -------------------------------------------------------------------- */
     144                 : /*      We assume now that it is NAS.  Close and instantiate a          */
     145                 : /*      NASReader on it.                                                */
     146                 : /* -------------------------------------------------------------------- */
     147               5 :     VSIFClose( fp );
     148                 :     
     149               5 :     poReader = CreateNASReader();
     150               5 :     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               5 :     poReader->SetSourceFile( pszNewName );
     161                 :     
     162               5 :     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               5 :     int        bHaveSchema = FALSE;
     170                 : 
     171               5 :     pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
     172               5 :     if( CPLStat( pszGFSFilename, &sGFSStatBuf ) == 0 )
     173                 :     {
     174               2 :         CPLStat( pszNewName, &sNASStatBuf );
     175                 : 
     176               2 :         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               2 :             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               5 :     CPLErrorReset();
     195               8 :     if( !bHaveSchema 
     196               3 :         && !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               5 :     if( !bHaveSchema && poReader->GetClassCount() > 0 )
     208                 :     {
     209               2 :         FILE    *fp = NULL;
     210                 : 
     211               2 :         pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
     212               2 :         if( CPLStat( pszGFSFilename, &sGFSStatBuf ) != 0 
     213                 :             && (fp = VSIFOpen( pszGFSFilename, "wt" )) != NULL )
     214                 :         {
     215               2 :             VSIFClose( fp );
     216               2 :             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               5 :         CPLCalloc( sizeof(OGRNASLayer *), poReader->GetClassCount()+1 );
     231               5 :     nLayers = 0;
     232                 : 
     233             137 :     while( nLayers < poReader->GetClassCount() )
     234                 :     {
     235             127 :         papoLayers[nLayers] = TranslateNASSchema(poReader->GetClass(nLayers));
     236             127 :         nLayers++;
     237                 :     }
     238                 :     
     239               5 :     poRelationLayer = new OGRNASRelationLayer( this );
     240               5 :     papoLayers[nLayers++] = poRelationLayer;
     241                 :     
     242               5 :     return TRUE;
     243                 : }
     244                 : 
     245                 : /************************************************************************/
     246                 : /*                         TranslateNASSchema()                         */
     247                 : /************************************************************************/
     248                 : 
     249             127 : OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
     250                 : 
     251                 : {
     252                 :     OGRNASLayer *poLayer;
     253                 :     OGRwkbGeometryType eGType 
     254             127 :         = (OGRwkbGeometryType) poClass->GetGeometryType();
     255                 : 
     256             127 :     if( poClass->GetFeatureCount() == 0 )
     257               0 :         eGType = wkbUnknown;
     258                 : 
     259                 : /* -------------------------------------------------------------------- */
     260                 : /*      Translate SRS.                                                  */
     261                 : /* -------------------------------------------------------------------- */
     262             127 :     const char* pszSRSName = poClass->GetSRSName();
     263             127 :     OGRSpatialReference* poSRS = NULL;
     264             127 :     if (pszSRSName)
     265                 :     {
     266                 :         int i;
     267                 : 
     268               0 :         poSRS = new OGRSpatialReference();
     269                 :         
     270               0 :         const char *pszHandle = strrchr( pszSRSName, ':' );
     271               0 :         if( pszHandle != NULL )
     272               0 :             pszHandle += 1;
     273                 : 
     274               0 :         for( i = 0; apszURNNames[i*2+0] != NULL; i++ )
     275                 :         {
     276               0 :             const char *pszTarget = apszURNNames[i*2+0];
     277               0 :             int nTLen = strlen(pszTarget);
     278                 : 
     279                 :             // Are we just looking for a prefix match?
     280               0 :             if( pszTarget[nTLen-1] == '*' )
     281                 :             {
     282               0 :                 if( EQUALN(pszTarget,pszHandle,nTLen-1) )
     283               0 :                     pszSRSName = apszURNNames[i*2+1];
     284                 :             }
     285                 :             else
     286                 :             {
     287               0 :                 if( EQUAL(pszTarget,pszHandle) )
     288               0 :                     pszSRSName = apszURNNames[i*2+1];
     289                 :             }
     290                 :         }
     291                 :         
     292               0 :         if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE)
     293                 :         {
     294                 :             CPLDebug( "NAS", "Failed to translate srsName='%s'", 
     295               0 :                       pszSRSName );
     296               0 :             delete poSRS;
     297               0 :             poSRS = NULL;
     298                 :         }
     299                 :     }
     300                 : 
     301                 : /* -------------------------------------------------------------------- */
     302                 : /*      Create an empty layer.                                          */
     303                 : /* -------------------------------------------------------------------- */
     304             127 :     poLayer = new OGRNASLayer( poClass->GetName(), poSRS, eGType, this );
     305             127 :     delete poSRS;
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Added attributes (properties).                                  */
     309                 : /* -------------------------------------------------------------------- */
     310            1091 :     for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
     311                 :     {
     312             964 :         GMLPropertyDefn *poProperty = poClass->GetProperty( iField );
     313                 :         OGRFieldType eFType;
     314                 : 
     315             964 :         if( poProperty->GetType() == GMLPT_Untyped )
     316              34 :             eFType = OFTString;
     317             930 :         else if( poProperty->GetType() == GMLPT_String )
     318             571 :             eFType = OFTString;
     319             359 :         else if( poProperty->GetType() == GMLPT_Integer )
     320             330 :             eFType = OFTInteger;
     321              29 :         else if( poProperty->GetType() == GMLPT_Real )
     322              12 :             eFType = OFTReal;
     323              17 :         else if( poProperty->GetType() == GMLPT_StringList )
     324              13 :             eFType = OFTStringList;
     325               4 :         else if( poProperty->GetType() == GMLPT_IntegerList )
     326               4 :             eFType = OFTIntegerList;
     327               0 :         else if( poProperty->GetType() == GMLPT_RealList )
     328               0 :             eFType = OFTRealList;
     329                 :         else
     330               0 :             eFType = OFTString;
     331                 :         
     332             964 :         OGRFieldDefn oField( poProperty->GetName(), eFType );
     333             964 :         if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
     334               0 :           oField.SetName(poProperty->GetName()+4);
     335             964 :         if( poProperty->GetWidth() > 0 )
     336             571 :             oField.SetWidth( poProperty->GetWidth() );
     337                 : 
     338             964 :         poLayer->GetLayerDefn()->AddFieldDefn( &oField );
     339                 :     }
     340                 : 
     341             127 :     return poLayer;
     342                 : }
     343                 : 
     344                 : /************************************************************************/
     345                 : /*                              GetLayer()                              */
     346                 : /************************************************************************/
     347                 : 
     348             116 : OGRLayer *OGRNASDataSource::GetLayer( int iLayer )
     349                 : 
     350                 : {
     351             116 :     if( iLayer < 0 || iLayer >= nLayers )
     352               0 :         return NULL;
     353                 :     else
     354             116 :         return papoLayers[iLayer];
     355                 : }
     356                 : 
     357                 : /************************************************************************/
     358                 : /*                           TestCapability()                           */
     359                 : /************************************************************************/
     360                 : 
     361               0 : int OGRNASDataSource::TestCapability( const char * pszCap )
     362                 : 
     363                 : {
     364               0 :     return FALSE;
     365                 : }
     366                 : 
     367                 : /************************************************************************/
     368                 : /*                         PopulateRelations()                          */
     369                 : /************************************************************************/
     370                 : 
     371               1 : void OGRNASDataSource::PopulateRelations()
     372                 : 
     373                 : {
     374                 :     GMLFeature  *poFeature;
     375                 : 
     376               1 :     poReader->ResetReading();
     377            8394 :     while( (poFeature = poReader->NextFeature()) != NULL )
     378                 :     {
     379            8392 :         char **papszOBProperties = poFeature->GetOBProperties();
     380                 :         int i;
     381                 : 
     382           10228 :         for( i = 0; papszOBProperties != NULL && papszOBProperties[i] != NULL;
     383                 :              i++ )
     384                 :         {
     385            1836 :             int nGMLIdIndex = poFeature->GetClass()->GetPropertyIndex( "gml_id" );
     386            1836 :             const GMLProperty *psGMLId = (nGMLIdIndex >= 0) ? poFeature->GetProperty(nGMLIdIndex ) : NULL;
     387            1836 :             char *pszName = NULL;
     388            1836 :             const char *pszValue = CPLParseNameValue( papszOBProperties[i], 
     389            3672 :                                                       &pszName );
     390                 : 
     391            1836 :             if( EQUALN(pszValue,"urn:adv:oid:",12) 
     392                 :                 && psGMLId != NULL && psGMLId->nSubProperties == 1 )
     393                 :             {
     394            1836 :                 poRelationLayer->AddRelation( psGMLId->papszSubProperties[0],
     395                 :                                               pszName, 
     396            3672 :                                               pszValue + 12 );
     397                 :             }
     398            1836 :             CPLFree( pszName );
     399                 :         }
     400                 :         
     401            8392 :         delete poFeature;
     402                 :     }
     403                 : 
     404               1 :     poRelationLayer->MarkRelationsPopulated();
     405               1 : }

Generated by: LCOV version 1.7