otbOGRDataSourceWrapper.cxx 22.3 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(ITK_NULLPTR);
Luc Hermitte's avatar
Luc Hermitte committed
48 49 50
  return true;
}

51
void otb::ogr::DataSource::Reset(otb::ogr::version_proxy::GDALDatasetType * 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
  };
Luc Hermitte's avatar
Luc Hermitte committed
90 91 92 93 94 95 96 97
/**\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".
 */
98 99 100 101 102 103 104
char const* DeduceDriverName(std::string filename)
  {
  std::transform(filename.begin(), filename.end(), filename.begin(), (int (*)(int))toupper);
  if (0 == strncmp(filename.c_str(), "PG:", 3))
    {
    return "PostgreSQL";
    }
105
  const std::string extension = itksys::SystemTools::GetFilenameLastExtension(filename);
106 107 108 109 110 111
  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))
    {
112
    return ITK_NULLPTR; // nothing found
113 114 115 116 117 118
    }
  return whichIt->driverName;
  }
} // Anonymous namespace


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

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

135 136 137 138 139 140 141
otb::ogr::DataSource::DataSource( 
    otb::ogr::version_proxy::GDALDatasetType * source ,
    Modes::type mode ,
    std::vector< std::string > options /*NULL*/ )
: m_DataSource(source) ,
  m_LayerOptions(options) ,
  m_OpenMode(mode) ,
142
  m_FirstModifiableLayerID(0)
Luc Hermitte's avatar
Luc Hermitte committed
143
{
144
  m_FirstModifiableLayerID = GetLayersCount();
Luc Hermitte's avatar
Luc Hermitte committed
145 146
}

147
otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string const& datasourceName, Modes::type mode)
148
{
149
  FileNameHelperType::Pointer fileNameHelper = FileNameHelperType::New();
150
  bool update = (mode != Modes::Read);
151
  fileNameHelper->SetExtendedFileName( datasourceName.c_str() );
152

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

    // Hand made factory based on file extension.
    char const* driverName = DeduceDriverName(datasourceName);
    if (!driverName)
      {
      itkGenericExceptionMacro(<< "No OGR driver known to OTB to create and handle a DataSource named <"
        <<datasourceName<<">.");
      }

176
    ogr::version_proxy::GDALDriverType * d = ogr::version_proxy::GetDriverByName(driverName);
177 178 179 180 181 182

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

183 184 185
    source = ogr::version_proxy::Create( 
                  d ,
                  simpleFileName.c_str() ,
186
                  fileNameHelper->GetGDALCreationOptions() );
187
    if (!source) {
188
      itkGenericExceptionMacro(<< "Failed to create GDALDataset <"<<datasourceName
189 190 191 192 193 194 195 196
        <<"> (driver name: <" << driverName<<">: " << CPLGetLastErrorMsg());
    }
    }
  return otb::ogr::DataSource::New(source, mode);
}

void DeleteDataSource(std::string const& datasourceName)
{
197 198
  bool ret = otb::ogr::version_proxy::Delete(datasourceName.c_str());
  if (!ret)
199
    {
200 201 202
    itkGenericExceptionMacro(<< "Deletion of data source " << datasourceName
                             << " failed: " << CPLGetLastErrorMsg());
    }
203 204
}

Luc Hermitte's avatar
Luc Hermitte committed
205
otb::ogr::DataSource::Pointer
206
otb::ogr::DataSource::New(std::string const& datasourceName, Modes::type mode)
Luc Hermitte's avatar
Luc Hermitte committed
207
{
Julien Malik's avatar
Julien Malik committed
208 209 210 211 212
  if (mode < Modes::Read || mode >= Modes::MAX__)
    {
    itkGenericExceptionMacro(<< "Wrong mode when opening " << datasourceName);
    }

Luc Hermitte's avatar
Luc Hermitte committed
213 214
  Drivers::Init();

215 216
  ogr::version_proxy::GDALDatasetType * ds = ogr::version_proxy::Open(datasourceName.c_str(),true);

217
  bool ds_exists = (ds!=ITK_NULLPTR);
218 219

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

221 222

  if (ds_exists && mode == Modes::Overwrite)
223 224 225 226 227
    {
    DeleteDataSource(datasourceName);
    }

  return OpenDataSource(datasourceName, mode);
Luc Hermitte's avatar
Luc Hermitte committed
228 229
}

OTB Bot's avatar
STYLE  
OTB Bot committed
230
/*static*/
Luc Hermitte's avatar
Luc Hermitte committed
231
otb::ogr::DataSource::Pointer
232
otb::ogr::DataSource::New(otb::ogr::version_proxy::GDALDatasetType * source, Modes::type mode)
Luc Hermitte's avatar
Luc Hermitte committed
233
{
234
  Pointer res = new DataSource(source, mode);
235
  res->UnRegister();
Luc Hermitte's avatar
Luc Hermitte committed
236 237 238 239 240 241 242 243 244 245 246
  return res;
}

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

/*===========================================================================*/
/*================================[ layers ]=================================*/
/*===========================================================================*/
247 248
otb::ogr::DataSource::const_iterator otb::ogr::DataSource::cbegin() const
{
249
  return const_iterator(*this, 0);
250 251 252 253
}

otb::ogr::DataSource::const_iterator otb::ogr::DataSource::cend() const
{
254
  return const_iterator(*this, GetLayersCount());
255 256 257 258 259 260 261 262 263 264 265 266
}

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

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

267
otb::ogr::Layer otb::ogr::DataSource::CreateLayer(
OTB Bot's avatar
STYLE  
OTB Bot committed
268 269 270
  std::string const& name,
  OGRSpatialReference * poSpatialRef/* = NULL */,
  OGRwkbGeometryType eGType/* = wkbUnknown */,
271
  std::vector<std::string> const& papszOptions/* = NULL */)
272 273
{
  assert(m_DataSource && "Datasource not initialized");
274

275 276 277 278 279
  // 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
280
    itkGenericOutputMacro(<< "Requesting layer creation in read-only GDALDataset. Returning the existing layer");
281 282 283 284 285 286
    return l;
    }

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

287 288
  switch (m_OpenMode)
  {
289
  case Modes::Update_LayerOverwrite:
290
    {
291 292 293 294 295 296 297 298 299 300
    // First delete the layer
    if (layer)
      {
      DeleteLayer(GetLayerID(name));
      }

    // Then create it
    OGRLayer * ol = m_DataSource->CreateLayer(
      name.c_str(), poSpatialRef, eGType, otb::ogr::StringListConverter(papszOptions).to_ogr());
    if (!ol)
301
      {
302
      itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
303
                               << "> in the GDALDataset file <" << GetDatasetDescription()
304 305 306 307 308
        <<">: " << CPLGetLastErrorMsg());
      }

    const bool modifiable = true;
    return Layer(ol, modifiable);
309
    }
310 311 312 313 314 315 316 317 318 319 320 321 322 323
    break;
  case Modes::Overwrite:
  case Modes::Update_LayerUpdate:
    {
    if (layer)
      {
      return layer;
      }
    else
      {
      // Then create it
      OGRLayer * ol = m_DataSource->CreateLayer(
        name.c_str(), poSpatialRef, eGType, otb::ogr::StringListConverter(papszOptions).to_ogr());
      if (!ol)
324
        {
325
        itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
326
                                 << "> in the GDALDataset file <" <<  GetDatasetDescription()
327 328
          <<">: " << CPLGetLastErrorMsg());
        }
329

330 331 332 333 334 335
      const bool modifiable = true;
      return Layer(ol, modifiable);
      }
    }
    break;
  case Modes::Update_LayerCreateOnly:
336
    {
337
    // The layer exists. Returns it
338
    // It will be non-modifiable if already existing at GDALDataset creation time
339 340 341 342 343 344 345 346 347 348 349
    if (layer)
      {
      return layer;
      }

    // Case where the layer does not exists
    OGRLayer * ol = m_DataSource->CreateLayer(
      name.c_str(), poSpatialRef, eGType, otb::ogr::StringListConverter(papszOptions).to_ogr());
    if (!ol)
      {
      itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
350
                               << "> in the GDALDataset file <" <<  GetDatasetDescription()
351 352 353 354 355
        <<">: " << CPLGetLastErrorMsg());
      }

    const bool modifiable = true;
    return Layer(ol, modifiable);
356
    }
357 358 359
    break;
  default :
    assert(false && "Should never be there");
360
    itkGenericExceptionMacro(<< "GDALDataset opening mode not supported");
361 362
    break;
  }
363

364
  itkGenericExceptionMacro(<< "GDALDataset opening mode not supported");
365
  return Layer(ITK_NULLPTR, false); // keep compiler happy
366 367 368
}

otb::ogr::Layer otb::ogr::DataSource::CopyLayer(
OTB Bot's avatar
STYLE  
OTB Bot committed
369 370
  Layer & srcLayer,
  std::string const& newName,
371
  std::vector<std::string> const& papszOptions/* = NULL */)
372 373
{
  assert(m_DataSource && "Datasource not initialized");
374 375 376 377

  switch (m_OpenMode)
  {
    case Modes::Invalid:
378 379
      assert(false && "Invalid GDALDataset opening mode");
      itkGenericExceptionMacro(<< "Invalid GDALDataset opening mode");
380 381
      break;
    case Modes::Read:
382
      itkGenericExceptionMacro(<< "GDALDataset is opened in Read mode : cannot create a layer");
383 384 385 386 387
      break;
    default:
      break;
  }

388
  OGRLayer * l0 = &srcLayer.ogr();
389
  OGRLayer * ol = m_DataSource->CopyLayer(l0, newName.c_str(), otb::ogr::StringListConverter(papszOptions).to_ogr());
390
  if (!ol)
391
    {
392 393
    itkGenericExceptionMacro(<< "Failed to copy the layer <"
      << srcLayer.GetName() << "> into the new layer <" <<newName
394
                             << "> in the GDALDataset file <" <<  GetDatasetDescription()
395
      <<">: " << CPLGetLastErrorMsg());
396
    }
397 398
  const bool modifiable = true;
  Layer l(ol, modifiable);
399 400 401 402
  return l;
}

void otb::ogr::DataSource::DeleteLayer(size_t i)
Luc Hermitte's avatar
Luc Hermitte committed
403
{
404 405 406 407 408
  assert(m_DataSource && "Datasource not initialized");

  switch (m_OpenMode)
  {
    case Modes::Invalid:
409 410
      assert(false && "Invalid GDALDataset opening mode");
      itkGenericExceptionMacro(<< "Invalid GDALDataset opening mode");
411 412
      break;
    case Modes::Read:
413
      itkGenericExceptionMacro(<< "GDALDataset is opened in Read mode : cannot delete a layer");
414 415
      break;
    case Modes::Update_LayerCreateOnly:
416
      itkGenericExceptionMacro(<< "GDALDataset is opened in Update_LayerCreateOnly mode : cannot delete a layer");
417 418 419 420 421
      break;
    default:
      break;
  }

Luc Hermitte's avatar
Luc Hermitte committed
422 423
  const int nb_layers = GetLayersCount();
  if (int(i) >= nb_layers)
424
    {
425
    itkExceptionMacro(<< "Cannot delete " << i << "th layer in the GDALDataset <"
426
                      <<  GetDatasetDescription() << "> as it contains only " << nb_layers << "layers.");
Luc Hermitte's avatar
Luc Hermitte committed
427
    }
428 429
  const OGRErr err = m_DataSource->DeleteLayer(int(i));
  if (err != OGRERR_NONE)
Luc Hermitte's avatar
Luc Hermitte committed
430
    {
431
    itkExceptionMacro(<< "Cannot delete " << i << "th layer in the GDALDataset <"
432
                      <<  GetDatasetDescription() << ">: " << CPLGetLastErrorMsg());
Luc Hermitte's avatar
Luc Hermitte committed
433 434 435
    }
}

436 437
bool otb::ogr::DataSource::IsLayerModifiable(size_t i) const
{
438
  assert(m_DataSource && "Datasource not initialized");
439 440 441 442 443 444 445 446 447 448 449 450 451
  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
{
452
  assert(m_DataSource && "Datasource not initialized");
453 454 455 456 457 458 459 460 461 462 463 464
  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;
  }
465 466
}

467
int otb::ogr::DataSource::GetLayerIDUnchecked(std::string const& name) const
468
{
469 470
  assert(m_DataSource && "Datasource not initialized");
  for (int i = 0, N = GetLayersCount(); i < N; i++)
471
    {
472 473 474 475
    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)
476 477 478 479
      {
      return i;
      }
    }
480 481
  return -1;
}
482

483 484 485 486
size_t otb::ogr::DataSource::GetLayerID(std::string const& name) const
{
  int const id = GetLayerIDUnchecked(name);
  if (id < 0)
487
    {
488
    itkExceptionMacro( << "Cannot fetch any layer named <" << name
489
                       << "> in the GDALDataset <" <<  GetDatasetDescription() << ">: "
490 491
      << CPLGetLastErrorMsg());
    }
492 493
  return 0; // keep compiler happy
}
494 495

otb::ogr::Layer otb::ogr::DataSource::GetLayerChecked(size_t i)
Luc Hermitte's avatar
Luc Hermitte committed
496
{
497
  assert(m_DataSource && "Datasource not initialized");
498 499
  const int nb_layers = GetLayersCount();
  if (int(i) >= nb_layers)
500
    {
501
    itkExceptionMacro(<< "Cannot fetch " << i << "th layer in the GDALDataset <"
502
                      << GetDatasetDescription() << "> as it contains only " << nb_layers << "layers.");
503 504 505 506
    }
  OGRLayer * layer_ptr = m_DataSource->GetLayer(int(i));
  if (!layer_ptr)
    {
507
    itkExceptionMacro( << "Unexpected error: cannot fetch " << i << "th layer in the GDALDataset <"
508
                       << GetDatasetDescription() << ">: " << CPLGetLastErrorMsg());
509
    }
510
  return otb::ogr::Layer(layer_ptr, IsLayerModifiable(i));
Luc Hermitte's avatar
Luc Hermitte committed
511 512 513 514
}

OGRLayer* otb::ogr::DataSource::GetLayerUnchecked(size_t i)
{
515
  assert(m_DataSource && "Datasource not initialized");
Luc Hermitte's avatar
Luc Hermitte committed
516
  OGRLayer * layer_ptr = m_DataSource->GetLayer(int(i));
Luc Hermitte's avatar
Luc Hermitte committed
517
  return layer_ptr;
Luc Hermitte's avatar
Luc Hermitte committed
518 519
}

520 521 522 523
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());
524
  return otb::ogr::Layer(layer_ptr, layer_ptr ? IsLayerModifiable(name) : false);
525 526 527 528 529 530 531 532 533
}

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
534
      << "> in the GDALDataset <" << GetDatasetDescription() << ">: "
535
      << CPLGetLastErrorMsg());
536
    }
537
  return otb::ogr::Layer(layer_ptr, IsLayerModifiable(name));
538 539
}

Luc Hermitte's avatar
Luc Hermitte committed
540 541
int otb::ogr::DataSource::GetLayersCount() const
{
542
  assert(m_DataSource && "Datasource not initialized");
Luc Hermitte's avatar
Luc Hermitte committed
543 544 545
  return m_DataSource->GetLayerCount();
}

546
otb::ogr::Layer otb::ogr::DataSource::ExecuteSQL(
OTB Bot's avatar
STYLE  
OTB Bot committed
547 548
  std::string const& statement,
  OGRGeometry * poSpatialFilter,
549 550 551
  char        const* pszDialect)
{
  assert(m_DataSource && "Datasource not initialized");
552
  const bool modifiable = false;
553 554 555 556 557 558
  OGRLayer * layer_ptr = m_DataSource->ExecuteSQL(
    statement.c_str(), poSpatialFilter, pszDialect);
  if (!layer_ptr)
    {
#if defined(PREFER_EXCEPTION)
    itkExceptionMacro( << "Unexpected error: cannot execute the SQL request <" << statement
559
      << "> in the GDALDataset <" <<  GetDatasetDescription() << ">: " << CPLGetLastErrorMsg());
OTB Bot's avatar
STYLE  
OTB Bot committed
560
#else
561
    // Cannot use the deleter made for result sets obtained from
562
    // GDALDataset::ExecuteSQL because it checks for non-nullity....
563
    // *sigh*
564
    return otb::ogr::Layer(ITK_NULLPTR, modifiable);
565 566
#endif
    }
567
  return otb::ogr::Layer(layer_ptr, *m_DataSource, modifiable);
568 569 570
}


Luc Hermitte's avatar
Luc Hermitte committed
571 572 573 574
/*===========================================================================*/
/*===============================[ features ]================================*/
/*===========================================================================*/
namespace  { // Anonymous namespace
Luc Hermitte's avatar
Luc Hermitte committed
575 576 577 578 579 580 581 582 583
/**\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
584
    {
Luc Hermitte's avatar
Luc Hermitte committed
585 586 587 588 589 590
    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
STYLE  
OTB Bot committed
591
} // Anonymous namespace
Luc Hermitte's avatar
Luc Hermitte committed
592 593 594

int otb::ogr::DataSource::Size(bool doForceComputation) const
{
595
  return std::accumulate(begin(),end(), 0, AccuLayersSizes(doForceComputation));
Luc Hermitte's avatar
Luc Hermitte committed
596 597 598 599 600 601
}

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

602
OGREnvelope otb::ogr::DataSource::GetGlobalExtent(bool force/* = false */, std::string *outwkt) const
603
{
604
  assert(m_DataSource && "Datasource not initialized");
605
  const_iterator lit = this->begin();
606

607
  if(lit==this->end())
OTB Bot's avatar
STYLE  
OTB Bot committed
608
    {
609 610 611
    itkGenericExceptionMacro(<< "Cannot compute global extent because there are no layers in the DataSource");
    }

612
  const OGRSpatialReference * ref_srs = lit->GetSpatialRef();
613
  OGREnvelope sExtent = lit->GetExtent(force);
614

615 616 617 618 619
  if (outwkt)
    {
    *outwkt = lit->GetProjectionRef();
    }

620 621
  ++lit;

OTB Bot's avatar
STYLE  
OTB Bot committed
622
  for(; lit!=this->end(); ++lit)
623
    {
624 625 626 627
    OGREnvelope cExtent = lit->GetExtent(force); // may throw

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

628
  // If both srs are valid and if they are different
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
    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;

#if GDAL_VERSION_NUM >= 1700
      OGRCoordinateTransformation::DestroyCT(coordTransformation);
#else
#warning the following resource release may crash, please update your version of GDAL
      delete coordTransformation; // note there is no garanty
#endif
      }
    // else: If srs are invalid, we assume that extent are coherent

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

  return sExtent;
}
665

666 667 668 669 670 671 672 673
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);
674 675 676 677
  ulx = sExtent.MinX;
  uly = sExtent.MinY;
  lrx = sExtent.MaxX;
  lry = sExtent.MaxY;
678 679

  return outwkt;
680 681 682
}


Luc Hermitte's avatar
Luc Hermitte committed
683 684 685 686
/*virtual*/
void otb::ogr::DataSource::PrintSelf(
  std::ostream& os, itk::Indent indent) const
{
687
  assert(m_DataSource && "Datasource not initialized");
688
  BOOST_FOREACH(Layer const& l, *this)
689 690 691
    {
    l.PrintSelf(os, indent);
    }
Luc Hermitte's avatar
Luc Hermitte committed
692 693
}

694
/*virtual*/ void otb::ogr::DataSource::Graft(const itk::DataObject * itkNotUsed(data))
Luc Hermitte's avatar
Luc Hermitte committed
695 696 697
{
  assert(! "Disabled to check if it makes sense...");
}
698

Luc Hermitte's avatar
Luc Hermitte committed
699
bool otb::ogr::DataSource::HasCapability(std::string const& capabilityName) const
700 701
{
  assert(m_DataSource && "Datasource not initialized");
702
  return m_DataSource->TestCapability(capabilityName.c_str());
703 704 705 706 707
}

void otb::ogr::DataSource::SyncToDisk()
{
  assert(m_DataSource && "Datasource not initialized");
708
  bool ret = otb::ogr::version_proxy::SyncToDisk(m_DataSource);
709

710
  if(!ret)
711
    {
712
    itkExceptionMacro( << "Cannot flush the pending of the OGRDataSource <"
713
                       << GetDatasetDescription() << ">: " << CPLGetLastErrorMsg());
714 715
    }
}
716 717 718 719


std::string otb::ogr::DataSource::GetDatasetDescription() const
{
720
  std::vector<std::string> files = otb::ogr::version_proxy::GetFileListAsStringVector(m_DataSource);
721 722 723 724 725 726
  std::string description = "";
  for(std::vector<std::string>::const_iterator it = files.begin();it!=files.end();++it)
    description+=(*it)+", ";

  return description;
}