~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
FGdbDataSource::FGdbDataSource():
 
48
OGRDataSource(),
 
49
m_pszName(0), m_pGeodatabase(NULL)
 
50
{
 
51
}
 
52
 
 
53
/************************************************************************/
 
54
/*                          ~FGdbDataSource()                          */
 
55
/************************************************************************/
 
56
 
 
57
FGdbDataSource::~FGdbDataSource()
 
58
{   
 
59
    CPLFree( m_pszName );
 
60
 
 
61
    size_t count = m_layers.size();
 
62
    for(size_t i = 0; i < count; ++i )
 
63
        delete m_layers[i];
 
64
 
 
65
    if (m_pGeodatabase)
 
66
    {
 
67
        ::CloseGeodatabase(*m_pGeodatabase);
 
68
        delete m_pGeodatabase;
 
69
    }
 
70
}
 
71
 
 
72
 
 
73
/************************************************************************/
 
74
/*                                Open()                                */
 
75
/************************************************************************/
 
76
 
 
77
int FGdbDataSource::Open(Geodatabase* pGeodatabase, const char * pszNewName, int bUpdate )
 
78
{
 
79
    m_pszName = CPLStrdup( pszNewName );
 
80
    m_pGeodatabase = pGeodatabase;
 
81
 
 
82
    std::vector<std::wstring> typesRequested;
 
83
 
 
84
        // We're only interested in Tables, Feature Datasets and Feature Classes
 
85
        typesRequested.push_back(L"Feature Class");
 
86
        typesRequested.push_back(L"Table");
 
87
        typesRequested.push_back(L"Feature Dataset");
 
88
        
 
89
    bool rv = LoadLayers(L"\\");
 
90
 
 
91
    return rv;
 
92
}
 
93
 
 
94
/************************************************************************/
 
95
/*                          OpenFGDBTables()                            */
 
96
/************************************************************************/
 
97
 
 
98
bool FGdbDataSource::OpenFGDBTables(const std::wstring &type,
 
99
                                    const std::vector<std::wstring> &layers)
 
100
{
 
101
    fgdbError hr;
 
102
    for ( unsigned int i = 0; i < layers.size(); i++ )
 
103
    {
 
104
        Table* pTable = new Table;
 
105
        //CPLDebug("FGDB", "Opening %s", WStringToString(layers[i]).c_str());
 
106
        if (FAILED(hr = m_pGeodatabase->OpenTable(layers[i], *pTable)))
 
107
        {
 
108
            delete pTable;
 
109
            GDBDebug(hr, "Error opening " + WStringToString(layers[i]) + ". Skipping it");
 
110
            continue;
 
111
        }
 
112
        FGdbLayer* pLayer = new FGdbLayer;
 
113
        if (!pLayer->Initialize(this, pTable, layers[i], type))
 
114
        {
 
115
            delete pLayer;
 
116
            return GDBErr(hr, "Error initializing OGRLayer for " + WStringToString(layers[i]));
 
117
        }
 
118
 
 
119
        m_layers.push_back(pLayer);
 
120
    }
 
121
    return true;
 
122
}
 
123
 
 
124
/************************************************************************/
 
125
/*                            LoadLayers()                             */
 
126
/************************************************************************/
 
127
 
 
128
bool FGdbDataSource::LoadLayers(const std::wstring &root) 
 
129
{
 
130
    std::vector<wstring> tables;
 
131
    std::vector<wstring> featureclasses;
 
132
    std::vector<wstring> featuredatasets;
 
133
    fgdbError hr;
 
134
 
 
135
    /* Find all the Tables in the root */
 
136
    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Table", tables)) )
 
137
    {
 
138
        return GDBErr(hr, "Error reading Tables in " + WStringToString(root));
 
139
    }
 
140
    /* Open the tables we found */
 
141
    if ( tables.size() > 0 && ! OpenFGDBTables(L"Table", tables) )
 
142
        return false;
 
143
 
 
144
    /* Find all the Feature Classes in the root */
 
145
    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Class", featureclasses)) )
 
146
    {
 
147
        return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(root));
 
148
    }
 
149
    /* Open the tables we found */
 
150
    if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
 
151
        return false;
 
152
 
 
153
    /* Find all the Feature Datasets in the root */
 
154
    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Dataset", featuredatasets)) )
 
155
    {
 
156
        return GDBErr(hr, "Error reading Feature Datasets in " + WStringToString(root));
 
157
    }
 
158
    /* Look for Feature Classes inside the Feature Dataset */
 
159
    for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
 
160
    {
 
161
        if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(featuredatasets[i], L"Feature Class", featureclasses)) )
 
162
        {
 
163
            return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(featuredatasets[i]));
 
164
        }
 
165
        if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
 
166
            return false;
 
167
    }
 
168
    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
OGRErr FGdbDataSource::DeleteLayer( int iLayer )
 
255
{
 
256
    if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
 
257
        return OGRERR_FAILURE;
 
258
 
 
259
    // Fetch FGDBAPI Table before deleting OGR layer object
 
260
 
 
261
    Table* pTable = m_layers[iLayer]->GetTable();
 
262
 
 
263
    std::string name = m_layers[iLayer]->GetLayerDefn()->GetName();
 
264
    std::wstring strPath = m_layers[iLayer]->GetTablePath();
 
265
    std::wstring strType = m_layers[iLayer]->GetType();
 
266
 
 
267
    // delete OGR layer
 
268
    delete m_layers[iLayer];
 
269
 
 
270
    pTable = NULL; // OGR Layer had ownership of FGDB Table
 
271
 
 
272
    m_layers.erase(m_layers.begin() + iLayer);
 
273
 
 
274
    long hr;
 
275
  
 
276
    if (FAILED(hr = m_pGeodatabase->Delete(strPath, strType)))
 
277
    {
 
278
        CPLError( CE_Warning, CPLE_AppDefined,
 
279
                 "%s was not deleted however it has been closed", name.c_str());
 
280
        GDBErr(hr, "Failed deleting dataset");
 
281
        return OGRERR_FAILURE;
 
282
    }
 
283
 
 
284
    return OGRERR_NONE;
 
285
}
 
286
 
 
287
/************************************************************************/
 
288
/*                           TestCapability()                           */
 
289
/************************************************************************/
 
290
 
 
291
int FGdbDataSource::TestCapability( const char * pszCap )
 
292
{
 
293
    if( EQUAL(pszCap,ODsCCreateLayer) )
 
294
        return TRUE;
 
295
 
 
296
    else if( EQUAL(pszCap,ODsCDeleteLayer) )
 
297
        return TRUE;
 
298
 
 
299
    return FALSE;
 
300
}
 
301
 
 
302
 
 
303
/************************************************************************/
 
304
/*                              GetLayer()                              */
 
305
/************************************************************************/
 
306
 
 
307
OGRLayer *FGdbDataSource::GetLayer( int iLayer )
 
308
 
309
    int count = static_cast<int>(m_layers.size());
 
310
 
 
311
    if( iLayer < 0 || iLayer >= count )
 
312
        return NULL;
 
313
    else
 
314
        return m_layers[iLayer];
 
315
}
 
316
 
 
317
/************************************************************************/
 
318
/*                              CreateLayer()                           */
 
319
/*                                                                      */
 
320
/* See FGdbLayer::Create for creation options                           */
 
321
/************************************************************************/
 
322
 
 
323
OGRLayer *
 
324
FGdbDataSource::CreateLayer( const char * pszLayerName,
 
325
                              OGRSpatialReference *poSRS,
 
326
                              OGRwkbGeometryType eType,
 
327
                              char ** papszOptions )
 
328
{
 
329
    FGdbLayer* pLayer = new FGdbLayer;
 
330
    if (!pLayer->Create(this, pszLayerName, poSRS, eType, papszOptions))
 
331
    {
 
332
        delete pLayer;
 
333
        return NULL;
 
334
    }
 
335
 
 
336
    m_layers.push_back(pLayer);
 
337
 
 
338
    return pLayer;  
 
339
}