otbOGRDataSourceWrapper.cxx 23.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Luc Hermitte's avatar
Luc Hermitte committed
20 21 22 23 24


#include "otbOGRDataSourceWrapper.h"
// standard includes
#include <cassert>
25
#include <numeric>
26 27
#include <algorithm>
#include <clocale> // toupper
Luc Hermitte's avatar
Luc Hermitte committed
28
#include <boost/bind.hpp>
29
#include <boost/foreach.hpp>
30 31
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
Luc Hermitte's avatar
Luc Hermitte committed
32 33 34
// ITK includes
#include "itkMacro.h" // itkExceptionMacro
#include "itkExceptionObject.h"
35
#include "itksys/SystemTools.hxx"
Luc Hermitte's avatar
Luc Hermitte committed
36 37
// OTB includes
#include "otbOGRDriversInit.h"
38
#include "otbSystem.h"
Luc Hermitte's avatar
Luc Hermitte committed
39 40 41 42 43
// OGR includes

/*===========================================================================*/
/*=======================[ construction/destruction ]========================*/
/*===========================================================================*/
44

Luc Hermitte's avatar
Luc Hermitte committed
45 46
bool otb::ogr::DataSource::Clear()
{
47
  Reset(nullptr);
Luc Hermitte's avatar
Luc Hermitte committed
48 49 50
  return true;
}

51
void otb::ogr::DataSource::Reset(GDALDataset * source)
Luc Hermitte's avatar
Luc Hermitte committed
52 53 54
{
  if (m_DataSource) {
    // OGR makes a pointless check for non-nullity in
55
    // GDALDataset::DestroyDataSource (pointless because "delete 0" is
Luc Hermitte's avatar
Luc Hermitte committed
56
    // perfectly valid -> it's a no-op)
57
    ogr::version_proxy::Close(m_DataSource); // void, noexcept
Luc Hermitte's avatar
Luc Hermitte committed
58 59 60 61
  }
  m_DataSource = source;
}

62
namespace  { // Anonymous namespace
Luc Hermitte's avatar
Luc Hermitte committed
63 64 65 66
/**\ingroup GeometryInternals
 * \brief Type for associating filename extension with OGR driver names.
 * \since OTB v 3.14.0
 */
67 68 69 70 71 72 73 74 75
struct ExtensionDriverAssociation
  {
  char const* extension;
  char const* driverName;
  bool Matches(std::string const& ext) const
    {
    return ext == extension;
    }
  };
Luc Hermitte's avatar
Luc Hermitte committed
76 77 78 79
/**\ingroup GeometryInternals
 * \brief Associative table of filename extension -> OGR driver names.
 * \since OTB v 3.14.0
 */
80 81
const ExtensionDriverAssociation k_ExtensionDriverMap[] =
  {
82 83 84
    {".SHP", "ESRI Shapefile"},
    {".TAB", "MapInfo File"},
    {".GML", "GML"},
85
    {".GMT", "OGR_GMT"},
86 87 88
    {".GPX", "GPX"},
    {".SQLITE", "SQLite"},
    {".KML", "KML"},
89
    {".CSV", "CSV"},
90
    {".GPKG", "GPKG"}
91
  };
Luc Hermitte's avatar
Luc Hermitte committed
92 93 94 95 96 97 98 99
/**\ingroup GeometryInternals
 * \brief Returns the OGR driver name associated to a filename.
 * \since OTB v 3.14.0
 * \note Relies on the driver name associated to the filename extension in \c
 * k_ExtensionDriverMap.
 * \note As a special case, filenames starting with "PG:" are bound to
 * "PostgreSQL".
 */
100 101 102
char const* DeduceDriverName(std::string filename)
  {
  std::transform(filename.begin(), filename.end(), filename.begin(), (int (*)(int))toupper);
103
  if(filename.compare(0, 3, "PG:") == 0)
104 105 106
    {
    return "PostgreSQL";
    }
107
  const std::string extension = itksys::SystemTools::GetFilenameLastExtension(filename);
108 109 110 111 112 113
  ExtensionDriverAssociation const* whichIt =
    std::find_if(
      boost::begin(k_ExtensionDriverMap), boost::end(k_ExtensionDriverMap),
      boost::bind(&ExtensionDriverAssociation::Matches, _1, extension));
  if (whichIt ==  boost::end(k_ExtensionDriverMap))
    {
114
    return nullptr; // nothing found
115 116 117 118 119 120
    }
  return whichIt->driverName;
  }
} // Anonymous namespace


Luc Hermitte's avatar
Luc Hermitte committed
121
otb::ogr::DataSource::DataSource()
122
: m_DataSource(nullptr),
123
  m_LayerOptions() , 
124
  m_OpenMode(Modes::Update_LayerUpdate),
125
  m_FirstModifiableLayerID(0)
Luc Hermitte's avatar
Luc Hermitte committed
126 127 128
{
  Drivers::Init();

129
  ogr::version_proxy::GDALDriverType * d = 
130
    GetGDALDriverManager()->GetDriverByName("Memory");
Luc Hermitte's avatar
Luc Hermitte committed
131
  assert(d && "OGR Memory driver not found");
132
  m_DataSource = ogr::version_proxy::Create(d,"in-memory");
Luc Hermitte's avatar
Luc Hermitte committed
133
  if (!m_DataSource) {
134 135
    itkExceptionMacro(<< "Failed to create OGRMemDataSource: " 
                      << CPLGetLastErrorMsg());
Luc Hermitte's avatar
Luc Hermitte committed
136 137 138
  }
}

139
otb::ogr::DataSource::DataSource( 
140
    GDALDataset * source ,
141
    Modes::type mode ,
142
    const std::vector< std::string > & options /*NULL*/ )
143 144 145
: m_DataSource(source) ,
  m_LayerOptions(options) ,
  m_OpenMode(mode) ,
146
  m_FirstModifiableLayerID(0)
Luc Hermitte's avatar
Luc Hermitte committed
147
{
148
  m_FirstModifiableLayerID = GetLayersCount();
Luc Hermitte's avatar
Luc Hermitte committed
149 150
}

151
otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string const& datasourceName, Modes::type mode)
152
{
153 154 155
  FileNameHelperType::Pointer fileNameHelper = FileNameHelperType::New();
  fileNameHelper->SetExtendedFileName( datasourceName.c_str() );
  std::string simpleFileName = fileNameHelper->GetSimpleFileName();
156 157

  bool update = (mode != Modes::Read);
158
  GDALDataset * source = 
159 160
    ogr::version_proxy::Open( simpleFileName.c_str() ,
                              !update ,
161
                              fileNameHelper->GetGDALOpenOptions() );
162 163 164 165 166 167
  if (!source)
    {
    // In read mode, this is a failure
    // In write mode (Overwrite and Update), create the data source transparently
    if (mode == Modes::Read)
      {
168
      itkGenericExceptionMacro(<< "Failed to open GDALDataset file "
169
        << simpleFileName<<" : " << CPLGetLastErrorMsg());
170 171 172
      }

    // Hand made factory based on file extension.
173
    char const* driverName = DeduceDriverName(simpleFileName);
174 175
    if (!driverName)
      {
176 177
      itkGenericExceptionMacro(<< "No OGR driver known to OTB to create and "
        "handle a DataSource named <"
178
        <<simpleFileName<<">.");
179 180
      }

181
    ogr::version_proxy::GDALDriverType * d = 
182
      GetGDALDriverManager()->GetDriverByName(  driverName  );
183 184 185

    if(!d)
      {
186 187
      itkGenericExceptionMacro(<< "Could not create OGR driver " << driverName 
        << ", check your OGR configuration for available drivers." );
188 189
      }

190 191 192
    source = ogr::version_proxy::Create( 
                  d ,
                  simpleFileName.c_str() ,
193
                  fileNameHelper->GetGDALCreationOptions() );
194
    if (!source) {
195
      itkGenericExceptionMacro(<< "Failed to create GDALDataset <"
196
        << simpleFileName << "> (driver name: <" << driverName 
197
        <<">: " << CPLGetLastErrorMsg());
198 199
    }
    }
200
  return otb::ogr::DataSource::New( source , mode , fileNameHelper->GetGDALLayerOptions() );
201 202 203 204
}

void DeleteDataSource(std::string const& datasourceName)
{
205 206 207 208 209 210
  otb::OGRExtendedFilenameToOptions::Pointer fileNameHelper = 
    otb::OGRExtendedFilenameToOptions::New();
  fileNameHelper->SetExtendedFileName( datasourceName.c_str() );
  std::string simpleFileName = fileNameHelper->GetSimpleFileName();

  bool ret = otb::ogr::version_proxy::Delete(simpleFileName.c_str());
211
  if (!ret)
212
    {
213
    itkGenericExceptionMacro(<< "Deletion of data source " << simpleFileName
214 215
                             << " failed: " << CPLGetLastErrorMsg());
    }
216 217
}

Luc Hermitte's avatar
Luc Hermitte committed
218
otb::ogr::DataSource::Pointer
219
otb::ogr::DataSource::New(std::string const& datasourceName, Modes::type mode)
Luc Hermitte's avatar
Luc Hermitte committed
220
{
221 222 223 224
  FileNameHelperType::Pointer fileNameHelper = FileNameHelperType::New();
  fileNameHelper->SetExtendedFileName( datasourceName.c_str() );
  std::string simpleFileName = fileNameHelper->GetSimpleFileName();

225 226
  if (mode < Modes::Read || mode >= Modes::MAX__)
    {
227
    itkGenericExceptionMacro(<< "Wrong mode when opening " << simpleFileName );
228 229
    }

Luc Hermitte's avatar
Luc Hermitte committed
230
  Drivers::Init();
231
  GDALDataset * ds = 
232
    ogr::version_proxy::Open( simpleFileName.c_str() , true );
233

234
  bool ds_exists = (ds!=nullptr);
235 236

  ogr::version_proxy::Close(ds);
237

238 239

  if (ds_exists && mode == Modes::Overwrite)
240 241 242 243 244
    {
    DeleteDataSource(datasourceName);
    }

  return OpenDataSource(datasourceName, mode);
Luc Hermitte's avatar
Luc Hermitte committed
245 246
}

OTB Bot's avatar
OTB Bot committed
247
/*static*/
Luc Hermitte's avatar
Luc Hermitte committed
248
otb::ogr::DataSource::Pointer
249
otb::ogr::DataSource::New(GDALDataset * source , Modes::type mode , const std::vector< std::string > & layerOptions )
Luc Hermitte's avatar
Luc Hermitte committed
250
{
251
  Pointer res = new DataSource( source , mode , layerOptions );
252
  res->UnRegister();
Luc Hermitte's avatar
Luc Hermitte committed
253 254 255 256 257 258 259 260 261 262 263
  return res;
}

/*virtual*/  otb::ogr::DataSource::~DataSource()
{
  Clear();
}

/*===========================================================================*/
/*================================[ layers ]=================================*/
/*===========================================================================*/
264 265
otb::ogr::DataSource::const_iterator otb::ogr::DataSource::cbegin() const
{
266
  return const_iterator(*this, 0);
267 268 269 270
}

otb::ogr::DataSource::const_iterator otb::ogr::DataSource::cend() const
{
271
  return const_iterator(*this, GetLayersCount());
272 273 274 275 276 277 278 279 280 281 282 283
}

otb::ogr::DataSource::iterator otb::ogr::DataSource::begin()
{
  return iterator(*this, 0);
}

otb::ogr::DataSource::iterator otb::ogr::DataSource::end()
{
  return iterator(*this, GetLayersCount());
}

284
otb::ogr::Layer otb::ogr::DataSource::CreateLayer(
OTB Bot's avatar
OTB Bot committed
285 286 287
  std::string const& name,
  OGRSpatialReference * poSpatialRef/* = NULL */,
  OGRwkbGeometryType eGType/* = wkbUnknown */,
288
  std::vector<std::string> const& papszOptions/* = NULL */)
289 290
{
  assert(m_DataSource && "Datasource not initialized");
291

292 293 294 295 296
  // In read mode, try to return an existing layer.
  // and throw if not found
  if (m_OpenMode == Modes::Read)
    {
    otb::ogr::Layer l = GetLayerChecked(name); // will throw if not existing
297 298
    itkGenericOutputMacro(<< "Requesting layer creation in read-only "
                             "GDALDataset. Returning the existing layer");
299 300 301 302 303 304
    return l;
    }

  // Other mode : Check if the layer already exists.
  otb::ogr::Layer layer = GetLayer(name); // won't throw on failure

305 306 307 308 309 310
  FileNameHelperType::Pointer layerOptionHelper = 
    FileNameHelperType::GetGDALLayerOptionsHelper( m_LayerOptions );
  layerOptionHelper->AddGDALLayerOptions( papszOptions );
  std::vector<std::string> layerOptions = 
    layerOptionHelper->GetGDALLayerOptions();

311 312
  switch (m_OpenMode)
  {
313
  case Modes::Update_LayerOverwrite:
314
    {
315 316 317 318 319 320 321 322
    // First delete the layer
    if (layer)
      {
      DeleteLayer(GetLayerID(name));
      }

    // Then create it
    OGRLayer * ol = m_DataSource->CreateLayer(
323 324 325 326 327
      name.c_str() ,
      poSpatialRef ,
      eGType ,
      otb::ogr::StringListConverter( layerOptions ).to_ogr() );

328
    if (!ol)
329
      {
330
      itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
331
        << "> in the GDALDataset file <" << GetDatasetDescription()
332 333 334 335 336
        <<">: " << CPLGetLastErrorMsg());
      }

    const bool modifiable = true;
    return Layer(ol, modifiable);
337
    }
338 339 340 341 342 343 344 345 346 347 348 349
    break;
  case Modes::Overwrite:
  case Modes::Update_LayerUpdate:
    {
    if (layer)
      {
      return layer;
      }
    else
      {
      // Then create it
      OGRLayer * ol = m_DataSource->CreateLayer(
350 351 352 353 354
        name.c_str() ,
        poSpatialRef ,
        eGType ,
        otb::ogr::StringListConverter( layerOptions ).to_ogr() );

355
      if (!ol)
356
        {
357
        itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
358
          << "> in the GDALDataset file <" <<  GetDatasetDescription()
359 360
          <<">: " << CPLGetLastErrorMsg());
        }
361

362 363 364 365 366 367
      const bool modifiable = true;
      return Layer(ol, modifiable);
      }
    }
    break;
  case Modes::Update_LayerCreateOnly:
368
    {
369
    // The layer exists. Returns it
370
    // It will be non-modifiable if already existing at GDALDataset creation time
371 372 373 374 375 376 377
    if (layer)
      {
      return layer;
      }

    // Case where the layer does not exists
    OGRLayer * ol = m_DataSource->CreateLayer(
378 379 380 381 382
          name.c_str() ,
          poSpatialRef ,
          eGType ,
          otb::ogr::StringListConverter( layerOptions ).to_ogr() );

383 384 385
    if (!ol)
      {
      itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
386
        << "> in the GDALDataset file <" <<  GetDatasetDescription()
387 388 389 390 391
        <<">: " << CPLGetLastErrorMsg());
      }

    const bool modifiable = true;
    return Layer(ol, modifiable);
392
    }
393 394 395
    break;
  default :
    assert(false && "Should never be there");
396
    itkGenericExceptionMacro(<< "GDALDataset opening mode not supported");
397 398
    break;
  }
399

400
  itkGenericExceptionMacro(<< "GDALDataset opening mode not supported");
401
  return Layer(nullptr, false); // keep compiler happy
402 403 404
}

otb::ogr::Layer otb::ogr::DataSource::CopyLayer(
OTB Bot's avatar
OTB Bot committed
405 406
  Layer & srcLayer,
  std::string const& newName,
407
  std::vector<std::string> const& papszOptions/* = NULL */)
408 409
{
  assert(m_DataSource && "Datasource not initialized");
410 411 412 413

  switch (m_OpenMode)
  {
    case Modes::Invalid:
414 415
      assert(false && "Invalid GDALDataset opening mode");
      itkGenericExceptionMacro(<< "Invalid GDALDataset opening mode");
416 417
      break;
    case Modes::Read:
418 419
      itkGenericExceptionMacro(<< "GDALDataset is opened in Read mode : "
                                  "cannot create a layer");
420 421 422 423
      break;
    default:
      break;
  }
424 425 426 427 428 429
  
  FileNameHelperType::Pointer layerOptionHelper = 
    FileNameHelperType::GetGDALLayerOptionsHelper( m_LayerOptions );
  layerOptionHelper->AddGDALLayerOptions( papszOptions );
  std::vector<std::string> layerOptions = 
    layerOptionHelper->GetGDALLayerOptions();
430

431
  OGRLayer * l0 = &srcLayer.ogr();
432 433 434 435
  OGRLayer * ol = m_DataSource->CopyLayer( 
                  l0 ,
                  newName.c_str() ,
                  otb::ogr::StringListConverter( layerOptions ).to_ogr() );
436
  if (!ol)
437
    {
438
    itkGenericExceptionMacro(<< "Failed to copy the layer <"
439 440
      << srcLayer.GetName() << "> into the new layer <" << newName
      << "> in the GDALDataset file <" <<  GetDatasetDescription()
441
      <<">: " << CPLGetLastErrorMsg());
442
    }
443
  const bool modifiable = true;
444
  Layer l( ol , modifiable );
445 446 447 448
  return l;
}

void otb::ogr::DataSource::DeleteLayer(size_t i)
Luc Hermitte's avatar
Luc Hermitte committed
449
{
450 451 452 453 454
  assert(m_DataSource && "Datasource not initialized");

  switch (m_OpenMode)
  {
    case Modes::Invalid:
455 456
      assert(false && "Invalid GDALDataset opening mode");
      itkGenericExceptionMacro(<< "Invalid GDALDataset opening mode");
457 458
      break;
    case Modes::Read:
459 460
      itkGenericExceptionMacro(<< "GDALDataset is opened in Read mode : "
        "cannot delete a layer");
461 462
      break;
    case Modes::Update_LayerCreateOnly:
463 464
      itkGenericExceptionMacro(<< "GDALDataset is opened in "
        "Update_LayerCreateOnly mode : cannot delete a layer");
465 466 467 468 469
      break;
    default:
      break;
  }

Luc Hermitte's avatar
Luc Hermitte committed
470 471
  const int nb_layers = GetLayersCount();
  if (int(i) >= nb_layers)
472
    {
473 474 475
    itkExceptionMacro(<< "Cannot delete " << i 
      << "th layer in the GDALDataset <" <<  GetDatasetDescription() 
      << "> as it contains only " << nb_layers << "layers.");
Luc Hermitte's avatar
Luc Hermitte committed
476
    }
477 478
  const OGRErr err = m_DataSource->DeleteLayer(int(i));
  if (err != OGRERR_NONE)
Luc Hermitte's avatar
Luc Hermitte committed
479
    {
480 481 482
    itkExceptionMacro(<< "Cannot delete " << i 
      << "th layer in the GDALDataset <" <<  GetDatasetDescription() 
      << ">: " << CPLGetLastErrorMsg());
Luc Hermitte's avatar
Luc Hermitte committed
483 484 485
    }
}

486 487
bool otb::ogr::DataSource::IsLayerModifiable(size_t i) const
{
488
  assert(m_DataSource && "Datasource not initialized");
489 490 491 492 493 494 495 496 497 498 499 500 501
  switch(m_OpenMode)
  {
    case Modes::Read:
      return false;
    case Modes::Update_LayerCreateOnly:
      return int(i) >= m_FirstModifiableLayerID;
    default:
      return true;
  }
}

bool otb::ogr::DataSource::IsLayerModifiable(std::string const& layername) const
{
502
  assert(m_DataSource && "Datasource not initialized");
503 504 505 506 507 508 509 510 511 512 513 514
  switch(m_OpenMode)
  {
    case Modes::Read:
      return false;
    case Modes::Update_LayerCreateOnly:
        {
        const int id = this->GetLayerIDUnchecked(layername);
        return id >= m_FirstModifiableLayerID;
        }
    default:
      return true;
  }
515 516
}

517
int otb::ogr::DataSource::GetLayerIDUnchecked(std::string const& name) const
518
{
519 520
  assert(m_DataSource && "Datasource not initialized");
  for (int i = 0, N = GetLayersCount(); i < N; i++)
521
    {
522 523 524 525
    OGRLayer * raw_layer = GetLayerUnchecked(i);
    // wrapping to give access to GetName() that doesn't exist with all version of gdal/ogr
    Layer layer(raw_layer, false);
    if (layer.GetName() == name)
526 527 528 529
      {
      return i;
      }
    }
530 531
  return -1;
}
532

533 534 535 536
size_t otb::ogr::DataSource::GetLayerID(std::string const& name) const
{
  int const id = GetLayerIDUnchecked(name);
  if (id < 0)
537
    {
538
    itkExceptionMacro( << "Cannot fetch any layer named <" << name
539
      << "> in the GDALDataset <" <<  GetDatasetDescription() << ">: "
540 541
      << CPLGetLastErrorMsg());
    }
542 543
  return 0; // keep compiler happy
}
544 545

otb::ogr::Layer otb::ogr::DataSource::GetLayerChecked(size_t i)
Luc Hermitte's avatar
Luc Hermitte committed
546
{
547
  assert(m_DataSource && "Datasource not initialized");
548 549
  const int nb_layers = GetLayersCount();
  if (int(i) >= nb_layers)
550
    {
551
    itkExceptionMacro(<< "Cannot fetch " << i << "th layer in the GDALDataset <"
552 553
      << GetDatasetDescription() << "> as it contains only " << nb_layers 
      << "layers.");
554 555 556 557
    }
  OGRLayer * layer_ptr = m_DataSource->GetLayer(int(i));
  if (!layer_ptr)
    {
558 559 560
    itkExceptionMacro( << "Unexpected error: cannot fetch " << i 
      << "th layer in the GDALDataset <" << GetDatasetDescription() 
      << ">: " << CPLGetLastErrorMsg());
561
    }
562
  return otb::ogr::Layer(layer_ptr, IsLayerModifiable(i));
Luc Hermitte's avatar
Luc Hermitte committed
563 564 565 566
}

OGRLayer* otb::ogr::DataSource::GetLayerUnchecked(size_t i)
{
567
  assert(m_DataSource && "Datasource not initialized");
Luc Hermitte's avatar
Luc Hermitte committed
568
  OGRLayer * layer_ptr = m_DataSource->GetLayer(int(i));
Luc Hermitte's avatar
Luc Hermitte committed
569
  return layer_ptr;
Luc Hermitte's avatar
Luc Hermitte committed
570 571
}

572 573 574 575
otb::ogr::Layer otb::ogr::DataSource::GetLayer(std::string const& name)
{
  assert(m_DataSource && "Datasource not initialized");
  OGRLayer * layer_ptr = m_DataSource->GetLayerByName(name.c_str());
576
  return otb::ogr::Layer(layer_ptr, layer_ptr ? IsLayerModifiable(name) : false);
577 578 579 580 581 582 583 584 585
}

otb::ogr::Layer otb::ogr::DataSource::GetLayerChecked(std::string const& name)
{
  assert(m_DataSource && "Datasource not initialized");
  OGRLayer * layer_ptr = m_DataSource->GetLayerByName(name.c_str());
  if (!layer_ptr)
    {
    itkExceptionMacro( << "Cannot fetch any layer named <" << name
586
      << "> in the GDALDataset <" << GetDatasetDescription() << ">: "
587
      << CPLGetLastErrorMsg());
588
    }
589
  return otb::ogr::Layer(layer_ptr, IsLayerModifiable(name));
590 591
}

Luc Hermitte's avatar
Luc Hermitte committed
592 593
int otb::ogr::DataSource::GetLayersCount() const
{
594
  assert(m_DataSource && "Datasource not initialized");
Luc Hermitte's avatar
Luc Hermitte committed
595 596 597
  return m_DataSource->GetLayerCount();
}

598
otb::ogr::Layer otb::ogr::DataSource::ExecuteSQL(
OTB Bot's avatar
OTB Bot committed
599 600
  std::string const& statement,
  OGRGeometry * poSpatialFilter,
601 602 603
  char        const* pszDialect)
{
  assert(m_DataSource && "Datasource not initialized");
604
  const bool modifiable = false;
605 606 607 608 609
  OGRLayer * layer_ptr = m_DataSource->ExecuteSQL(
    statement.c_str(), poSpatialFilter, pszDialect);
  if (!layer_ptr)
    {
#if defined(PREFER_EXCEPTION)
610 611 612
    itkExceptionMacro( << "Unexpected error: cannot execute the SQL request <" 
      << statement << "> in the GDALDataset <" <<  GetDatasetDescription() 
      << ">: " << CPLGetLastErrorMsg());
OTB Bot's avatar
OTB Bot committed
613
#else
614
    // Cannot use the deleter made for result sets obtained from
615
    // GDALDataset::ExecuteSQL because it checks for non-nullity....
616
    // *sigh*
617
    return otb::ogr::Layer(nullptr, modifiable);
618 619
#endif
    }
620
  return otb::ogr::Layer(layer_ptr, *m_DataSource, modifiable);
621 622
}

623 624
void
otb::ogr::DataSource::
625
SetLayerCreationOptions( const std::vector< std::string > & options )
626 627 628 629 630 631
{
  FileNameHelperType::Pointer helper = FileNameHelperType::New();
  helper->SetGDALLayerOptions( options );
  m_LayerOptions = helper->GetGDALLayerOptions();
  // perf : do we move code from  helper->SetGDALLayerOptions in here?
}
632

633 634 635 636 637 638 639 640 641 642 643
void
otb::ogr::DataSource::
AddLayerCreationOptions( std::vector< std::string > options )
{
  FileNameHelperType::Pointer helper = FileNameHelperType::New();
  helper->SetGDALLayerOptions( m_LayerOptions );
  helper->AddGDALLayerOptions( options );
  m_LayerOptions = helper->GetGDALLayerOptions();
  // perf : do we move code from helper->AddGDALLayerOptions in here?
}

644
const std::vector< std::string > &
645
otb::ogr::DataSource::
646
GetLayerCreationOptions() const
647 648 649
{
  return m_LayerOptions;
}
Luc Hermitte's avatar
Luc Hermitte committed
650 651 652 653
/*===========================================================================*/
/*===============================[ features ]================================*/
/*===========================================================================*/
namespace  { // Anonymous namespace
Luc Hermitte's avatar
Luc Hermitte committed
654 655 656 657 658 659 660 661 662
/**\ingroup GeometryInternals
 * \brief %Functor used to accumulate the sizes of the layers in a \c DataSource.
 * \since OTB v 3.14.0
 */
struct AccuLayersSizes
  {
  AccuLayersSizes(bool doForceComputation)
    : m_doForceComputation(doForceComputation) { }
  int operator()(int accumulated, otb::ogr::Layer const& layer) const
Luc Hermitte's avatar
Luc Hermitte committed
663
    {
Luc Hermitte's avatar
Luc Hermitte committed
664 665 666 667 668 669
    const int loc_size = layer.GetFeatureCount(m_doForceComputation);
    return loc_size < 0 ? loc_size : loc_size+accumulated;
    }
private:
  bool m_doForceComputation;
  };
OTB Bot's avatar
OTB Bot committed
670
} // Anonymous namespace
Luc Hermitte's avatar
Luc Hermitte committed
671 672 673

int otb::ogr::DataSource::Size(bool doForceComputation) const
{
674
  return std::accumulate(begin(),end(), 0, AccuLayersSizes(doForceComputation));
Luc Hermitte's avatar
Luc Hermitte committed
675 676 677 678 679 680
}

/*===========================================================================*/
/*=================================[ Misc ]==================================*/
/*===========================================================================*/

681
OGREnvelope otb::ogr::DataSource::GetGlobalExtent(bool force/* = false */, std::string *outwkt) const
682
{
683
  assert(m_DataSource && "Datasource not initialized");
684
  const_iterator lit = this->begin();
685

686
  if(lit==this->end())
OTB Bot's avatar
OTB Bot committed
687
    {
688 689
    itkGenericExceptionMacro(<< "Cannot compute global extent because there "
      "are no layers in the DataSource");
690 691
    }

692
  const OGRSpatialReference * ref_srs = lit->GetSpatialRef();
693
  OGREnvelope sExtent = lit->GetExtent(force);
694

695 696 697 698 699
  if (outwkt)
    {
    *outwkt = lit->GetProjectionRef();
    }

700 701
  ++lit;

OTB Bot's avatar
OTB Bot committed
702
  for(; lit!=this->end(); ++lit)
703
    {
704 705 706 707
    OGREnvelope cExtent = lit->GetExtent(force); // may throw

    const OGRSpatialReference * current_srs = lit->GetSpatialRef();

708
  // If both srs are valid and if they are different
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
    if(ref_srs && current_srs && current_srs->IsSame(ref_srs) == 0)
      {
      // Reproject cExtent in ref_srs
      // OGRCreateCoordinateTransformation is not const-correct
      OGRCoordinateTransformation * coordTransformation = OGRCreateCoordinateTransformation(
        const_cast<OGRSpatialReference *>(current_srs),
        const_cast<OGRSpatialReference *>(ref_srs));

      coordTransformation->Transform(1,&cExtent.MinX,&cExtent.MinY);
      coordTransformation->Transform(1,&cExtent.MaxX,&cExtent.MaxY);

      const double real_minx = std::min(cExtent.MinX,cExtent.MaxX);
      const double real_miny = std::min(cExtent.MinY,cExtent.MaxY);
      const double real_maxx = std::max(cExtent.MinX,cExtent.MaxX);
      const double real_maxy = std::max(cExtent.MinY,cExtent.MaxY);

      cExtent.MinX = real_minx;
      cExtent.MinY = real_miny;
      cExtent.MaxX = real_maxx;
      cExtent.MaxY = real_maxy;

      OGRCoordinateTransformation::DestroyCT(coordTransformation);
      }
    // else: If srs are invalid, we assume that extent are coherent

    // Merge with previous layers' extent
    sExtent.Merge(cExtent);
    } // for each layer

  return sExtent;
}
740

741 742 743 744 745 746 747 748
std::string otb::ogr::DataSource::GetGlobalExtent(double & ulx,
                                           double & uly,
                                           double & lrx,
                                           double & lry,
                                           bool force) const
{
  std::string outwkt;
  const OGREnvelope sExtent = GetGlobalExtent(force, &outwkt);
749 750 751 752
  ulx = sExtent.MinX;
  uly = sExtent.MinY;
  lrx = sExtent.MaxX;
  lry = sExtent.MaxY;
753 754

  return outwkt;
755 756 757
}


Luc Hermitte's avatar
Luc Hermitte committed
758 759 760 761
/*virtual*/
void otb::ogr::DataSource::PrintSelf(
  std::ostream& os, itk::Indent indent) const
{
762
  assert(m_DataSource && "Datasource not initialized");
763
  BOOST_FOREACH(Layer const& l, *this)
764 765 766
    {
    l.PrintSelf(os, indent);
    }
Luc Hermitte's avatar
Luc Hermitte committed
767 768
}

769
/*virtual*/ void otb::ogr::DataSource::Graft(const itk::DataObject * itkNotUsed(data))
Luc Hermitte's avatar
Luc Hermitte committed
770 771 772
{
  assert(! "Disabled to check if it makes sense...");
}
773

774
bool otb::ogr::DataSource::HasCapability(std::string const& capabilityName) const
775 776
{
  assert(m_DataSource && "Datasource not initialized");
777
  return m_DataSource->TestCapability(capabilityName.c_str());
778 779 780 781 782
}

void otb::ogr::DataSource::SyncToDisk()
{
  assert(m_DataSource && "Datasource not initialized");
783
  m_DataSource->FlushCache();
784
}
785 786 787 788


std::string otb::ogr::DataSource::GetDatasetDescription() const
{
789 790
  std::vector<std::string> files = 
    otb::ogr::version_proxy::GetFileListAsStringVector( m_DataSource );
791
  std::string description = "";
792 793
  for( std::vector<std::string>::const_iterator it = files.begin() ; 
       it!=files.end() ; ++it )
794 795 796 797
    description+=(*it)+", ";

  return description;
}