All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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/ST_Intersects.h"
44 #include "../dataaccess/query/ST_EnvelopeIntersects.h"
45 #include "../dataaccess/query/Where.h"
46 #include "../dataaccess/utils/Utils.h"
47 #include "../datatype/Property.h"
48 #include "../geometry/GeometryProperty.h"
49 #include "Exception.h"
50 #include "QueryLayer.h"
51 #include "RendererFactory.h"
52 
53 // Boost
54 #include <boost/format.hpp>
55 
56 // STL
57 #include <memory>
58 
59 const std::string te::map::QueryLayer::sm_type("QUERYLAYER");
60 
62  : AbstractLayer(parent),
63  m_query(0)
64 {
65 }
66 
67 te::map::QueryLayer::QueryLayer(const std::string& id, AbstractLayer* parent)
68  : AbstractLayer(id, parent),
69  m_query(0)
70 {
71 }
72 
73 te::map::QueryLayer::QueryLayer(const std::string& id,
74  const std::string& title,
75  AbstractLayer* parent)
76  : AbstractLayer(id, title, parent),
77  m_query(0)
78 {
79 }
80 
82 {
83  delete m_query;
84 }
85 
86 std::auto_ptr<te::map::LayerSchema> te::map::QueryLayer::getSchema() const
87 {
88  std::auto_ptr<te::map::LayerSchema> output(new te::map::LayerSchema(getTitle()));
89 
90  te::da::PrimaryKey* outKey = new te::da::PrimaryKey();
91 
92  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
93 
94  const te::da::Fields* fields = m_query->getFields();
95  const te::da::From* from = m_query->getFrom();
96 
97  for(size_t i = 0; i < fields->size(); ++i)
98  {
99  te::da::Field field = fields->at(i);
100  te::da::Expression* exp = field.getExpression();
101 
102  te::da::PropertyName* pName = dynamic_cast<te::da::PropertyName*>(exp);
103 
104  std::vector<std::string> tokens;
105  te::common::Tokenize(pName->getName(), tokens, ".");
106 
107  assert(tokens.size() == 2);
108 
109  std::string name;
110 
111  for(size_t j = 0; j < from->size(); ++j)
112  {
113  const te::da::FromItem& item = from->at(j);
114  const te::da::DataSetName* dsName = dynamic_cast<const te::da::DataSetName*>(&item);
115  if(dsName != 0)
116  {
117  if(dsName->getAlias() == tokens[0])
118  name = dsName->getName();
119  }
120  else
121  {
122  const te::da::Join* dsJoin = dynamic_cast<const te::da::Join*>(&item);
123  const te::da::FromItem* first = dsJoin->getFirst();
124  const te::da::DataSetName* dsName = dynamic_cast<const te::da::DataSetName*>(first);
125  if(dsName->getAlias() == tokens[0])
126  {
127  name = dsName->getName();
128  }
129  else
130  {
131  const te::da::FromItem* second = dsJoin->getSecond();
132  const te::da::DataSetName* dsName = dynamic_cast<const te::da::DataSetName*>(second);
133  name = dsName->getName();
134  }
135  }
136  }
137 
138  assert(!name.empty());
139 
140  std::auto_ptr<te::da::DataSetType> input = ds->getDataSetType(name);
141 
142  te::dt::Property* pRef = input->getProperty(tokens[1]);
143  assert(pRef);
144 
145  std::auto_ptr<te::dt::Property> p(pRef->clone());
146  p->setDatasetName(name);
147  output->add(p.release());
148 
149  if(input->getPrimaryKey()->has(pRef))
150  outKey->add(output->getProperty(pRef->getName()));
151  }
152 
153  if(!outKey->getProperties().empty())
154  output->setPrimaryKey(outKey);
155 
156  return output;
157 }
158 
159 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(te::common::TraverseType travType,
160  const te::common::AccessPolicy accessPolicy) const
161 {
162  return getData(m_query, travType, accessPolicy);
163 }
164 
165 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(const std::string& propertyName,
166  const te::gm::Envelope* e,
168  te::common::TraverseType travType,
169  const te::common::AccessPolicy accessPolicy) const
170 {
171  te::da::LiteralEnvelope* lenv = new te::da::LiteralEnvelope(*e, m_srid);
172 
173  te::da::PropertyName* pname = new te::da::PropertyName(propertyName);
174 
175  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
176 
177  const te::da::DataSourceCapabilities dsCap = ds->getCapabilities();
178 
179  const te::da::QueryCapabilities queryCap = dsCap.getQueryCapabilities();
180 
181  std::set<std::string> spatialTopOp = queryCap.getSpatialTopologicOperators();
182 
183  // The final select
184  std::auto_ptr<te::da::Select> select(static_cast<te::da::Select*>(m_query->clone()));
185 
186  // Original Where
187  te::da::Where* wh = select->getWhere();
188 
189  if(wh != 0)
190  {
191  // Original restriction expression
192  te::da::Expression* exp = wh->getExp()->clone();
193 
194  // TODO: switch that verifies the given te::gm::SpatialRelation and build the query object (ST_Intersects. ST_Touches, etc).
195 
196  if(spatialTopOp.find(te::da::FunctionNames::sm_ST_EnvelopeIntersects) != spatialTopOp.end())
197  {
198  te::da::ST_EnvelopeIntersects* intersects = new te::da::ST_EnvelopeIntersects(pname, lenv);
199 
200  // The final restriction: original restriction expression + extent restriction
201  te::da::And* andop = new te::da::And(exp, intersects);
202 
203  wh->setExp(andop);
204  }
205  else if(spatialTopOp.find(te::da::FunctionNames::sm_ST_Intersects) != spatialTopOp.end())
206  {
207  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(pname, lenv);
208 
209  // The final restriction: original restriction expression + extent restriction
210  te::da::And* andop = new te::da::And(exp, intersects);
211 
212  wh->setExp(andop);
213  }
214  }
215  else
216  {
217  if(spatialTopOp.find(te::da::FunctionNames::sm_ST_EnvelopeIntersects) != spatialTopOp.end())
218  {
219  te::da::ST_EnvelopeIntersects* intersects = new te::da::ST_EnvelopeIntersects(pname, lenv);
220  wh = new te::da::Where(intersects);
221  }
222  else if(spatialTopOp.find(te::da::FunctionNames::sm_ST_Intersects) != spatialTopOp.end())
223  {
224  te::da::ST_Intersects* intersects = new te::da::ST_Intersects(pname, lenv);
225  wh = new te::da::Where(intersects);
226  }
227  select->setWhere(wh);
228  }
229 
230  return getData(select.get(), travType, accessPolicy);
231 }
232 
233 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(const std::string& propertyName,
234  const te::gm::Geometry* /*g*/,
236  te::common::TraverseType /*travType*/,
237  const te::common::AccessPolicy) const
238 {
239  throw Exception("Not implemented yet!");
240 }
241 
242 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(te::da::Expression* restriction,
243  te::common::TraverseType travType,
244  const te::common::AccessPolicy accessPolicy) const
245 {
246  // The final select
247  std::auto_ptr<te::da::Select> select(static_cast<te::da::Select*>(m_query->clone()));
248 
249  // Original Where
250  te::da::Where* wh = select->getWhere();
251 
252  if(wh != 0)
253  {
254  // Original restriction expression
255  te::da::Expression* exp = wh->getExp()->clone();
256 
257  // The final restriction: original restriction expression + the given restriction expression
258  te::da::And* andop = new te::da::And(exp, restriction);
259  wh->setExp(andop);
260  }
261  else
262  {
263  wh = new te::da::Where(restriction);
264  select->setWhere(wh);
265  }
266 
267  return getData(select.get(), travType, accessPolicy);
268 }
269 
270 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(const te::da::ObjectIdSet* oids,
271  te::common::TraverseType travType,
272  const te::common::AccessPolicy accessPolicy) const
273 {
274  // The final select
275  std::auto_ptr<te::da::Select> select(static_cast<te::da::Select*>(m_query->clone()));
276 
277  // Original Where
278  te::da::Where* wh = select->getWhere();
279 
280  if(wh != 0)
281  {
282  // Original restriction expression
283  te::da::Expression* exp = wh->getExp()->clone();
284 
285  // The final restriction: original restriction expression + the oids restriction
286  te::da::And* andop = new te::da::And(exp, oids->getExpression());
287  wh->setExp(andop);
288  }
289  else
290  {
291  wh = new te::da::Where(oids->getExpression());
292  select->setWhere(wh);
293  }
294 
295  return getData(select.get(), travType, accessPolicy);
296 }
297 
299 {
300  if(m_query == 0)
301  return false;
302 
303  if(m_datasourceId.empty())
304  return false;
305 
307  try
308  {
309  ds = te::da::GetDataSource(m_datasourceId, true);
310  }
311  catch(...)
312  {
313  return false;
314  }
315 
316  if(ds.get() == 0 || !ds->isValid() || !ds->isOpened())
317  return false;
318 
319  return true;
320 }
321 
322 void te::map::QueryLayer::draw(Canvas* canvas, const te::gm::Envelope& bbox, int srid)
323 {
324  if(m_rendererType.empty())
325  throw Exception((boost::format(TE_TR("Could not draw the query layer %1%. The renderer type is empty!")) % getTitle()).str());
326 
327  // Try get the defined renderer
328  std::auto_ptr<AbstractRenderer> renderer(RendererFactory::make(m_rendererType));
329  if(renderer.get() == 0)
330  throw Exception((boost::format(TE_TR("Could not draw the query layer %1%. The renderer %2% could not be created!")) % getTitle() % m_rendererType).str());
331 
332  renderer->draw(this, canvas, bbox, srid);
333 }
334 
335 const std::string& te::map::QueryLayer::getType() const
336 {
337  return sm_type;
338 }
339 
341 {
342  return m_query;
343 }
344 
346 {
347  delete m_query;
348 
349  m_query = s;
350 }
351 
352 const std::string& te::map::QueryLayer::getDataSourceId() const
353 {
354  return m_datasourceId;
355 }
356 
357 void te::map::QueryLayer::setDataSourceId(const std::string& id)
358 {
359  m_datasourceId = id;
360 }
361 
362 const std::string& te::map::QueryLayer::getRendererType() const
363 {
364  return m_rendererType;
365 }
366 
367 void te::map::QueryLayer::setRendererType(const std::string& t)
368 {
369  m_rendererType = t;
370 }
371 
373 {
374  if(m_mbr.isValid())
375  return;
376 
377  // Get the associated data source
378  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
379 
380  std::auto_ptr<te::da::DataSet> dataset;
381 
382  // Get the dataset
383  dataset = ds->query(m_query);
384  assert(dataset.get());
385 
386  // MBR
387  m_mbr = *dataset->getExtent(te::da::GetFirstPropertyPos(dataset.get(), te::dt::GEOMETRY_TYPE));
388 }
389 
390 std::auto_ptr<te::da::DataSet> te::map::QueryLayer::getData(te::da::Select* query,
391  te::common::TraverseType travType,
392  const te::common::AccessPolicy accessPolicy) const
393 {
394  te::da::DataSourcePtr ds = te::da::GetDataSource(m_datasourceId, true);
395 
396  return ds->query(query, travType, accessPolicy);
397 }
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:86
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:61
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:347
const QueryCapabilities & getQueryCapabilities() const
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.
AccessPolicy
Supported data access policies (can be used as bitfield).
Definition: Enums.h:40
~QueryLayer()
Destructor.
Definition: QueryLayer.cpp:81
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:216
void setRendererType(const std::string &t)
Definition: QueryLayer.cpp:367
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:352
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:340
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
A canvas is an abstraction of a drawing area.
Definition: Canvas.h:91
void setDataSourceId(const std::string &id)
Definition: QueryLayer.cpp:357
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:322
void setQuery(te::da::Select *s)
Definition: QueryLayer.cpp:345
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:362
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:159
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:173
const std::string & getType() const
It returns the layer type: QUERY_LAYER.
Definition: QueryLayer.cpp:335
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:298
FromItem * getFirst() const
It returns the first from item involved in the join.
Definition: Join.cpp:91
const std::string & getName() const
It returns the property name.
Definition: Property.h:127