LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vrt - ogrvrtdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 279 206 73.8 %
Date: 2012-12-26 Functions: 18 15 83.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrvrtdatasource.cpp 25110 2012-10-13 13:53:53Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRVRTDataSource class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2003, 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_vrt.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "ogrwarpedlayer.h"
      34                 : #include "ogrunionlayer.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ogrvrtdatasource.cpp 25110 2012-10-13 13:53:53Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                       OGRVRTGetGeometryType()                        */
      40                 : /************************************************************************/
      41                 : 
      42                 : typedef struct
      43                 : {
      44                 :     OGRwkbGeometryType  eType;
      45                 :     const char          *pszName;
      46                 : } OGRGeomTypeName;
      47                 : 
      48                 : static const OGRGeomTypeName asGeomTypeNames[] = { /* 25D versions are implicit */
      49                 :     { wkbUnknown, "wkbUnknown" },
      50                 :     { wkbPoint, "wkbPoint" },
      51                 :     { wkbLineString, "wkbLineString" },
      52                 :     { wkbPolygon, "wkbPolygon" },
      53                 :     { wkbMultiPoint, "wkbMultiPoint" },
      54                 :     { wkbMultiLineString, "wkbMultiLineString" },
      55                 :     { wkbMultiPolygon, "wkbMultiPolygon" },
      56                 :     { wkbGeometryCollection, "wkbGeometryCollection" },
      57                 :     { wkbNone, "wkbNone" },
      58                 :     { wkbNone, NULL }
      59                 : };
      60                 : 
      61             207 : OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError)
      62                 : {
      63                 :     int iType;
      64             207 :     OGRwkbGeometryType eGeomType = wkbUnknown;
      65                 : 
      66             207 :     if (pbError)
      67             207 :         *pbError = FALSE;
      68                 : 
      69             426 :     for( iType = 0; asGeomTypeNames[iType].pszName != NULL; iType++ )
      70                 :     {
      71             425 :         if( EQUALN(pszGType, asGeomTypeNames[iType].pszName,
      72                 :                 strlen(asGeomTypeNames[iType].pszName)) )
      73                 :         {
      74             206 :             eGeomType = asGeomTypeNames[iType].eType;
      75                 : 
      76             206 :             if( strstr(pszGType,"25D") != NULL )
      77               9 :                 eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
      78             206 :             break;
      79                 :         }
      80                 :     }
      81                 : 
      82             207 :     if( asGeomTypeNames[iType].pszName == NULL )
      83                 :     {
      84               1 :         if (pbError)
      85               1 :             *pbError = TRUE;
      86                 :     }
      87                 : 
      88             207 :     return eGeomType;
      89                 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          OGRVRTDataSource()                          */
      93                 : /************************************************************************/
      94                 : 
      95             190 : OGRVRTDataSource::OGRVRTDataSource()
      96                 : 
      97                 : {
      98             190 :     pszName = NULL;
      99             190 :     papoLayers = NULL;
     100             190 :     nLayers = 0;
     101             190 :     psTree = NULL;
     102             190 :     nCallLevel = 0;
     103             190 :     poLayerPool = NULL;
     104             190 :     poParentDS = NULL;
     105             190 :     bRecursionDetected = FALSE;
     106             190 : }
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                         ~OGRVRTDataSource()                         */
     110                 : /************************************************************************/
     111                 : 
     112             190 : OGRVRTDataSource::~OGRVRTDataSource()
     113                 : 
     114                 : {
     115                 :     int         i;
     116                 : 
     117             190 :     CPLFree( pszName );
     118                 : 
     119             557 :     for( i = 0; i < nLayers; i++ )
     120             367 :         delete papoLayers[i];
     121                 :     
     122             190 :     CPLFree( papoLayers );
     123                 : 
     124             190 :     if( psTree != NULL)
     125             190 :         CPLDestroyXMLNode( psTree );
     126                 : 
     127             190 :     delete poLayerPool;
     128             190 : }
     129                 : 
     130                 : /************************************************************************/
     131                 : /*                        InstanciateWarpedLayer()                      */
     132                 : /************************************************************************/
     133                 : 
     134               2 : OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
     135                 :                                         CPLXMLNode *psLTree,
     136                 :                                         const char *pszVRTDirectory,
     137                 :                                         int bUpdate,
     138                 :                                         int nRecLevel)
     139                 : {
     140               2 :     if( !EQUAL(psLTree->pszValue,"OGRVRTWarpedLayer") )
     141               0 :         return NULL;
     142                 : 
     143                 :     CPLXMLNode *psSubNode;
     144               2 :     OGRLayer* poSrcLayer = NULL;
     145                 : 
     146               2 :     for( psSubNode=psLTree->psChild;
     147                 :          psSubNode != NULL;
     148                 :          psSubNode=psSubNode->psNext )
     149                 :     {
     150               2 :         if( psSubNode->eType != CXT_Element )
     151               0 :             continue;
     152                 : 
     153                 :         poSrcLayer = InstanciateLayer(psSubNode, pszVRTDirectory,
     154               2 :                                  bUpdate, nRecLevel + 1);
     155               2 :         if( poSrcLayer != NULL )
     156               2 :             break;
     157                 :     }
     158                 : 
     159               2 :     if( poSrcLayer == NULL )
     160                 :     {
     161                 :         CPLError( CE_Failure, CPLE_AppDefined,
     162               0 :                   "Cannot instanciate source layer" );
     163               0 :         return NULL;
     164                 :     }
     165                 : 
     166               2 :     const char* pszTargetSRS = CPLGetXMLValue(psLTree, "TargetSRS", NULL);
     167               2 :     if( pszTargetSRS == NULL )
     168                 :     {
     169                 :         CPLError( CE_Failure, CPLE_AppDefined,
     170               0 :                   "Missing TargetSRS element within OGRVRTWarpedLayer" );
     171               0 :         return NULL;
     172                 :     }
     173                 : 
     174                 :     OGRSpatialReference* poSrcSRS;
     175                 :     OGRSpatialReference* poTargetSRS;
     176               2 :     const char* pszSourceSRS = CPLGetXMLValue(psLTree, "SrcSRS", NULL);
     177                 : 
     178               2 :     if( pszSourceSRS == NULL )
     179                 :     {
     180               2 :         poSrcSRS = poSrcLayer->GetSpatialRef();
     181               2 :         if( poSrcSRS != NULL)
     182               2 :             poSrcSRS = poSrcSRS->Clone();
     183                 :     }
     184                 :     else
     185                 :     {
     186               0 :         poSrcSRS = new OGRSpatialReference();
     187               0 :         if( poSrcSRS->SetFromUserInput(pszSourceSRS) != OGRERR_NONE )
     188                 :         {
     189               0 :             delete poSrcSRS;
     190               0 :             poSrcSRS = NULL;
     191                 :         }
     192                 :     }
     193                 : 
     194               2 :     if( poSrcSRS == NULL )
     195                 :     {
     196                 :         CPLError( CE_Failure, CPLE_AppDefined,
     197               0 :                   "Failed to import source SRS" );
     198               0 :         delete poSrcLayer;
     199               0 :         return NULL;
     200                 :     }
     201                 : 
     202               2 :     poTargetSRS = new OGRSpatialReference();
     203               2 :     if( poTargetSRS->SetFromUserInput(pszTargetSRS) != OGRERR_NONE )
     204                 :     {
     205               0 :         delete poTargetSRS;
     206               0 :         poTargetSRS = NULL;
     207                 :     }
     208                 : 
     209               2 :     if( poTargetSRS == NULL )
     210                 :     {
     211                 :         CPLError( CE_Failure, CPLE_AppDefined,
     212               0 :                   "Failed to import target SRS" );
     213               0 :         delete poSrcSRS;
     214               0 :         delete poSrcLayer;
     215               0 :         return NULL;
     216                 :     }
     217                 : 
     218               2 :     if( pszSourceSRS == NULL && poSrcSRS->IsSame(poTargetSRS) )
     219                 :     {
     220               0 :         delete poSrcSRS;
     221               0 :         delete poTargetSRS;
     222               0 :         return poSrcLayer;
     223                 :     }
     224                 : 
     225                 :     OGRCoordinateTransformation* poCT =
     226               2 :         OGRCreateCoordinateTransformation( poSrcSRS, poTargetSRS );
     227                 :     OGRCoordinateTransformation* poReversedCT = (poCT != NULL) ?
     228               2 :         OGRCreateCoordinateTransformation( poTargetSRS, poSrcSRS ) : NULL;
     229                 : 
     230               2 :     delete poSrcSRS;
     231               2 :     delete poTargetSRS;
     232                 : 
     233               2 :     if( poCT == NULL )
     234                 :     {
     235               0 :         delete poSrcLayer;
     236               0 :         return NULL;
     237                 :     }
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      Build the OGRWarpedLayer.                                       */
     241                 : /* -------------------------------------------------------------------- */
     242                 : 
     243               2 :     OGRWarpedLayer* poLayer = new OGRWarpedLayer(poSrcLayer, TRUE, poCT, poReversedCT);
     244                 : 
     245                 : /* -------------------------------------------------------------------- */
     246                 : /*      Set Extent if provided                                          */
     247                 : /* -------------------------------------------------------------------- */
     248               2 :     const char* pszExtentXMin = CPLGetXMLValue( psLTree, "ExtentXMin", NULL );
     249               2 :     const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL );
     250               2 :     const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL );
     251               2 :     const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL );
     252               2 :     if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
     253                 :         pszExtentXMax != NULL && pszExtentYMax != NULL )
     254                 :     {
     255                 :         poLayer->SetExtent( CPLAtof(pszExtentXMin),
     256                 :                             CPLAtof(pszExtentYMin),
     257                 :                             CPLAtof(pszExtentXMax),
     258               0 :                             CPLAtof(pszExtentYMax) );
     259                 :     }
     260                 : 
     261               2 :     return poLayer;
     262                 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                        InstanciateUnionLayer()                       */
     266                 : /************************************************************************/
     267                 : 
     268              57 : OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
     269                 :                                         CPLXMLNode *psLTree,
     270                 :                                         const char *pszVRTDirectory,
     271                 :                                         int bUpdate,
     272                 :                                         int nRecLevel)
     273                 : {
     274                 :     CPLXMLNode *psSubNode;
     275                 : 
     276              57 :     if( !EQUAL(psLTree->pszValue,"OGRVRTUnionLayer") )
     277               0 :         return NULL;
     278                 : 
     279                 : /* -------------------------------------------------------------------- */
     280                 : /*      Get layer name.                                                 */
     281                 : /* -------------------------------------------------------------------- */
     282              57 :     const char *pszLayerName = CPLGetXMLValue( psLTree, "name", NULL );
     283                 : 
     284              57 :     if( pszLayerName == NULL )
     285                 :     {
     286                 :         CPLError( CE_Failure, CPLE_AppDefined,
     287               0 :                   "Missing name attribute on OGRVRTUnionLayer" );
     288               0 :         return FALSE;
     289                 :     }
     290                 : 
     291                 : /* -------------------------------------------------------------------- */
     292                 : /*      Do we have a fixed geometry type?  If not derive from the       */
     293                 : /*      source layer.                                                   */
     294                 : /* -------------------------------------------------------------------- */
     295              57 :     const char* pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
     296              57 :     OGRwkbGeometryType eGeomType = wkbUnknown;
     297              57 :     GeometryTypeUnionStrategy eGeometryTypeStrategy = GEOMTYPE_UNION_ALL_LAYERS;
     298              57 :     if( pszGType != NULL )
     299                 :     {
     300                 :         int bError;
     301               9 :         eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
     302               9 :         if( bError )
     303                 :         {
     304                 :             CPLError( CE_Failure, CPLE_AppDefined,
     305                 :                     "GeometryType %s not recognised.",
     306               0 :                     pszGType );
     307               0 :             return NULL;
     308                 :         }
     309                 : 
     310               9 :         eGeometryTypeStrategy = GEOMTYPE_SPECIFIED;
     311                 :     }
     312                 : 
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      Apply a spatial reference system if provided                    */
     315                 : /* -------------------------------------------------------------------- */
     316              57 :      const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
     317              57 :      OGRSpatialReference* poSRS = NULL;
     318              57 :      int bSRSSet = FALSE;
     319              57 :      if( pszLayerSRS != NULL )
     320                 :      {
     321               9 :          bSRSSet = TRUE;
     322               9 :          if( EQUAL(pszLayerSRS,"NULL") )
     323               0 :              poSRS = NULL;
     324                 :          else
     325                 :          {
     326               9 :              OGRSpatialReference oSRS;
     327                 : 
     328               9 :              if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE )
     329                 :              {
     330                 :                  CPLError( CE_Failure, CPLE_AppDefined,
     331               0 :                            "Failed to import LayerSRS `%s'.", pszLayerSRS );
     332               0 :                  return FALSE;
     333                 :              }
     334               9 :              poSRS = oSRS.Clone();
     335                 :          }
     336                 :      }
     337                 : 
     338                 : /* -------------------------------------------------------------------- */
     339                 : /*      Find field declarations.                                        */
     340                 : /* -------------------------------------------------------------------- */
     341              57 :     OGRFieldDefn** papoFields = NULL;
     342              57 :     int nFields = 0;
     343                 : 
     344             318 :     for( psSubNode=psLTree->psChild;
     345                 :          psSubNode != NULL;
     346                 :          psSubNode=psSubNode->psNext )
     347                 :     {
     348             261 :          if( psSubNode->eType != CXT_Element )
     349              57 :              continue;
     350                 : 
     351             204 :          if( psSubNode->eType == CXT_Element && EQUAL(psSubNode->pszValue,"Field") )
     352                 :          {
     353                 : /* -------------------------------------------------------------------- */
     354                 : /*      Field name.                                                     */
     355                 : /* -------------------------------------------------------------------- */
     356               0 :              const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL );
     357               0 :              if( pszName == NULL )
     358                 :              {
     359                 :                  CPLError( CE_Failure, CPLE_AppDefined,
     360               0 :                            "Unable to identify Field name." );
     361               0 :                  break;
     362                 :              }
     363                 : 
     364               0 :              OGRFieldDefn oFieldDefn( pszName, OFTString );
     365                 : 
     366                 : /* -------------------------------------------------------------------- */
     367                 : /*      Type                                                            */
     368                 : /* -------------------------------------------------------------------- */
     369               0 :              const char *pszArg = CPLGetXMLValue( psSubNode, "type", NULL );
     370                 : 
     371               0 :              if( pszArg != NULL )
     372                 :              {
     373                 :                  int iType;
     374                 : 
     375               0 :                  for( iType = 0; iType <= (int) OFTMaxType; iType++ )
     376                 :                  {
     377               0 :                      if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName(
     378                 :                                    (OGRFieldType)iType)) )
     379                 :                      {
     380               0 :                          oFieldDefn.SetType( (OGRFieldType) iType );
     381               0 :                          break;
     382                 :                      }
     383                 :                  }
     384                 : 
     385               0 :                  if( iType > (int) OFTMaxType )
     386                 :                  {
     387                 :                      CPLError( CE_Failure, CPLE_AppDefined,
     388                 :                                "Unable to identify Field type '%s'.",
     389               0 :                                pszArg );
     390                 :                      break;
     391                 :                  }
     392                 :              }
     393                 : 
     394                 : /* -------------------------------------------------------------------- */
     395                 : /*      Width and precision.                                            */
     396                 : /* -------------------------------------------------------------------- */
     397               0 :              int nWidth = atoi(CPLGetXMLValue( psSubNode, "width", "0" ));
     398               0 :              if (nWidth < 0)
     399                 :              {
     400                 :                 CPLError( CE_Failure, CPLE_IllegalArg,
     401                 :                           "Invalid width for field %s.",
     402               0 :                           pszName );
     403                 :                 break;
     404                 :              }
     405               0 :              oFieldDefn.SetWidth(nWidth);
     406                 : 
     407               0 :              int nPrecision = atoi(CPLGetXMLValue( psSubNode, "precision", "0" ));
     408               0 :              if (nPrecision < 0 || nPrecision > 1024)
     409                 :              {
     410                 :                 CPLError( CE_Failure, CPLE_IllegalArg,
     411                 :                           "Invalid precision for field %s.",
     412               0 :                           pszName );
     413                 :                 break;
     414                 :              }
     415               0 :              oFieldDefn.SetPrecision(nPrecision);
     416                 : 
     417                 :              papoFields = (OGRFieldDefn**) CPLRealloc(papoFields,
     418               0 :                                         sizeof(OGRFieldDefn*) * (nFields + 1));
     419               0 :              papoFields[nFields] = new OGRFieldDefn(&oFieldDefn);
     420               0 :              nFields ++;
     421                 :          }
     422                 :     }
     423                 : 
     424                 : /* -------------------------------------------------------------------- */
     425                 : /*      Find source layers                                              */
     426                 : /* -------------------------------------------------------------------- */
     427                 : 
     428              57 :     int nSrcLayers = 0;
     429              57 :     OGRLayer** papoSrcLayers = NULL;
     430                 : 
     431             318 :     for( psSubNode=psLTree->psChild;
     432                 :          psSubNode != NULL;
     433                 :          psSubNode=psSubNode->psNext )
     434                 :     {
     435             261 :         if( psSubNode->eType != CXT_Element )
     436              57 :             continue;
     437                 : 
     438                 :         OGRLayer* poSrcLayer = InstanciateLayer(psSubNode, pszVRTDirectory,
     439             204 :                                            bUpdate, nRecLevel + 1);
     440             204 :         if( poSrcLayer != NULL )
     441                 :         {
     442                 :             papoSrcLayers = (OGRLayer**)
     443             114 :                 CPLRealloc(papoSrcLayers, sizeof(OGRLayer*) * (nSrcLayers + 1));
     444             114 :             papoSrcLayers[nSrcLayers] = poSrcLayer;
     445             114 :             nSrcLayers ++;
     446                 :         }
     447                 :     }
     448                 : 
     449              57 :     if( nSrcLayers == 0 )
     450                 :     {
     451                 :         CPLError( CE_Failure, CPLE_AppDefined,
     452               0 :                   "Cannot find source layers" );
     453               0 :         for(int iField = 0; iField < nFields; iField++)
     454               0 :             delete papoFields[iField];
     455               0 :         CPLFree(papoFields);
     456               0 :         delete poSRS;
     457               0 :         return NULL;
     458                 :     }
     459                 : 
     460                 : /* -------------------------------------------------------------------- */
     461                 : /*      Build the OGRUnionLayer.                                        */
     462                 : /* -------------------------------------------------------------------- */
     463                 :     OGRUnionLayer* poLayer = new OGRUnionLayer( pszLayerName,
     464                 :                                                 nSrcLayers,
     465                 :                                                 papoSrcLayers,
     466              57 :                                                 TRUE );
     467                 : 
     468                 : /* -------------------------------------------------------------------- */
     469                 : /*      Set SRS if provided                                             */
     470                 : /* -------------------------------------------------------------------- */
     471              57 :     if( bSRSSet )
     472               9 :         poLayer->SetSRS(poSRS);
     473                 : 
     474              57 :     delete poSRS;
     475                 : 
     476                 : /* -------------------------------------------------------------------- */
     477                 : /*      Set geometry type                                               */
     478                 : /* -------------------------------------------------------------------- */
     479              57 :     poLayer->SetGeometryType(eGeometryTypeStrategy, eGeomType);
     480                 : 
     481                 : /* -------------------------------------------------------------------- */
     482                 : /*      Set the source layer field name attribute.                      */
     483                 : /* -------------------------------------------------------------------- */
     484                 :     const char* pszSourceLayerFieldName =
     485              57 :         CPLGetXMLValue( psLTree, "SourceLayerFieldName", NULL );
     486              57 :     poLayer->SetSourceLayerFieldName(pszSourceLayerFieldName);
     487                 : 
     488                 : /* -------------------------------------------------------------------- */
     489                 : /*      Set the PreserveSrcFID attribute.                               */
     490                 : /* -------------------------------------------------------------------- */
     491              57 :     int bPreserveSrcFID = FALSE;
     492              57 :     const char* pszPreserveFID = CPLGetXMLValue( psLTree, "PreserveSrcFID", NULL );
     493              57 :     if( pszPreserveFID != NULL )
     494               9 :         bPreserveSrcFID = CSLTestBoolean(pszPreserveFID);
     495              57 :     poLayer->SetPreserveSrcFID(bPreserveSrcFID);
     496                 : 
     497                 : /* -------------------------------------------------------------------- */
     498                 : /*      Set fields                                                      */
     499                 : /* -------------------------------------------------------------------- */
     500              57 :     FieldUnionStrategy eFieldStrategy = FIELD_UNION_ALL_LAYERS;
     501              57 :     const char* pszFieldStrategy = CPLGetXMLValue( psLTree, "FieldStrategy", NULL );
     502              57 :     if( pszFieldStrategy != NULL )
     503                 :     {
     504               9 :         if( EQUAL(pszFieldStrategy, "FirstLayer") )
     505               0 :             eFieldStrategy = FIELD_FROM_FIRST_LAYER;
     506               9 :         else if( EQUAL(pszFieldStrategy, "Union") )
     507               0 :             eFieldStrategy = FIELD_UNION_ALL_LAYERS;
     508               9 :         else if( EQUAL(pszFieldStrategy, "Intersection") )
     509               9 :             eFieldStrategy = FIELD_INTERSECTION_ALL_LAYERS;
     510                 :         else
     511                 :         {
     512                 :             CPLError( CE_Warning, CPLE_AppDefined,
     513               0 :                       "Unhandled value for FieldStrategy `%s'.", pszFieldStrategy );
     514                 :         }
     515                 :     }
     516              57 :     if( nFields != 0 )
     517                 :     {
     518               0 :         if( pszFieldStrategy != NULL )
     519                 :             CPLError( CE_Warning, CPLE_AppDefined,
     520               0 :                       "Ignoring FieldStrategy value, because explicit Field is provided") ;
     521               0 :         eFieldStrategy = FIELD_SPECIFIED;
     522                 :     }
     523                 : 
     524              57 :     poLayer->SetFields(eFieldStrategy, nFields, papoFields);
     525              57 :     for(int iField = 0; iField < nFields; iField++)
     526               0 :         delete papoFields[iField];
     527              57 :     CPLFree(papoFields);
     528                 : 
     529                 : /* -------------------------------------------------------------------- */
     530                 : /*      Set FeatureCount if provided                                    */
     531                 : /* -------------------------------------------------------------------- */
     532              57 :     const char* pszFeatureCount = CPLGetXMLValue( psLTree, "FeatureCount", NULL );
     533              57 :     if( pszFeatureCount != NULL )
     534                 :     {
     535               9 :         poLayer->SetFeatureCount(atoi(pszFeatureCount));
     536                 :     }
     537                 : 
     538                 : /* -------------------------------------------------------------------- */
     539                 : /*      Set Extent if provided                                          */
     540                 : /* -------------------------------------------------------------------- */
     541              57 :     const char* pszExtentXMin = CPLGetXMLValue( psLTree, "ExtentXMin", NULL );
     542              57 :     const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL );
     543              57 :     const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL );
     544              57 :     const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL );
     545              57 :     if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
     546                 :         pszExtentXMax != NULL && pszExtentYMax != NULL )
     547                 :     {
     548                 :         poLayer->SetExtent( CPLAtof(pszExtentXMin),
     549                 :                             CPLAtof(pszExtentYMin),
     550                 :                             CPLAtof(pszExtentXMax),
     551               9 :                             CPLAtof(pszExtentYMax) );
     552                 :     }
     553                 : 
     554              57 :     return poLayer;
     555                 : }
     556                 : 
     557                 : /************************************************************************/
     558                 : /*                     InstanciateLayerInternal()                       */
     559                 : /************************************************************************/
     560                 : 
     561             621 : OGRLayer* OGRVRTDataSource::InstanciateLayerInternal(CPLXMLNode *psLTree,
     562                 :                                                 const char *pszVRTDirectory,
     563                 :                                                 int bUpdate,
     564                 :                                                 int nRecLevel)
     565                 : {
     566                 : /* -------------------------------------------------------------------- */
     567                 : /*      Create the layer object.                                        */
     568                 : /* -------------------------------------------------------------------- */
     569             621 :     if( EQUAL(psLTree->pszValue,"OGRVRTLayer") )
     570                 :     {
     571             472 :         OGRVRTLayer* poVRTLayer = new OGRVRTLayer(this);
     572                 : 
     573             472 :         if( !poVRTLayer->FastInitialize( psLTree, pszVRTDirectory, bUpdate ) )
     574                 :         {
     575               3 :             delete poVRTLayer;
     576               3 :             return NULL;
     577                 :         }
     578                 : 
     579             469 :         return poVRTLayer;
     580                 :     }
     581             149 :     else if( EQUAL(psLTree->pszValue,"OGRVRTWarpedLayer") && nRecLevel < 30 )
     582                 :     {
     583                 :         return InstanciateWarpedLayer( psLTree, pszVRTDirectory,
     584               2 :                                        bUpdate, nRecLevel + 1 );
     585                 :     }
     586             147 :     else if( EQUAL(psLTree->pszValue,"OGRVRTUnionLayer") && nRecLevel < 30 )
     587                 :     {
     588                 :         return InstanciateUnionLayer( psLTree, pszVRTDirectory,
     589              57 :                                       bUpdate, nRecLevel + 1 );
     590                 :     }
     591                 :     else
     592              90 :         return NULL;
     593                 : }
     594                 : 
     595                 : /************************************************************************/
     596                 : /*                        OGRVRTOpenProxiedLayer()                      */
     597                 : /************************************************************************/
     598                 : 
     599                 : typedef struct
     600                 : {
     601                 :     OGRVRTDataSource* poDS;
     602                 :     CPLXMLNode *psNode;
     603                 :     char       *pszVRTDirectory;
     604                 :     int         bUpdate;
     605                 : } PooledInitData;
     606                 : 
     607              47 : static OGRLayer* OGRVRTOpenProxiedLayer(void* pUserData)
     608                 : {
     609              47 :     PooledInitData* pData = (PooledInitData*) pUserData;
     610                 :     return pData->poDS->InstanciateLayerInternal(pData->psNode,
     611                 :                                             pData->pszVRTDirectory,
     612                 :                                             pData->bUpdate,
     613              47 :                                             0);
     614                 : }
     615                 : 
     616                 : /************************************************************************/
     617                 : /*                     OGRVRTFreeProxiedLayerUserData()                 */
     618                 : /************************************************************************/
     619                 : 
     620               2 : static void OGRVRTFreeProxiedLayerUserData(void* pUserData)
     621                 : {
     622               2 :     PooledInitData* pData = (PooledInitData*) pUserData;
     623               2 :     CPLFree(pData->pszVRTDirectory);
     624               2 :     CPLFree(pData);
     625               2 : }
     626                 : 
     627                 : /************************************************************************/
     628                 : /*                          InstanciateLayer()                          */
     629                 : /************************************************************************/
     630                 : 
     631             576 : OGRLayer* OGRVRTDataSource::InstanciateLayer(CPLXMLNode *psLTree,
     632                 :                                         const char *pszVRTDirectory,
     633                 :                                         int bUpdate,
     634                 :                                         int nRecLevel)
     635                 : {
     636             576 :     if( poLayerPool != NULL && EQUAL(psLTree->pszValue,"OGRVRTLayer"))
     637                 :     {
     638               2 :         PooledInitData* pData = (PooledInitData*) CPLMalloc(sizeof(PooledInitData));
     639               2 :         pData->poDS = this;
     640               2 :         pData->psNode = psLTree;
     641               2 :         pData->pszVRTDirectory = CPLStrdup(pszVRTDirectory);
     642               2 :         pData->bUpdate = bUpdate;
     643                 :         return new OGRProxiedLayer(poLayerPool,
     644                 :                                     OGRVRTOpenProxiedLayer,
     645                 :                                     OGRVRTFreeProxiedLayerUserData,
     646               2 :                                     pData);
     647                 :     }
     648                 :     else
     649                 :     {
     650                 :         return InstanciateLayerInternal(psLTree, pszVRTDirectory,
     651             574 :                                     bUpdate, nRecLevel);
     652                 :     }
     653                 : }
     654                 : 
     655                 : /************************************************************************/
     656                 : /*                           CountOGRVRTLayers()                        */
     657                 : /************************************************************************/
     658                 : 
     659            4901 : static int CountOGRVRTLayers(CPLXMLNode *psTree)
     660                 : {
     661            4901 :     if( psTree->eType != CXT_Element )
     662            2696 :         return 0;
     663                 : 
     664            2205 :     int nCount = 0;
     665            2205 :     if( EQUAL(psTree->pszValue, "OGRVRTLayer") )
     666             427 :         nCount ++;
     667                 : 
     668                 :     CPLXMLNode* psNode;
     669            6916 :     for( psNode=psTree->psChild; psNode != NULL; psNode=psNode->psNext )
     670                 :     {
     671            4711 :         nCount += CountOGRVRTLayers(psNode);
     672                 :     }
     673                 : 
     674            2205 :     return nCount;
     675                 : }
     676                 : 
     677                 : /************************************************************************/
     678                 : /*                             Initialize()                             */
     679                 : /************************************************************************/
     680                 : 
     681             190 : int OGRVRTDataSource::Initialize( CPLXMLNode *psTree, const char *pszNewName,
     682                 :                                   int bUpdate )
     683                 : 
     684                 : {
     685             190 :     CPLAssert( nLayers == 0 );
     686                 : 
     687             190 :     this->psTree = psTree;
     688                 : 
     689                 : /* -------------------------------------------------------------------- */
     690                 : /*      Set name, and capture the directory path so we can use it       */
     691                 : /*      for relative datasources.                                       */
     692                 : /* -------------------------------------------------------------------- */
     693             190 :     CPLString osVRTDirectory = CPLGetPath( pszNewName );
     694                 : 
     695             190 :     pszName = CPLStrdup( pszNewName );
     696                 : 
     697                 : /* -------------------------------------------------------------------- */
     698                 : /*      Look for the OGRVRTDataSource node, it might be after an        */
     699                 : /*      <xml> node.                                                     */
     700                 : /* -------------------------------------------------------------------- */
     701             190 :     CPLXMLNode *psVRTDSXML = CPLGetXMLNode( psTree, "=OGRVRTDataSource" );
     702             190 :     if( psVRTDSXML == NULL )
     703                 :     {
     704                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     705                 :                   "Did not find the <OGRVRTDataSource> node in the root of the document,\n"
     706               0 :                   "this is not really an OGR VRT." );
     707               0 :         return FALSE;
     708                 :     }
     709                 : 
     710                 : /* -------------------------------------------------------------------- */
     711                 : /*      Determine if we must proxy layers.                              */
     712                 : /* -------------------------------------------------------------------- */
     713             190 :     int nOGRVRTLayerCount = CountOGRVRTLayers(psVRTDSXML);
     714                 : 
     715             190 :     int nMaxSimultaneouslyOpened = atoi(CPLGetConfigOption("OGR_VRT_MAX_OPENED", "100"));
     716             190 :     if( nMaxSimultaneouslyOpened < 1 )
     717               0 :         nMaxSimultaneouslyOpened = 1;
     718             190 :     if( nOGRVRTLayerCount > nMaxSimultaneouslyOpened )
     719               1 :         poLayerPool = new OGRLayerPool(nMaxSimultaneouslyOpened);
     720                 : 
     721                 : /* -------------------------------------------------------------------- */
     722                 : /*      Look for layers.                                                */
     723                 : /* -------------------------------------------------------------------- */
     724                 :     CPLXMLNode *psLTree;
     725                 : 
     726             561 :     for( psLTree=psVRTDSXML->psChild; psLTree != NULL; psLTree=psLTree->psNext )
     727                 :     {
     728             371 :         if( psLTree->eType != CXT_Element )
     729               1 :             continue;
     730                 : 
     731                 : /* -------------------------------------------------------------------- */
     732                 : /*      Create the layer object.                                        */
     733                 : /* -------------------------------------------------------------------- */
     734             370 :         OGRLayer  *poLayer = InstanciateLayer(psLTree, osVRTDirectory, bUpdate);
     735             370 :         if( poLayer == NULL )
     736               3 :             continue;
     737                 : 
     738                 : /* -------------------------------------------------------------------- */
     739                 : /*      Add layer to data source layer list.                            */
     740                 : /* -------------------------------------------------------------------- */
     741                 :         papoLayers = (OGRLayer **)
     742             367 :             CPLRealloc( papoLayers,  sizeof(OGRLayer *) * (nLayers+1) );
     743             367 :         papoLayers[nLayers++] = poLayer;
     744                 :     }
     745                 : 
     746             190 :     return TRUE;
     747                 : }
     748                 : 
     749                 : /************************************************************************/
     750                 : /*                           TestCapability()                           */
     751                 : /************************************************************************/
     752                 : 
     753               5 : int OGRVRTDataSource::TestCapability( const char * pszCap )
     754                 : 
     755                 : {
     756               5 :     return FALSE;
     757                 : }
     758                 : 
     759                 : /************************************************************************/
     760                 : /*                              GetLayer()                              */
     761                 : /************************************************************************/
     762                 : 
     763             375 : OGRLayer *OGRVRTDataSource::GetLayer( int iLayer )
     764                 : 
     765                 : {
     766             375 :     if( iLayer < 0 || iLayer >= nLayers )
     767              10 :         return NULL;
     768                 :     else
     769             365 :         return papoLayers[iLayer];
     770                 : }
     771                 : 
     772                 : /************************************************************************/
     773                 : /*                         AddForbiddenNames()                          */
     774                 : /************************************************************************/
     775                 : 
     776               4 : void OGRVRTDataSource::AddForbiddenNames(const char* pszOtherDSName)
     777                 : {
     778               4 :     aosOtherDSNameSet.insert(pszOtherDSName);
     779               4 : }
     780                 : 
     781                 : /************************************************************************/
     782                 : /*                         IsInForbiddenNames()                         */
     783                 : /************************************************************************/
     784                 : 
     785              31 : int OGRVRTDataSource::IsInForbiddenNames(const char* pszOtherDSName)
     786                 : {
     787              31 :     return aosOtherDSNameSet.find(pszOtherDSName) != aosOtherDSNameSet.end();
     788                 : }

Generated by: LCOV version 1.7