Project.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 Project.cpp
22 
23 // \brief This class models the concept of a project for the TerraView application.
24 //*/
25 
26 // TerraLib
27 #include "Project.h"
28 
29 #include "../terralib/common/BoostUtils.h"
30 #include "../terralib/core/utils/Platform.h"
31 #include "../terralib/core/uri/Utils.h"
32 #include "../terralib/dataaccess/datasource/DataSourceInfoManager.h"
33 #include "../terralib/dataaccess/serialization/xml/Serializer.h"
34 #include "../terralib/maptools/serialization/xml/Layer.h"
35 #include "../terralib/xml/AbstractWriter.h"
36 #include "../terralib/xml/AbstractWriterFactory.h"
37 #include "../terralib/xml/Reader.h"
38 #include "../terralib/xml/ReaderFactory.h"
39 #include "../terralib/Version.h"
40 
41 // Boost
42 #include <boost/algorithm/string/replace.hpp>
43 
44 // Qt
45 #include <QFileInfo>
46 
47 void updateLayerDataSource(const te::map::AbstractLayerPtr& layer, const std::map<std::string, std::string>& invalidToValidIds)
48 {
49  size_t count = layer->getChildrenCount();
50 
51  for (size_t i = 0; i < count; ++i)
52  {
53  te::map::AbstractLayerPtr child(boost::dynamic_pointer_cast<te::map::AbstractLayer>(layer->getChild(i)));
54  if (child.get())
55  updateLayerDataSource(child, invalidToValidIds);
56  }
57 
58  std::map<std::string, std::string>::const_iterator end = invalidToValidIds.end();
59 
60  if (invalidToValidIds.find(layer->getDataSourceId()) != end)
61  layer->setDataSourceId(invalidToValidIds.find(layer->getDataSourceId())->second);
62 }
63 
64 std::vector<std::string> getDataSourceIds(const std::list<te::map::AbstractLayerPtr>& layers)
65 {
66  std::vector<std::string> dsIds;
67 
68  for (std::list<te::map::AbstractLayerPtr>::const_iterator itL = layers.begin(); itL != layers.end(); ++itL)
69  {
70  te::map::AbstractLayerPtr layer = (*itL);
71 
72  if (layer->getType() != "FOLDERLAYER")
73  dsIds.push_back(layer->getDataSourceId());
74  else
75  {
76  std::list<te::map::AbstractLayerPtr> converted;
77 
78  std::list<te::common::TreeItemPtr> children = layer->getChildren();
79  std::list<te::common::TreeItemPtr>::iterator childrenB = children.begin();
80  std::list<te::common::TreeItemPtr>::iterator childrenE = children.end();
81 
82  while (childrenB != childrenE)
83  {
84  te::map::AbstractLayerPtr currentLayer = dynamic_cast<te::map::AbstractLayer*>((*childrenB).get());
85  converted.push_back(currentLayer);
86  childrenB++;
87  }
88 
89  std::vector<std::string> childrenDsIds = getDataSourceIds(converted);
90  dsIds.insert(dsIds.end(), childrenDsIds.begin(), childrenDsIds.end());
91  }
92  }
93 
94  return dsIds;
95 }
96 
97 void SaveProject(const ProjectMetadata& proj, const std::list<te::map::AbstractLayerPtr>& layers)
98 {
99  std::unique_ptr<te::xml::AbstractWriter> writer(te::xml::AbstractWriterFactory::make());
100 
101  writer->setURI(proj.m_fileName.toUtf8().data());
102 
103  std::string schema_loc = te::core::FindInTerraLibPath("share/terralib/schemas/terralib/qt/af/project.xsd");
104 
105  writer->writeStartDocument("UTF-8", "no");
106 
107  writer->writeStartElement("Project");
108 
109  boost::replace_all(schema_loc, " ", "%20");
110 
111  writer->writeAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema-instance");
112  writer->writeAttribute("xmlns:te_da", "http://www.terralib.org/schemas/dataaccess");
113  writer->writeAttribute("xmlns:te_map", "http://www.terralib.org/schemas/maptools");
114  writer->writeAttribute("xmlns:te_qt_af", "http://www.terralib.org/schemas/common/af");
115 
116  writer->writeAttribute("xmlns:se", "http://www.opengis.net/se");
117  writer->writeAttribute("xmlns:ogc", "http://www.opengis.net/ogc");
118  writer->writeAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
119 
120  writer->writeAttribute("xmlns", "http://www.terralib.org/schemas/qt/af");
121  writer->writeAttribute("xsd:schemaLocation", "http://www.terralib.org/schemas/qt/af " + schema_loc);
122  writer->writeAttribute("version", TERRALIB_VERSION_STRING);
123 
124  writer->writeElement("Title", proj.m_title.toUtf8().data());
125  writer->writeElement("Author", proj.m_author.toUtf8().data());
126 
127  //write data source list
128  writer->writeStartElement("te_da:DataSourceList");
129 
130  writer->writeAttribute("xmlns:te_common", "http://www.terralib.org/schemas/common");
131 
135 
136  std::vector<std::string> dsIdVec = getDataSourceIds(layers);
137 
138  for(it=itBegin; it!=itEnd; ++it)
139  {
140 
141  if (std::find(dsIdVec.begin(), dsIdVec.end(), it->second->getId()) == dsIdVec.end())
142  continue;
143 
144  writer->writeStartElement("te_da:DataSource");
145 
146  writer->writeAttribute("id", it->second->getId());
147  writer->writeAttribute("type", it->second->getType());
148  writer->writeAttribute("access_driver", it->second->getAccessDriver());
149 
150  writer->writeStartElement("te_da:Title");
151  writer->writeValue(it->second->getTitle());
152  writer->writeEndElement("te_da:Title");
153 
154  writer->writeStartElement("te_da:Description");
155  writer->writeValue(it->second->getDescription());
156  writer->writeEndElement("te_da:Description");
157 
158  writer->writeStartElement("te_da:URI");
159  writer->writeValue(te::core::URIEncode(it->second->getConnInfoAsString()));
160  writer->writeEndElement("te_da:URI");
161 
162  writer->writeEndElement("te_da:DataSource");
163  }
164 
165  writer->writeEndElement("te_da:DataSourceList");
166  //end write
167 
168  writer->writeStartElement("ComponentList");
169  writer->writeEndElement("ComponentList");
170 
171  writer->writeStartElement("te_map:LayerList");
172 
174 
175  for(std::list<te::map::AbstractLayerPtr>::const_iterator itL = layers.begin(); itL != layers.end(); ++itL)
176  lserial.write((*itL).get(), *writer.get());
177 
178  writer->writeEndElement("te_map:LayerList");
179 
180  writer->writeEndElement("Project");
181 
182  writer->writeToFile();
183 }
184 
185 void LoadProject(const QString& projFile, ProjectMetadata& proj, std::list<te::map::AbstractLayerPtr>& layers)
186 {
187  QFileInfo info(projFile);
188  std::string fName = projFile.toUtf8().data();
189 
190  if(!info.exists() || !info.isFile())
191  {
192  QString msg = QObject::tr("Could not read project file: ") + projFile;
193  throw te::common::Exception(msg.toUtf8().data());
194  }
195 
196  std::unique_ptr<te::xml::Reader> xmlReader(te::xml::ReaderFactory::make());
197 
198  xmlReader->read(fName);
199 
200  if(!xmlReader->next())
201  {
202  QString msg = QObject::tr("Could not read project information in the file: ") + projFile + ".";
203  throw te::common::Exception(msg.toUtf8().data());
204  }
205 
206  if(xmlReader->getNodeType() != te::xml::START_ELEMENT)
207  {
208  QString msg = QObject::tr("Error reading the document ") + projFile + QObject::tr(", the start element wasn't found.");
209  throw te::common::Exception(msg.toUtf8().data());
210  }
211 
212  if(xmlReader->getElementLocalName() != "Project")
213  {
214  QString msg = QObject::tr("The first tag in the document ") + projFile + QObject::tr(" is not 'Project'.");
215  throw te::common::Exception(msg.toUtf8().data());
216  }
217 
218  xmlReader->next();
219  assert(xmlReader->getNodeType() == te::xml::START_ELEMENT);
220  assert(xmlReader->getElementLocalName() == "Title");
221 
222  xmlReader->next();
223  assert(xmlReader->getNodeType() == te::xml::VALUE);
224  proj.m_title = xmlReader->getElementValue().c_str();
225 
226  xmlReader->next(); // End element
227 
228  xmlReader->next();
229  assert(xmlReader->getNodeType() == te::xml::START_ELEMENT);
230  assert(xmlReader->getElementLocalName() == "Author");
231 
232  xmlReader->next();
233 
234  if(xmlReader->getNodeType() == te::xml::VALUE)
235  {
236  proj.m_author = xmlReader->getElementValue().c_str();
237  xmlReader->next(); // End element
238  }
239 
240  // //read data source list from this project
241  xmlReader->next();
242 
243  assert(xmlReader->getNodeType() == te::xml::START_ELEMENT);
244  assert(xmlReader->getElementLocalName() == "DataSourceList");
245 
246  xmlReader->next();
247 
248  // DataSourceList contract form
249  if(xmlReader->getNodeType() == te::xml::END_ELEMENT &&
250  xmlReader->getElementLocalName() == "DataSourceList")
251  {
252  xmlReader->next();
253  }
254 
255  //Datasources that may need to be updated
256  std::map<std::string, std::string> invalidDsConnInfo;
257 
258  while((xmlReader->getNodeType() == te::xml::START_ELEMENT) &&
259  (xmlReader->getElementLocalName() == "DataSource"))
260  {
262  std::string dsId = ds->getId();
264  invalidDsConnInfo.insert(std::make_pair(dsId, ds->getId()));
265  }
266 
267  // //end read data source list
268 
269  assert(xmlReader->getNodeType() == te::xml::START_ELEMENT);
270  assert(xmlReader->getElementLocalName() == "ComponentList");
271  xmlReader->next(); // End element
272  xmlReader->next(); // next after </ComponentList>
273 
274  assert(xmlReader->getNodeType() == te::xml::START_ELEMENT);
275  assert(xmlReader->getElementLocalName() == "LayerList");
276 
277  xmlReader->next();
278 
280 
281  // Read the layers
282  while((xmlReader->getNodeType() != te::xml::END_ELEMENT) &&
283  (xmlReader->getElementLocalName() != "LayerList"))
284  {
285  te::map::AbstractLayerPtr layer(lserial.read(*(xmlReader.get())));
286 
287  assert(layer.get());
288 
289  layers.push_back(layer);
290  }
291 
292  assert(xmlReader->getNodeType() == te::xml::END_ELEMENT);
293  assert(xmlReader->getElementLocalName() == "LayerList");
294 
295  xmlReader->next();
296  assert((xmlReader->getNodeType() == te::xml::END_ELEMENT) || (xmlReader->getNodeType() == te::xml::END_DOCUMENT));
297  assert(xmlReader->getElementLocalName() == "Project");
298 
299  proj.m_fileName = projFile;
300 
301  //updating the datasources of any layers with outdated ids, whenever possible
302  for (te::map::AbstractLayerPtr layer : layers) {
303  updateLayerDataSource(layer, invalidDsConnInfo);
304  }
305 }
std::map< std::string, DataSourceInfoPtr >::iterator iterator
This is the base class for layers.
Definition: AbstractLayer.h:77
TECOREEXPORT std::string URIEncode(const std::string &srcUri)
Encodes an decoded URI. The algorithm implementation is based on http://www.codeguru.com/cpp/cpp/algorithms/strings/article.php/c12759/URI-Encoding-and-Decoding.htm.
void SaveProject(const ProjectMetadata &proj, const std::list< te::map::AbstractLayerPtr > &layers)
Definition: Project.cpp:97
This class models the concept of a project for the TerraView.
void LoadProject(const QString &projFile, ProjectMetadata &proj, std::list< te::map::AbstractLayerPtr > &layers)
Definition: Project.cpp:185
static te::xml::AbstractWriter * make()
It creates a new XML writer using the dafault implementation.
static te::dt::Date ds(2010, 01, 01)
static te::xml::Reader * make()
It creates a new XML reader using the dafault implementation.
void updateLayerDataSource(const te::map::AbstractLayerPtr &layer, const std::map< std::string, std::string > &invalidToValidIds)
Definition: Project.cpp:47
QString m_fileName
The project file.
Definition: Project.h:44
te::map::AbstractLayer * read(te::xml::Reader &reader) const
static DataSourceInfoManager & getInstance()
It returns a reference to the singleton instance.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
QString m_author
The author of the project.
Definition: Project.h:42
std::vector< std::string > getDataSourceIds(const std::list< te::map::AbstractLayerPtr > &layers)
Definition: Project.cpp:64
void write(const te::map::AbstractLayer *alayer, te::xml::AbstractWriter &writer) const
TECOREEXPORT std::string FindInTerraLibPath(const std::string &path)
Returns the path relative to a directory or file in the context of TerraLib.
QString m_title
The title of the project.
Definition: Project.h:41
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
TEDATAACCESSEXPORT void ReadDataSourceInfo(const std::string &datasourcesFileName)