All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DataSourceCatalog.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/dataaccess/datasource/DataSourceCatalog.cpp
22 
23  \brief It represents the system catalog of a DataSource.
24 */
25 
26 // TerraLib
27 #include "../../common/STLUtils.h"
28 #include "../../common/Translator.h"
29 #include "../../datatype/Enums.h"
30 #include "../../datatype/Property.h"
31 #include "../dataset/DataSetType.h"
32 #include "../dataset/Sequence.h"
33 #include "../dataset/ForeignKey.h"
34 #include "../Exception.h"
35 #include "DataSource.h"
36 #include "DataSourceCatalog.h"
37 
38 // STL
39 #include <cassert>
40 
41 // Boost
42 #include <boost/format.hpp>
43 
45 
47  : m_id(0),
48  m_ds(0)
49 {
50 }
51 
53 {
54  te::common::FreeContents(m_sequences.begin(), m_sequences.end());
55 }
56 
58 {
59 // datasets
60  m_datasets.clear();
61 
62 // sequences
63  te::common::FreeContents(m_sequences.begin(), m_sequences.end());
64  m_sequences.clear();
65 
66  m_seqFTIdx.clear();
67 
68 // foreign key
69  m_dependentFkIdx.clear();
70 }
71 
72 bool te::da::DataSourceCatalog::datasetExists(const std::string& name) const
73 {
74  dataset_idx_type::const_iterator it = m_datasets.find(name);
75 
76  return (it != m_datasets.end());
77 }
78 
80 {
81  if(dt.get() == 0)
82  throw Exception(TE_TR("Can not add a NULL dataset schema to the catalog!"));
83 
84  if(dt->getName().empty())
85  throw Exception(TE_TR("Can not add a dataset schema with an empty name to the catalog!"));
86 
87  if(datasetExists(dt->getName()))
88  throw Exception((boost::format(TE_TR("Can not add dataset schema %1% to the catalog. There is already another one with this name!")) % dt->getName()).str());
89 
90  if(dt->getCatalog() != 0)
91  throw Exception((boost::format(TE_TR("Can not add dataset schema %1% to the catalog. It is already attached to one!")) % dt->getName()).str());
92 
93  checkFKsDependency(dt.get());
94 
95  m_datasets.insert(dt);
96  dt->setCatalog(this);
97  indexFKs(dt.get());
98 }
99 
100 void te::da::DataSourceCatalog::remove(DataSetType* dt, const bool cascade)
101 {
102  if(dt == 0)
103  throw Exception(TE_TR("Can not remove a NULL dataset schema from the catalog!"));
104 
105  if(dt->getName().empty())
106  throw Exception(TE_TR("Can not remove a dataset schema with an empty name from the catalog!"));
107 
108  if(dt->getCatalog() != this)
109  throw Exception(TE_TR("Can not remove a dataset from another catalog!"));
110 
111  assert(datasetExists(dt->getName()));
112  assert(m_datasets.find(dt->getName()) != m_datasets.end());
113  assert((*m_datasets.find(dt->getName())).get() == dt);
114 
115  if(cascade)
116  {
117  dropDependentSequences(dt);
118  dropDependentFKs(dt);
119  }
120  else
121  {
122  m_seqFTIdx.erase(dt);
123  m_dependentFkIdx.erase(dt);
124  }
125 
126  m_datasets.erase(dt->getName());
127 }
128 
129 void te::da::DataSourceCatalog::rename(DataSetType* dt, const std::string& newName)
130 {
131  if(dt == 0)
132  throw Exception(TE_TR("Can not rename a NULL dataset schema!"));
133 
134  if(datasetExists(newName))
135  throw Exception(TE_TR("Could not rename DataSetType because the new name already exist in the catalog!"));
136 
137  if(dt->getCatalog() != this)
138  throw Exception(TE_TR("Could not rename a dataset from another catalog!"));
139 
140  dataset_idx_type::iterator it = m_datasets.find(dt->getName());
141 
142  if(it == m_datasets.end())
143  throw Exception(TE_TR("Could not find dataset schema in the catalog!"));
144 
145  if((*it).get() != dt)
146  throw Exception(TE_TR("The dataset schema is not registered in this catalog!"));
147 
148  DataSetTypePtr aux = *it;
149 
150  m_datasets.erase(it);
151 
152  aux->setName(newName);
153 
154  m_datasets.insert(aux);
155 }
156 
158 {
159  assert(i < m_datasets.size());
160 
161  const dataset_idx_type::nth_index<1>::type& pos_idx = m_datasets.get<1>();
162 
163  return pos_idx[i];
164 }
165 
167 {
168  assert(!name.empty());
169 
170  dataset_idx_type::const_iterator it = m_datasets.find(name);
171 
172  if(it != m_datasets.end())
173  return *it;
174 
175  return sm_nullds;
176 }
177 
179 {
180  if(getSequence(s->getName()))
181  throw Exception(TE_TR("Could not add Sequence because there is already another Sequence with the same name in the catalog!"));
182 
183  checkSequenceDependency(s);
184  m_sequences.insert(s);
185  s->setCatalog(this);
186  indexSequenceDependency(s);
187 }
188 
190 {
191  detach(s);
192  delete s;
193 }
194 
196 {
197  m_sequences.erase(s->getName());
198  dropDependentSequenceEntry(s);
199 }
200 
202 {
203  const sequence_idx_type::nth_index<1>::type& pos_idx = m_sequences.get<1>();
204 
205  return pos_idx[i];
206 }
207 
209 {
210  sequence_idx_type::const_iterator it = m_sequences.find(name);
211 
212  if(it != m_sequences.end())
213  return *it;
214 
215  return 0;
216 }
217 
219 {
221 
222  if((refFT == 0) || (getDataSetType(refFT->getName()).get() != refFT))
223  throw Exception(TE_TR("Could not find the DataSetType referenced in foreign key!"));
224 
225  m_dependentFkIdx.insert(std::pair<DataSetType*, ForeignKey*>(refFT, fk));
226 }
227 
229 {
231 
232  if((refFT == 0) || (getDataSetType(refFT->getName()).get() != refFT))
233  throw Exception(TE_TR("Could not find the DataSetType referenced in foreign key!"));
234 
235  std::pair<std::multimap<DataSetType*, ForeignKey*>::iterator,
236  std::multimap<DataSetType*, ForeignKey*>::iterator> range = m_dependentFkIdx.equal_range(refFT);
237 
238  while(range.first != range.second)
239  {
240  std::multimap<DataSetType*, ForeignKey*>::iterator it = range.first; // keep a pointer to current element... we must erase it!
241 
242  ++range.first; // go to next element before erasing current!
243 
244 // is the iterator pointing to the right entry?
245  if(it->second == fk)
246  {
247  m_dependentFkIdx.erase(it);
248  return;
249  }
250  }
251 
252  throw Exception(TE_TR("Something went wrong when removing the association of a foreign key and a DataSetType in the DataSourceCatalog!"));
253 }
254 
256 {
257  te::dt::Property* parent = p;
258 
259  while(parent)
260  {
261  parent = parent->getParent();
262 
263  if(parent &&
264  (parent->getType() == te::dt::DATASET_TYPE) &&
265  (getDataSetType(parent->getName()).get() == parent))
266  {
267  te::da::DataSetType* dt = static_cast<te::da::DataSetType*>(parent);
268 
269 // is the dt owner of a sequence?
270  std::pair<std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator,
271  std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator> range = m_seqFTIdx.equal_range(dt);
272 
273  while(range.first != range.second)
274  {
275  std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator it = range.first;
276  ++range.first;
277 
278  te::da::Sequence* s = *(it->second);
279 
280 // is the property owner of the sequence?
281  if(s->getOwner() == p)
282  {
283  m_sequences.erase(it->second);
284  delete s;
285  m_seqFTIdx.erase(it);
286  }
287  }
288 
289  return;
290  }
291  }
292 }
293 
295 {
296  if(s->getOwner() == 0)
297  return;
298 
299  te::dt::Property* parent = s->getOwner();
300 
301  while(parent)
302  {
303  parent = parent->getParent();
304 
305 // if the parent is a FetaureType and it is in the catalog, stop!
306  if(parent &&
307  (parent->getType() == te::dt::DATASET_TYPE) &&
308  (getDataSetType(parent->getName()).get() == parent))
309  return;
310  }
311 
312  throw Exception(TE_TR("Could not find in the catalog the DataSetType that owns the given sequence!"));
313 }
314 
316 {
317  if(s->getOwner() == 0)
318  return;
319 
320  te::dt::Property* parent = s->getOwner();
321 
322  sequence_idx_type::iterator it = m_sequences.find(s->getName());
323 
324  while(parent)
325  {
326  parent = parent->getParent();
327 
328 // if the parent is a FetaureType and it is in the catalog, make index and stop!
329  if(parent &&
330  (parent->getType() == te::dt::DATASET_TYPE) &&
331  (getDataSetType(parent->getName()).get() == parent))
332  {
333  te::da::DataSetType* dt = static_cast<te::da::DataSetType*>(parent);
334  m_seqFTIdx.insert(std::pair<DataSetType*, sequence_idx_type::iterator>(dt, it));
335  return;
336  }
337  }
338 
339  throw Exception(TE_TR("Could not find in the catalog the DataSetType that owns the given sequence!"));
340 }
341 
343 {
344  std::pair<std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator,
345  std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator> range = m_seqFTIdx.equal_range(dt);
346 
347  while(range.first != range.second)
348  {
349  std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator it = range.first;
350  ++range.first;
351 
352 // remove sequence and all its entry in the catalog
353 // !! DON'T CALL remove(s) THIS WILL NEED EXTRA COMPUTATIONS AND ALSO WILL NEED TO CHANGE THE LOGIC OF CODE BLOCK!!
354  te::da::Sequence* s = *(it->second);
355  m_sequences.erase(it->second);
356  delete s;
357  m_seqFTIdx.erase(it);
358  }
359 }
360 
362 {
363  if(s->getOwner() == 0)
364  return;
365 
366  te::dt::Property* parent = s->getOwner();
367 
368  sequence_idx_type::iterator itpos = m_sequences.find(s->getName());
369 
370  while(parent)
371  {
372  parent = parent->getParent();
373 
374 // if the parent is a FetaureType and it is in the catalog, make index and stop!
375  if(parent &&
376  (parent->getType() == te::dt::DATASET_TYPE) &&
377  (getDataSetType(parent->getName()).get() == parent))
378  {
379  te::da::DataSetType* dt = static_cast<te::da::DataSetType*>(parent);
380 
381  std::pair<std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator,
382  std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator> range = m_seqFTIdx.equal_range(dt);
383 
384  while(range.first != range.second)
385  {
386  std::multimap<DataSetType*, sequence_idx_type::iterator>::iterator it = range.first;
387  ++range.first;
388 
389  if(*(it->second) == *itpos)
390  {
391  m_seqFTIdx.erase(it);
392  return;
393  }
394  }
395  }
396  }
397 
398  throw Exception(TE_TR("Could not find in the catalog the DataSetType that owns the given sequence in order to remove the sequence entry!"));
399 }
400 
402 {
403  std::size_t size = dt->getNumberOfForeignKeys();
404 
405  for(std::size_t i = 0; i < size; ++i)
406  {
407  te::da::ForeignKey* fk = dt->getForeignKey(i);
409 
410  if((refFT == 0) || (getDataSetType(refFT->getName()).get() != refFT))
411  throw Exception(TE_TR("There is a foreign key in the DataSetType referencing another DataSetType that is not in the catalog!"));
412  }
413 }
414 
416 {
417  std::size_t size = dt->getNumberOfForeignKeys();
418 
419  for(std::size_t i = 0; i < size; ++i)
420  {
421  te::da::ForeignKey* fk = dt->getForeignKey(i);
423 
424  assert(getDataSetType(refFT->getName()).get() == refFT);
425 
426  m_dependentFkIdx.insert(std::pair<DataSetType*, ForeignKey*>(refFT, fk));
427  }
428 }
429 
431 {
432  std::pair<std::multimap<DataSetType*, ForeignKey*>::iterator,
433  std::multimap<DataSetType*, ForeignKey*>::iterator> range = m_dependentFkIdx.equal_range(dt);
434 
435  while(range.first != range.second)
436  {
437  std::multimap<DataSetType*, ForeignKey*>::iterator it = range.first; // keep a pointer to current element... we must erase it!
438 
439  ++range.first; // go to next element before erasing current!
440 
441 // who is the owner of the fk? ask it to drop the fk!
442  te::da::ForeignKey* fk = it->second;
443  te::da::DataSetType* fkOwner = fk->getDataSetType();
444  fkOwner->remove(fk);
445  }
446 }
447 
449 {
450  return dt->getName();
451 }
452 
454 {
455  return s->getName();
456 }
457 
DataSourceCatalog * getCatalog() const
It returns the catalog that owns the DataSetType.
Definition: DataSetType.h:158
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
result_type operator()(const Sequence *const s) const
te::dt::Property * getOwner() const
It returns the property type associated to the sequence.
Definition: Sequence.h:237
result_type operator()(const DataSetTypePtr &dt) const
An abstract class for data providers like a DBMS, Web Services or a regular file. ...
A class that models the description of a dataset.
Definition: DataSetType.h:72
void remove(DataSetType *dt, const bool cascade=false)
It removes the dataset schema from the catalog.
It describes a sequence (a number generator).
Definition: Sequence.h:56
bool datasetExists(const std::string &name) const
It checks if a dataset schema with the given name is in the catalog.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
void detach(Sequence *s)
It will detaches the Sequence from the catalog.
It models a property definition.
Definition: Property.h:59
void removeRef(ForeignKey *fk)
It drops the reference between the foreign key and its referenced DataSetType.
const DataSetTypePtr & getDataSetType(std::size_t i) const
It returns the i-th dataset schema.
void checkSequenceDependency(Sequence *s) const
It checks if the Sequence is owned by a DataSetType property and if that DataSetType is in the catalo...
void clear()
It clears the catalog, releasing all the resources used by it.
void remove(Constraint *c)
It removes the constraint.
std::size_t getNumberOfForeignKeys() const
It returns the number of foreign keys defined for the dataset type.
Definition: DataSetType.h:467
void dropDependentSequences(te::dt::Property *p)
It drops Sequences that depends on the property.
void add(const DataSetTypePtr &dt)
It adds a new dataset schema to the catalog.
void addRef(ForeignKey *fk)
It checks if the referenced DataSetType is in the catalog and associate the fk to it...
Sequence * getSequence(std::size_t i) const
It returns the i-th Sequence.
DataSetType * getReferencedDataSetType() const
It returns the referenced DataSetType of this foreign key constraint.
Definition: ForeignKey.h:153
It models a foreign key constraint for a DataSetType.
Definition: ForeignKey.h:50
It represents the system catalog of a DataSource.
Property * getParent() const
It returns the parent of this property, or NULL, if it doesn't have one.
Definition: Property.h:168
int getType() const
It returns the property data type.
Definition: Property.h:161
void rename(DataSetType *dt, const std::string &newName)
It renames the dataset schema in the catalog.
ForeignKey * getForeignKey(std::size_t i) const
It returns the i-th foreign key associated to the dataset type.
Definition: DataSetType.h:480
void checkFKsDependency(DataSetType *dt) const
It checks if the DataSetTypes referenced by dt's foreign keys are in the catalog. ...
void dropDependentSequenceEntry(Sequence *s)
It drops the Sequence entry in the DataSetType sequence dependency list.
static DataSetTypePtr sm_nullds
virtual DataSetType * getDataSetType() const
It returns the DataSetType associated to the constraint.
Definition: Constraint.h:133
DataSourceCatalog()
It creates a new DataSourceCatalog.
void dropDependentFKs(DataSetType *dt)
It drops foreign keys from other DataSetTypes that depends on the attributes in the given DataSetType...
const std::string & getName() const
It returns the sequence name.
Definition: Sequence.h:140
void indexFKs(DataSetType *dt)
It looks for foreign keys in the DataSetType dt and try to index then with respect to referenced Data...
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
void setCatalog(DataSourceCatalog *catalog)
It sets the catalog associated to the sequence.
Definition: Sequence.h:264
void indexSequenceDependency(Sequence *s)
It looks if the sequence is owned by a given DataSetType property and insert this information into th...
const std::string & getName() const
It returns the property name.
Definition: Property.h:127