Commit b9fb07af authored by Antoine Regimbeau's avatar Antoine Regimbeau

MRG: Merge branch 'OGR_extended_filename' into develop

parents c0a46285 d3c8486f
......@@ -315,6 +315,36 @@ The available syntax for boolean options are:
- OFF, Off, off, false, False, 0 are available for setting a ’false’
boolean value
OGR DataSource options
^^^^^^^^^^^^^^^^^^^^^^^
We extended this process to OGR DataSource. There are three different type of
option : open, creation and layer creation. Those options come from the GDAL
API. In order to use them one just need to specify to which of this family
the option one want to use is from.
For open option :
::
&gdal:oo:<GDALKEY>=<VALUE>
For creation option :
::
&gdal:co:<GDALKEY>=<VALUE>
For layer creation option :
::
&gdal:lco:<GDALKEY>=<VALUE>
Examples
^^^^^^^^^^^^^^
......
......@@ -46,6 +46,7 @@
#include "otbOGRLayerWrapper.h"
#include "otbOGRVersionProxy.h"
#include "otbOGRExtendedFilenameToOptions.h"
class OGRLayer;
class OGRSpatialReference;
......@@ -88,6 +89,7 @@ public:
typedef itk::SmartPointer<const Self> ConstPointer;
//@}
typedef OGRExtendedFilenameToOptions FileNameHelperType;
/**\name Standard macros */
//@{
/** Default builder.
......@@ -162,7 +164,7 @@ public:
* \note No condition is assumed on the non-nullity of \c source.
* \see \c DataSource(GDALDataset *)
*/
static Pointer New(ogr::version_proxy::GDALDatasetType * sourcemode, Modes::type mode = Modes::Read);
static Pointer New(ogr::version_proxy::GDALDatasetType * sourcemode, Modes::type mode = Modes::Read , const std::vector< std::string > & layerOptions = std::vector< std::string >() );
//@}
/**\name Projection Reference property */
......@@ -368,7 +370,7 @@ public:
Layer CopyLayer(
Layer & srcLayer,
std::string const& newName,
char ** papszOptions = ITK_NULLPTR);
std::vector<std::string> const& papszOptions = std::vector<std::string>() );
//@}
/**\name Layers access
......@@ -497,6 +499,10 @@ public:
*/
ogr::version_proxy::GDALDatasetType & ogr();
void SetLayerCreationOptions( const std::vector< std::string > & options );
void AddLayerCreationOptions( std::vector< std::string > options );
const std::vector< std::string > & GetLayerCreationOptions() const ;
protected:
/** Default constructor.
* The actual \c GDALDataset is using the <em>in-memory</em> \c
......@@ -511,7 +517,7 @@ protected:
/** Init constructor.
* \post The newly constructed object owns the \c source parameter.
*/
DataSource(ogr::version_proxy::GDALDatasetType * source, Modes::type mode);
DataSource(ogr::version_proxy::GDALDatasetType * source, Modes::type mode , const std::vector< std::string > & layerOption = std::vector< std::string >() );
/** Destructor.
* \post The \c GDALDataset owned is released (if not null).
*/
......@@ -549,6 +555,7 @@ private:
private:
ogr::version_proxy::GDALDatasetType *m_DataSource;
std::vector< std::string > m_LayerOptions;
Modes::type m_OpenMode;
int m_FirstModifiableLayerID;
}; // end class DataSource
......
/*
* 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.
*/
#ifndef otbOGRExtendedFilenameToOptions_h
#define otbOGRExtendedFilenameToOptions_h
#include <unordered_map>
#include "otbExtendedFilenameHelper.h"
namespace otb
{
/** \class OGRExtendedFilenameToOptions
* \brief This class aim at processing GDAL option that can be pass through
* extended filename.
* \ingroup OTBExtendedFilename
* \ingroup OTBGdalAdapters
*
*/
#include "OTBGdalAdaptersExport.h"
class OTBGdalAdapters_EXPORT OGRExtendedFilenameToOptions : public ExtendedFilenameHelper
{
public:
/** Standard class typedefs. */
typedef OGRExtendedFilenameToOptions Self;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
typedef ExtendedFilenameHelper Superclass;
typedef Superclass::OptionMapType OptionMapType;
typedef OptionMapType::const_iterator ConstMapIteratorType;
typedef std::vector<std::string> GDALOptionType;
itkTypeMacro(OGRExtendedFilenameToOptions, otb::ExtendedFilenameHelper);
itkNewMacro(Self);
/** The creation option structure. */
struct OpenOptionType
{
GDALOptionType gdalOptions;
// std::unordered_map< std::string , bool > availableOptions;
};
struct CreationOptionType
{
GDALOptionType gdalOptions;
// std::unordered_map< std::string , bool > availableOptions;
};
struct LayerOptionType
{
std::unordered_map< std::string , std::string > gdalOptions;
};
/** Set extended filename */
void SetExtendedFileName(const char * extFname) override;
/** Get the GDAL option for type operation */
GDALOptionType GetGDALOptions( const std::string & type ) const ;
/** Get the deffierent GDAL options*/
GDALOptionType GetGDALOpenOptions() const ;
GDALOptionType GetGDALCreationOptions() const ;
GDALOptionType GetGDALLayerOptions() const ;
bool SimpleFileNameIsSet() const;
bool HasGDALLayerOption() const;
/** Set GDAL layer option through a vector of string */
void SetGDALLayerOptions( const GDALOptionType & options );
/** Add GDAL layer option to existing one */
void AddGDALLayerOptions( const GDALOptionType & options );
/** Constructor that return a pointer to an OGRExtendedFilename with
* GDAL layer option as options
*/
static Pointer GetGDALLayerOptionsHelper( const GDALOptionType & options );
protected:
OGRExtendedFilenameToOptions();
OGRExtendedFilenameToOptions( const GDALOptionType & options );
~OGRExtendedFilenameToOptions() override {};
private:
OGRExtendedFilenameToOptions(const Self &) = delete ;
void operator =(const Self&) = delete ;
OpenOptionType m_OpenOptions;
CreationOptionType m_CreationOptions;
LayerOptionType m_LayerOptions;
bool m_HasFileName;
};
} //end namespace otb
#endif // otbOGRExtendedFilenameToOptions_h
......@@ -97,7 +97,7 @@ OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type);
* \return NULL if file could not be open.
*/
OTBGdalAdapters_EXPORT
GDALDatasetType * Open(const char * filename, bool readOnly = true);
GDALDatasetType * Open(const char * filename, bool readOnly = true , std::vector< std::string > const & options = std::vector< std::string >() );
/**
* This function closes a dataset.
......@@ -126,7 +126,7 @@ OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type);
* \return NULL if dataset could not be created.
*/
OTBGdalAdapters_EXPORT
GDALDatasetType * Create(GDALDriverType * driver, const char * name);
GDALDatasetType * Create(GDALDriverType * driver, const char * name , std::vector< std::string > const & options = std::vector< std::string >() );
/**
......
......@@ -29,6 +29,9 @@ ENABLE_SHARED
OTBGDAL
OTBITK
TEST_DEPENDS
OTBTestKernel
DESCRIPTION
"${DOCUMENTATION}"
)
......@@ -29,6 +29,7 @@ set(OTBGdalAdapters_SRC
otbGeometriesToGeometriesFilter.cxx
otbOGRDataSourceWrapper.cxx
otbOGRVersionProxy.cxx
otbOGRExtendedFilenameToOptions.cxx
)
add_library(OTBGdalAdapters ${OTBGdalAdapters_SRC})
......
/*
* 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.
*/
#include "otbOGRExtendedFilenameToOptions.h"
#include "otb_boost_string_header.h"
#include "otb_boost_tokenizer_header.h"
namespace otb
{
OGRExtendedFilenameToOptions::
OGRExtendedFilenameToOptions():
m_HasFileName(false)
{
}
OGRExtendedFilenameToOptions::
OGRExtendedFilenameToOptions( const GDALOptionType & options ):
m_LayerOptions(),
m_HasFileName(false)
{
this->SetGDALLayerOptions( options );
}
OGRExtendedFilenameToOptions::Pointer
OGRExtendedFilenameToOptions::
GetGDALLayerOptionsHelper( const GDALOptionType & options )
{
Pointer res = new OGRExtendedFilenameToOptions( options );
res->UnRegister();
return res;
}
void
OGRExtendedFilenameToOptions::
SetExtendedFileName(const char *extFname)
{
Superclass::SetExtendedFileName(extFname);
m_HasFileName = true;
const OptionMapType & map = GetOptionMap();
ConstMapIteratorType it;
for ( it=map.begin(); it != map.end(); it++ )
{
std::vector<std::string> tmp;
boost::split(tmp, it->first, boost::is_any_of(":"), boost::token_compress_on);
if (tmp.size()>2 && (tmp[0]=="gdal") )
{
if ( tmp[1]=="oo" )
{
m_OpenOptions.gdalOptions.push_back(tmp[2] + "=" +it->second);
}
else if ( tmp[1]=="co" )
{
m_CreationOptions.gdalOptions.push_back(tmp[2] + "=" +it->second);
}
else if ( tmp[1]=="lco" )
{
m_LayerOptions.gdalOptions[tmp[2]] = it->second;
}
else
{
// log a warning
}
}
}
}
OGRExtendedFilenameToOptions::
GDALOptionType
OGRExtendedFilenameToOptions::
GetGDALOptions( const std::string & type ) const
{
if ( type == "layer" )
return GetGDALLayerOptions();
else if ( type == "creation" )
return m_CreationOptions.gdalOptions;
else if ( type == "open" )
return m_OpenOptions.gdalOptions;
else
{
// warn user : wrong option
return GDALOptionType();
}
}
void
OGRExtendedFilenameToOptions::
SetGDALLayerOptions( const OGRExtendedFilenameToOptions::GDALOptionType & options )
{
std::vector<std::string> tmp;
for ( const auto & option : options )
{
boost::split(tmp, option , boost::is_any_of(":"), boost::token_compress_on);
if ( tmp.size()<2 )
boost::split(tmp, option , boost::is_any_of("="), boost::token_compress_on);
m_LayerOptions.gdalOptions[ tmp[0] ] = tmp[1] ;
}
}
void
OGRExtendedFilenameToOptions::
AddGDALLayerOptions( const OGRExtendedFilenameToOptions::GDALOptionType & options )
{
for ( const auto & option : options )
{
std::vector<std::string> tmp;
boost::split(tmp, option , boost::is_any_of(":"), boost::token_compress_on);
if ( tmp.size()<2 )
boost::split(tmp, option , boost::is_any_of("="), boost::token_compress_on);
m_LayerOptions.gdalOptions[ tmp[0] ] = tmp[1] ;
}
}
bool
OGRExtendedFilenameToOptions::
SimpleFileNameIsSet() const
{
return m_HasFileName;
}
bool
OGRExtendedFilenameToOptions::
HasGDALLayerOption() const
{
return ! m_LayerOptions.gdalOptions.empty() ;
}
OGRExtendedFilenameToOptions::
GDALOptionType
OGRExtendedFilenameToOptions::
GetGDALLayerOptions() const
{
GDALOptionType options;
for (const auto & option : m_LayerOptions.gdalOptions )
{
options.push_back( option.first + "=" + option.second );
}
return options;
}
#define GetGDALOptionMacro( Type ) \
OGRExtendedFilenameToOptions:: \
GDALOptionType \
OGRExtendedFilenameToOptions:: \
GetGDAL##Type##Options() const \
{ \
return m_##Type##Options.gdalOptions; \
} \
GetGDALOptionMacro( Open )
GetGDALOptionMacro( Creation )
// GetGDALOptionMacro( Layer )
} //end namespace otb
......@@ -19,6 +19,7 @@
*/
#include "otbOGRVersionProxy.h"
#include "otbOGRHelpers.h"
#include "itkMacro.h"
......@@ -60,12 +61,17 @@ OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type)
}
GDALDatasetType * Open(const char * filename, bool readOnly)
GDALDatasetType * Open(const char * filename, bool readOnly , std::vector< std::string > const & options )
{
#if GDAL_VERSION_NUM<2000000
return OGRSFDriverRegistrar::Open(filename,!readOnly);
#else
return (GDALDatasetType *)GDALOpenEx(filename, (readOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR,NULL,NULL,NULL);
return (GDALDatasetType *)GDALOpenEx(
filename,
(readOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR,
NULL,
otb::ogr::StringListConverter( options ).to_ogr(),
NULL);
#endif
}
......@@ -78,7 +84,7 @@ void Close(GDALDatasetType * dataset)
#endif
}
GDALDatasetType * Create(GDALDriverType * driver, const char * name)
GDALDatasetType * Create(GDALDriverType * driver, const char * name , std::vector< std::string > const & options )
{
#if GDAL_VERSION_NUM<2000000
GDALDatasetType * ds = driver->CreateDataSource(name);
......@@ -88,7 +94,12 @@ GDALDatasetType * Create(GDALDriverType * driver, const char * name)
return ds;
#else
return driver->Create(name,0,0,0,GDT_Unknown,NULL);
return driver->Create( name ,
0 ,
0 ,
0 ,
GDT_Unknown ,
otb::ogr::StringListConverter( options ).to_ogr() );
#endif
}
......
......@@ -35,5 +35,52 @@ endif()
add_executable(otbOGRTestsIO otbOGRDataSourceWrapperIO.cxx)
target_link_libraries(otbOGRTestsIO ${OTBGdalAdapters-Test_LIBRARIES})
add_test(NAME coTuOGRDataSourceWrapperIO
otb_add_test(NAME coTuOGRDataSourceWrapperIO
COMMAND otbOGRTestsIO ${INPUTDATA}/ToulousePoints-examples.shp )
set(OTBOGRTests
otbOGRTestDriver.cxx
otbOGRExtendedFilenameToOptionsTest.cxx
otbOGRExtendedFilenameToOptionsGDALTest.cxx
)
add_executable(otbOGRTestDriver ${OTBOGRTests})
target_link_libraries(otbOGRTestDriver ${OTBGdalAdapters-Test_LIBRARIES})
otb_module_target_label(otbOGRTestDriver)
otb_add_test(NAME TvOGRExtendedFilename
COMMAND otbOGRTestDriver
--compare-ascii ${NOTOL}
${BASELINE}/TvOGRExtendedFilename.txt
${TEMP}/TvOGRExtendedFilenameTest.txt
otbOGRExtendedFileName
test.shp?&writegeom=ON&gdal:co:QUALITY=75&gdal:co:TILED=YES&gdal:co:BLOCKYSIZE=1024&gdal:lco:layeroption=OPTION&gdal:oo:openoption=OPTION
${TEMP}/TvOGRExtendedFilenameTest.txt )
#Problem with error thrown by GDAL : unable to catch it with "CPLGetLastErrorMsg"
# otb_add_test(NAME TvOGRExtendedFilenameGDALOpen
# COMMAND otbOGRTestDriver
# otbOGRExtendedFileNameGDALOpen
# ${INPUTDATA}/ToulousePoints-examples.shp?&gdal:oo:openOption=OPTION
# )
otb_add_test(NAME TvOGRExtendedFilenameGDALCreate
COMMAND otbOGRTestDriver
otbOGRExtendedFileNameGDALCreate
test.shp?gdal:co:creationOption=OPTION
)
otb_add_test(NAME TvOGRExtendedFilenameGDALLayer
COMMAND otbOGRTestDriver
otbOGRExtendedFileNameGDALLayer
test.shp?&gdal:lco:layeroption=OPTION
)
otb_add_test(NAME TvOGRExtendedFilenameGDALLayerOption
COMMAND otbOGRTestDriver
otbOGRExtendedFileNameGDALLayerOption
test.shp
)
message(STATUS "Test link : ${OTBGdalAdapters-Test_LIBRARIES}")
\ No newline at end of file
/*
* 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.
*/
#include "cpl_error.h"
#include "otbOGRExtendedFilenameToOptions.h"
#include "otbOGRDataSourceWrapper.h"
#include <iostream>
#include <fstream>
int otbOGRExtendedFileNameGDALOpen(int , char* argv[])
{
auto test = otb::ogr::DataSource::New( argv[1] );
std::string error = CPLGetLastErrorMsg();
return 0;
}
int otbOGRExtendedFileNameGDALCreate(int , char* argv[])
{
auto test = otb::ogr::DataSource::New( argv[1] , otb::ogr::DataSource::Modes::Overwrite);
std::string error = CPLGetLastErrorMsg();
if ( error.find( "does not support creation option creationOption" ) )
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
int otbOGRExtendedFileNameGDALLayer(int , char* argv[])
{
auto test = otb::ogr::DataSource::New( argv[1] , otb::ogr::DataSource::Modes::Update_LayerOverwrite);
test->CreateLayer( "2layertest" ,
ITK_NULLPTR ,
wkbUnknown );
std::string error = CPLGetLastErrorMsg();
if ( error.find( "does not support layer creation option layeroption" ) )
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
int otbOGRExtendedFileNameGDALLayerOption(int , char* argv[])
{
auto test = otb::ogr::DataSource::New( argv[1] , otb::ogr::DataSource::Modes::Update_LayerOverwrite);
std::vector<std::string> option { "vectorlayeroption=OPTION" };
test->CreateLayer( "2layertest" ,
ITK_NULLPTR ,
wkbUnknown ,
option );
std::string error = CPLGetLastErrorMsg();
if ( error.find( "does not support layer creation option vectorlayeroption" ) )
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
/*
* 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.
*/
#include "otbOGRExtendedFilenameToOptions.h"
#include <algorithm>
#include <iostream>
#include <fstream>
using namespace otb;
typedef OGRExtendedFilenameToOptions FilenameHelperType;
int otbOGRExtendedFileName(int , char* argv[])
{
// Verify the number of parameters in the command line
const char * inputExtendedFilename = argv[1];
const char * outputFilename = argv[2];
std::cout<< argv[1] <<" "<<argv[2]<<std::endl;
FilenameHelperType::Pointer helper = FilenameHelperType::New();
helper->SetExtendedFileName(inputExtendedFilename);
std::ofstream file;
file.open(outputFilename);
file << helper->SimpleFileNameIsSet() << std::endl;
file << helper->GetSimpleFileName() << std::endl;
file << "Open option :"<<std::endl;
FilenameHelperType::GDALOptionType open = helper->GetGDALOpenOptions();
for ( auto option : open )
{
file<< option << std::endl;
}
file << "Create option :"<<std::endl;
FilenameHelperType::GDALOptionType create = helper->GetGDALOptions("creation");
for ( auto option : create )
{
file<< option << std::endl;
}
file << "Layer option :"<<std::endl;
FilenameHelperType::GDALOptionType layer = helper->GetGDALOptions("layer");
for ( auto option : layer )
{
file<< option << std::endl;
}
file<< "End of classic helper."<<std::endl;
layer.push_back("TOTO=first");
FilenameHelperType::Pointer layerHelper =
FilenameHelperType::GetGDALLayerOptionsHelper ( layer );
std::cout<< layerHelper->GetGDALLayerOptions()[0] <<std::endl;
FilenameHelperType::GDALOptionType newOptions;