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