Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRVRTDataSource class.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2009-2014, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "ogr_vrt.h"
16 :
17 : #include <stdlib.h>
18 : #include <string.h>
19 : #include <algorithm>
20 : #include <set>
21 : #include <string>
22 :
23 : #include "cpl_conv.h"
24 : #include "cpl_error.h"
25 : #include "cpl_minixml.h"
26 : #include "cpl_string.h"
27 : #include "gdal_priv.h"
28 : #include "ogr_core.h"
29 : #include "ogr_feature.h"
30 : #include "ogr_spatialref.h"
31 : #include "ogrlayerpool.h"
32 : #include "ogrunionlayer.h"
33 : #include "ogrwarpedlayer.h"
34 : #include "ogrsf_frmts.h"
35 : #include "ogrvrtgeometrytypes.h"
36 :
37 : /************************************************************************/
38 : /* OGRVRTDataSource() */
39 : /************************************************************************/
40 :
41 404 : OGRVRTDataSource::OGRVRTDataSource(GDALDriver *poDriverIn)
42 : {
43 404 : poDriver = poDriverIn;
44 404 : }
45 :
46 : /************************************************************************/
47 : /* ~OGRVRTDataSource() */
48 : /************************************************************************/
49 :
50 808 : OGRVRTDataSource::~OGRVRTDataSource()
51 :
52 : {
53 404 : OGRVRTDataSource::CloseDependentDatasets();
54 :
55 404 : CPLFree(paeLayerType);
56 :
57 404 : if (psTree != nullptr)
58 404 : CPLDestroyXMLNode(psTree);
59 808 : }
60 :
61 : /************************************************************************/
62 : /* CloseDependentDatasets() */
63 : /************************************************************************/
64 :
65 404 : int OGRVRTDataSource::CloseDependentDatasets()
66 : {
67 404 : const int bHasClosedDependentDatasets = nLayers > 0;
68 1114 : for (int i = 0; i < nLayers; i++)
69 : {
70 710 : delete papoLayers[i];
71 : }
72 404 : CPLFree(papoLayers);
73 404 : nLayers = 0;
74 404 : papoLayers = nullptr;
75 404 : return bHasClosedDependentDatasets;
76 : }
77 :
78 : /************************************************************************/
79 : /* InstantiateWarpedLayer() */
80 : /************************************************************************/
81 :
82 21 : OGRLayer *OGRVRTDataSource::InstantiateWarpedLayer(CPLXMLNode *psLTree,
83 : const char *pszVRTDirectory,
84 : int bUpdate, int nRecLevel)
85 : {
86 21 : if (!EQUAL(psLTree->pszValue, "OGRVRTWarpedLayer"))
87 0 : return nullptr;
88 :
89 21 : OGRLayer *poSrcLayer = nullptr;
90 :
91 21 : for (CPLXMLNode *psSubNode = psLTree->psChild; psSubNode != nullptr;
92 0 : psSubNode = psSubNode->psNext)
93 : {
94 21 : if (psSubNode->eType != CXT_Element)
95 0 : continue;
96 :
97 21 : poSrcLayer = InstantiateLayer(psSubNode, pszVRTDirectory, bUpdate,
98 : nRecLevel + 1);
99 21 : if (poSrcLayer != nullptr)
100 21 : break;
101 : }
102 :
103 21 : if (poSrcLayer == nullptr)
104 : {
105 0 : CPLError(CE_Failure, CPLE_AppDefined,
106 : "Cannot instantiate source layer");
107 0 : return nullptr;
108 : }
109 :
110 21 : const char *pszTargetSRS = CPLGetXMLValue(psLTree, "TargetSRS", nullptr);
111 21 : if (pszTargetSRS == nullptr)
112 : {
113 1 : CPLError(CE_Failure, CPLE_AppDefined,
114 : "Missing TargetSRS element within OGRVRTWarpedLayer");
115 1 : delete poSrcLayer;
116 1 : return nullptr;
117 : }
118 :
119 : const char *pszGeomFieldName =
120 20 : CPLGetXMLValue(psLTree, "WarpedGeomFieldName", nullptr);
121 20 : int iGeomField = 0;
122 20 : if (pszGeomFieldName != nullptr)
123 : {
124 : iGeomField =
125 3 : poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomFieldName);
126 3 : if (iGeomField < 0)
127 : {
128 1 : CPLError(CE_Failure, CPLE_AppDefined,
129 : "Cannot find source geometry field '%s'",
130 : pszGeomFieldName);
131 1 : delete poSrcLayer;
132 1 : return nullptr;
133 : }
134 : }
135 :
136 19 : const OGRSpatialReference *poSrcSRS = nullptr;
137 19 : const char *pszSourceSRS = CPLGetXMLValue(psLTree, "SrcSRS", nullptr);
138 :
139 19 : if (pszSourceSRS == nullptr)
140 : {
141 16 : if (iGeomField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount())
142 : {
143 13 : poSrcSRS = poSrcLayer->GetLayerDefn()
144 13 : ->GetGeomFieldDefn(iGeomField)
145 13 : ->GetSpatialRef();
146 13 : if (poSrcSRS != nullptr)
147 13 : poSrcSRS = poSrcSRS->Clone();
148 : }
149 : }
150 : else
151 : {
152 3 : auto poSrcSRSNonConst = new OGRSpatialReference();
153 3 : poSrcSRSNonConst->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
154 3 : if (poSrcSRSNonConst->SetFromUserInput(
155 : pszSourceSRS,
156 3 : OGRSpatialReference::SET_FROM_USER_INPUT_LIMITATIONS_get()) !=
157 : OGRERR_NONE)
158 : {
159 1 : delete poSrcSRSNonConst;
160 : }
161 : else
162 : {
163 2 : poSrcSRS = poSrcSRSNonConst;
164 : }
165 : }
166 :
167 19 : if (poSrcSRS == nullptr)
168 : {
169 4 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to import source SRS");
170 4 : delete poSrcLayer;
171 4 : return nullptr;
172 : }
173 :
174 15 : OGRSpatialReference *poTargetSRS = new OGRSpatialReference();
175 15 : poTargetSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
176 15 : if (poTargetSRS->SetFromUserInput(
177 : pszTargetSRS,
178 15 : OGRSpatialReference::SET_FROM_USER_INPUT_LIMITATIONS_get()) !=
179 : OGRERR_NONE)
180 : {
181 1 : delete poTargetSRS;
182 1 : poTargetSRS = nullptr;
183 : }
184 :
185 15 : if (poTargetSRS == nullptr)
186 : {
187 1 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to import target SRS");
188 1 : delete poSrcSRS;
189 1 : delete poSrcLayer;
190 1 : return nullptr;
191 : }
192 :
193 14 : if (pszSourceSRS == nullptr && poSrcSRS->IsSame(poTargetSRS))
194 : {
195 1 : delete poSrcSRS;
196 1 : delete poTargetSRS;
197 1 : return poSrcLayer;
198 : }
199 :
200 : OGRCoordinateTransformation *poCT =
201 13 : OGRCreateCoordinateTransformation(poSrcSRS, poTargetSRS);
202 : OGRCoordinateTransformation *poReversedCT =
203 : poCT != nullptr
204 13 : ? OGRCreateCoordinateTransformation(poTargetSRS, poSrcSRS)
205 13 : : nullptr;
206 :
207 13 : delete poSrcSRS;
208 13 : delete poTargetSRS;
209 :
210 13 : if (poCT == nullptr)
211 : {
212 0 : delete poSrcLayer;
213 0 : return nullptr;
214 : }
215 :
216 : // Build the OGRWarpedLayer.
217 : OGRWarpedLayer *poLayer =
218 13 : new OGRWarpedLayer(poSrcLayer, iGeomField, TRUE, poCT, poReversedCT);
219 :
220 : // Set Extent if provided.
221 13 : const char *pszExtentXMin = CPLGetXMLValue(psLTree, "ExtentXMin", nullptr);
222 13 : const char *pszExtentYMin = CPLGetXMLValue(psLTree, "ExtentYMin", nullptr);
223 13 : const char *pszExtentXMax = CPLGetXMLValue(psLTree, "ExtentXMax", nullptr);
224 13 : const char *pszExtentYMax = CPLGetXMLValue(psLTree, "ExtentYMax", nullptr);
225 13 : if (pszExtentXMin != nullptr && pszExtentYMin != nullptr &&
226 1 : pszExtentXMax != nullptr && pszExtentYMax != nullptr)
227 : {
228 1 : poLayer->SetExtent(CPLAtof(pszExtentXMin), CPLAtof(pszExtentYMin),
229 : CPLAtof(pszExtentXMax), CPLAtof(pszExtentYMax));
230 : }
231 :
232 13 : return poLayer;
233 : }
234 :
235 : /************************************************************************/
236 : /* InstantiateUnionLayer() */
237 : /************************************************************************/
238 :
239 84 : OGRLayer *OGRVRTDataSource::InstantiateUnionLayer(CPLXMLNode *psLTree,
240 : const char *pszVRTDirectory,
241 : int bUpdate, int nRecLevel)
242 : {
243 84 : if (!EQUAL(psLTree->pszValue, "OGRVRTUnionLayer"))
244 0 : return nullptr;
245 :
246 : // Get layer name.
247 84 : const char *pszLayerName = CPLGetXMLValue(psLTree, "name", nullptr);
248 :
249 84 : if (pszLayerName == nullptr)
250 : {
251 0 : CPLError(CE_Failure, CPLE_AppDefined,
252 : "Missing name attribute on OGRVRTUnionLayer");
253 0 : return nullptr;
254 : }
255 :
256 : // Do we have a fixed geometry type? If not derive from the
257 : // source layer.
258 84 : const char *pszGType = CPLGetXMLValue(psLTree, "GeometryType", nullptr);
259 84 : bool bGlobalGeomTypeSet = false;
260 84 : OGRwkbGeometryType eGlobalGeomType = wkbUnknown;
261 84 : if (pszGType != nullptr)
262 : {
263 12 : bGlobalGeomTypeSet = true;
264 12 : int bError = FALSE;
265 12 : eGlobalGeomType = OGRVRTGetGeometryType(pszGType, &bError);
266 12 : if (bError)
267 : {
268 0 : CPLError(CE_Failure, CPLE_AppDefined,
269 : "GeometryType %s not recognised.", pszGType);
270 0 : return nullptr;
271 : }
272 : }
273 :
274 : // Apply a spatial reference system if provided.
275 84 : const char *pszLayerSRS = CPLGetXMLValue(psLTree, "LayerSRS", nullptr);
276 84 : OGRSpatialReference *poGlobalSRS = nullptr;
277 84 : bool bGlobalSRSSet = false;
278 84 : if (pszLayerSRS != nullptr)
279 : {
280 9 : bGlobalSRSSet = true;
281 9 : if (!EQUAL(pszLayerSRS, "NULL"))
282 : {
283 9 : OGRSpatialReference oSRS;
284 9 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
285 :
286 9 : if (oSRS.SetFromUserInput(
287 : pszLayerSRS,
288 : OGRSpatialReference::
289 9 : SET_FROM_USER_INPUT_LIMITATIONS_get()) != OGRERR_NONE)
290 : {
291 0 : CPLError(CE_Failure, CPLE_AppDefined,
292 : "Failed to import LayerSRS `%s'.", pszLayerSRS);
293 0 : return nullptr;
294 : }
295 9 : poGlobalSRS = oSRS.Clone();
296 : }
297 : }
298 :
299 : // Find field declarations.
300 84 : OGRFieldDefn **papoFields = nullptr;
301 84 : int nFields = 0;
302 84 : OGRUnionLayerGeomFieldDefn **papoGeomFields = nullptr;
303 84 : int nGeomFields = 0;
304 :
305 441 : for (CPLXMLNode *psSubNode = psLTree->psChild; psSubNode != nullptr;
306 357 : psSubNode = psSubNode->psNext)
307 : {
308 357 : if (psSubNode->eType != CXT_Element)
309 84 : continue;
310 :
311 273 : if (EQUAL(psSubNode->pszValue, "Field"))
312 : {
313 : // Field name.
314 0 : const char *l_pszName = CPLGetXMLValue(psSubNode, "name", nullptr);
315 0 : if (l_pszName == nullptr)
316 : {
317 0 : CPLError(CE_Failure, CPLE_AppDefined,
318 : "Unable to identify Field name.");
319 0 : break;
320 : }
321 :
322 0 : OGRFieldDefn oFieldDefn(l_pszName, OFTString);
323 :
324 : // Type.
325 0 : const char *pszArg = CPLGetXMLValue(psSubNode, "type", nullptr);
326 :
327 0 : if (pszArg != nullptr)
328 : {
329 0 : int iType = 0; // Used after for.
330 :
331 0 : for (; iType <= static_cast<int>(OFTMaxType); iType++)
332 : {
333 0 : if (EQUAL(pszArg, OGRFieldDefn::GetFieldTypeName(
334 : static_cast<OGRFieldType>(iType))))
335 : {
336 0 : oFieldDefn.SetType(static_cast<OGRFieldType>(iType));
337 0 : break;
338 : }
339 : }
340 :
341 0 : if (iType > static_cast<int>(OFTMaxType))
342 : {
343 0 : CPLError(CE_Failure, CPLE_AppDefined,
344 : "Unable to identify Field type '%s'.", pszArg);
345 0 : break;
346 : }
347 : }
348 :
349 : // Width and precision.
350 0 : const int nWidth = atoi(CPLGetXMLValue(psSubNode, "width", "0"));
351 0 : if (nWidth < 0)
352 : {
353 0 : CPLError(CE_Failure, CPLE_IllegalArg,
354 : "Invalid width for field %s.", l_pszName);
355 0 : break;
356 : }
357 0 : oFieldDefn.SetWidth(nWidth);
358 :
359 : const int nPrecision =
360 0 : atoi(CPLGetXMLValue(psSubNode, "precision", "0"));
361 0 : if (nPrecision < 0 || nPrecision > 1024)
362 : {
363 0 : CPLError(CE_Failure, CPLE_IllegalArg,
364 : "Invalid precision for field %s.", l_pszName);
365 0 : break;
366 : }
367 0 : oFieldDefn.SetPrecision(nPrecision);
368 :
369 : papoFields = static_cast<OGRFieldDefn **>(
370 0 : CPLRealloc(papoFields, sizeof(OGRFieldDefn *) * (nFields + 1)));
371 0 : papoFields[nFields] = new OGRFieldDefn(&oFieldDefn);
372 0 : nFields++;
373 : }
374 273 : else if (EQUAL(psSubNode->pszValue, "GeometryField"))
375 : {
376 12 : const char *l_pszName = CPLGetXMLValue(psSubNode, "name", nullptr);
377 12 : if (l_pszName == nullptr)
378 : {
379 0 : CPLError(CE_Failure, CPLE_AppDefined,
380 : "Unable to identify GeometryField name.");
381 0 : break;
382 : }
383 :
384 12 : pszGType = CPLGetXMLValue(psSubNode, "GeometryType", nullptr);
385 12 : if (pszGType == nullptr && nGeomFields == 0)
386 3 : pszGType = CPLGetXMLValue(psLTree, "GeometryType", nullptr);
387 12 : OGRwkbGeometryType eGeomType = wkbUnknown;
388 12 : bool bGeomTypeSet = false;
389 12 : if (pszGType != nullptr)
390 : {
391 3 : int bError = FALSE;
392 3 : eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
393 3 : bGeomTypeSet = true;
394 3 : if (bError || eGeomType == wkbNone)
395 : {
396 0 : CPLError(CE_Failure, CPLE_AppDefined,
397 : "GeometryType %s not recognised.", pszGType);
398 0 : break;
399 : }
400 : }
401 :
402 12 : const char *pszSRS = CPLGetXMLValue(psSubNode, "SRS", nullptr);
403 12 : if (pszSRS == nullptr && nGeomFields == 0)
404 6 : pszSRS = CPLGetXMLValue(psLTree, "LayerSRS", nullptr);
405 12 : OGRSpatialReference *poSRS = nullptr;
406 12 : bool bSRSSet = false;
407 12 : if (pszSRS != nullptr)
408 : {
409 3 : bSRSSet = true;
410 3 : if (!EQUAL(pszSRS, "NULL"))
411 : {
412 3 : OGRSpatialReference oSRS;
413 3 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
414 :
415 3 : if (oSRS.SetFromUserInput(
416 : pszSRS,
417 : OGRSpatialReference::
418 3 : SET_FROM_USER_INPUT_LIMITATIONS_get()) !=
419 : OGRERR_NONE)
420 : {
421 0 : CPLError(CE_Failure, CPLE_AppDefined,
422 : "Failed to import SRS `%s'.", pszSRS);
423 0 : break;
424 : }
425 3 : poSRS = oSRS.Clone();
426 : }
427 : }
428 :
429 : OGRUnionLayerGeomFieldDefn *poFieldDefn =
430 12 : new OGRUnionLayerGeomFieldDefn(l_pszName, eGeomType);
431 12 : if (poSRS != nullptr)
432 : {
433 3 : poFieldDefn->SetSpatialRef(poSRS);
434 3 : poSRS->Dereference();
435 : }
436 12 : poFieldDefn->bGeomTypeSet = bGeomTypeSet;
437 12 : poFieldDefn->bSRSSet = bSRSSet;
438 :
439 : const char *pszExtentXMin =
440 12 : CPLGetXMLValue(psSubNode, "ExtentXMin", nullptr);
441 : const char *pszExtentYMin =
442 12 : CPLGetXMLValue(psSubNode, "ExtentYMin", nullptr);
443 : const char *pszExtentXMax =
444 12 : CPLGetXMLValue(psSubNode, "ExtentXMax", nullptr);
445 : const char *pszExtentYMax =
446 12 : CPLGetXMLValue(psSubNode, "ExtentYMax", nullptr);
447 12 : if (pszExtentXMin != nullptr && pszExtentYMin != nullptr &&
448 3 : pszExtentXMax != nullptr && pszExtentYMax != nullptr)
449 : {
450 3 : poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
451 3 : poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
452 3 : poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
453 3 : poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
454 : }
455 :
456 : papoGeomFields =
457 24 : static_cast<OGRUnionLayerGeomFieldDefn **>(CPLRealloc(
458 : papoGeomFields,
459 12 : sizeof(OGRUnionLayerGeomFieldDefn *) * (nGeomFields + 1)));
460 12 : papoGeomFields[nGeomFields] = poFieldDefn;
461 12 : nGeomFields++;
462 : }
463 : }
464 :
465 : // Set Extent if provided.
466 84 : const char *pszExtentXMin = CPLGetXMLValue(psLTree, "ExtentXMin", nullptr);
467 84 : const char *pszExtentYMin = CPLGetXMLValue(psLTree, "ExtentYMin", nullptr);
468 84 : const char *pszExtentXMax = CPLGetXMLValue(psLTree, "ExtentXMax", nullptr);
469 84 : const char *pszExtentYMax = CPLGetXMLValue(psLTree, "ExtentYMax", nullptr);
470 :
471 84 : if (eGlobalGeomType != wkbNone && nGeomFields == 0 &&
472 66 : (bGlobalGeomTypeSet || bGlobalSRSSet ||
473 0 : (pszExtentXMin != nullptr && pszExtentYMin != nullptr &&
474 0 : pszExtentXMax != nullptr && pszExtentYMax != nullptr)))
475 : {
476 : OGRUnionLayerGeomFieldDefn *poFieldDefn =
477 9 : new OGRUnionLayerGeomFieldDefn("", eGlobalGeomType);
478 9 : if (poGlobalSRS != nullptr)
479 : {
480 9 : poFieldDefn->SetSpatialRef(poGlobalSRS);
481 9 : poGlobalSRS->Dereference();
482 9 : poGlobalSRS = nullptr;
483 : }
484 9 : poFieldDefn->bGeomTypeSet = bGlobalGeomTypeSet;
485 9 : poFieldDefn->bSRSSet = bGlobalSRSSet;
486 9 : if (pszExtentXMin != nullptr && pszExtentYMin != nullptr &&
487 9 : pszExtentXMax != nullptr && pszExtentYMax != nullptr)
488 : {
489 9 : poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
490 9 : poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
491 9 : poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
492 9 : poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
493 : }
494 :
495 : papoGeomFields = static_cast<OGRUnionLayerGeomFieldDefn **>(
496 18 : CPLRealloc(papoGeomFields, sizeof(OGRUnionLayerGeomFieldDefn *) *
497 9 : (nGeomFields + 1)));
498 9 : papoGeomFields[nGeomFields] = poFieldDefn;
499 9 : nGeomFields++;
500 : }
501 : else
502 : {
503 75 : delete poGlobalSRS;
504 75 : poGlobalSRS = nullptr;
505 : }
506 :
507 : // Find source layers.
508 84 : int nSrcLayers = 0;
509 84 : OGRLayer **papoSrcLayers = nullptr;
510 :
511 441 : for (CPLXMLNode *psSubNode = psLTree->psChild; psSubNode != nullptr;
512 357 : psSubNode = psSubNode->psNext)
513 : {
514 357 : if (psSubNode->eType != CXT_Element)
515 84 : continue;
516 :
517 273 : OGRLayer *poSrcLayer = InstantiateLayer(psSubNode, pszVRTDirectory,
518 : bUpdate, nRecLevel + 1);
519 273 : if (poSrcLayer != nullptr)
520 : {
521 322 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
522 161 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
523 161 : papoSrcLayers[nSrcLayers] = poSrcLayer;
524 161 : nSrcLayers++;
525 : }
526 : }
527 :
528 84 : if (nSrcLayers == 0)
529 : {
530 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot find source layers");
531 0 : for (int iField = 0; iField < nFields; iField++)
532 0 : delete papoFields[iField];
533 0 : CPLFree(papoFields);
534 0 : for (int iField = 0; iField < nGeomFields; iField++)
535 0 : delete papoGeomFields[iField];
536 0 : CPLFree(papoGeomFields);
537 0 : return nullptr;
538 : }
539 :
540 : // Build the OGRUnionLayer.
541 : OGRUnionLayer *poLayer =
542 84 : new OGRUnionLayer(pszLayerName, nSrcLayers, papoSrcLayers, TRUE);
543 :
544 : // Set the source layer field name attribute.
545 : const char *pszSourceLayerFieldName =
546 84 : CPLGetXMLValue(psLTree, "SourceLayerFieldName", nullptr);
547 84 : poLayer->SetSourceLayerFieldName(pszSourceLayerFieldName);
548 :
549 : // Set the PreserveSrcFID attribute.
550 84 : bool bPreserveSrcFID = false;
551 : const char *pszPreserveFID =
552 84 : CPLGetXMLValue(psLTree, "PreserveSrcFID", nullptr);
553 84 : if (pszPreserveFID != nullptr)
554 9 : bPreserveSrcFID = CPLTestBool(pszPreserveFID);
555 84 : poLayer->SetPreserveSrcFID(bPreserveSrcFID);
556 :
557 : // Set fields.
558 84 : FieldUnionStrategy eFieldStrategy = FIELD_UNION_ALL_LAYERS;
559 : const char *pszFieldStrategy =
560 84 : CPLGetXMLValue(psLTree, "FieldStrategy", nullptr);
561 84 : if (pszFieldStrategy != nullptr)
562 : {
563 15 : if (EQUAL(pszFieldStrategy, "FirstLayer"))
564 3 : eFieldStrategy = FIELD_FROM_FIRST_LAYER;
565 12 : else if (EQUAL(pszFieldStrategy, "Union"))
566 0 : eFieldStrategy = FIELD_UNION_ALL_LAYERS;
567 12 : else if (EQUAL(pszFieldStrategy, "Intersection"))
568 12 : eFieldStrategy = FIELD_INTERSECTION_ALL_LAYERS;
569 : else
570 : {
571 0 : CPLError(CE_Warning, CPLE_AppDefined,
572 : "Unhandled value for FieldStrategy `%s'.",
573 : pszFieldStrategy);
574 : }
575 : }
576 84 : if (nFields != 0 || nGeomFields > 1)
577 : {
578 6 : if (pszFieldStrategy != nullptr)
579 0 : CPLError(CE_Warning, CPLE_AppDefined,
580 : "Ignoring FieldStrategy value, "
581 : "because explicit Field or GeometryField is provided");
582 6 : eFieldStrategy = FIELD_SPECIFIED;
583 : }
584 :
585 153 : poLayer->SetFields(
586 : eFieldStrategy, nFields, papoFields,
587 69 : (nGeomFields == 0 && eGlobalGeomType == wkbNone) ? -1 : nGeomFields,
588 : papoGeomFields);
589 :
590 84 : for (int iField = 0; iField < nFields; iField++)
591 0 : delete papoFields[iField];
592 84 : CPLFree(papoFields);
593 105 : for (int iField = 0; iField < nGeomFields; iField++)
594 21 : delete papoGeomFields[iField];
595 84 : CPLFree(papoGeomFields);
596 :
597 : // Set FeatureCount if provided.
598 : const char *pszFeatureCount =
599 84 : CPLGetXMLValue(psLTree, "FeatureCount", nullptr);
600 84 : if (pszFeatureCount != nullptr)
601 : {
602 9 : poLayer->SetFeatureCount(atoi(pszFeatureCount));
603 : }
604 :
605 84 : return poLayer;
606 : }
607 :
608 : /************************************************************************/
609 : /* InstantiateLayerInternal() */
610 : /************************************************************************/
611 :
612 : OGRLayer *
613 1129 : OGRVRTDataSource::InstantiateLayerInternal(CPLXMLNode *psLTree,
614 : const char *pszVRTDirectory,
615 : int bUpdate, int nRecLevel)
616 : {
617 : // Create the layer object.
618 1129 : if (EQUAL(psLTree->pszValue, "OGRVRTLayer"))
619 : {
620 906 : OGRVRTLayer *poVRTLayer = new OGRVRTLayer(this);
621 :
622 906 : if (!poVRTLayer->FastInitialize(psLTree, pszVRTDirectory, bUpdate))
623 : {
624 3 : delete poVRTLayer;
625 3 : return nullptr;
626 : }
627 :
628 903 : return poVRTLayer;
629 : }
630 223 : else if (EQUAL(psLTree->pszValue, "OGRVRTWarpedLayer") && nRecLevel < 30)
631 : {
632 21 : return InstantiateWarpedLayer(psLTree, pszVRTDirectory, bUpdate,
633 21 : nRecLevel + 1);
634 : }
635 202 : else if (EQUAL(psLTree->pszValue, "OGRVRTUnionLayer") && nRecLevel < 30)
636 : {
637 84 : return InstantiateUnionLayer(psLTree, pszVRTDirectory, bUpdate,
638 84 : nRecLevel + 1);
639 : }
640 :
641 118 : return nullptr;
642 : }
643 :
644 : /************************************************************************/
645 : /* OGRVRTOpenProxiedLayer() */
646 : /************************************************************************/
647 :
648 : struct PooledInitData
649 : {
650 : OGRVRTDataSource *poDS = nullptr;
651 : CPLXMLNode *psNode = nullptr;
652 : std::string osVRTDirectory{};
653 : bool bUpdate = false;
654 : };
655 :
656 113 : static OGRLayer *OGRVRTOpenProxiedLayer(void *pUserData)
657 : {
658 113 : const PooledInitData *pData =
659 : static_cast<const PooledInitData *>(pUserData);
660 339 : return pData->poDS->InstantiateLayerInternal(
661 113 : pData->psNode, pData->osVRTDirectory.c_str(), pData->bUpdate, 0);
662 : }
663 :
664 : /************************************************************************/
665 : /* OGRVRTFreeProxiedLayerUserData() */
666 : /************************************************************************/
667 :
668 4 : static void OGRVRTFreeProxiedLayerUserData(void *pUserData)
669 : {
670 4 : delete static_cast<PooledInitData *>(pUserData);
671 4 : }
672 :
673 : /************************************************************************/
674 : /* InstantiateLayer() */
675 : /************************************************************************/
676 :
677 1020 : OGRLayer *OGRVRTDataSource::InstantiateLayer(CPLXMLNode *psLTree,
678 : const char *pszVRTDirectory,
679 : int bUpdate, int nRecLevel)
680 : {
681 1020 : if (poLayerPool != nullptr && EQUAL(psLTree->pszValue, "OGRVRTLayer"))
682 : {
683 4 : auto pData = std::make_unique<PooledInitData>();
684 4 : pData->poDS = this;
685 4 : pData->psNode = psLTree;
686 4 : pData->osVRTDirectory = pszVRTDirectory ? pszVRTDirectory : "";
687 4 : pData->bUpdate = CPL_TO_BOOL(bUpdate);
688 4 : return new OGRProxiedLayer(poLayerPool.get(), OGRVRTOpenProxiedLayer,
689 : OGRVRTFreeProxiedLayerUserData,
690 4 : pData.release());
691 : }
692 :
693 1016 : return InstantiateLayerInternal(psLTree, pszVRTDirectory, bUpdate,
694 1016 : nRecLevel);
695 : }
696 :
697 : /************************************************************************/
698 : /* CountOGRVRTLayers() */
699 : /************************************************************************/
700 :
701 9260 : static int CountOGRVRTLayers(const CPLXMLNode *psTree)
702 : {
703 9260 : if (psTree->eType != CXT_Element)
704 5104 : return 0;
705 :
706 4156 : int nCount = 0;
707 4156 : if (EQUAL(psTree->pszValue, "OGRVRTLayer"))
708 797 : ++nCount;
709 :
710 13013 : for (const CPLXMLNode *psNode = psTree->psChild; psNode != nullptr;
711 8857 : psNode = psNode->psNext)
712 : {
713 8857 : nCount += CountOGRVRTLayers(psNode);
714 : }
715 :
716 4156 : return nCount;
717 : }
718 :
719 : /************************************************************************/
720 : /* Initialize() */
721 : /************************************************************************/
722 :
723 404 : bool OGRVRTDataSource::Initialize(CPLXMLNode *psTreeIn, const char *pszNewName,
724 : int bUpdate)
725 :
726 : {
727 404 : CPLAssert(nLayers == 0);
728 :
729 404 : AddForbiddenNames(pszNewName);
730 :
731 404 : psTree = psTreeIn;
732 :
733 : // Set name, and capture the directory path so we can use it
734 : // for relative datasources.
735 808 : CPLString osVRTDirectory = CPLGetPathSafe(pszNewName);
736 :
737 : // Look for the OGRVRTDataSource node, it might be after an <xml> node.
738 404 : CPLXMLNode *psVRTDSXML = CPLGetXMLNode(psTree, "=OGRVRTDataSource");
739 404 : if (psVRTDSXML == nullptr)
740 : {
741 1 : CPLError(CE_Failure, CPLE_AppDefined,
742 : "Did not find the <OGRVRTDataSource> node in the root of the "
743 : "document, this is not really an OGR VRT.");
744 1 : return false;
745 : }
746 :
747 : // Determine if we must proxy layers.
748 403 : const int nOGRVRTLayerCount = CountOGRVRTLayers(psVRTDSXML);
749 :
750 : const int nMaxSimultaneouslyOpened =
751 403 : std::max(atoi(CPLGetConfigOption("OGR_VRT_MAX_OPENED", "100")), 1);
752 403 : if (nOGRVRTLayerCount > nMaxSimultaneouslyOpened)
753 2 : poLayerPool = std::make_unique<OGRLayerPool>(nMaxSimultaneouslyOpened);
754 :
755 : // Apply any dataset level metadata.
756 403 : oMDMD.XMLInit(psVRTDSXML, TRUE);
757 :
758 : // Look for layers.
759 1130 : for (CPLXMLNode *psLTree = psVRTDSXML->psChild; psLTree != nullptr;
760 727 : psLTree = psLTree->psNext)
761 : {
762 727 : if (psLTree->eType != CXT_Element)
763 1 : continue;
764 :
765 : // Create the layer object.
766 726 : OGRLayer *poLayer = InstantiateLayer(psLTree, osVRTDirectory, bUpdate);
767 726 : if (poLayer == nullptr)
768 16 : continue;
769 :
770 : // Add layer to data source layer list.
771 710 : nLayers++;
772 710 : papoLayers = static_cast<OGRLayer **>(
773 710 : CPLRealloc(papoLayers, sizeof(OGRLayer *) * nLayers));
774 710 : papoLayers[nLayers - 1] = poLayer;
775 :
776 710 : paeLayerType = static_cast<OGRLayerType *>(
777 710 : CPLRealloc(paeLayerType, sizeof(int) * nLayers));
778 710 : if (poLayerPool != nullptr && EQUAL(psLTree->pszValue, "OGRVRTLayer"))
779 : {
780 0 : paeLayerType[nLayers - 1] = OGR_VRT_PROXIED_LAYER;
781 : }
782 710 : else if (EQUAL(psLTree->pszValue, "OGRVRTLayer"))
783 : {
784 613 : paeLayerType[nLayers - 1] = OGR_VRT_LAYER;
785 : }
786 : else
787 : {
788 97 : paeLayerType[nLayers - 1] = OGR_VRT_OTHER_LAYER;
789 : }
790 : }
791 :
792 403 : return true;
793 : }
794 :
795 : /************************************************************************/
796 : /* TestCapability() */
797 : /************************************************************************/
798 :
799 139 : int OGRVRTDataSource::TestCapability(const char *pszCap)
800 : {
801 139 : if (EQUAL(pszCap, ODsCCurveGeometries))
802 29 : return true;
803 110 : else if (EQUAL(pszCap, ODsCZGeometries))
804 24 : return true;
805 86 : else if (EQUAL(pszCap, ODsCMeasuredGeometries))
806 24 : return true;
807 :
808 62 : return false;
809 : }
810 :
811 : /************************************************************************/
812 : /* GetLayer() */
813 : /************************************************************************/
814 :
815 898 : OGRLayer *OGRVRTDataSource::GetLayer(int iLayer)
816 :
817 : {
818 898 : if (iLayer < 0 || iLayer >= nLayers)
819 32 : return nullptr;
820 :
821 866 : return papoLayers[iLayer];
822 : }
823 :
824 : /************************************************************************/
825 : /* AddForbiddenNames() */
826 : /************************************************************************/
827 :
828 407 : void OGRVRTDataSource::AddForbiddenNames(const char *pszOtherDSName)
829 : {
830 407 : aosOtherDSNameSet.insert(pszOtherDSName);
831 407 : }
832 :
833 : /************************************************************************/
834 : /* IsInForbiddenNames() */
835 : /************************************************************************/
836 :
837 79 : bool OGRVRTDataSource::IsInForbiddenNames(const char *pszOtherDSName) const
838 : {
839 79 : return aosOtherDSNameSet.find(pszOtherDSName) != aosOtherDSNameSet.end();
840 : }
841 :
842 : /************************************************************************/
843 : /* GetFileList() */
844 : /************************************************************************/
845 :
846 16 : char **OGRVRTDataSource::GetFileList()
847 : {
848 32 : CPLStringList oList;
849 16 : oList.AddString(GetDescription());
850 32 : for (int i = 0; i < nLayers; i++)
851 : {
852 16 : OGRLayer *poLayer = papoLayers[i];
853 16 : OGRVRTLayer *poVRTLayer = nullptr;
854 16 : switch (paeLayerType[nLayers - 1])
855 : {
856 0 : case OGR_VRT_PROXIED_LAYER:
857 0 : poVRTLayer = cpl::down_cast<OGRVRTLayer *>(
858 : cpl::down_cast<OGRProxiedLayer *>(poLayer)
859 : ->GetUnderlyingLayer());
860 0 : break;
861 7 : case OGR_VRT_LAYER:
862 7 : poVRTLayer = cpl::down_cast<OGRVRTLayer *>(poLayer);
863 7 : break;
864 9 : default:
865 9 : break;
866 : }
867 16 : if (poVRTLayer != nullptr)
868 : {
869 7 : GDALDataset *poSrcDS = poVRTLayer->GetSrcDataset();
870 7 : if (poSrcDS != nullptr)
871 : {
872 7 : char **papszFileList = poSrcDS->GetFileList();
873 7 : char **papszIter = papszFileList;
874 35 : for (; papszIter != nullptr && *papszIter != nullptr;
875 : papszIter++)
876 : {
877 28 : if (oList.FindString(*papszIter) < 0)
878 28 : oList.AddString(*papszIter);
879 : }
880 7 : CSLDestroy(papszFileList);
881 : }
882 : }
883 : }
884 32 : return oList.StealList();
885 : }
|