src/terralib/ogr/DataSource.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 //Terralib
21 #include "DataSource.h"
22 #include "Globals.h"
23 #include "Transactor.h"
24 #include "Utils.h"
25 
26 #include "../core/filesystem/FileSystem.h"
27 #include "../core/translator/Translator.h"
28 #include "../core/uri/URI.h"
29 #include "../core/uri/Utils.h"
30 #include "../dataaccess/query/SQLDialect.h"
31 
32 // OGR
33 #include <ogrsf_frmts.h>
34 #include <ogr_core.h>
35 #include <gdal_priv.h>
36 #include <ogr_api.h>
37 #include <gdal.h>
38 
39 // Boost
40 #include <boost/filesystem/operations.hpp>
41 #include <boost/algorithm/string/replace.hpp>
42 
44 
46 {
48 
49  dt_caps.setSupportInt32(true);
50  dt_caps.setSupportInt64(true);
51  dt_caps.setSupportArray(true);
52  dt_caps.setSupportString(true);
53  dt_caps.setSupportDouble(true);
54  dt_caps.setSupportNumeric(true);
55  dt_caps.setSupportByteArray(true);
56  dt_caps.setSupportDateTime(true);
57  dt_caps.setSupportGeometry(true);
58 
59  caps.setDataTypeCapabilities(dt_caps);
60 }
61 
63 {
65 
66  // Spatial Topologic Operators
67  qy_caps.addSpatialTopologicOperator("st_envelopeintersects");
68 
69  // Comparsion Operators
70  qy_caps.addComparsionOperator("=");
71  qy_caps.addComparsionOperator("<>");
72  qy_caps.addComparsionOperator("<");
73  qy_caps.addComparsionOperator(">");
74  qy_caps.addComparsionOperator("<=");
75  qy_caps.addComparsionOperator(">=");
76  qy_caps.addComparsionOperator("like");
77 
78  qy_caps.addLogicalOperator("and");
79  qy_caps.addLogicalOperator("or");
80 
81  caps.setQueryCapabilities(qy_caps);
82 }
83 
85 {
86  // DataSet
87  if(!ds || ds->GetLayerCount() <= 0)
88  return;
89 
91 
92  OGRLayer* l = ds->GetLayer(0);
93 
94  ds_caps.setSupportEfficientMove((l->TestCapability(OLCFastSetNextByIndex)) ? true : false);
95  ds_caps.setSupportRandomTraversing((l->TestCapability(OLCRandomRead)) ? true : false);
96  ds_caps.setSupportBidirectionalTraversing((l->TestCapability(OLCRandomRead)) ? true : false);
97  ds_caps.setSupportEfficientDataSetSize((l->TestCapability(OLCFastGetExtent)) ? true : false);
98  ds_caps.setAsConnected(false);
99 
100  caps.setDataSetCapabilities(ds_caps);
101 }
102 
103 te::ogr::DataSource::DataSource(const std::string& connInfo)
104  : te::da::DataSource(connInfo),
105  m_ogrDS(nullptr),
106  m_isValid(false),
107  m_encoding(te::core::EncodingType::UTF8)
108 {
109 }
110 
112  : te::da::DataSource(uri),
113  m_ogrDS(nullptr),
114  m_isValid(false),
115  m_encoding(te::core::EncodingType::UTF8)
116 {
117 }
118 
120 {
121  close();
122 }
123 
124 std::string te::ogr::DataSource::getType() const
125 {
127 }
128 
129 std::unique_ptr<te::da::DataSourceTransactor> te::ogr::DataSource::getTransactor()
130 {
131  return std::unique_ptr<te::da::DataSourceTransactor>(new Transactor(this));
132 }
133 
135 {
136  close();
137 
138  if (!m_uri.isValid())
139  throw Exception(TE_TR("There is no valid information about the data source"));
140 
141  std::string path = te::core::URIDecode(m_uri.uri());
142  boost::replace_all(path, "file://", "");
143 
144  std::map<std::string, std::string> kvp = te::core::Expand(m_uri.query());
145  std::map<std::string, std::string>::const_iterator it;
146 
147  if (path.empty())
148  throw(Exception(TE_TR("Not enough information to open the data source.")));
149 
150  // Retrieve the char encoding
151  it = kvp.find("SHAPE_ENCODING");
152  if (it != kvp.end())
153  CPLSetConfigOption("SHAPE_ENCODING", it->second.c_str());
154 
156  m_ogrDS = (GDALDataset*)GDALOpenEx(path.c_str(), GDAL_OF_UPDATE, nullptr, nullptr, nullptr);
157 
158  // let's try to open it without update permission
159  if (!m_ogrDS)
160  {
161  m_ogrDS = (GDALDataset*)GDALOpenEx(path.c_str(), GDAL_OF_READONLY, nullptr, nullptr, nullptr);
162  if (m_ogrDS)
164  }
165  else
167 
168  m_isValid = true;
169 
172 
173  if (m_ogrDS)
175 }
176 
178 {
179  if (m_ogrDS)
180  //OGRDataSource::DestroyDataSource(m_ogrDS);
181  GDALClose(m_ogrDS);
182 
183  m_ogrDS = nullptr;
184 
185  m_isValid = false;
186 }
187 
189 {
190  return m_ogrDS != nullptr;
191 }
192 
194 {
195  return m_isValid;
196 }
197 
199 {
200  return m_capabilities;
201 }
202 
204 {
205  return sm_myDialect;
206 }
207 
209 {
210  if(sm_myDialect != nullptr)
211  delete sm_myDialect;
212 
214 }
215 
217 {
218  return m_ogrDS;
219 }
220 
222 {
223  if (!m_ogrDS)
224  {
225  if (!m_uri.isValid())
226  throw Exception(TE_TR("There is no valid information about the data source"));
227 
228  std::string path = te::core::URIDecode(m_uri.uri());
229  boost::replace_all(path, "file://", "");
230 
231  std::map<std::string, std::string> kvp = te::core::Expand(m_uri.query());
232  std::map<std::string, std::string>::const_iterator it;
233 
234  if (path.empty())
235  throw(Exception(TE_TR("Not enough information to create data set.")));
236 
237  boost::filesystem::path bpath(path);
238  std::string dir = bpath.parent_path().string();
239  if (!dir.empty() && !te::core::FileSystem::exists(dir))
241 
242  // Retrieve the char encoding
243  it = kvp.find("SHAPE_ENCODING");
244  if (it != kvp.end())
245  CPLSetConfigOption("SHAPE_ENCODING", it->second.c_str());
246 
247  GDALDriverManager* driverManager = GetGDALDriverManager();
248  GDALDriver* driver;
249 
250  it = kvp.find("DRIVER");
251  if (it != kvp.end())
252  driver = driverManager->GetDriverByName(it->second.c_str());
253  else
254  driver = driverManager->GetDriverByName(GetDriverName(path).c_str());
255 
256  if (driver == nullptr)
257  throw(Exception(TE_TR("Driver not found.")));
258 
259  if (!OGR_Dr_TestCapability(driver, ODrCCreateDataSource))
260  throw(Exception(TE_TR("The driver has no capability for creating a datasource!")));
261 
262  char** papszOptions = nullptr;
263  it = kvp.begin();
264  while (it != kvp.end())
265  {
266  papszOptions = CSLSetNameValue(papszOptions, it->first.c_str(), it->second.c_str());
267  ++it;
268  }
269 
270  m_ogrDS = driver->Create(path.c_str(), 0, 0, 0, GDT_Unknown, papszOptions);
271 
272  if (papszOptions)
273  CSLDestroy(papszOptions);
274  }
275 
276  if (!m_ogrDS)
277  throw(Exception(TE_TR("Error creating the dataset!")));
278 }
279 
280 void te::ogr::DataSource::create(const std::string& /*connInfo*/)
281 {
283  close();
284 }
285 
287 {
288  return m_encoding;
289 }
290 
292 {
293  m_encoding = et;
294 }
295 
296 void te::ogr::DataSource::createDataSet(te::da::DataSetType* dt, const std::map<std::string, std::string>& options)
297 {
298  std::unique_ptr<te::da::DataSourceTransactor> t = getTransactor();
299  return t->createDataSet(dt, options);
300 }
301 
302 void te::ogr::DataSource::drop(const std::string& connInfo)
303 {
304  te::core::URI auxURI(connInfo);
305 
306  std::string path = auxURI.path();
307 
308  if (m_ogrDS != nullptr && path.compare(m_ogrDS->GetDescription()) == 0)
309  close();
310 
311  GDALDriverManager* driverManager = GetGDALDriverManager();
312  GDALDriver* driver = driverManager->GetDriverByName(GetDriverName(path).c_str());
313 
314  if (driver == nullptr)
315  throw(Exception(TE_TR("Driver not found!")));
316 
317  if (!OGR_Dr_TestCapability(driver, ODrCDeleteDataSource))
318  throw(Exception(TE_TR("The driver has no drop capability!")));
319 
320  GDALClose(driver);
321 }
322 
323 bool te::ogr::DataSource::exists(const std::string& connInfo)
324 {
325  te::core::URI auxURI(connInfo);
326  std::string path = te::core::URIDecode(auxURI.uri());
327  boost::replace_all(path, "file://", "");
328 
329  return te::core::FileSystem::exists(path);
330 }
331 
332 std::vector<std::string> te::ogr::DataSource::getDataSourceNames(const std::string& connInfo)
333 {
334  te::core::URI auxURI(connInfo);
335 
336  std::string path = te::core::URIDecode(auxURI.uri());
337  boost::replace_all(path, "file://", "");
338 
339  std::vector<std::string> names;
340 
341  if (!path.empty())
342  {
343  names.push_back(path);
344  }
345 
346  return names;
347 }
348 
350 {
351  te::da::DataSource* ds = new DataSource(uri);
352  return ds;
353 }
bool isOpened() const
It returns true if the data source is opened, otherwise it returns false.
std::string getType() const
It returns the data source type name (in UPPER CASE). Ex: POSTGIS, SQLITE, WFS, WMS, or MYSQL.
std::string path() const
Retrieving the path.
Definition: URI.cpp:118
void setSupportString(const bool &support)
te::da::SQLDialect * dialect
Definition: WFSDialect.h:1
static bool exists(const std::string &path)
Checks if a given path in UTF-8 exists.
Definition: FileSystem.cpp:142
void open()
It opens the data source and makes it ready for using.
Base exception class for plugin module.
A class that models the description of a dataset.
Definition: DataSetType.h:72
te::core::EncodingType getEncoding()
It return the DataSource current encoding.
void addSpatialTopologicOperator(const std::string &op)
void setSupportGeometry(const bool &support)
void setSupportNumeric(const bool &support)
DataSource(const std::string &connInfo)
It represents the SQL query dialect accepted by a given data source.
Definition: SQLDialect.h:55
void addComparsionOperator(const std::string &op)
void setSupportEfficientMove(const bool &support)
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
bool isValid() const
Return if the given URI is valid or not.
Definition: URI.cpp:133
void setAccessPolicy(const te::common::AccessPolicy &accessPolicy)
static te::dt::Date ds(2010, 01, 01)
An abstract class for data providers like a DBMS, Web Services or a regular file. ...
A class that informs what the dataset implementation of a given data source can perform.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
void setSupportInt64(const bool &support)
void setSupportDouble(const bool &support)
void setQueryCapabilities(const QueryCapabilities &capabilities)
void setAsConnected(const bool &connected)
void setSupportByteArray(const bool &support)
std::string query() const
Retrieving the query.
Definition: URI.cpp:123
std::string GetDriverName(const std::string &path)
It tries extract the driver name used by OGR Library based on the given path.
void addLogicalOperator(const std::string &op)
te::da::DataSourceCapabilities m_capabilities
OGR capabilities.
void GetCapabilities(GDALDataset *ds, te::da::DataSourceCapabilities &caps)
EncodingType
Supported character encodings.
Definition: CharEncoding.h:50
A class that represents the supported data types of a specific data source.
te::core::EncodingType m_encoding
The data source encoding type.
static te::da::SQLDialect * sm_myDialect
OGR SQL dialect.
A class that informs the query support of a given data source.
This file contains include headers for the TerraLib GDAL driver.
URI C++ Library.
Definition: Attributes.h:37
static te::dt::TimeDuration dt(20, 30, 50, 11)
te::da::DataSource * Build(const te::core::URI &uri)
void createDataSet(te::da::DataSetType *dt, const std::map< std::string, std::string > &options)
It creates the dataset schema definition in the target data source.
void setDataSetCapabilities(const DataSetCapabilities &capabilities)
const te::da::DataSourceCapabilities & getCapabilities() const
It returns the known capabilities of the data source.
bool isValid() const
It checks if the data source is valid (available for using).
std::vector< std::string > getDataSourceNames(const std::string &connInfo)
It gets the data source names available in a driver.
const std::string & uri() const
Retrieving the full URI.
Definition: URI.cpp:88
The OGR data source provider.
void setSupportInt32(const bool &support)
void setSupportBidirectionalTraversing(const bool &support)
A class for representing an Uniform Resource Identifier (URI).
Definition: URI.h:49
GDALDataset * m_ogrDS
A pointer to OGR Data Source.
void GetQueryCapabilities(te::da::DataSourceCapabilities &caps)
~DataSource()
Virtual destructor.
static bool createDirectory(const std::string &path)
Creates a directory from a given path in UTF-8.
Definition: FileSystem.cpp:147
void setEncoding(const te::core::EncodingType &et)
It sets the encodings for the data source.
std::unique_ptr< te::da::DataSourceTransactor > getTransactor()
It returns the set of parameters used to set up the access channel to the underlying repository...
This file contains utility functions used to manipulate data from a URI.
void setSupportRandomTraversing(const bool &support)
A class for data providers of OGR.
void setDataTypeCapabilities(const DataTypeCapabilities &capabilities)
te::core::URI m_uri
The URI used to describe the datasource connection;.
TECOREEXPORT std::map< std::string, std::string > Expand(const std::string &query_str)
Split a query string into its components.
void drop(const std::string &connInfo)
It removes the data source with the connection information from a driver.
void setSupportDateTime(const bool &support)
void close()
It closes the data source and clears all the resources used by its internal communication channel...
TECOREEXPORT std::string URIDecode(const std::string &srcUri)
Decodes an encoded URI. The algorithm implementation is based on http://www.codeguru.com/cpp/cpp/algorithms/strings/article.php/c12759/URI-Encoding-and-Decoding.htm.
void setSupportArray(const bool &support)
const te::da::SQLDialect * getDialect() const
It returns the data source SQL dialect, if there is one.
bool exists(const std::string &connInfo)
Check the existence of a data source in a driver.
static void setDialect(te::da::SQLDialect *dialect)
bool m_isValid
True if this is a valid datasource.
static const std::string m_driverIdentifier
The OGR driver identifier.
An static class with global definitions.
void setSupportEfficientDataSetSize(const bool &support)
void GetDataSetTypeCapabilities(te::da::DataSourceCapabilities &caps)
void create(const std::string &connInfo)
It creates a new data source.