GeopackageSynchronizer.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011-2012 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 src/terraMobilePlugin/core/GeoPackageSynchronizer.h
22 
23 \brief This file is used to Synchronizer operation.
24 */
25 
26 #include "../../../../dataaccess/dataset/ObjectIdSet.h"
27 #include "../../../../dataaccess/dataset/ObjectId.h"
28 #include "../../../../dataaccess/datasource/DataSourceTransactor.h"
29 #include "../../../../dataaccess/utils/Utils.h"
30 #include "../../../../datatype/SimpleData.h"
31 #include "../../../../geometry/GeometryProperty.h"
32 #include "../../../../geometry/MultiPoint.h"
33 #include "../../../../geometry/Point.h"
34 #include "../../../../memory/DataSet.h"
35 #include "../../../../memory/DataSetItem.h"
36 
37 #include "../Config.h"
38 #include "GeopackageSynchronizer.h"
39 
40 
41 // Boost
42 #include <boost/uuid/random_generator.hpp>
43 #include <boost/uuid/uuid_io.hpp>
44 
45 
47  m_inputDataSource(0),
48  m_inputDataSet(""),
49  m_outputDataSource(0),
50  m_outputDataset("")
51 {
52 
53 }
54 
56 {
57 
58 }
59 
60 void te::qt::plugins::terramobile::GeoPackageSynchronizer::setInputParameters(te::da::DataSource* inputDataSource, std::string inputDataSet, te::da::DataSource* outputDataSource, std::string outputDataset)
61 {
62  m_inputDataSource = inputDataSource;
63  m_inputDataSet = inputDataSet;
64 
65  m_outputDataSource = outputDataSource;
66  m_outputDataset = outputDataset;
67 }
68 
70 {
72 
73  //get dataset type
74  std::auto_ptr<te::da::DataSetType> gpkgDsType = m_inputDataSource->getDataSetType(m_inputDataSet);
75 
76  //get data from gpkg
77  std::auto_ptr<te::da::DataSet> gpkgDataSet = m_inputDataSource->getDataSet(m_inputDataSet);
78 
79  //get gpkg ds attr pk index
80  int gpkgDataSetAttrPKIdx = -1;
81  if (gpkgDsType->getPrimaryKey())
82  {
83  te::da::PrimaryKey* pk = gpkgDsType->getPrimaryKey();
84  if (!pk->getProperties().empty())
85  {
86  gpkgDataSetAttrPKIdx = te::da::GetPropertyIndex(gpkgDataSet.get(), pk->getProperties()[0]->getName());
87  }
88  }
89 
90  int gpkgDataSetObjIdIdx = te::da::GetPropertyIndex(gpkgDataSet.get(), LAYER_GATHERING_OBJID_COLUMN);
91 
92  int gpkgDataSetGeomIdx = te::da::GetFirstSpatialPropertyPos(gpkgDataSet.get());
93 
94 
95  //create dataset memory to insert into output datasource
96  std::auto_ptr<te::da::DataSetType> dsTypeAux = m_outputDataSource->getDataSetType(m_outputDataset);
97  dsTypeAux->remove(dsTypeAux->getProperty("FID"));
98  te::mem::DataSet* insertDataSetDataSource = new te::mem::DataSet(dsTypeAux.get());
99 
100  //create dataset memory to update into output datasource
101  std::auto_ptr<te::da::DataSetType> dsTypeAux2 = m_outputDataSource->getDataSetType(m_outputDataset);
102  te::mem::DataSet* updateDataSetDataSource = new te::mem::DataSet(dsTypeAux2.get());
103 
104  te::gm::GeometryProperty* outputGeomProp = te::da::GetFirstGeomProperty(dsTypeAux.get());
105 
106  //remove entries
107  te::da::ObjectIdSet* objIdSet;
108  te::da::GetEmptyOIDSet(dsTypeAux2.get(), objIdSet);
109 
110  std::vector<std::string> pnames;
111  te::da::GetOIDPropertyNames(dsTypeAux2.get(), pnames);
112 
113  std::vector<te::dt::Property*> props = dsTypeAux2->getProperties();
114 
115  static boost::uuids::basic_random_generator<boost::mt19937> gen;
116 
117  gpkgDataSet->moveBeforeFirst();
118 
119  while (gpkgDataSet->moveNext())
120  {
121  if (gpkgDataSet->isNull(LAYER_GATHERING_OBJID_COLUMN))
122  {
123  //set obj id info
124  boost::uuids::uuid u = gen();
125  std::string id = boost::uuids::to_string(u);
126 
127  //create memory items
128  te::mem::DataSetItem* dsItem = new te::mem::DataSetItem(insertDataSetDataSource);
129 
130  for (std::size_t t = 0; t < props.size(); ++t)
131  {
132  if (props[t]->getName() == "FID" || props[t]->getName() == "fid")
133  {
134  continue;
135  }
136  else if (props[t]->getName() == LAYER_GATHERING_OBJID_COLUMN)
137  {
139  }
140  else if (props[t]->getName() == LAYER_GATHERING_STATUS_COLUMN)
141  {
143  }
144  else
145  {
146 
147  if (props[t]->getType() == te::dt::GEOMETRY_TYPE)
148  {
149  std::auto_ptr<te::gm::Geometry> geom = gpkgDataSet->getGeometry(gpkgDataSetGeomIdx);
150 
151  te::gm::Point* point = 0;
152 
153  if (geom->getGeomTypeId() == te::gm::MultiPointType)
154  {
155  point = (te::gm::Point*)((te::gm::MultiPoint*)geom.get())->getGeometryN(0);
156  }
157  else if (geom->getGeomTypeId() == te::gm::PointType)
158  {
159  point = (te::gm::Point*)geom.get();
160  }
161 
162  if (point)
163  {
164  point->setSRID(4326); //the geometry from geopackage always has to be 4326
165 
166  point->transform(outputGeomProp->getSRID());
167 
168  dsItem->setGeometry(props[t]->getName(), new te::gm::Point(*point));
169  }
170  }
171  else
172  {
173  if (te::da::GetPropertyPos(gpkgDataSet.get(), props[t]->getName()) != std::string::npos)
174  {
175  dsItem->setValue(props[t]->getName(), gpkgDataSet->getValue(props[t]->getName()).release());
176  }
177  }
178  }
179  }
180 
181  insertDataSetDataSource->add(dsItem);
182  }
183  else
184  {
185  if (gpkgDataSet->getInt32(LAYER_GATHERING_STATUS_COLUMN) == 1)
186  {
187  //create memory items
188  te::mem::DataSetItem* dsItem = new te::mem::DataSetItem(updateDataSetDataSource);
189 
190  for (std::size_t t = 0; t < props.size(); ++t)
191  {
192  if (props[t]->getName() == "FID" || props[t]->getName() == "fid")
193  {
194  std::string objId = gpkgDataSet->getString(LAYER_GATHERING_OBJID_COLUMN);
195 
196  std::string sql = "SELECT FID from ";
197  sql += dsTypeAux2->getName();
198  sql += " WHERE ";
200  sql += " = '";
201  sql += gpkgDataSet->getAsString(LAYER_GATHERING_OBJID_COLUMN);
202  sql += "'";
203 
204  std::auto_ptr<te::da::DataSet> dataSetQuery = m_outputDataSource->query(sql);
205 
206  if (!dataSetQuery->isEmpty())
207  {
208  dataSetQuery->moveFirst();
209 
210  int idValue = dataSetQuery->getInt32(0);
211 
212  dsItem->setValue(props[t]->getName(), new te::dt::SimpleData<int32_t, te::dt::INT32_TYPE>(idValue));
213  }
214  }
215  else if (props[t]->getName() == LAYER_GATHERING_STATUS_COLUMN)
216  {
218  }
219  else if (props[t]->getType() == te::dt::GEOMETRY_TYPE)
220  {
221  std::auto_ptr<te::gm::Geometry> geom = gpkgDataSet->getGeometry(props[t]->getName());
222 
223  te::gm::Point* point = 0;
224 
225  if (geom->getGeomTypeId() == te::gm::MultiPointType)
226  {
227  point = (te::gm::Point*)((te::gm::MultiPoint*)geom.get())->getGeometryN(0);
228  }
229  else if (geom->getGeomTypeId() == te::gm::PointType)
230  {
231  point = (te::gm::Point*)geom.get();
232  }
233 
234  if (point)
235  {
236  point->setSRID(4326); //the geometry from geopackage always has to be 4326
237 
238  point->transform(outputGeomProp->getSRID());
239 
240  dsItem->setGeometry(props[t]->getName(), new te::gm::Point(*point));
241  }
242  }
243  else
244  {
245  if (te::da::GetPropertyPos(gpkgDataSet.get(), props[t]->getName()) != std::string::npos)
246  {
247  dsItem->setValue(props[t]->getName(), gpkgDataSet->getValue(props[t]->getName()).release());
248  }
249  }
250  }
251 
252  updateDataSetDataSource->add(dsItem);
253  }
254  else if (gpkgDataSet->getInt32(LAYER_GATHERING_STATUS_COLUMN) == 2)
255  {
256  std::string objId = gpkgDataSet->getString(LAYER_GATHERING_OBJID_COLUMN);
257 
258  std::string sql = "SELECT * from ";
259  sql += dsTypeAux2->getName();
260  sql += " WHERE ";
262  sql += " = '";
263  sql += gpkgDataSet->getAsString(LAYER_GATHERING_OBJID_COLUMN);
264  sql += "'";
265 
266  std::auto_ptr<te::da::DataSet> dataSetQuery = m_outputDataSource->query(sql);
267 
268  if (!dataSetQuery->isEmpty())
269  {
270  dataSetQuery->moveFirst();
271 
272  objIdSet->add(te::da::GenerateOID(dataSetQuery.get(), pnames));
273  }
274  }
275  }
276  }
277 
278  //INSERT into output datasource
279  if (!insertDataSetDataSource->isEmpty())
280  {
281  std::unique_ptr<te::da::DataSourceTransactor> transactor = m_outputDataSource->getTransactor();
282 
283  std::map<std::string, std::string> op;
284 
285  try
286  {
287  transactor->add(m_outputDataset, insertDataSetDataSource, op);
288  }
289  catch (const te::common::Exception& e)
290  {
291  transactor->rollBack();
292 
293  return;
294  }
295  catch (const std::exception& e)
296  {
297  transactor->rollBack();
298 
299  return;
300  }
301  catch (...)
302  {
303  transactor->rollBack();
304 
305  return;
306  }
307 
308  transactor->commit();
309  }
310 
311  //UPDATE into output datasource
312  if (!updateDataSetDataSource->isEmpty())
313  {
314  std::unique_ptr<te::da::DataSourceTransactor> transactor = m_outputDataSource->getTransactor();
315 
316  try
317  {
318  std::vector<size_t> ids;
319  ids.push_back(0);
320 
321  std::vector< std::set<int> > properties;
322  std::size_t dsSize = updateDataSetDataSource->size();
323 
324  for (std::size_t t = 0; t < dsSize; ++t)
325  {
326  std::set<int> setPos;
327 
328  for (std::size_t p = 0; p < updateDataSetDataSource->getNumProperties(); ++p)
329  {
330  setPos.insert(p);
331  }
332 
333  properties.push_back(setPos);
334  }
335 
336  transactor->update(m_outputDataset, updateDataSetDataSource, properties, ids);
337  }
338  catch (const te::common::Exception& e)
339  {
340  transactor->rollBack();
341 
342  return;
343  }
344  catch (const std::exception& e)
345  {
346  transactor->rollBack();
347 
348  return;
349  }
350  catch (...)
351  {
352  transactor->rollBack();
353 
354  return;
355  }
356  transactor->commit();
357  }
358 
359  //remove entries
360  if (objIdSet->size() != 0)
361  {
362  std::unique_ptr<te::da::DataSourceTransactor> transactor = m_outputDataSource->getTransactor();
363 
364  try
365  {
366  transactor->remove(m_outputDataset, objIdSet);
367  }
368  catch (const te::common::Exception& e)
369  {
370  transactor->rollBack();
371 
372  return;
373  }
374  catch (const std::exception& e)
375  {
376  transactor->rollBack();
377 
378  return;
379  }
380  catch (...)
381  {
382  transactor->rollBack();
383 
384  return;
385  }
386 
387  transactor->commit();
388  }
389 }
390 
392 {
393  if (!m_inputDataSource)
394  throw;
395 
396  if (m_inputDataSet.empty())
397  throw;
398 
399  if (!m_outputDataSource)
400  throw;
401 
402  if (m_outputDataset.empty())
403  throw;
404 }
std::size_t size() const
It returns the collection size, if it is known.
Geometric property.
void setGeometry(std::size_t i, te::gm::Geometry *value)
It sets the value of the i-th property.
virtual std::unique_ptr< DataSourceTransactor > getTransactor()=0
It returns the set of parameters used to set up the access channel to the underlying repository...
TEDATAACCESSEXPORT void GetEmptyOIDSet(const DataSetType *type, ObjectIdSet *&set)
Returns an empty ObjectIdSet, with the definitions of fields that compose it.
void setSRID(int srid) _NOEXCEPT_OP(true)
It sets the Spatial Reference System ID of the Point.
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
void setInputParameters(te::da::DataSource *inputDataSource, std::string inputDataSet, te::da::DataSource *outputDataSource, std::string outputDataset)
TEDATAACCESSEXPORT std::size_t GetPropertyPos(const DataSet *dataset, const std::string &name)
void setValue(std::size_t i, te::dt::AbstractData *value)
It sets the value of the i-th property.
An abstract class for data providers like a DBMS, Web Services or a regular file. ...
bool isEmpty() const
It returns true if the collection is empty.
TEDATAACCESSEXPORT int GetPropertyIndex(te::da::DataSet *dataSet, const std::string propName)
void add(DataSetItem *item)
It adds a new item to the dataset and takes its ownership.
const std::vector< te::dt::Property * > & getProperties() const
It returns the properties that take part of the primary key.
Definition: PrimaryKey.h:109
virtual std::unique_ptr< DataSet > query(const Select &q, te::common::TraverseType travType=te::common::FORWARDONLY, const te::common::AccessPolicy accessPolicy=te::common::RAccess)
It executes a query that may return some data using a generic query. This method always returns a dis...
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
MultiPoint is a GeometryCollection whose elements are restricted to points.
Definition: MultiPoint.h:50
TEDATAACCESSEXPORT std::size_t GetFirstSpatialPropertyPos(const te::da::DataSet *dataset)
It returns the first dataset spatial property or NULL if none is found.
A point with x and y coordinate values.
Definition: Point.h:50
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:55
void DataSet()
void transform(int srid) _NOEXCEPT_OP(false)
It converts the coordinate values of the point to the new spatial reference system.
te::gm::Polygon * p
virtual std::unique_ptr< te::da::DataSetType > getDataSetType(const std::string &name)
It gets information about the given dataset.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
#define LAYER_GATHERING_STATUS_COLUMN
virtual std::unique_ptr< DataSet > getDataSet(const std::string &name, te::common::TraverseType travType=te::common::FORWARDONLY, const te::common::AccessPolicy accessPolicy=te::common::RAccess)
It gets the dataset identified by the given name. This method always returns a disconnected dataset...
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
#define LAYER_GATHERING_OBJID_COLUMN
TEDATAACCESSEXPORT void GetOIDPropertyNames(const DataSetType *type, std::vector< std::string > &pnames)
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
std::size_t getNumProperties() const
It returns the number of properties that composes an item of the dataset.