Commit e5fd32d1 authored by Julien Malik's avatar Julien Malik

BUG: layer creation was still buggy

parent a3add895
......@@ -115,7 +115,7 @@ char const* DeduceDriverName(std::string filename)
otb::ogr::DataSource::DataSource()
: m_DataSource(0),
m_OpenMode(Modes::Update_LayerOverwrite),
m_OpenMode(Modes::Update_LayerUpdate),
m_FirstModifiableLayerID(0)
{
Drivers::Init();
......@@ -170,28 +170,6 @@ otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string c
source->SetDriver(d);
}
return otb::ogr::DataSource::New(source, mode);
#if 0
// Hand made factory based on file extension.
char const* driverName = DeduceDriverName(filename);
if (!driverName)
{
itkGenericExceptionMacro(<< "No OGR driver known to OTB to create and handle a DataSource named <"
<<filename<<">.");
}
OGRSFDriver * d = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driverName);
assert(d && "OGR driver not found");
OGRDataSource * source = d->CreateDataSource(filename.c_str());
if (!source) {
itkGenericExceptionMacro(<< "Failed to create OGRDataSource <"<<filename
<<"> (driver name: " << driverName<<">: " << CPLGetLastErrorMsg());
}
source->SetDriver(d);
otb::ogr::DataSource::Pointer res = new otb::ogr::DataSource(source, mode);
res->UnRegister();
return res;
#endif
}
void DeleteDataSource(std::string const& datasourceName)
......@@ -210,13 +188,13 @@ void DeleteDataSource(std::string const& datasourceName)
OGRErr ret = ogrDriver->DeleteDataSource(datasourceName.c_str());
if (ret != OGRERR_NONE)
{
itkGenericOutputMacro(<< "Deletion of data source " << datasourceName
itkGenericExceptionMacro(<< "Deletion of data source " << datasourceName
<< " failed: " << CPLGetLastErrorMsg());
}
}
else
{
itkGenericOutputMacro(<< "Cannot delete data source " << datasourceName);
itkGenericExceptionMacro(<< "Cannot delete data source " << datasourceName);
}
} // if (poDS != NULL)
}
......@@ -237,76 +215,6 @@ otb::ogr::DataSource::New(std::string const& datasourceName, Modes::type mode)
}
return OpenDataSource(datasourceName, mode);
#if 0
const bool write = mode & Modes::write;
// std::cout << "Opening datasource " << filename << " update=" << update << "\n";
if (itksys::SystemTools::FileExists(filename.c_str()))
{
if (mode & Modes::read)
{
// Open in read mode
OGRDataSource * source = OGRSFDriverRegistrar::Open(filename.c_str(), FALSE);
if (!source)
{
itkGenericExceptionMacro(<< "Failed to open OGRDataSource file "
<< filename<<": " << CPLGetLastErrorMsg());
}
Pointer res = new DataSource(source);
res->UnRegister();
return res;
}
else if (mode & Modes::append)
{
// Open in "update" mode
OGRDataSource * source = OGRSFDriverRegistrar::Open(filename.c_str(), TRUE);
if (!source)
{
itkGenericExceptionMacro(<< "Failed to open OGRDataSource file "
<< filename<<": " << CPLGetLastErrorMsg());
}
Pointer res = new DataSource(source);
res->UnRegister();
return res;
}
else if (mode & Modes::write)
{
// Attempt to delete the datasource if it already exists
OGRDataSource * poDS = OGRSFDriverRegistrar::Open(filename.c_str(), TRUE);
if (poDS != NULL)
{
OGRSFDriver * ogrDriver = poDS->GetDriver();
OGRDataSource::DestroyDataSource(poDS);
//Erase the data if possible
if (ogrDriver->TestCapability(ODrCDeleteDataSource))
{
//Delete datasource
OGRErr ret = ogrDriver->DeleteDataSource(filename.c_str());
if (ret != OGRERR_NONE)
{
itkGenericOutputMacro(<< "Deletion of data source " << filename
<< " failed: " << CPLGetLastErrorMsg());
}
}
else
{
itkGenericOutputMacro(<< "Cannot delete data source " << filename);
}
} // if (poDS != NULL)
} // else if (update)
} // if (itksys::SystemTools::FileExists(filename.c_str()))
else
{
// File does not exists
if (mode & Modes::read || mode & Modes::append)
{
itkGenericExceptionMacro(<< "No DataSource named <"<<filename<<"> exists,"
" and the file opening mode does not permit updates. DataSource creation is thus aborted.");
}
}
return CreateDataSourceFromDriver(filename);
#endif
}
/*static*/
......@@ -354,39 +262,97 @@ otb::ogr::Layer otb::ogr::DataSource::CreateLayer(
{
assert(m_DataSource && "Datasource not initialized");
// 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
itkGenericOutputMacro(<< "Requesting layer creation in read-only OGRDataSource. Returning the existing layer");
return l;
}
// Other mode : Check if the layer already exists.
otb::ogr::Layer layer = GetLayer(name); // won't throw on failure
switch (m_OpenMode)
{
case Modes::Invalid:
assert(false && "Invalid OGRDataSource opening mode");
itkGenericExceptionMacro(<< "Invalid OGRDataSource opening mode");
break;
case Modes::Read:
itkGenericExceptionMacro(<< "OGRDataSource is opened in Read mode : cannot create a layer");
break;
default:
break;
}
// Make a local copy
std::vector<std::string> options(papszOptions);
if (m_OpenMode == Modes::Update_LayerOverwrite)
case Modes::Update_LayerOverwrite:
{
options.push_back("OVERWRITE=YES");
// 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)
{
itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
<< "> in the OGRDataSource file <" << m_DataSource->GetName()
<<">: " << CPLGetLastErrorMsg());
}
const bool modifiable = true;
return Layer(ol, modifiable);
}
char** papszOptionsChar = otb::ogr::StringListConverter(options).to_ogr();
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)
{
itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
<< "> in the OGRDataSource file <" << m_DataSource->GetName()
<<">: " << CPLGetLastErrorMsg());
}
OGRLayer * ol = m_DataSource->CreateLayer(
name.c_str(), poSpatialRef, eGType, papszOptionsChar);
if (!ol)
const bool modifiable = true;
return Layer(ol, modifiable);
}
}
break;
case Modes::Update_LayerCreateOnly:
{
itkGenericExceptionMacro(<< "Failed to create the layer <"<<name
<< "> in the OGRDataSource file <" << m_DataSource->GetName()
<<">: " << CPLGetLastErrorMsg());
// The layer exists. Returns it
// It will be non-modifiable if already existing at OGRDataSource creation time
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
<< "> in the OGRDataSource file <" << m_DataSource->GetName()
<<">: " << CPLGetLastErrorMsg());
}
const bool modifiable = true;
return Layer(ol, modifiable);
}
break;
default :
assert(false && "Should never be there");
itkGenericExceptionMacro(<< "OGRDataSource opening mode not supported");
break;
}
const bool modifiable = true;
Layer l(ol, modifiable);
return l;
itkGenericExceptionMacro(<< "OGRDataSource opening mode not supported");
return Layer(0, false); // keep compiler happy
}
otb::ogr::Layer otb::ogr::DataSource::CopyLayer(
......
......@@ -158,36 +158,34 @@ BOOST_AUTO_TEST_CASE(OGRDataSource_shp_overwrite)
}
const std::string k_name = boost::unit_test::framework::master_test_suite().argv[1];
std::cout << "Working in directory : " << k_name << std::endl;
const std::string workingdir = k_name + "/shp";
// Create an empty temporary directory for the test
if ( itksys::SystemTools::FileExists(k_name.c_str()) )
if ( itksys::SystemTools::FileExists(workingdir.c_str()) )
{
itksys::SystemTools::RemoveADirectory(k_name.c_str());
itksys::SystemTools::RemoveADirectory(workingdir.c_str());
}
itksys::SystemTools::MakeDirectory(k_name.c_str());
itksys::SystemTools::MakeDirectory(workingdir.c_str());
std::string shp_filename = k_name + "/" + k_name + ".shp";
shp_filename = itksys::SystemTools::ConvertToOutputPath(shp_filename.c_str());
std::cout << "shp_filename : " << shp_filename << std::endl;
std::string filename = workingdir + "/" + k_name + ".shp";
filename = itksys::SystemTools::ConvertToOutputPath(filename.c_str());
const std::string layer1 = k_name;
// Cannot create read data source if file does not exists
BOOST_CHECK_THROW(ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Read),
BOOST_CHECK_THROW(ogr::DataSource::New(filename, ogr::DataSource::Modes::Read),
itk::ExceptionObject);
// Check invalid modes
BOOST_CHECK_THROW(ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Invalid),
BOOST_CHECK_THROW(ogr::DataSource::New(filename, ogr::DataSource::Modes::Invalid),
itk::ExceptionObject);
BOOST_CHECK_THROW(ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::MAX__),
BOOST_CHECK_THROW(ogr::DataSource::New(filename, ogr::DataSource::Modes::MAX__),
itk::ExceptionObject);
// Overwrite mode supports the creation of file if it does not exists
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Overwrite);
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Overwrite);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1, 0, wkbPoint);
OGRFeatureDefn & defn = l.GetLayerDefn();
......@@ -205,7 +203,7 @@ BOOST_AUTO_TEST_CASE(OGRDataSource_shp_overwrite)
// Read file we have written
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Read);
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Read);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> GetLayerChecked(layer1);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 1);
......@@ -221,7 +219,7 @@ BOOST_AUTO_TEST_CASE(OGRDataSource_shp_overwrite)
// Now really test overwriting the file already exists)
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Overwrite);
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Overwrite);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1, 0, wkbPoint);
OGRFeatureDefn & defn = l.GetLayerDefn();
......@@ -239,13 +237,13 @@ BOOST_AUTO_TEST_CASE(OGRDataSource_shp_overwrite)
// Read file we have written
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Read);
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Read);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> GetLayerChecked(layer1);
BOOST_ASSERT(l.GetFeatureCount(true) == 1);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 1);
ogr::Feature f = l.GetFeature(0);
BOOST_ASSERT(f[0].GetValue<int>() == 43);
BOOST_ASSERT(f[1].GetValue<double>() == 43.0);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 43);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 43.0);
ogr::UniqueGeometryPtr p = f.StealGeometry();
const OGRPoint ref(43, 43);
......@@ -256,21 +254,21 @@ BOOST_AUTO_TEST_CASE(OGRDataSource_shp_overwrite)
// Open in Update_LayerUpdate
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Update_LayerUpdate);
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Update_LayerUpdate);
// Check that we can read the file
BOOST_ASSERT(ds);
ogr::Layer l = ds -> GetLayerChecked(layer1);
BOOST_ASSERT(l.GetFeatureCount(true) == 1);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 1);
ogr::Feature f = l.GetFeature(0);
BOOST_ASSERT(f[0].GetValue<int>() == 43);
BOOST_ASSERT(f[1].GetValue<double>() == 43.0);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 43);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 43.0);
ogr::UniqueGeometryPtr p = f.StealGeometry();
const OGRPoint ref(43, 43);
BOOST_CHECK(ogr::Equals(*p, ref));
// Add a new feature
// Add a second feature
ogr::Feature f2(l.GetLayerDefn());
f2[0].SetValue(44);
f2[1].SetValue(44.0);
......@@ -281,30 +279,297 @@ BOOST_AUTO_TEST_CASE(OGRDataSource_shp_overwrite)
}
// Read file we have written
// Read the file we have written
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(shp_filename, ogr::DataSource::Modes::Read);
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Read);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> GetLayerChecked(0);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 2);
ogr::Feature f = l.GetFeature(0);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 43);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 43.0);
ogr::UniqueGeometryPtr p1 = f.StealGeometry();
const OGRPoint ref1(43, 43);
BOOST_CHECK(ogr::Equals(*p1, ref1));
f = l.GetFeature(1);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 44);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 44.0);
ogr::UniqueGeometryPtr p2 = f.StealGeometry();
const OGRPoint ref2(44, 44);
BOOST_CHECK(ogr::Equals(*p2, ref2));
}
#if 0 // shp files do not support Update_LayerOverwrite
// Open in Update_LayerOverwrite
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Update_LayerOverwrite);
// Check that we can read the file
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1);
BOOST_ASSERT(l.GetFeatureCount(true) == 2);
ogr::Feature f = l.GetFeature(0);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 43);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 43.0);
ogr::UniqueGeometryPtr p1 = f.StealGeometry();
const OGRPoint ref1(43, 43);
BOOST_CHECK(ogr::Equals(*p1, ref1));
f = l.GetFeature(1);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 44);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 44.0);
ogr::UniqueGeometryPtr p2 = f.StealGeometry();
const OGRPoint ref2(44, 44);
BOOST_CHECK(ogr::Equals(*p2, ref2));
// Add a new feature
ogr::Feature f3(l.GetLayerDefn());
f3[0].SetValue(45);
f3[1].SetValue(45.0);
const OGRPoint p3(45, 45);
f3.SetGeometry(&p3);
l.CreateFeature(f3);
BOOST_CHECK_EQUAL(l.GetFeatureCount(false), 1);
}
// Read file we have written
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Read);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> GetLayerChecked(0);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 1);
ogr::Feature f = l.GetFeature(0);
BOOST_ASSERT(f[0].GetValue<int>() == 43);
BOOST_ASSERT(f[1].GetValue<double>() == 43.0);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 43);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 43.0);
ogr::UniqueGeometryPtr p1 = f.StealGeometry();
const OGRPoint ref1(43, 43);
BOOST_CHECK(ogr::Equals(*p1, ref1));
f = l.GetFeature(1);
BOOST_ASSERT(f[0].GetValue<int>() == 44);
BOOST_ASSERT(f[1].GetValue<double>() == 44.0);
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 44);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 44.0);
ogr::UniqueGeometryPtr p2 = f.StealGeometry();
const OGRPoint ref2(44, 44);
BOOST_CHECK(ogr::Equals(*p2, ref2));
}
#endif
}
BOOST_AUTO_TEST_CASE(OGRDataSource_sqlite_overwrite)
{
if (boost::unit_test::framework::master_test_suite().argc < 2)
{
BOOST_THROW_EXCEPTION( std::runtime_error("not enough arguments") );
}
const std::string k_name = boost::unit_test::framework::master_test_suite().argv[1];
const std::string workingdir = k_name + "/sqlite";
// Create an empty temporary directory for the test
if ( itksys::SystemTools::FileExists(workingdir.c_str()) )
{
itksys::SystemTools::RemoveADirectory(workingdir.c_str());
}
itksys::SystemTools::MakeDirectory(workingdir.c_str());
std::string filename = workingdir + "/" + k_name + ".sqlite";
filename = itksys::SystemTools::ConvertToOutputPath(filename.c_str());
const std::string layer1 = k_name;
// Cannot create read data source if file does not exists
BOOST_CHECK_THROW(ogr::DataSource::New(filename, ogr::DataSource::Modes::Read),
itk::ExceptionObject);
// Check invalid modes
BOOST_CHECK_THROW(ogr::DataSource::New(filename, ogr::DataSource::Modes::Invalid),
itk::ExceptionObject);
BOOST_CHECK_THROW(ogr::DataSource::New(filename, ogr::DataSource::Modes::MAX__),
itk::ExceptionObject);
// Overwrite mode supports the creation of file if it does not exists
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Overwrite);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1, 0, wkbPoint);
OGRFeatureDefn & defn = l.GetLayerDefn();
l.CreateField(k_f0);
l.CreateField(k_f1);
ogr::Feature f(defn);
f[0].SetValue(42);
f[1].SetValue(42.0);
const OGRPoint p(42, 42);
f.SetGeometry(&p);
l.CreateFeature(f);
BOOST_CHECK_EQUAL(l.GetFeatureCount(false), 1);
}
// Read file we have written
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Read);
BOOST_ASSERT(ds);
ogr::Layer l = ds->GetLayerChecked(layer1);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 1);
ogr::Feature f = *l.begin();
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 42);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 42.0);
ogr::UniqueGeometryPtr p = f.StealGeometry();
const OGRPoint ref(42, 42);
BOOST_CHECK(ogr::Equals(*p, ref));
}
// Now really test overwriting the file already exists)
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Overwrite);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1, 0, wkbPoint);
OGRFeatureDefn & defn = l.GetLayerDefn();
l.CreateField(k_f0);
l.CreateField(k_f1);
ogr::Feature f(defn);
f[0].SetValue(43);
f[1].SetValue(43.0);
const OGRPoint p(43, 43);
f.SetGeometry(&p);
l.CreateFeature(f);
BOOST_CHECK_EQUAL(l.GetFeatureCount(false), 1);
}
// Read file we have written
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Read);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 1);
ogr::Feature f = *l.begin();
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 43);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 43.0);
ogr::UniqueGeometryPtr p = f.StealGeometry();
const OGRPoint ref(43, 43);
BOOST_CHECK(ogr::Equals(*p, ref));
}
// Open in Update_LayerUpdate
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Update_LayerUpdate);
// Check that we can read the file
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 1);
ogr::Layer::iterator fIt = l.begin();
ogr::Feature f = *fIt;
BOOST_CHECK_EQUAL(f[0].GetValue<int>(), 43);
BOOST_CHECK_EQUAL(f[1].GetValue<double>(), 43.0);
ogr::UniqueGeometryPtr p = f.StealGeometry();
const OGRPoint ref(43, 43);
BOOST_CHECK(ogr::Equals(*p, ref));
// Add a second feature
ogr::Feature f2(l.GetLayerDefn());
f2[0].SetValue(44);
f2[1].SetValue(44.0);
const OGRPoint p2(44, 44);
f2.SetGeometry(&p2);
l.CreateFeature(f2);
BOOST_CHECK_EQUAL(l.GetFeatureCount(false), 2);
}
// Read the file we have written
{
ogr::DataSource::Pointer ds
= ogr::DataSource::New(filename, ogr::DataSource::Modes::Read);
BOOST_ASSERT(ds);
ogr::Layer l = ds -> CreateLayer(layer1);
BOOST_CHECK_EQUAL(l.GetFeatureCount(true), 2);
ogr::Layer::iterator fIt = l.begin();
ogr::Feature f = *fIt;