1 : /******************************************************************************
2 : * $Id: ogrmdbdatasource.cpp 21562 2011-01-23 12:29:25Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRMDBDataSource class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
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_mdb.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include <vector>
34 : #include "ogrgeomediageometry.h"
35 :
36 : CPL_CVSID("$Id: ogrmdbdatasource.cpp 21562 2011-01-23 12:29:25Z rouault $");
37 :
38 : /************************************************************************/
39 : /* OGRMDBDataSource() */
40 : /************************************************************************/
41 :
42 6 : OGRMDBDataSource::OGRMDBDataSource()
43 :
44 : {
45 6 : pszName = NULL;
46 6 : papoLayers = NULL;
47 6 : papoLayersInvisible = NULL;
48 6 : nLayers = 0;
49 6 : nLayersWithInvisible = 0;
50 6 : poDB = NULL;
51 6 : }
52 :
53 : /************************************************************************/
54 : /* ~OGRMDBDataSource() */
55 : /************************************************************************/
56 :
57 6 : OGRMDBDataSource::~OGRMDBDataSource()
58 :
59 : {
60 : int i;
61 :
62 6 : CPLFree( pszName );
63 :
64 24 : for( i = 0; i < nLayers; i++ )
65 18 : delete papoLayers[i];
66 6 : CPLFree( papoLayers );
67 :
68 6 : for( i = 0; i < nLayersWithInvisible; i++ )
69 0 : delete papoLayersInvisible[i];
70 6 : CPLFree( papoLayersInvisible );
71 :
72 :
73 6 : delete poDB;
74 6 : }
75 :
76 :
77 : /************************************************************************/
78 : /* OpenGDB() */
79 : /************************************************************************/
80 :
81 6 : int OGRMDBDataSource::OpenGDB(OGRMDBTable* poGDB_GeomColumns)
82 : {
83 6 : int iTableName = poGDB_GeomColumns->GetColumnIndex("TableName", TRUE);
84 6 : int iFieldName = poGDB_GeomColumns->GetColumnIndex("FieldName", TRUE);
85 6 : int iShapeType = poGDB_GeomColumns->GetColumnIndex("ShapeType", TRUE);
86 6 : int iExtentLeft = poGDB_GeomColumns->GetColumnIndex("ExtentLeft", TRUE);
87 6 : int iExtentRight = poGDB_GeomColumns->GetColumnIndex("ExtentRight", TRUE);
88 6 : int iExtentBottom = poGDB_GeomColumns->GetColumnIndex("ExtentBottom", TRUE);
89 6 : int iExtentTop = poGDB_GeomColumns->GetColumnIndex("ExtentTop", TRUE);
90 6 : int iSRID = poGDB_GeomColumns->GetColumnIndex("SRID", TRUE);
91 6 : int iHasZ = poGDB_GeomColumns->GetColumnIndex("HasZ", TRUE);
92 :
93 6 : if (iTableName < 0 || iFieldName < 0 || iShapeType < 0 ||
94 : iExtentLeft < 0 || iExtentRight < 0 || iExtentBottom < 0 ||
95 : iExtentTop < 0 || iSRID < 0 || iHasZ < 0)
96 0 : return FALSE;
97 :
98 30 : while(poGDB_GeomColumns->GetNextRow())
99 : {
100 : OGRMDBLayer *poLayer;
101 :
102 18 : char* pszTableName = poGDB_GeomColumns->GetColumnAsString(iTableName);
103 18 : char* pszFieldName = poGDB_GeomColumns->GetColumnAsString(iFieldName);
104 18 : if (pszTableName == NULL || pszFieldName == NULL)
105 : {
106 0 : CPLFree(pszTableName);
107 0 : CPLFree(pszFieldName);
108 0 : continue;
109 : }
110 :
111 18 : OGRMDBTable* poTable = poDB->GetTable(pszTableName);
112 18 : if (poTable == NULL)
113 : {
114 0 : CPLFree(pszTableName);
115 0 : CPLFree(pszFieldName);
116 0 : continue;
117 : }
118 :
119 18 : poLayer = new OGRMDBLayer( this, poTable );
120 :
121 18 : if( poLayer->Initialize( pszTableName,
122 : pszFieldName,
123 : poGDB_GeomColumns->GetColumnAsInt(iShapeType),
124 : poGDB_GeomColumns->GetColumnAsDouble(iExtentLeft),
125 : poGDB_GeomColumns->GetColumnAsDouble(iExtentRight),
126 : poGDB_GeomColumns->GetColumnAsDouble(iExtentBottom),
127 : poGDB_GeomColumns->GetColumnAsDouble(iExtentTop),
128 : poGDB_GeomColumns->GetColumnAsInt(iSRID),
129 : poGDB_GeomColumns->GetColumnAsInt(iHasZ) )
130 : != CE_None )
131 : {
132 0 : delete poLayer;
133 : }
134 : else
135 : {
136 18 : papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
137 18 : papoLayers[nLayers++] = poLayer;
138 : }
139 :
140 18 : CPLFree(pszTableName);
141 18 : CPLFree(pszFieldName);
142 : }
143 :
144 6 : return TRUE;
145 : }
146 :
147 : /************************************************************************/
148 : /* OpenGeomediaWarehouse() */
149 : /************************************************************************/
150 :
151 0 : int OGRMDBDataSource::OpenGeomediaWarehouse(OGRMDBTable* poGAliasTable)
152 : {
153 0 : int iTableName = poGAliasTable->GetColumnIndex("TableName", TRUE);
154 0 : int iTableType = poGAliasTable->GetColumnIndex("TableType", TRUE);
155 :
156 0 : if (iTableName < 0 || iTableType < 0)
157 0 : return FALSE;
158 :
159 0 : char* pszFeatureTableName = NULL;
160 0 : char* pszGeometryProperties = NULL;
161 0 : char* pszGCoordSystemTable = NULL;
162 0 : while(poGAliasTable->GetNextRow())
163 : {
164 0 : char* pszTableType = poGAliasTable->GetColumnAsString(iTableType);
165 0 : if (pszTableType == NULL)
166 0 : continue;
167 :
168 0 : if (strcmp(pszTableType, "INGRFeatures") == 0)
169 : {
170 0 : pszFeatureTableName = poGAliasTable->GetColumnAsString(iTableName);
171 : }
172 0 : else if (strcmp(pszTableType, "INGRGeometryProperties") == 0)
173 : {
174 0 : pszGeometryProperties = poGAliasTable->GetColumnAsString(iTableName);
175 : }
176 0 : else if (strcmp(pszTableType, "GCoordSystemTable") == 0)
177 : {
178 0 : pszGCoordSystemTable = poGAliasTable->GetColumnAsString(iTableName);
179 : }
180 :
181 0 : CPLFree(pszTableType);
182 : }
183 :
184 0 : if (pszFeatureTableName == NULL)
185 : {
186 0 : CPLFree(pszGeometryProperties);
187 0 : CPLFree(pszGCoordSystemTable);
188 0 : return FALSE;
189 : }
190 :
191 0 : OGRMDBTable* poGFeaturesTable = poDB->GetTable(pszFeatureTableName);
192 0 : CPLFree(pszFeatureTableName);
193 0 : pszFeatureTableName = NULL;
194 :
195 : OGRMDBTable* poGeometryPropertiesTable;
196 0 : if (pszGeometryProperties)
197 0 : poGeometryPropertiesTable = poDB->GetTable(pszGeometryProperties);
198 : else
199 0 : poGeometryPropertiesTable = NULL;
200 0 : CPLFree(pszGeometryProperties);
201 0 : pszGeometryProperties = NULL;
202 :
203 0 : if (poGFeaturesTable == NULL)
204 : {
205 0 : delete poGeometryPropertiesTable;
206 0 : CPLFree(pszGCoordSystemTable);
207 0 : return FALSE;
208 : }
209 :
210 0 : int iFeatureName = poGFeaturesTable->GetColumnIndex("FeatureName", TRUE);
211 0 : int iGeometryType = poGFeaturesTable->GetColumnIndex("GeometryType", TRUE);
212 0 : int iPrimaryGeometryFieldName = poGFeaturesTable->GetColumnIndex("PrimaryGeometryFieldName", TRUE);
213 :
214 0 : if (iFeatureName < 0 || iGeometryType < 0 || iPrimaryGeometryFieldName < 0)
215 : {
216 0 : delete poGeometryPropertiesTable;
217 0 : delete poGFeaturesTable;
218 0 : CPLFree(pszGCoordSystemTable);
219 0 : return FALSE;
220 : }
221 :
222 0 : if (poGeometryPropertiesTable != NULL && poGeometryPropertiesTable->GetRowCount() != poGFeaturesTable->GetRowCount())
223 : {
224 0 : delete poGeometryPropertiesTable;
225 0 : poGeometryPropertiesTable = NULL;
226 : }
227 :
228 0 : int iGCoordSystemGUID = -1;
229 0 : if (poGeometryPropertiesTable)
230 : {
231 0 : iGCoordSystemGUID = poGeometryPropertiesTable->GetColumnIndex("GCoordSystemGUID", TRUE);
232 0 : if (iGCoordSystemGUID < 0)
233 : {
234 0 : delete poGeometryPropertiesTable;
235 0 : delete poGFeaturesTable;
236 0 : CPLFree(pszGCoordSystemTable);
237 0 : return FALSE;
238 : }
239 : }
240 :
241 0 : while(poGFeaturesTable->GetNextRow() &&
242 : (poGeometryPropertiesTable == NULL || poGeometryPropertiesTable->GetNextRow()))
243 : {
244 0 : char* pszFeatureName = poGFeaturesTable->GetColumnAsString(iFeatureName);
245 : //int nGeometryType = poGFeaturesTable->GetColumnAsInt(iGeometryType);
246 0 : char* pszGeometryFieldName = poGFeaturesTable->GetColumnAsString(iPrimaryGeometryFieldName);
247 : char* pszGCoordSystemGUID;
248 0 : if (poGeometryPropertiesTable)
249 0 : pszGCoordSystemGUID = poGeometryPropertiesTable->GetColumnAsString(iGCoordSystemGUID);
250 : else
251 0 : pszGCoordSystemGUID = NULL;
252 0 : if (pszFeatureName && pszGeometryFieldName)
253 : {
254 0 : OGRMDBTable* poTable = poDB->GetTable(pszFeatureName);
255 0 : if (poTable)
256 : {
257 0 : OGRMDBLayer* poLayer = new OGRMDBLayer( this, poTable );
258 :
259 0 : if( poLayer->Initialize( pszFeatureName,
260 : pszGeometryFieldName,
261 : GetGeomediaSRS(pszGCoordSystemTable, pszGCoordSystemGUID) )
262 : != CE_None )
263 : {
264 0 : delete poLayer;
265 : }
266 : else
267 : {
268 0 : papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
269 0 : papoLayers[nLayers++] = poLayer;
270 : }
271 : }
272 : }
273 0 : CPLFree(pszFeatureName);
274 0 : CPLFree(pszGeometryFieldName);
275 0 : CPLFree(pszGCoordSystemGUID);
276 : }
277 :
278 0 : delete poGeometryPropertiesTable;
279 0 : delete poGFeaturesTable;
280 0 : CPLFree(pszGCoordSystemTable);
281 :
282 0 : return TRUE;
283 : }
284 :
285 : /************************************************************************/
286 : /* Open() */
287 : /************************************************************************/
288 :
289 6 : int OGRMDBDataSource::Open( const char * pszNewName, int bUpdate,
290 : int bTestOpen )
291 :
292 : {
293 6 : CPLAssert( nLayers == 0 );
294 :
295 6 : pszName = CPLStrdup( pszNewName );
296 :
297 6 : if (!env.Init())
298 0 : return FALSE;
299 :
300 6 : poDB = OGRMDBDatabase::Open(&env, pszNewName);
301 6 : if (!poDB)
302 0 : return FALSE;
303 :
304 6 : poDB->FetchTableNames();
305 :
306 : /* Is it a ESRI Personal Geodatabase ? */
307 6 : OGRMDBTable* poGDB_GeomColumns = poDB->GetTable("GDB_GeomColumns");
308 6 : if (poGDB_GeomColumns && !CSLTestBoolean(CPLGetConfigOption("MDB_RAW", "OFF")))
309 : {
310 6 : int nRet = OpenGDB(poGDB_GeomColumns);
311 6 : delete poGDB_GeomColumns;
312 6 : return nRet;
313 : }
314 0 : delete poGDB_GeomColumns;
315 :
316 : /* Is it a Geomedia warehouse ? */
317 0 : OGRMDBTable* poGAliasTable = poDB->GetTable("GAliasTable");
318 0 : if (poGAliasTable && !CSLTestBoolean(CPLGetConfigOption("MDB_RAW", "OFF")))
319 : {
320 0 : int nRet = OpenGeomediaWarehouse(poGAliasTable);
321 0 : delete poGAliasTable;
322 0 : return nRet;
323 : }
324 0 : delete poGAliasTable;
325 :
326 : /* Well, no, just a regular MDB */
327 0 : int nTables = (int) poDB->apoTableNames.size();
328 0 : for(int i=0;i<nTables;i++)
329 : {
330 0 : OGRMDBTable* poTable = poDB->GetTable(poDB->apoTableNames[i]);
331 0 : if (poTable == NULL)
332 0 : continue;
333 :
334 0 : OGRMDBLayer* poLayer = new OGRMDBLayer( this, poTable );
335 0 : if( poLayer->BuildFeatureDefn() != CE_None )
336 : {
337 0 : delete poLayer;
338 0 : continue;
339 : }
340 :
341 0 : papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
342 0 : papoLayers[nLayers++] = poLayer;
343 : }
344 :
345 0 : return TRUE;
346 : }
347 :
348 : /************************************************************************/
349 : /* TestCapability() */
350 : /************************************************************************/
351 :
352 2 : int OGRMDBDataSource::TestCapability( const char * pszCap )
353 :
354 : {
355 2 : return FALSE;
356 : }
357 :
358 : /************************************************************************/
359 : /* GetLayer() */
360 : /************************************************************************/
361 :
362 71 : OGRLayer *OGRMDBDataSource::GetLayer( int iLayer )
363 :
364 : {
365 71 : if( iLayer < 0 || iLayer >= nLayers )
366 4 : return NULL;
367 : else
368 67 : return papoLayers[iLayer];
369 : }
370 :
371 : /************************************************************************/
372 : /* GetLayer() */
373 : /************************************************************************/
374 :
375 26 : OGRLayer *OGRMDBDataSource::GetLayerByName( const char* pszName )
376 :
377 : {
378 26 : if (pszName == NULL)
379 0 : return NULL;
380 26 : OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszName);
381 26 : if (poLayer)
382 24 : return poLayer;
383 :
384 2 : for( int i = 0; i < nLayersWithInvisible; i++ )
385 : {
386 0 : poLayer = papoLayersInvisible[i];
387 :
388 0 : if( strcmp( pszName, poLayer->GetName() ) == 0 )
389 0 : return poLayer;
390 : }
391 :
392 2 : OGRMDBTable* poTable = poDB->GetTable(pszName);
393 2 : if (poTable == NULL)
394 2 : return NULL;
395 :
396 0 : OGRMDBLayer* poMDBLayer = new OGRMDBLayer( this, poTable );
397 0 : if( poMDBLayer->BuildFeatureDefn() != CE_None )
398 : {
399 0 : delete poMDBLayer;
400 0 : return NULL;
401 : }
402 :
403 : papoLayersInvisible = (OGRMDBLayer**)CPLRealloc(papoLayersInvisible,
404 0 : (nLayersWithInvisible+1) * sizeof(OGRMDBLayer*));
405 0 : papoLayersInvisible[nLayersWithInvisible++] = poMDBLayer;
406 :
407 0 : return poMDBLayer;
408 : }
409 :
410 : /************************************************************************/
411 : /* GetGeomediaSRS() */
412 : /************************************************************************/
413 :
414 0 : OGRSpatialReference* OGRMDBDataSource::GetGeomediaSRS(const char* pszGCoordSystemTable,
415 : const char* pszGCoordSystemGUID)
416 : {
417 0 : if (pszGCoordSystemTable == NULL || pszGCoordSystemGUID == NULL)
418 0 : return NULL;
419 :
420 0 : OGRLayer* poGCoordSystemTable = GetLayerByName(pszGCoordSystemTable);
421 0 : if (poGCoordSystemTable == NULL)
422 0 : return NULL;
423 :
424 0 : poGCoordSystemTable->ResetReading();
425 :
426 : OGRFeature* poFeature;
427 0 : while((poFeature = poGCoordSystemTable->GetNextFeature()) != NULL)
428 : {
429 0 : const char* pszCSGUID = poFeature->GetFieldAsString("CSGUID");
430 0 : if (pszCSGUID && strcmp(pszCSGUID, pszGCoordSystemGUID) == 0)
431 : {
432 0 : OGRSpatialReference* poSRS = OGRGetGeomediaSRS(poFeature);
433 0 : delete poFeature;
434 0 : return poSRS;
435 : }
436 :
437 0 : delete poFeature;
438 : }
439 :
440 0 : return NULL;
441 : }
|