LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/filegdb - FGdbDatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 88 66 75.0 %
Date: 2011-12-18 Functions: 15 11 73.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: FGdbDatasource.cpp 23394 2011-11-19 19:20:12Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements FileGDB OGR Datasource.
       6                 :  * Author:   Ragi Yaser Burhum, ragi@burhum.com
       7                 :  *           Paul Ramsey, pramsey at cleverelephant.ca
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2010, Ragi Yaser Burhum
      11                 :  * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "ogr_fgdb.h"
      33                 : #include "cpl_conv.h"
      34                 : #include "cpl_string.h"
      35                 : #include "gdal.h"
      36                 : #include "FGdbUtils.h"
      37                 : 
      38                 : CPL_CVSID("$Id: FGdbDatasource.cpp 23394 2011-11-19 19:20:12Z rouault $");
      39                 : 
      40                 : using std::vector;
      41                 : using std::wstring;
      42                 : 
      43                 : /************************************************************************/
      44                 : /*                          FGdbDataSource()                           */
      45                 : /************************************************************************/
      46                 : 
      47              10 : FGdbDataSource::FGdbDataSource():
      48                 : OGRDataSource(),
      49              10 : m_pszName(0), m_pGeodatabase(NULL)
      50                 : {
      51              10 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                          ~FGdbDataSource()                          */
      55                 : /************************************************************************/
      56                 : 
      57              10 : FGdbDataSource::~FGdbDataSource()
      58                 : {   
      59              10 :     CPLFree( m_pszName );
      60                 : 
      61              10 :     size_t count = m_layers.size();
      62              89 :     for(size_t i = 0; i < count; ++i )
      63              79 :         delete m_layers[i];
      64                 : 
      65              10 :     if (m_pGeodatabase)
      66                 :     {
      67              10 :         ::CloseGeodatabase(*m_pGeodatabase);
      68              10 :         delete m_pGeodatabase;
      69                 :     }
      70              10 : }
      71                 : 
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                                Open()                                */
      75                 : /************************************************************************/
      76                 : 
      77              10 : int FGdbDataSource::Open(Geodatabase* pGeodatabase, const char * pszNewName, int bUpdate )
      78                 : {
      79              10 :     m_pszName = CPLStrdup( pszNewName );
      80              10 :     m_pGeodatabase = pGeodatabase;
      81                 : 
      82              10 :     std::vector<std::wstring> typesRequested;
      83                 : 
      84                 :   // We're only interested in Tables, Feature Datasets and Feature Classes
      85              10 :   typesRequested.push_back(L"Feature Class");
      86              20 :   typesRequested.push_back(L"Table");
      87              20 :   typesRequested.push_back(L"Feature Dataset");
      88                 :   
      89              20 :     bool rv = LoadLayers(L"\\");
      90                 : 
      91              10 :     return rv;
      92                 : }
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                          OpenFGDBTables()                            */
      96                 : /************************************************************************/
      97                 : 
      98               7 : bool FGdbDataSource::OpenFGDBTables(const std::wstring &type,
      99                 :                                     const std::vector<std::wstring> &layers)
     100                 : {
     101                 :     fgdbError hr;
     102              71 :     for ( unsigned int i = 0; i < layers.size(); i++ )
     103                 :     {
     104              64 :         Table* pTable = new Table;
     105                 :         //CPLDebug("FGDB", "Opening %s", WStringToString(layers[i]).c_str());
     106              64 :         if (FAILED(hr = m_pGeodatabase->OpenTable(layers[i], *pTable)))
     107                 :         {
     108               0 :             delete pTable;
     109               0 :             GDBDebug(hr, "Error opening " + WStringToString(layers[i]) + ". Skipping it");
     110               0 :             continue;
     111                 :         }
     112              64 :         FGdbLayer* pLayer = new FGdbLayer;
     113             128 :         if (!pLayer->Initialize(this, pTable, layers[i], type))
     114                 :         {
     115               0 :             delete pLayer;
     116               0 :             return GDBErr(hr, "Error initializing OGRLayer for " + WStringToString(layers[i]));
     117                 :         }
     118                 : 
     119              64 :         m_layers.push_back(pLayer);
     120                 :     }
     121               7 :     return true;
     122                 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                            LoadLayers()                             */
     126                 : /************************************************************************/
     127                 : 
     128              10 : bool FGdbDataSource::LoadLayers(const std::wstring &root) 
     129                 : {
     130              10 :     std::vector<wstring> tables;
     131              10 :     std::vector<wstring> featureclasses;
     132              10 :     std::vector<wstring> featuredatasets;
     133                 :     fgdbError hr;
     134                 : 
     135                 :     /* Find all the Tables in the root */
     136              10 :     if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Table", tables)) )
     137                 :     {
     138               0 :         return GDBErr(hr, "Error reading Tables in " + WStringToString(root));
     139                 :     }
     140                 :     /* Open the tables we found */
     141              10 :     if ( tables.size() > 0 && ! OpenFGDBTables(L"Table", tables) )
     142               0 :         return false;
     143                 : 
     144                 :     /* Find all the Feature Classes in the root */
     145              10 :     if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Class", featureclasses)) )
     146                 :     {
     147               0 :         return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(root));
     148                 :     }
     149                 :     /* Open the tables we found */
     150              10 :     if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
     151               0 :         return false;
     152                 : 
     153                 :     /* Find all the Feature Datasets in the root */
     154              10 :     if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Dataset", featuredatasets)) )
     155                 :     {
     156               0 :         return GDBErr(hr, "Error reading Feature Datasets in " + WStringToString(root));
     157                 :     }
     158                 :     /* Look for Feature Classes inside the Feature Dataset */
     159              11 :     for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
     160                 :     {
     161               1 :         if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(featuredatasets[i], L"Feature Class", featureclasses)) )
     162                 :         {
     163               0 :             return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(featuredatasets[i]));
     164                 :         }
     165               1 :         if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
     166               0 :             return false;
     167                 :     }
     168              10 :     return true;
     169                 : }
     170                 : 
     171                 : 
     172                 : #if 0
     173                 : /************************************************************************/
     174                 : /*                            LoadLayersOld()                              */
     175                 : /************************************************************************/
     176                 : 
     177                 : /* Old recursive LoadLayers. Removed in favor of simple one that only
     178                 :    looks at FeatureClasses and Tables. */
     179                 : 
     180                 : // Flattens out hierarchichal GDB structure
     181                 : bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
     182                 :                                 const wstring & parent)
     183                 : {
     184                 :     long hr = S_OK;
     185                 : 
     186                 :     // I didn't find an API to give me the type of the dataset based on name - I am *not*
     187                 :     // parsing XML for something like this - in the meantime I can use this hack to see
     188                 :     // if the dataset had any children whatsoever - if so, then I won't attempt to open it
     189                 :     // otherwise, do attempt to do that
     190                 : 
     191                 :     bool childrenFound = false;
     192                 :     bool errorsEncountered = false;
     193                 : 
     194                 :     for (size_t dsTypeIndex = 0; dsTypeIndex < datasetTypes.size(); dsTypeIndex++)
     195                 :     {
     196                 :         std::vector<wstring> childDatasets;
     197                 :         m_pGeodatabase->GetChildDatasets( parent, datasetTypes[dsTypeIndex], childDatasets);
     198                 : 
     199                 :         if (childDatasets.size() > 0)
     200                 :         {
     201                 :             //it is a container of other datasets
     202                 : 
     203                 :             for (size_t childDatasetIndex = 0;
     204                 :                  childDatasetIndex < childDatasets.size();
     205                 :                  childDatasetIndex++)
     206                 :             {
     207                 :                 childrenFound = true;
     208                 : 
     209                 :                 // do something with it
     210                 :                 // For now, we just ignore dataset containers and only open the children
     211                 :                 //std::wcout << datasetTypes[dsTypeIndex] << L" " << childDatasets[childDatasetIndex] << std::endl;
     212                 : 
     213                 :                 if (!LoadLayersOld(datasetTypes, childDatasets[childDatasetIndex]))
     214                 :                     errorsEncountered = true;
     215                 :             }
     216                 :         }
     217                 :     }
     218                 : 
     219                 :     //it is a full fledged dataset itself without children - open it (except the root)
     220                 : 
     221                 :     if ((!childrenFound) && parent != L"\\")
     222                 :     {
     223                 :         //wcout << "Opening " << parent << "...";
     224                 :         Table* pTable = new Table;
     225                 :         if (FAILED(hr = m_pGeodatabase->OpenTable(parent,*pTable)))
     226                 :         {
     227                 :             delete pTable;
     228                 :             return GDBErr(hr, "Error opening " + WStringToString(parent));
     229                 :         }
     230                 : 
     231                 :         FGdbLayer* pLayer = new FGdbLayer;
     232                 : 
     233                 :         //pLayer has ownership of the table pointer as soon Initialize is called
     234                 :         if (!pLayer->Initialize(this, pTable, parent))
     235                 :         {
     236                 :             delete pLayer;
     237                 : 
     238                 :             return GDBErr(hr, "Error initializing OGRLayer for " +
     239                 :                           WStringToString(parent));
     240                 :         }
     241                 : 
     242                 :         m_layers.push_back(pLayer);
     243                 :     }
     244                 : 
     245                 :     return !errorsEncountered;
     246                 : }
     247                 : #endif
     248                 : 
     249                 : 
     250                 : /************************************************************************/
     251                 : /*                            DeleteLayer()                             */
     252                 : /************************************************************************/
     253                 : 
     254               2 : OGRErr FGdbDataSource::DeleteLayer( int iLayer )
     255                 : {
     256               2 :     if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
     257               0 :         return OGRERR_FAILURE;
     258                 : 
     259                 :     // Fetch FGDBAPI Table before deleting OGR layer object
     260                 : 
     261               2 :     Table* pTable = m_layers[iLayer]->GetTable();
     262                 : 
     263               2 :     std::string name = m_layers[iLayer]->GetLayerDefn()->GetName();
     264               4 :     std::wstring strPath = m_layers[iLayer]->GetTablePath();
     265               2 :     std::wstring strType = m_layers[iLayer]->GetType();
     266                 : 
     267                 :     // delete OGR layer
     268               2 :     delete m_layers[iLayer];
     269                 : 
     270               2 :     pTable = NULL; // OGR Layer had ownership of FGDB Table
     271                 : 
     272               2 :     m_layers.erase(m_layers.begin() + iLayer);
     273                 : 
     274                 :     long hr;
     275                 :   
     276               2 :     if (FAILED(hr = m_pGeodatabase->Delete(strPath, strType)))
     277                 :     {
     278                 :         CPLError( CE_Warning, CPLE_AppDefined,
     279               0 :                  "%s was not deleted however it has been closed", name.c_str());
     280               0 :         GDBErr(hr, "Failed deleting dataset");
     281               0 :         return OGRERR_FAILURE;
     282                 :     }
     283                 : 
     284               2 :     return OGRERR_NONE;
     285                 : }
     286                 : 
     287                 : /************************************************************************/
     288                 : /*                           TestCapability()                           */
     289                 : /************************************************************************/
     290                 : 
     291               1 : int FGdbDataSource::TestCapability( const char * pszCap )
     292                 : {
     293               1 :     if( EQUAL(pszCap,ODsCCreateLayer) )
     294               1 :         return TRUE;
     295                 : 
     296               0 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
     297               0 :         return TRUE;
     298                 : 
     299               0 :     return FALSE;
     300                 : }
     301                 : 
     302                 : 
     303                 : /************************************************************************/
     304                 : /*                              GetLayer()                              */
     305                 : /************************************************************************/
     306                 : 
     307             404 : OGRLayer *FGdbDataSource::GetLayer( int iLayer )
     308                 : { 
     309             404 :     int count = static_cast<int>(m_layers.size());
     310                 : 
     311             404 :     if( iLayer < 0 || iLayer >= count )
     312               0 :         return NULL;
     313                 :     else
     314             404 :         return m_layers[iLayer];
     315                 : }
     316                 : 
     317                 : /************************************************************************/
     318                 : /*                              CreateLayer()                           */
     319                 : /*                                                                      */
     320                 : /* See FGdbLayer::Create for creation options                           */
     321                 : /************************************************************************/
     322                 : 
     323                 : OGRLayer *
     324              17 : FGdbDataSource::CreateLayer( const char * pszLayerName,
     325                 :                               OGRSpatialReference *poSRS,
     326                 :                               OGRwkbGeometryType eType,
     327                 :                               char ** papszOptions )
     328                 : {
     329              17 :     FGdbLayer* pLayer = new FGdbLayer;
     330              17 :     if (!pLayer->Create(this, pszLayerName, poSRS, eType, papszOptions))
     331                 :     {
     332               0 :         delete pLayer;
     333               0 :         return NULL;
     334                 :     }
     335                 : 
     336              17 :     m_layers.push_back(pLayer);
     337                 : 
     338              17 :     return pLayer;  
     339            1947 : }

Generated by: LCOV version 1.7