diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx index 34829c80653090da921925efc929a964fa9b54e7..f252c2368f9f5fd3d01ab895ddb63439a7d20298 100644 --- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx +++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.cxx @@ -122,6 +122,30 @@ otb::ogr::DataSource::New(OGRDataSource * source) /*===========================================================================*/ /*================================[ layers ]=================================*/ /*===========================================================================*/ +otb::ogr::DataSource::const_iterator otb::ogr::DataSource::cbegin() const +{ + // return const_iterator(*this, 0); + assert(!"not-ready"); + return const_iterator(); +} + +otb::ogr::DataSource::const_iterator otb::ogr::DataSource::cend() const +{ + // return const_iterator(*this, GetLayersCount()); + assert(!"not-ready"); + return const_iterator(); +} + +otb::ogr::DataSource::iterator otb::ogr::DataSource::begin() +{ + return iterator(*this, 0); +} + +otb::ogr::DataSource::iterator otb::ogr::DataSource::end() +{ + return iterator(*this, GetLayersCount()); +} + otb::ogr::Layer otb::ogr::DataSource::CreateLayer( std::string const& name, OGRSpatialReference * poSpatialRef/* = NULL */, diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h index 9f234ef5910cf84ec74c327c0072d6d2a57def93..8db6b1465a450c987c68393c721ce138b677e9d2 100644 --- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h +++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRDataSourceWrapper.h @@ -36,494 +36,558 @@ class OGRGeometry; #include "ogr_core.h" // OGRwkbGeometryType namespace otb { namespace ogr { - /**\ingroup Geometry - * \class ImageReference - * \todo see how mix it with the \c otb::ogr::DataSource wrapper as it was - * with \c VectorData. +/**\ingroup Geometry + * \class ImageReference + * \todo see how mix it with the \c otb::ogr::DataSource wrapper as it was + * with \c VectorData. + */ +template <typename TPrecision> class ImageReference + { +public: + typedef TPrecision PrecisionType; + enum { Dimension = 2 }; + /**\name Standard ITK typedefs */ + //@{ + //@} + /**\name Template-parameters typedefs */ + //@{ + typedef itk::Vector<PrecisionType, 2> SpacingType; + typedef itk::Point<PrecisionType, 2> OriginType; + typedef itk::Point<PrecisionType, 2> PointType; + //@} + + /** Default constructor. + * \post <tt>m_Spacing = {1,1}</tt> + * \post <tt>m_Origin = {0,0}</tt> + */ + ImageReference() + { + m_Spacing.Fill(1); + m_Origin.Fill(0); + } + /** Init constructor. + * \post <tt>m_Spacing = spacing</tt> + * \post <tt>m_Origin = origin</tt> + */ + ImageReference(SpacingType const& spacing, OriginType const& origin) + : m_Spacing(spacing), m_Origin(origin) + { + } + + /**\name Origin property + * Represents the origin of the geometries in the image coordinates system. + */ + //@{ + itkGetConstReferenceMacro(Origin, OriginType); //!< Origin getter. + itkSetMacro(Origin, OriginType); //!< Origin setter. + void SetOrigin(const TPrecision origin[Dimension]) //!< Origin setter. + { + const OriginType p(origin); + this->SetOrigin(p); + } + //@} + + /**\name Spacing property + * Spacing of the geometries to put in the corresponding image coordinates. */ - template <typename TPrecision> - class ImageReference + //@{ + itkGetConstReferenceMacro(Spacing, SpacingType); //!< Spacing getter. + void SetSpacing(const SpacingType& spacing) //!< Spacing setter. + { + itkDebugMacro("setting Spacing to " << spacing); + if (this->m_Spacing != spacing) { - public: - typedef TPrecision PrecisionType; - enum { Dimension = 2 }; - /**\name Standard ITK typedefs */ - //@{ - //@} - /**\name Template-parameters typedefs */ - //@{ - typedef itk::Vector<PrecisionType, 2> SpacingType; - typedef itk::Point<PrecisionType, 2> OriginType; - typedef itk::Point<PrecisionType, 2> PointType; - //@} - - /** Default constructor. - * \post <tt>m_Spacing = {1,1}</tt> - * \post <tt>m_Origin = {0,0}</tt> - */ - ImageReference() - { - m_Spacing.Fill(1); - m_Origin.Fill(0); - } - /** Init constructor. - * \post <tt>m_Spacing = spacing</tt> - * \post <tt>m_Origin = origin</tt> - */ - ImageReference(SpacingType const& spacing, OriginType const& origin) - : m_Spacing(spacing), m_Origin(origin) - { - } - - /**\name Origin property - * Represents the origin of the geometries in the image coordinates system. - */ - //@{ - itkGetConstReferenceMacro(Origin, OriginType); //!< Origin getter. - itkSetMacro(Origin, OriginType); //!< Origin setter. - void SetOrigin(const TPrecision origin[Dimension]) //!< Origin setter. - { - const OriginType p(origin); - this->SetOrigin(p); - } - //@} - - /**\name Spacing property - * Spacing of the geometries to put in the corresponding image coordinates. - */ - //@{ - itkGetConstReferenceMacro(Spacing, SpacingType); //!< Spacing getter. - void SetSpacing(const SpacingType& spacing) //!< Spacing setter. - { - itkDebugMacro("setting Spacing to " << spacing); - if (this->m_Spacing != spacing) - { - this->m_Spacing = spacing; - this->Modified(); - } - } - void SetSpacing(const TPrecision spacing[Dimension]) //!< Spacing setter. - { - const SpacingType s(spacing); - this->SetSpacing(s); - } - //@} - - /** - * Projects a point from the Data Source coordinates system to the image - * coordinates system. - * \param[in] point point in Data Source coordinates system - * \param[out] physicalPoint point in the image coordinates system. - * \throw None - */ - void TransformPointToPhysicalPoint(const PointType& point, PointType& physicalPoint) const - { - for (size_t i=0; i!=Dimension; ++i) - physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i]; - } - - /** - * Projects a point from the Data Source coordinates system to the image - * coordinates system. - * \param[in] point point in Data Source coordinates system - * \return the point projected in the image coordinates system. - * \throw None - */ - void TransformPointToPhysicalPoint(const PointType& point) const - { - // why no loop on VDimension ? - PointType physicalPoint; - for (size_t i=0; i!=Dimension; ++i) - physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i]; - return physicalPoint; - } - private: - SpacingType m_Spacing; - OriginType m_Origin; - }; - - /**\ingroup Geometry - * \class DataSource - * Collection of geometric objects. - * - * This class is meant to supercede \c otb::VectorData class. It provides - * an encapsulation of OGR classes. In that particular case, it's an - * encapsulation of \c OGRDataSource. - * - * \note Not meant to be inherited - * \note This class has an entity semantics: \em non-copyable, nor \em - * assignable. - * \note \c OGRRegisterAll() is implicitly called on construction - * \internal As the class is not meant to be inherited, no new function is virtual. - * - * \note The following function haven't been encapsulated (yet?): - * - \c SetStyleTable() & \c GetStyleTable() - * - \c SetDriver() & \c GetDriver() - * - all functions related to the reference count. - */ - class DataSource : public itk::DataObject + this->m_Spacing = spacing; + this->Modified(); + } + } + void SetSpacing(const TPrecision spacing[Dimension]) //!< Spacing setter. + { + const SpacingType s(spacing); + this->SetSpacing(s); + } + //@} + + /** + * Projects a point from the Data Source coordinates system to the image + * coordinates system. + * \param[in] point point in Data Source coordinates system + * \param[out] physicalPoint point in the image coordinates system. + * \throw None + */ + void TransformPointToPhysicalPoint(const PointType& point, PointType& physicalPoint) const + { + for (size_t i=0; i!=Dimension; ++i) + physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i]; + } + + /** + * Projects a point from the Data Source coordinates system to the image + * coordinates system. + * \param[in] point point in Data Source coordinates system + * \return the point projected in the image coordinates system. + * \throw None + */ + void TransformPointToPhysicalPoint(const PointType& point) const { + // why no loop on VDimension ? + PointType physicalPoint; + for (size_t i=0; i!=Dimension; ++i) + physicalPoint[i] = point[i] * m_Spacing[i] + m_Origin[i]; + return physicalPoint; + } +private: + SpacingType m_Spacing; + OriginType m_Origin; + }; + +/**\ingroup Geometry + * \class DataSource + * Collection of geometric objects. + * + * This class is meant to supercede \c otb::VectorData class. It provides + * an encapsulation of OGR classes. In that particular case, it's an + * encapsulation of \c OGRDataSource. + * + * \note Not meant to be inherited + * \note This class has an entity semantics: \em non-copyable, nor \em + * assignable. + * \note \c OGRRegisterAll() is implicitly called on construction + * \internal As the class is not meant to be inherited, no new function is virtual. + * + * \note The following function haven't been encapsulated (yet?): + * - \c SetStyleTable() & \c GetStyleTable() + * - \c SetDriver() & \c GetDriver() + * - all functions related to the reference count. + */ +class DataSource : public itk::DataObject + { +public: + /**\name Standard ITK typedefs */ + //@{ + typedef DataSource Self; + typedef itk::DataObject Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + //@} + + /**\name Standard macros */ + //@{ + /** Default builder. + * This builder function creates a new \c DataSource() with its default + * constructor. The actual \c OGRDataSource is using the <em>in-memory</em> + * \c OGRSFDriver: \c OGRMemDriver. + * + * \throw itk::ExceptionObject if the inner \c OGRDataSource cannot be + * opened. + * + * \note \c OGRRegisterAll() is implicitly called on construction + * \see \c DataSource() + */ + itkNewMacro(Self); + itkTypeMacro(Layer, DataObject); + // itkStaticConstMacro(Dimension, unsigned int, VDimension); + //@} + /**\name Creation functions */ + //@{ + struct Modes { enum type { invalid, read=1, write=2, MAX__ }; }; + + /** + * Builder from an existing named data source. + * \param[in] filename filename of the data source + * \param[in] mode opening mode (read or read-write) + * \return a newly created \c DataSource. + * \throw itk::ExceptionObject if the inner \c OGRDataSource cannot be + * opened. + * \note \c OGRRegisterAll() is implicitly called on construction + * \see \c DataSource(OGRDataSource *) + */ + static Pointer New(std::string const& filename, Modes::type mode=Modes::read); + /** + * Builder from a built \c OGRDataSource. + * \param[in,out] source \c OGRDataSource already constructed. + * \return a newly created \c DataSource that assumes ownership of \c + * source. + * \throw Nothing + * \note \c OGRRegisterAll() is supposed to have been called before building + * \c source. + * \note no condition is assumed on the non-nullity of \c source. + * \see \c DataSource(OGRDataSource *) + */ + static Pointer New(OGRDataSource * source); + //@} + + /**\name Projection Reference property */ + //@{ + void SetProjectionRef(const std::string& projectionRef); + std::string GetProjectionRef() const; + //@} + + /** Clears the data source. + * \post the \c OGRDataSource owned is destroyed with the dedicated function + * from OGR %API. + * \post <tt>m_DataSource = 0</tt> + */ + bool Clear(); + + /**\name Iteration */ + //@{ + /**\ingroup Geometry + * \class layer_iter + * Implementation class for \c Layer iterator. + * \internal + * \sa otb::ogr::Layer::iterator + * \sa otb::ogr::Layer::const_iterator + * \note Naming policy is compliant with C++ standard as the iterator are as + * well. This will permit transparent integration with all standard and boost + * algorithms, and C++11 <em>for-range loops</em> for instance. + * \see http://www.boost.org/doc/libs/1_49_0/libs/iterator/doc/iterator_facade.html#tutorial-example + */ + template <class Value> class layer_iter + : public boost::iterator_facade<layer_iter<Value>, Value, boost::random_access_traversal_tag> + { + struct enabler {}; public: - /**\name Standard ITK typedefs */ - //@{ - typedef DataSource Self; - typedef itk::DataObject Superclass; - typedef itk::SmartPointer<Self> Pointer; - typedef itk::SmartPointer<const Self> ConstPointer; - //@} - - /**\name Standard macros */ - //@{ - /** Default builder. - * This builder function creates a new \c DataSource() with its default - * constructor. The actual \c OGRDataSource is using the <em>in-memory</em> - * \c OGRSFDriver: \c OGRMemDriver. - * - * \throw itk::ExceptionObject if the inner \c OGRDataSource cannot be - * opened. - * - * \note \c OGRRegisterAll() is implicitly called on construction - * \see \c DataSource() - */ - itkNewMacro(Self); - itkTypeMacro(Layer, DataObject); - // itkStaticConstMacro(Dimension, unsigned int, VDimension); - //@} - /**\name Creation functions */ - //@{ - struct Modes { enum type { invalid, read=1, write=2, MAX__ }; }; - - /** - * Builder from an existing named data source. - * \param[in] filename filename of the data source - * \param[in] mode opening mode (read or read-write) - * \return a newly created \c DataSource. - * \throw itk::ExceptionObject if the inner \c OGRDataSource cannot be - * opened. - * \note \c OGRRegisterAll() is implicitly called on construction - * \see \c DataSource(OGRDataSource *) - */ - static Pointer New(std::string const& filename, Modes::type mode=Modes::read); - /** - * Builder from a built \c OGRDataSource. - * \param[in,out] source \c OGRDataSource already constructed. - * \return a newly created \c DataSource that assumes ownership of \c - * source. - * \throw Nothing - * \note \c OGRRegisterAll() is supposed to have been called before building - * \c source. - * \note no condition is assumed on the non-nullity of \c source. - * \see \c DataSource(OGRDataSource *) - */ - static Pointer New(OGRDataSource * source); - //@} - - /**\name Projection Reference property */ - //@{ - void SetProjectionRef(const std::string& projectionRef); - std::string GetProjectionRef() const; - //@} - - /** Clears the data source. - * \post the \c OGRDataSource owned is destroyed with the dedicated function - * from OGR %API. - * \post <tt>m_DataSource = 0</tt> - */ - bool Clear(); - - /** - * Applies a functor on all layers. - * \param[in] f functor (copied) to execute on each layer. - * - * \throw itk::ExceptionObject in case one layer can't be accessed. - * \throw * whatever the functor \c may throw. - * \note the functor is expected to receive an \c ogr::Layer by reference. - * \sa std::for_each - */ - template <class Functor> void ForEachLayer(Functor f) const; - - /** - * Accumulates the result of a functor on all layers. - * \param[in] f functor (copied) to execute on each layer. - * - * \return the result accumulated (with +) - * \throw itk::ExceptionObject in case one layer can't be accessed. - * \throw * whatever the functor \c may throw. - * \note the functor is expected to receive an \c ogr::Layer by reference. - * \sa std::accumulate - */ - template <class Functor, typename V> V AccumulateOnLayers(Functor f, V v0) const; - - /** Returns the number of elements in the Data Source. - * \param[in] doForceComputation indicates whether the size shall be - * computed on each layer even so it's expensive to do so. - * - * \return the number of features in the Data Source, -1 if count is unknown - * \throw None - * \sa OGRLayer::GetFeatureCount - */ - int Size(bool doForceComputation) const; - - /** Grafts data and information from one data source to another. - * \deprecated \c OGRLayer has an embedded input iterator. As a consequence, - * the layer cannot support multiple access to its elements. - * - * This is a convenience function to setup a second data source with all the - * meta information of another data source and use the same underlying \c - * OGRDataSource. - */ - virtual void Graft(const itk::DataObject *data); - - /** - * Resets current data source with the one in parameter. - * \param[in,out] source source \c OGRDataSource that this instance will own. - * \throw None - * \post Assumes ownership of the \c source. - */ - void Reset(OGRDataSource * source); - - /**\name Layers modification */ - //@{ - /** - * Creates a new layer. - * \param[in] name name for the layer - * \param poSpatialRef the coordinate system to use for the new layer, - * or NULL if no coordinate system is available. - * \param[in] eGType the geometry type for the layer. Use wkbUnknown - * if there are no constraints on the types - * geometry to be written. - * \param[in] papszOptions a StringList of name=value options. Options are - * driver specific. - * - * \return a proxy on the \c OGRLayer created. - * \throw itk::ExceptionObject in case the layer cannot be created on the - * data source. - * - * \note a \em proxy-class is returned instead of a plain \c OGRLayer is - * order to encapsulate all lifetime management of the \c OGRLayer obtained - * (i.e. never to be destroyed). If you want to delete a layer obtained - * with \c CreateLayer, you must use \c DeleteLayer. - * \note the \c papszOptions parameter may later become a \c - * std::vector<std::string> - * \sa OGRDataSource::CreateLayer - */ - Layer CreateLayer( - std::string const& name, - OGRSpatialReference * poSpatialRef = NULL, - OGRwkbGeometryType eGType = wkbUnknown, - char ** papszOptions = NULL); - - /** - * Deletes the i-th layer from the data source. - * \param[in] i layer index - * - * \throw it::ExceptionObject in case the index is out of range - * \throw it::ExceptionObject if the layer cannot be deleted from the data - * source. - * - * \pre the data source must support the delete operation - * \pre the index \c i must be in range [0, GetLayersCount()) - * \sa OGRDataSource::DeleteLayer - */ - void DeleteLayer(size_t i); - - /** - * Copies a layer. - * \param[in] srcLayer Source layer to copy. It may come from another \c - * DataSource. - * \param[in] newName Name of the new layer - * \param[in] papszOptions Creation options - * - * \return a proxy on the \c OGRLayer created. - * \throw itk::ExceptionObject in case the layer cannot be created on the - * data source. - * - * \note a \em proxy-class is returned instead of a plain \c OGRLayer is - * order to encapsulate all lifetime management of the \c OGRLayer obtained - * (i.e. never to be destroyed). If you want to delete a layer obtained - * with \c CreateLayer, you must use \c DeleteLayer. - * \note the \c papszOptions parameter may later become a \c - * std::vector<std::string> - * \sa OGRDataSource::CopyLayer - */ - Layer CopyLayer( - Layer & srcLayer, - std::string const& newName, - char ** papszOptions = NULL); - //@} - - /**\name Layers access - *\note as the following accessors are not inlined, they aren't optimized. - */ - //@{ - /** Returns the number of layers. - */ - int GetLayersCount() const; - - /** - * Unchecked Accessor to a given layer. - * \param[in] i index of the layer to access - * \return the layer requested. - * \pre <tt>i < GetLayersCount()</tt>, an assertion will abort the program - * otherwise. - * \pre the layer must available, an assertion will abort the program - * otherwise. - * \throw None - * \note Use \c GetLayerUnchecked() if invalid indices are programming - * errors, or if null layers are to be expected. - */ - Layer GetLayer(size_t i); - /**\copydoc otb::ogr::DataSource::GetLayer(size_t) - */ - Layer const GetLayer(size_t i) const; - - /** - * Unchecked Accessor to a given layer. - * \param[in] name name of the layer to search - * \return the layer requested, possibly a null one. - * \throw None - * \note Use \c GetLayerUnchecked(std::string const&) if you'd rather have - * an exception instead of testing whether the layer obtained is valid. - */ - Layer GetLayer(std::string const& name); - /**\copydoc otb::ogr::DataSource::GetLayer(std::string const&) - */ - Layer const GetLayer(std::string const& name) const; - - /** - * Checked Accessor to a given layer. - * \param[in] i index of the layer to access - * \return a reference to the layer requested. - * \pre <tt>i < GetLayersCount()</tt>, an exception is raised otherwise. - * \pre the layer must available, an exception is raised otherwise. - * \note Use \c GetLayer() if invalid indices, and null layers, are expected - * to be programming errors. - * \throw None - */ - Layer GetLayerChecked(size_t i); - /**\copydoc otb::ogr::DataSource::GetLayerChecked() - */ - Layer const GetLayerChecked(size_t i) const; - - /** - * Checked Accessor to a given layer. - * \param[in] name name of the layer to search - * \return the layer requested, possibly a null one. - * \throw itk::ExceptionObject if there exist no layer by that name - * \note use \c GetLayer(std::string const&) if you'd rather test the - * obtained layer instead of catching an exception. - */ - Layer GetLayerChecked(std::string const& name); - /**\copydoc otb::ogr::DataSource::GetLayerChecked(std::string const&) - */ - Layer const GetLayerChecked(std::string const& name) const; - - /** - * Excecutes the statement.. - * \param[in] statement textual description of the SQL statement. - * \param[in] poSpatialFilter \c Geometry representing a spatial filter -- may be null. - * \param[in] pszDialect allows control of the statement dialect. If set to - * NULL, the OGR SQL engine will be used, except for - * RDBMS drivers that will use their dedicated SQL - * engine, unless OGRSQL is explicitely passed as the - * dialect. - * \return a new \c Layer that contains the matching \c Features. In case of - * error, or no matching result sets, a \em null Layer will be returned. - * Check for \c Layer's validity before doing anything else. - * \throw None even when there is an error -- OGR can not report errors, - * neither this wrapping. - * \note the returned \c Layer will be automatically collected on its - * destruction; i.e. unlike OGR API, no need to explicitly call \c - * OGRDataSource::ReleaseResultSet(). - * \sa OGRDataSource::ExecuteSQL - */ - Layer ExecuteSQL( - std::string const& statement, - OGRGeometry * poSpatialFilter, - char const* pszDialect); - - //@} - - - struct boolean{ int i; }; - /** Can the data source be used (ie not null). - * - * Hack to provide a boolean operator that is convertible only to a - * boolean expression to be used in \c if tests. - * \see <em>Imperfect C++</em>, Matthew Wilson, Addisson-Welsey, par 24.6 - */ - operator int boolean ::* () const + layer_iter(otb::ogr::DataSource & datasource, size_t index) + : m_DataSource(&datasource), m_index(index) {} + layer_iter() + : m_DataSource(0), m_index(0) {} + template <class OtherValue> layer_iter( + layer_iter<OtherValue> const& other, + typename boost::enable_if<boost::is_convertible<OtherValue*,Value*> + , enabler + >::type = enabler() + ) + : m_DataSource(other.m_DataSource), m_index(other.m_index) + {} + private: + friend class boost::iterator_core_access; + template <class> friend class layer_iter; + + template <class OtherValue> bool equal(layer_iter<OtherValue> const& other) const + { + return m_DataSource == other.m_DataSource && other.m_index == m_index; + } + void increment() { - return m_DataSource ? &boolean::i : 0; + assert(m_DataSource && m_index < m_DataSource->GetLayersCount() && "cannot increment past end()"); + ++m_index; + } + Value dereference() const + { + assert(m_DataSource && m_index < m_DataSource->GetLayersCount() && "cannot dereference past end()"); + return m_DataSource->GetLayerUnchecked(m_index); } - /*otb::ogr::* - * Flushes all changes to disk. - * \throw itd::ExceptionObject in case the flush operation failed. - * \sa OGRDataSource::SyncToDisk - */ - void SyncToDisk(); - - /** - * Returns whether a capability is avalaible. - * \param[in] capabilityName name of the capability to check. - * \throw None - * \sa OGRDataSource::TestCapability - */ - bool HasCapability(std::string const& capabilityName); - - /** Access to raw \c OGRDataSource. - * This function provides an abstraction leak in case deeper control on the - * underlying \c OGRDataSource is required. - * \pre the underlying \c OGRDataSource must be valid, i.e. - * <tt>m_DataSource != 0</tt>, an assertion is fired otherwise. + otb::ogr::DataSource * m_DataSource; + size_t m_index; + }; + + template <class> friend class layer_iter; + typedef layer_iter<Layer > iterator; + typedef layer_iter<Layer const> const_iterator; + + const_iterator begin () const { return cbegin(); } + const_iterator end () const { return cend (); } + const_iterator cbegin() const; + const_iterator cend () const; + iterator begin (); + iterator end (); + //@} + + /** + * Applies a functor on all layers. + * \param[in] f functor (copied) to execute on each layer. + * + * \throw itk::ExceptionObject in case one layer can't be accessed. + * \throw * whatever the functor \c may throw. + * \note the functor is expected to receive an \c ogr::Layer by reference. + * \sa std::for_each + */ + template <class Functor> void ForEachLayer(Functor f) const; + + /** + * Accumulates the result of a functor on all layers. + * \param[in] f functor (copied) to execute on each layer. + * + * \return the result accumulated (with +) + * \throw itk::ExceptionObject in case one layer can't be accessed. + * \throw * whatever the functor \c may throw. + * \note the functor is expected to receive an \c ogr::Layer by reference. + * \sa std::accumulate + */ + template <class Functor, typename V> V AccumulateOnLayers(Functor f, V v0) const; + + /** Returns the number of elements in the Data Source. + * \param[in] doForceComputation indicates whether the size shall be + * computed on each layer even so it's expensive to do so. + * + * \return the number of features in the Data Source, -1 if count is unknown + * \throw None + * \sa OGRLayer::GetFeatureCount + */ + int Size(bool doForceComputation) const; + + /** Grafts data and information from one data source to another. + * \deprecated \c OGRLayer has an embedded input iterator. As a consequence, + * the layer cannot support multiple access to its elements. + * + * This is a convenience function to setup a second data source with all the + * meta information of another data source and use the same underlying \c + * OGRDataSource. + */ + virtual void Graft(const itk::DataObject *data); + + /** + * Resets current data source with the one in parameter. + * \param[in,out] source source \c OGRDataSource that this instance will own. + * \throw None + * \post Assumes ownership of the \c source. + */ + void Reset(OGRDataSource * source); + + /**\name Layers modification */ + //@{ + /** + * Creates a new layer. + * \param[in] name name for the layer + * \param poSpatialRef the coordinate system to use for the new layer, + * or NULL if no coordinate system is available. + * \param[in] eGType the geometry type for the layer. Use wkbUnknown + * if there are no constraints on the types + * geometry to be written. + * \param[in] papszOptions a StringList of name=value options. Options are + * driver specific. + * + * \return a proxy on the \c OGRLayer created. + * \throw itk::ExceptionObject in case the layer cannot be created on the + * data source. + * + * \note a \em proxy-class is returned instead of a plain \c OGRLayer is + * order to encapsulate all lifetime management of the \c OGRLayer obtained + * (i.e. never to be destroyed). If you want to delete a layer obtained + * with \c CreateLayer, you must use \c DeleteLayer. + * \note the \c papszOptions parameter may later become a \c + * std::vector<std::string> + * \sa OGRDataSource::CreateLayer + */ + Layer CreateLayer( + std::string const& name, + OGRSpatialReference * poSpatialRef = NULL, + OGRwkbGeometryType eGType = wkbUnknown, + char ** papszOptions = NULL); + + /** + * Deletes the i-th layer from the data source. + * \param[in] i layer index + * + * \throw it::ExceptionObject in case the index is out of range + * \throw it::ExceptionObject if the layer cannot be deleted from the data + * source. + * + * \pre the data source must support the delete operation + * \pre the index \c i must be in range [0, GetLayersCount()) + * \sa OGRDataSource::DeleteLayer + */ + void DeleteLayer(size_t i); + + /** + * Copies a layer. + * \param[in] srcLayer Source layer to copy. It may come from another \c + * DataSource. + * \param[in] newName Name of the new layer + * \param[in] papszOptions Creation options + * + * \return a proxy on the \c OGRLayer created. + * \throw itk::ExceptionObject in case the layer cannot be created on the + * data source. + * + * \note a \em proxy-class is returned instead of a plain \c OGRLayer is + * order to encapsulate all lifetime management of the \c OGRLayer obtained + * (i.e. never to be destroyed). If you want to delete a layer obtained + * with \c CreateLayer, you must use \c DeleteLayer. + * \note the \c papszOptions parameter may later become a \c + * std::vector<std::string> + * \sa OGRDataSource::CopyLayer + */ + Layer CopyLayer( + Layer & srcLayer, + std::string const& newName, + char ** papszOptions = NULL); + //@} + + /**\name Layers access + *\note as the following accessors are not inlined, they aren't optimized. + */ + //@{ + /** Returns the number of layers. + */ + int GetLayersCount() const; + + /** + * Unchecked Accessor to a given layer. + * \param[in] i index of the layer to access + * \return the layer requested. + * \pre <tt>i < GetLayersCount()</tt>, an assertion will abort the program + * otherwise. + * \pre the layer must available, an assertion will abort the program + * otherwise. + * \throw None + * \note Use \c GetLayerUnchecked() if invalid indices are programming + * errors, or if null layers are to be expected. + */ + Layer GetLayer(size_t i); + /**\copydoc otb::ogr::DataSource::GetLayer(size_t) + */ + Layer const GetLayer(size_t i) const; + + /** + * Unchecked Accessor to a given layer. + * \param[in] name name of the layer to search + * \return the layer requested, possibly a null one. + * \throw None + * \note Use \c GetLayerChecked(std::string const&) if you'd rather have + * an exception instead of testing whether the layer obtained is valid. + */ + Layer GetLayer(std::string const& name); + /**\copydoc otb::ogr::DataSource::GetLayer(std::string const&) + */ + Layer const GetLayer(std::string const& name) const; + + /** + * Checked Accessor to a given layer. + * \param[in] i index of the layer to access + * \return a reference to the layer requested. + * \pre <tt>i < GetLayersCount()</tt>, an exception is raised otherwise. + * \pre the layer must available, an exception is raised otherwise. + * \note Use \c GetLayer() if invalid indices, and null layers, are expected + * to be programming errors. + * \throw None + */ + Layer GetLayerChecked(size_t i); + /**\copydoc otb::ogr::DataSource::GetLayerChecked() + */ + Layer const GetLayerChecked(size_t i) const; + + /** + * Checked Accessor to a given layer. + * \param[in] name name of the layer to search + * \return the layer requested, possibly a null one. + * \throw itk::ExceptionObject if there exist no layer by that name + * \note use \c GetLayer(std::string const&) if you'd rather test the + * obtained layer instead of catching an exception. + */ + Layer GetLayerChecked(std::string const& name); + /**\copydoc otb::ogr::DataSource::GetLayerChecked(std::string const&) + */ + Layer const GetLayerChecked(std::string const& name) const; + + /** + * Excecutes the statement.. + * \param[in] statement textual description of the SQL statement. + * \param[in] poSpatialFilter \c Geometry representing a spatial filter -- may be null. + * \param[in] pszDialect allows control of the statement dialect. If set to + * NULL, the OGR SQL engine will be used, except for + * RDBMS drivers that will use their dedicated SQL + * engine, unless OGRSQL is explicitely passed as the + * dialect. + * \return a new \c Layer that contains the matching \c Features. In case of + * error, or no matching result sets, a \em null Layer will be returned. + * Check for \c Layer's validity before doing anything else. + * \throw None even when there is an error -- OGR can not report errors, + * neither this wrapping. + * \note the returned \c Layer will be automatically collected on its + * destruction; i.e. unlike OGR API, no need to explicitly call \c + * OGRDataSource::ReleaseResultSet(). + * \sa OGRDataSource::ExecuteSQL + */ + Layer ExecuteSQL( + std::string const& statement, + OGRGeometry * poSpatialFilter, + char const* pszDialect); + + //@} + + + struct boolean{ int i; }; + /** Can the data source be used (ie not null). + * + * Hack to provide a boolean operator that is convertible only to a + * boolean expression to be used in \c if tests. + * \see <em>Imperfect C++</em>, Matthew Wilson, Addisson-Welsey, par 24.6 + */ + operator int boolean ::* () const + { + return m_DataSource ? &boolean::i : 0; + } + + /*otb::ogr::* + * Flushes all changes to disk. + * \throw itd::ExceptionObject in case the flush operation failed. + * \sa OGRDataSource::SyncToDisk + */ + void SyncToDisk(); + + /** + * Returns whether a capability is avalaible. + * \param[in] capabilityName name of the capability to check. + * \throw None + * \sa OGRDataSource::TestCapability + */ + bool HasCapability(std::string const& capabilityName); + + /** Access to raw \c OGRDataSource. + * This function provides an abstraction leak in case deeper control on the + * underlying \c OGRDataSource is required. + * \pre the underlying \c OGRDataSource must be valid, i.e. + * <tt>m_DataSource != 0</tt>, an assertion is fired otherwise. * \warning you must under no circonstance try to delete the \c OGRDataSource * obtained this way. - */ - OGRDataSource & ogr(); - - protected: - /** Default constructor. - * The actual \c OGRDataSource is using the <em>in-memory</em> \c - * OGRSFDriver: \c OGRMemDriver. - * \throw itk::ExceptionObject if the inner \c OGRDataSource cannot be - * opened. - * - * \note \c OGRRegisterAll() is implicitly called on construction - * \see \c DataSource::New() - */ - DataSource(); - /** Init constructor. - * \post the newly constructed object owns the \c source parameter. - */ - DataSource(OGRDataSource * source); - /** Destructor. - * \post the \c OGRDataSource owned is released (if not null). - */ - virtual ~DataSource(); - /** Prints self into stream. */ - virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + */ + OGRDataSource & ogr(); + +protected: + /** Default constructor. + * The actual \c OGRDataSource is using the <em>in-memory</em> \c + * OGRSFDriver: \c OGRMemDriver. + * \throw itk::ExceptionObject if the inner \c OGRDataSource cannot be + * opened. + * + * \note \c OGRRegisterAll() is implicitly called on construction + * \see \c DataSource::New() + */ + DataSource(); + /** Init constructor. + * \post the newly constructed object owns the \c source parameter. + */ + DataSource(OGRDataSource * source); + /** Destructor. + * \post the \c OGRDataSource owned is released (if not null). + */ + virtual ~DataSource(); + /** Prints self into stream. */ + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + /** + * Internal unchecked accessor to a given layer. + * \param[in] i index of the layer to access + * \return a reference to the layer requested. + * \pre <tt>i < GetLayersCount()</tt>, return 0 otherwise + * \pre the layer must available, 0 is returned otherwise. + * \throw None + * \internal this function is a simple encapsulation of \c + * OGRDataSource::GetLayer(). + */ + OGRLayer* GetLayerUnchecked(size_t i); - private: - /** - * Internal unchecked accessor to a given layer. - * \param[in] i index of the layer to access - * \return a reference to the layer requested. - * \pre <tt>i < GetLayersCount()</tt>, return 0 otherwise - * \pre the layer must available, 0 is returned otherwise. - * \throw None - * \internal this function is a simple encapsulation of \c - * OGRDataSource::GetLayer(). - */ - OGRLayer* GetLayerUnchecked(size_t i); - - DataSource(const Self&); //purposely not implemented - DataSource& operator =(const Self&); //purposely not implemented + DataSource(const Self&); //purposely not implemented + DataSource& operator =(const Self&); //purposely not implemented - private: - OGRDataSource *m_DataSource; - // ImageReference m_ImageReference; - }; // end class DataSource +private: + OGRDataSource *m_DataSource; + // ImageReference m_ImageReference; + }; // end class DataSource } } // end namespace otb::ogr #ifndef OTB_MANUAL_INSTANTIATION