Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYXMLManager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #ifdef _MSC_VER
17  #pragma warning(disable : 4786)
18 #endif
19 
20 #include <qfile.h>
21 #include <iostream>
22 
23 #include "Tympan/core/logging.h"
24 #include "Tympan/core/exceptions.h"
26 #include "TYXMLManager.h"
27 
28 QString TYXMLManager::_savedFileName = QString("");
29 
34 void handle_xml_parsing_error(std::string cause, std::string msg, int err_line, int err_col)
35 {
36  std::string error_msg = "Error during parsing" + cause + +"\nerror message is:\n" + msg +
37  "\nat line:" + std::to_string(static_cast<long long>(err_line)) +
38  " at column:" + std::to_string(static_cast<long long>(err_col));
39  throw tympan::invalid_data(error_msg);
40 }
41 
46 QDomDocument parse_xml_file(const QString& filepath)
47 {
48  QDomDocument doc;
49  QString msg;
50  int err_line = 0, err_col = 0;
51  QFile file(filepath);
52  if (!file.open(QIODevice::ReadOnly))
53  {
54  std::string error_msg = "Error on opening " + filepath.toStdString();
55  throw tympan::invalid_data(error_msg);
56  }
57  file.close();
58  if (!doc.setContent(&file, &msg, &err_line, &err_col))
59  {
60  std::string cause = " of: " + filepath.toStdString();
61  handle_xml_parsing_error(cause, msg.toStdString(), err_line, err_col);
62  }
63  return doc;
64 }
65 
70 QDomDocument parse_xml_content(const QString& xml_content)
71 {
72  QDomDocument doc;
73  QString msg;
74  int err_line = 0, err_col = 0;
75  if (!doc.setContent(xml_content, &msg, &err_line, &err_col))
76  {
77  handle_xml_parsing_error(std::string("QString content"), msg.toStdString(), err_line, err_col);
78  }
79  return doc;
80 }
81 
83 
85 
86 void TYXMLManager::createDoc(QString docName, QString version)
87 {
88  QDomImplementation domImpl;
89  // Reset doc
90  resetDoc();
91  // Declaration du type de document (DTD)
92  QString qualifiedName = "Tympan"; // Nom du noeud root
93  QString systemId = "Tympan.dtd"; // URI de la DTD
94  QDomDocumentType docType = domImpl.createDocumentType(qualifiedName, QString(), systemId);
95 
96  // Creation d'un Document XML vide (Precision: document != fichier)
97  _domDocument = domImpl.createDocument(QString(), // root element namespace URI.
98  docName, // root element name
99  docType); // document type object (DTD).
100 
101  // Recuperation du noeud root du document
102  _rootElement = _domDocument.documentElement();
103 
104  TYXMLTools::addElementStringValue(_rootElement, "Version", version);
105 }
106 
107 int TYXMLManager::load(const QString& fileName, LPTYElementArray& eltCollection)
108 {
109  OMessageManager::get()->info("Charge le fichier %s.", fileName.toUtf8().data());
110 
111  try
112  {
113  _domDocument = parse_xml_file(fileName);
114  }
115  catch (tympan::invalid_data& exc)
116  {
117  OMessageManager::get()->error(exc.what());
118  return -2;
119  }
120 
121  // If the document contains any external elements, replace them by the
122  // content of the external file before elements creation
123  QDomNodeList ext_elements = _domDocument.documentElement().elementsByTagName(QString("ExternalElement"));
124  int processed = 0;
125  while (processed < ext_elements.length())
126  {
127  QDomNode ext_element = ext_elements.item(processed);
128  QDomNamedNodeMap attrs = ext_element.attributes();
129  if (attrs.contains(QString("filename")))
130  {
131  QString ext_filepath = attrs.namedItem(QString("filename")).nodeValue();
132  // External file must be in the same directory as the main file
133  QDir dir = QFileInfo(fileName).absoluteDir();
134  ext_filepath = dir.filePath(ext_filepath);
135  QDomDocument extdoc;
136  try
137  {
138  extdoc = parse_xml_file(ext_filepath);
139  }
140  catch (tympan::invalid_data& exc)
141  {
142  OMessageManager::get()->error(exc.what());
143  processed++;
144  continue;
145  }
146  QDomNodeList elements = extdoc.documentElement().childNodes();
147  if (elements.isEmpty())
148  {
149  OMessageManager::get()->error("External XML project %s seems empty.",
150  ext_filepath.toStdString().c_str());
151  processed++;
152  continue;
153  }
154  QDomNode parent = ext_element.parentNode();
155  // The first element of the external file will replace the ExternalElement markup.
156  // Then the following ones if any will be added to the parent of the
157  // ExternalElement markup.
158  // replaceChild removes element from "elements" list
159  parent.replaceChild(elements.item(0), ext_element);
160  for (int j = 0; j < elements.length(); j++)
161  {
162  parent.appendChild(elements.item(j));
163  }
164  }
165  else
166  {
167  // Si pas de fichier spécifié on ne peut pas lire l'entité
169  "XML project contains an external element defined without a file name");
170  processed++;
171  }
172  ext_elements = _domDocument.documentElement().elementsByTagName(QString("ExternalElement"));
173  }
174  create_tyelements(eltCollection);
175  return 1;
176 }
177 
179 {
180  // On recupere l'element XML root du document
181  _rootElement = _domDocument.documentElement();
182 
183  // Recense tous les elements enfants du root
184  QDomNodeList nodeList = _rootElement.childNodes();
185 
186  TYElement* pElt = NULL;
187  QString str;
188 
189  // On active la sauvegarde des instances de type TYElement et derivees
192 
193  int nodecount = nodeList.length();
194 
195  int readOk = 1; // Indicateur de probleme de relecture dans les calculs
196 
197  // Pour chaque noeud enfant du noeud root
198  for (int i = 0; i < nodecount; i++)
199  {
200  // Utilisation de la Prototype Factory pour creer un nouvel element a partir
201  // du nom du noeud enfant trouve
202 
203  OMessageManager::get()->info("Charge element du fichier %d/%d.", i + 1, nodecount);
204 
205  // Les donnees metiers ne sont pas prefixees par TY...
206  str = "TY";
207  str += nodeList.item(i).nodeName();
208 
209  try
210  {
211  pElt = dynamic_cast<TYElement*>(TYElement::findAndClone((char*)str.toLatin1().data()));
212  }
213  catch (tympan::invalid_data&)
214  {
215  pElt = nullptr;
216  }
217  if (pElt != nullptr)
218  {
219  // Si l element a ete trouve
220  // Auto chargement des parametres par l'element
221  readOk = pElt->fromXML(nodeList.item(i).toElement());
222 
223  // Ajout de l'element a la collection
224  eltCollection.push_back(pElt);
225  }
226  }
227 
228  // On desactive la sauvegarde des instances de type TYElement et derivees
229 
230  if (readOk == -1) // La relecture du calcul s'est mal effectuee
231  {
232  OMessageManager::get()->info("\n\n\t\t\t*** PROBLEME DE RELECTURE DES RESULTATS DU CALCUL ***\
233  \n\t\t*** CAUSE PROBABLE : MACHINE OU BATIMENT EN DOUBLON (MEME ID) ***\
234  \n\t\t\t\t*** INTEGRITE DES RESULTATS COMPROMISE ***\
235  \n\t\t\t\t\t\t*** REFAIRE LES CALCULS ***\n\n");
236  }
237 
238  OMessageManager::get()->info("Fin du chargement.");
239 }
240 
241 int TYXMLManager::save(QString fileName)
242 {
243  // Sauvegarde du document
244  return DOMSave::saveNodeToFile(_domDocument, fileName.toUtf8().data());
245 }
246 
247 int TYXMLManager::loadFromString(const QString& xmlString, LPTYElementArray& eltCollection)
248 {
249  try
250  {
251  // On recupere le noeud Document
252  _domDocument = parse_xml_content(xmlString);
253  }
254  catch (tympan::invalid_data& exc)
255  {
256  OMessageManager::get()->error(exc.what());
257  return -2;
258  }
259  create_tyelements(eltCollection);
260  return 1;
261 }
262 
264 {
265  // Sauvegarde du document
267 }
268 
269 int TYXMLManager::getEltType(const QString& fileName, QString& eltType)
270 {
271  try
272  {
273  // On recupere le noeud Document
274  _domDocument = parse_xml_file(fileName);
275  }
276  catch (tympan::invalid_data& exc)
277  {
278  OMessageManager::get()->error(exc.what());
279  return -2;
280  }
281 
282  // On recupere l'element XML root du document
283  _rootElement = _domDocument.documentElement();
284 
285  // On recupere le premier elements
286  DOM_Node node = _rootElement.firstChild();
287 
288  // Si null, on retourne zero
289  if (node.isNull())
290  {
291  return 0;
292  }
293 
294  // Si il correspond a la version de tympan, on passe au suivant
295  if (node.nodeName() == "Version")
296  {
297  node = node.nextSibling();
298  }
299 
300  // Si null, on retourne zero
301  if (node.isNull())
302  {
303  return 0;
304  }
305 
306  eltType = "TY";
307  eltType += node.nodeName();
308 
309  return 1;
310 }
311 
313 {
314  // Pour chaque element
315  for (unsigned int i = 0; i < eltCollection.size(); i++)
316  {
317  // Serialisation a partir du noeud root
318  eltCollection.at(i)->toXML(_rootElement);
319  }
320 
321  return true;
322 }
323 
325 {
326  if (pElt == NULL)
327  {
328  return false;
329  }
330 
331  // Serialisation a partir du noeud root
332  pElt->toXML(_rootElement);
333 
334  return true;
335 }
336 
338 {
339  if (_rootElement.isNull() && _domDocument.isNull())
340  {
341  return;
342  }
343  // Recense tous les elements enfants du root
344  QDomNodeList nodeList = _rootElement.childNodes();
345 
346  // Pour chaque noeud enfant du noeud root
347  for (unsigned int i = 0; i < nodeList.length(); i++)
348  {
349  _rootElement.removeChild(nodeList.item(i));
350  }
351 }
QDomNode DOM_Node
Definition: QT2DOM.h:32
std::vector< LPTYElement > LPTYElementArray
Definition: TYElement.h:345
void handle_xml_parsing_error(std::string cause, std::string msg, int err_line, int err_col)
QDomDocument parse_xml_file(const QString &filepath)
QDomDocument parse_xml_content(const QString &xml_content)
static QString saveNodeToString(DOM_Node &nodeToSave)
Methode pour la sauvegarde d'un noeud DOM dans une string XML.
Definition: DOMSave.cpp:144
static int saveNodeToFile(DOM_Node &nodeToSave, const char *fileName)
La methode principale pour la sauvegarde d'un noeud DOM dans un fichier XML.
Definition: DOMSave.cpp:37
virtual void error(const char *message,...)
Definition: logging.cpp:127
static OMessageManager * get()
Definition: logging.cpp:108
virtual void info(const char *message,...)
Definition: logging.cpp:143
static OPrototype * findAndClone(const char *className)
Definition: TYElement.cpp:37
static void setLogInstances(bool log)
Definition: TYElement.h:832
virtual DOM_Element toXML(DOM_Element &domElement)
Definition: TYElement.cpp:368
static void purgeInstances()
Definition: TYElement.cpp:171
virtual int fromXML(DOM_Element domElement)
Definition: TYElement.cpp:381
static QString _savedFileName
Le nom de fichier pdt la sauvegarde (util pour l'enregistrement du topofile en relatif.
Definition: TYXMLManager.h:163
int save(QString fileName)
int load(const QString &fileName, LPTYElementArray &eltCollection)
int getEltType(const QString &fileName, QString &eltType)
void createDoc(QString docName, QString version)
QString saveToString()
int addElement(TYElement *pElt)
DOM_Document _domDocument
Le document XML.
Definition: TYXMLManager.h:157
DOM_Element _rootElement
L'element racine du document XML.
Definition: TYXMLManager.h:160
int loadFromString(const QString &xmlString, LPTYElementArray &eltCollection)
int addElements(LPTYElementArray &eltCollection)
void create_tyelements(LPTYElementArray &eltCollection)
static void addElementStringValue(DOM_Element &parentElem, DOMString nodeName, DOMString nodeValue)
Definition: TYXMLTools.cpp:24
Utilities to handle exceptions and to pretty-print value.
The base exception class for errors due to invalid data.
Definition: exceptions.h:60