QueryLayer.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 /*!
21  \file terralib/maptools/QueryLayer.cpp
22 
23  \brief A layer resulting from a query.
24 */
25 
26 // TerraLib
27 #include "../common/StringUtils.h"
28 #include "../dataaccess/dataset/ObjectIdSet.h"
29 #include "../dataaccess/dataset/PrimaryKey.h"
30 #include "../dataaccess/datasource/DataSource.h"
31 #include "../dataaccess/datasource/DataSourceCapabilities.h"
32 #include "../dataaccess/query/And.h"
33 #include "../dataaccess/query/DataSetName.h"
34 #include "../dataaccess/query/Expression.h"
35 #include "../dataaccess/query/Field.h"
36 #include "../dataaccess/query/Function.h"
37 #include "../dataaccess/query/FunctionNames.h"
38 #include "../dataaccess/query/FromItem.h"
39 #include "../dataaccess/query/Join.h"
40 #include "../dataaccess/query/LiteralEnvelope.h"
41 #include "../dataaccess/query/PropertyName.h"
42 #include "../dataaccess/query/Select.h"
43 #include "../dataaccess/query/SQLVisitor.h"
44 #include "../dataaccess/query/ST_Intersects.h"
45 #include "../dataaccess/query/ST_EnvelopeIntersects.h"
46 #include "../dataaccess/query/Where.h"
47 #include "../dataaccess/utils/Utils.h"
48 #include "../datatype/Property.h"
49 #include "../geometry/GeometryProperty.h"
50 #include "Exception.h"
51 #include "QueryLayer.h"
52 #include "RendererFactory.h"
53 
54 // Boost
55 #include <boost/format.hpp>
56 
57 // STL
58 #include <memory>
59 
60 const std::string te::map::QueryLayer::sm_type("QUERYLAYER");
61 
63  : AbstractLayer(parent),
64  m_query(0)
65 {
66 }
67 
68 te::map::QueryLayer::QueryLayer(const std::string& id, AbstractLayer* parent)
69  : AbstractLayer(id, parent),
70  m_query(0)
71 {
72 }
73 
74 te::map::QueryLayer::QueryLayer(const std::string& id,
75  const std::string& title,
76  AbstractLayer* parent)
77  : AbstractLayer(id, title, parent),
78  m_query(0)
79 {
80 }
81 
83 {
84  delete m_query;
85 }
86 
87 std::auto_ptr<te::map::LayerSchema> te::map::QueryLayer::getSchema() const
88 {
89  std::auto_ptr<te::map::LayerSchema> output(new te::map::LayerSchema(getTitle()));
90 
91  te::da::PrimaryKey* outKey = new te::da::PrimaryKey();
92 
93  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
94 
95  const te::da::Fields* fields = m_query->getFields();
96  const te::da::From* from = m_query->getFrom();
97 
98  for(size_t i = 0; i < fields->size(); ++i)
99  {
100  te::da::Field field = fields->at(i);
101  te::da::Expression* exp = field.getExpression();
102 
103  te::da::PropertyName* pName = dynamic_cast<te::da::PropertyName*>(exp);
104 
105  std::vector<std::string> tokens;
106  te::common::Tokenize(pName->getName(), tokens, ".");
107 
108  assert(tokens.size() == 2);
109 
110  std::string name;
111 
112  for(size_t j = 0; j < from->size(); ++j)
113  {
114  const te::da::FromItem& item = from->at(j);
115  const te::da::DataSetName* dsName = dynamic_cast<const te::da::DataSetName*>(&item);
116  if(dsName != 0)
117  {
118  if(dsName->getAlias() == tokens[0])
119  name = dsName->getName();
120  }
121  else
122  {
123  const te::da::Join* dsJoin = dynamic_cast<const te::da::Join*>(&item);
124  const te::da::FromItem* first = dsJoin->getFirst();
125  const te::da::DataSetName* dsName = dynamic_cast<const te::da::DataSetName*>(first);
126  if(dsName->getAlias() == tokens[0])
127  {
128  name = dsName->getName();
129  }
130  else
131  {
132  const te::da::FromItem* second = dsJoin->getSecond();
133  const te::da::DataSetName* dsName = dynamic_cast<const te::da::DataSetName*>(second);
134  name = dsName->getName();
135  }
136  }
137  }
138 
139  assert(!name.empty());
140 
141  std::auto_ptr<te::da::DataSetType> input = ds->getDataSetType(name);
142 
143  te::dt::Property* pRef = input->getProperty(tokens[1]);
144  assert(pRef);
145 
146  te::dt::Property* p = (pRef->clone());
147  p->setDatasetName(name);
148  p->setId(i);
149  output->add(p);
150 
151  if(input->getPrimaryKey()->has(pRef))
152  outKey->add(output->getProperty(p->getId()));
153  }
154 
155  if(!outKey->getProperties().empty())
156  output->setPrimaryKey(outKey);
157 
158  return output;
159 }
160 
161 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(te::common::TraverseType travType,
162  const te::common::AccessPolicy accessPolicy) const
163 {
164  return getData(m_query, travType, accessPolicy);
165 }
166 
167 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(const std::string& propertyName,
168  const te::gm::Envelope* e,
170  te::common::TraverseType travType,
171  const te::common::AccessPolicy accessPolicy) const
172 {
173  te::da::LiteralEnvelope* lenv = new te::da::LiteralEnvelope(*e, m_srid);
174 
175  te::da::PropertyName* pname = new te::da::PropertyName(propertyName);
176 
177  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
178 
179  const te::da::DataSourceCapabilities dsCap = ds->getCapabilities();
180 
181  const te::da::QueryCapabilities queryCap = dsCap.getQueryCapabilities();
182 
183  std::set<std::string> spatialTopOp = queryCap.getSpatialTopologicOperators();
184 
185  // The final select
186  std::auto_ptr<te::da::Select> select(static_cast<te::da::Select*>(m_query->clone()));
187 
188  // Original Where
189  te::da::Where* wh = select->getWhere();
190 
191  if(wh != 0)
192  {
193  // Original restriction expression
194  te::da::Expression* exp = wh->getExp()->clone();
195 
196  // TODO: switch that verifies the given te::gm::SpatialRelation and build the query object (ST_Intersects. ST_Touches, etc).
197 
198  if(spatialTopOp.find(te::da::FunctionNames::sm_ST_EnvelopeIntersects) != spatialTopOp.end())
199  {
200  te::da::ST_EnvelopeIntersects* intersects = new te::da::ST_EnvelopeIntersects(pname, lenv);
201 
202  // The final restriction: original restriction expression + extent restriction
203  te::da::And* andop = new te::da::And(exp, intersects);
204 
205  wh->setExp(andop);
206  }
207  else if(spatialTopOp.find(te::da::FunctionNames::sm_ST_Intersects) != spatialTopOp.end())
208  {
209  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(pname, lenv);
210 
211  // The final restriction: original restriction expression + extent restriction
212  te::da::And* andop = new te::da::And(exp, intersects);
213 
214  wh->setExp(andop);
215  }
216  }
217  else
218  {
219  if(spatialTopOp.find(te::da::FunctionNames::sm_ST_EnvelopeIntersects) != spatialTopOp.end())
220  {
221  te::da::ST_EnvelopeIntersects* intersects = new te::da::ST_EnvelopeIntersects(pname, lenv);
222  wh = new te::da::Where(intersects);
223  }
224  else if(spatialTopOp.find(te::da::FunctionNames::sm_ST_Intersects) != spatialTopOp.end())
225  {
226  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(pname, lenv);
227  wh = new te::da::Where(intersects);
228  }
229  select->setWhere(wh);
230  }
231 
232  return getData(select.get(), travType, accessPolicy);
233 }
234 
235 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(const std::string& propertyName,
236  const te::gm::Geometry* /*g*/,
238  te::common::TraverseType /*travType*/,
239  const te::common::AccessPolicy) const
240 {
241  throw Exception("Not implemented yet!");
242 }
243 
244 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(te::da::Expression* restriction,
245  te::common::TraverseType travType,
246  const te::common::AccessPolicy accessPolicy) const
247 {
248  // The final select
249  std::auto_ptr<te::da::Select> select(static_cast<te::da::Select*>(m_query->clone()));
250 
251  // Original Where
252  te::da::Where* wh = select->getWhere();
253 
254  if(wh != 0)
255  {
256  // Original restriction expression
257  te::da::Expression* exp = wh->getExp()->clone();
258 
259  // The final restriction: original restriction expression + the given restriction expression
260  te::da::And* andop = new te::da::And(exp, restriction);
261  wh->setExp(andop);
262  }
263  else
264  {
265  wh = new te::da::Where(restriction);
266  select->setWhere(wh);
267  }
268 
269  return getData(select.get(), travType, accessPolicy);
270 }
271 
272 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(const te::da::ObjectIdSet* oids,
273  te::common::TraverseType travType,
274  const te::common::AccessPolicy accessPolicy) const
275 {
276  // The final select
277  std::auto_ptr<te::da::Select> select(static_cast<te::da::Select*>(m_query->clone()));
278 
279  // Original Where
280  te::da::Where* wh = select->getWhere();
281 
282  if(wh != 0)
283  {
284  // Original restriction expression
285  te::da::Expression* exp = wh->getExp()->clone();
286 
287  // The final restriction: original restriction expression + the oids restriction
288  te::da::And* andop = new te::da::And(exp, oids->getExpression());
289  wh->setExp(andop);
290  }
291  else
292  {
293  wh = new te::da::Where(oids->getExpression());
294  select->setWhere(wh);
295  }
296 
297  return getData(select.get(), travType, accessPolicy);
298 }
299 
301 {
302  if(m_query == 0)
303  return false;
304 
305  if(m_datasourceId.empty())
306  return false;
307 
309  try
310  {
311  ds = te::da::GetDataSource(m_datasourceId, true);
312  }
313  catch(...)
314  {
315  return false;
316  }
317 
318  if(ds.get() == 0 || !ds->isValid() || !ds->isOpened())
319  return false;
320 
321  return true;
322 }
323 
324 void te::map::QueryLayer::draw(Canvas* canvas, const te::gm::Envelope& bbox, int srid)
325 {
326  if(m_rendererType.empty())
327  throw Exception((boost::format(TE_TR("Could not draw the query layer %1%. The renderer type is empty!")) % getTitle()).str());
328 
329  // Try get the defined renderer
330  std::auto_ptr<AbstractRenderer> renderer(RendererFactory::make(m_rendererType));
331  if(renderer.get() == 0)
332  throw Exception((boost::format(TE_TR("Could not draw the query layer %1%. The renderer %2% could not be created!")) % getTitle() % m_rendererType).str());
333 
334  renderer->draw(this, canvas, bbox, srid);
335 }
336 
337 const std::string& te::map::QueryLayer::getType() const
338 {
339  return sm_type;
340 }
341 
343 {
344  return m_query;
345 }
346 
348 {
349  std::string sql;
350 
351  if (m_query)
352  {
353  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
354  te::da::SQLVisitor visitor(*ds->getDialect(), sql);
355 
356  try
357  {
358  m_query->accept(visitor);
359  }
360  catch (...)
361  {
362  return "";
363  }
364  }
365 
366  return sql;
367 }
368 
370 {
371  delete m_query;
372 
373  m_query = s;
374 }
375 
376 const std::string& te::map::QueryLayer::getDataSourceId() const
377 {
378  return m_datasourceId;
379 }
380 
381 void te::map::QueryLayer::setDataSourceId(const std::string& id)
382 {
383  m_datasourceId = id;
384 }
385 
386 const std::string& te::map::QueryLayer::getRendererType() const
387 {
388  return m_rendererType;
389 }
390 
391 void te::map::QueryLayer::setRendererType(const std::string& t)
392 {
393  m_rendererType = t;
394 }
395 
397 {
398  if(m_mbr.isValid())
399  return;
400 
401  // Get the associated data source
402  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
403 
404  std::auto_ptr<te::da::DataSet> dataset;
405 
406  // Get the dataset
407  dataset = ds->query(m_query);
408  assert(dataset.get());
409 
410  // MBR
411  m_mbr = *dataset->getExtent(te::da::GetFirstPropertyPos(dataset.get(), te::dt::GEOMETRY_TYPE));
412 }
413 
414 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(te::da::Select* query,
415  te::common::TraverseType travType,
416  const te::common::AccessPolicy accessPolicy) const
417 {
418  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
419 
420  return ds->query(query, travType, accessPolicy);
421 }
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
Definition: Utils.cpp:262
const std::string & getName() const
It returns the property name.
Definition: PropertyName.h:80
void add(te::dt::Property *p)
It adds a property to the list of properties of the primary key.
Definition: PrimaryKey.h:123
An abstract class that models a source of data in a query.
Definition: FromItem.h:50
The Field class can be used to model an expression that takes part of the output items of a SELECT...
Definition: Field.h:50
Spatial intersects operator.
Definition: ST_Intersects.h:46
This is the base class for layers.
Definition: AbstractLayer.h:76
A class that models the name of a dataset used in a From clause.
Definition: DataSetName.h:43
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
A class that models the name of any property of an object.
Definition: PropertyName.h:50
A class that models the description of a dataset.
Definition: DataSetType.h:72
static const std::string sm_ST_Intersects
Definition: FunctionNames.h:86
std::auto_ptr< LayerSchema > getSchema() const
It returns the layer schema.
Definition: QueryLayer.cpp:87
Expression * getExpression() const
It returns the expression set for an output select query.
Definition: Field.cpp:80
An abstract factory for layer renderers.
virtual Property * clone() const =0
It returns a clone of the object.
SpatialRelation
Spatial relations between geometric objects.
Definition: Enums.h:122
QueryLayer(AbstractLayer *parent=0)
It initializes a new layer.
Definition: QueryLayer.cpp:62
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:346
const QueryCapabilities & getQueryCapabilities() const
void setDatasetName(const std::string &dsName)
It sets the property name.
Definition: Property.h:154
It models a property definition.
Definition: Property.h:59
Boolean logic operator: AND.
Definition: And.h:46
This is an abstract class that models a query expression.
Definition: Expression.h:47
const std::vector< te::dt::Property * > & getProperties() const
It returns the properties that take part of the primary key.
Definition: PrimaryKey.h:109
An exception class for the MapTools module.
void setId(unsigned int id)
It sets the property identifier.
Definition: Property.h:118
AccessPolicy
Supported data access policies (can be used as bitfield).
Definition: Enums.h:40
~QueryLayer()
Destructor.
Definition: QueryLayer.cpp:82
TraverseType
A dataset can be traversed in two ways:
Definition: Enums.h:53
void Tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters=" ")
It tokenizes a given string with a delimiter of your own choice.
Definition: StringUtils.h:219
void setRendererType(const std::string &t)
Definition: QueryLayer.cpp:391
A class that informs the query support of a given data source.
An operator that considers the intersection among approximations or envelopes of geometries.
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
const std::string & getAlias() const
It returns the alias associated to the source item.
Definition: FromItem.cpp:47
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:55
boost::ptr_vector< Field > Fields
Fields is just a boost::ptr_vector of Field pointers.
Definition: Fields.h:37
const std::string & getDataSourceId() const
Definition: QueryLayer.cpp:376
A class that can be used to model a filter expression that can be applied to a query.
Definition: Where.h:47
static const std::string sm_ST_EnvelopeIntersects
Definition: FunctionNames.h:83
void setExp(Expression *exp)
Sets the expression.
Definition: Where.cpp:65
Expression * getExp() const
Definition: Where.cpp:60
te::da::Select * getQuery() const
Definition: QueryLayer.cpp:342
A Join clause combines two FromItems.
Definition: Join.h:50
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
static AbstractRenderer * make(const std::string &factoryKey)
It creates an object with the appropriated factory.
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
const std::set< std::string > & getSpatialTopologicOperators() const
boost::ptr_vector< FromItem > From
It models the FROM clause for a query.
Definition: From.h:37
FromItem * getSecond() const
It returns the second item involved in the join.
Definition: Join.cpp:101
std::string getQueryAsString() const
Definition: QueryLayer.cpp:347
A canvas is an abstraction of a drawing area.
Definition: Canvas.h:91
void setDataSourceId(const std::string &id)
Definition: QueryLayer.cpp:381
void draw(Canvas *canvas, const te::gm::Envelope &bbox, int srid)
It draws the layer geographic objects in the given canvas using the informed SRS. ...
Definition: QueryLayer.cpp:324
void setQuery(te::da::Select *s)
Definition: QueryLayer.cpp:369
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
A layer resulting from a query.
A class that models a literal for Envelope values.
const std::string & getRendererType() const
Definition: QueryLayer.cpp:386
const std::string & getName() const
It returns the dataset name.
Definition: DataSetName.cpp:57
std::auto_ptr< te::da::DataSet > getData(te::common::TraverseType travType=te::common::FORWARDONLY, const te::common::AccessPolicy accessPolicy=te::common::RAccess) const
It gets the dataset identified by the layer name.
Definition: QueryLayer.cpp:161
A visitor for building an SQL statement from a given Query hierarchy.
Definition: SQLVisitor.h:58
virtual Expression * clone() const =0
It creates a new copy of this expression.
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
Definition: Utils.cpp:481
static const std::string sm_type
A static data member used in the implementation of getType method.
Definition: QueryLayer.h:180
const std::string & getType() const
It returns the layer type: QUERY_LAYER.
Definition: QueryLayer.cpp:337
Expression * getExpression() const
It returns the expression that can be used to retrieve the data set that contains the all indentified...
bool isValid() const
It returns true if the layer can be used for instance to draw, otherwise, it returns false...
Definition: QueryLayer.cpp:300
unsigned int getId() const
It returns the property identifier.
Definition: Property.h:109
FromItem * getFirst() const
It returns the first from item involved in the join.
Definition: Join.cpp:91