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 : }
|