otsdaq  v2_05_02_indev
ConfigurationHandler.cc
1 #include "otsdaq/ConfigurationInterface/ConfigurationHandler.h"
2 #include "otsdaq/ConfigurationInterface/TimeFormatter.h"
3 
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/XmlUtilities/ConvertFromXML.h"
6 #include "otsdaq/XmlUtilities/ConvertToXML.h"
7 #include "otsdaq/XmlUtilities/DOMTreeErrorReporter.h"
8 
9 #include <xercesc/dom/DOMElement.hpp>
10 #include <xercesc/dom/DOMImplementation.hpp>
11 #include <xercesc/dom/DOMImplementationRegistry.hpp>
12 #include <xercesc/dom/DOMLSOutput.hpp>
13 #include <xercesc/dom/DOMLSSerializer.hpp>
14 #include <xercesc/dom/DOMNodeList.hpp>
15 #include <xercesc/dom/DOMText.hpp>
16 #include <xercesc/parsers/XercesDOMParser.hpp>
17 #include <xercesc/util/XMLUni.hpp>
18 //#include <xercesc/dom/DOMWriter.hpp>
19 
20 #include <xercesc/framework/LocalFileFormatTarget.hpp>
21 #include <xercesc/util/OutOfMemoryException.hpp>
22 
23 #include <sys/types.h>
24 #include <iostream>
25 #include <sstream>
26 #include <stdexcept>
27 
28 #include <errno.h>
29 #include <sys/stat.h>
30 
31 #include "otsdaq/TableCore/TableBase.h"
32 
33 using namespace ots;
34 
35 #undef __COUT_HDR__
36 #define __COUT_HDR__ "ConfigHandler"
37 
38 // The tag values must be given after the XML platform is initialized so they are defined
39 // in initPlatform
40 XMLCh* ConfigurationHandler::rootTag_ = 0;
41 XMLCh* ConfigurationHandler::headerTag_ = 0;
42 XMLCh* ConfigurationHandler::typeTag_ = 0;
43 XMLCh* ConfigurationHandler::extensionTableNameTag_ = 0;
44 XMLCh* ConfigurationHandler::nameTag_ = 0;
45 XMLCh* ConfigurationHandler::runTag_ = 0;
46 XMLCh* ConfigurationHandler::runTypeTag_ = 0;
47 XMLCh* ConfigurationHandler::runNumberTag_ = 0;
48 XMLCh* ConfigurationHandler::runBeginTimestampTag_ = 0;
49 XMLCh* ConfigurationHandler::locationTag_ = 0;
50 XMLCh* ConfigurationHandler::datasetTag_ = 0;
51 XMLCh* ConfigurationHandler::versionTag_ = 0;
52 XMLCh* ConfigurationHandler::commentDescriptionTag_ = 0;
53 XMLCh* ConfigurationHandler::createdByUserTag_ = 0;
54 XMLCh* ConfigurationHandler::partTag_ = 0;
55 XMLCh* ConfigurationHandler::nameLabelTag_ = 0;
56 XMLCh* ConfigurationHandler::kindOfPartTag_ = 0;
57 XMLCh* ConfigurationHandler::dataTag_ = 0;
58 
59 //==============================================================================
60 ConfigurationHandler::ConfigurationHandler(void) {}
61 
62 //==============================================================================
63 ConfigurationHandler::~ConfigurationHandler(void) {}
64 
65 //==============================================================================
66 void ConfigurationHandler::initPlatform(void)
67 {
68  try
69  {
70  xercesc::XMLPlatformUtils::Initialize(); // Initialize Xerces infrastructure
71  }
72  catch(xercesc::XMLException& e)
73  {
74  __MOUT_ERR__ << "XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
75  // throw exception here to return ERROR_XERCES_INIT
76  }
77 
78  rootTag_ = xercesc::XMLString::transcode("ROOT");
79  headerTag_ = xercesc::XMLString::transcode("HEADER");
80  typeTag_ = xercesc::XMLString::transcode("TYPE");
81  extensionTableNameTag_ = xercesc::XMLString::transcode("EXTENSION_TABLE_NAME");
82  nameTag_ = xercesc::XMLString::transcode("NAME");
83  runTag_ = xercesc::XMLString::transcode("RUN");
84  runTypeTag_ = xercesc::XMLString::transcode("RUN_TYPE");
85  runNumberTag_ = xercesc::XMLString::transcode("RUN_NUMBER");
86  runBeginTimestampTag_ = xercesc::XMLString::transcode("RUN_BEGIN_TIMESTAMP");
87  locationTag_ = xercesc::XMLString::transcode("LOCATION");
88  datasetTag_ = xercesc::XMLString::transcode("DATA_SET");
89  versionTag_ = xercesc::XMLString::transcode("VERSION");
90  commentDescriptionTag_ = xercesc::XMLString::transcode("COMMENT_DESCRIPTION");
91  createdByUserTag_ = xercesc::XMLString::transcode("CREATED_BY_USER");
92  partTag_ = xercesc::XMLString::transcode("PART");
93  nameLabelTag_ = xercesc::XMLString::transcode("NAME_LABEL");
94  kindOfPartTag_ = xercesc::XMLString::transcode("KIND_OF_PART");
95  dataTag_ = xercesc::XMLString::transcode("DATA");
96 }
97 
98 //==============================================================================
99 void ConfigurationHandler::terminatePlatform(void)
100 {
101  try
102  {
103  xercesc::XMLString::release(&rootTag_);
104  xercesc::XMLString::release(&headerTag_);
105  xercesc::XMLString::release(&typeTag_);
106  xercesc::XMLString::release(&extensionTableNameTag_);
107  xercesc::XMLString::release(&nameTag_);
108  xercesc::XMLString::release(&runTag_);
109  xercesc::XMLString::release(&runTypeTag_);
110  xercesc::XMLString::release(&runNumberTag_);
111  xercesc::XMLString::release(&runBeginTimestampTag_);
112  xercesc::XMLString::release(&locationTag_);
113  xercesc::XMLString::release(&datasetTag_);
114  xercesc::XMLString::release(&versionTag_);
115  xercesc::XMLString::release(&commentDescriptionTag_);
116  xercesc::XMLString::release(&createdByUserTag_);
117  xercesc::XMLString::release(&partTag_);
118  xercesc::XMLString::release(&nameLabelTag_);
119  xercesc::XMLString::release(&kindOfPartTag_);
120  xercesc::XMLString::release(&dataTag_);
121  }
122  catch(...)
123  {
124  __MOUT_ERR__ << "Unknown exception encountered in TagNames destructor" << std::endl;
125  }
126 
127  try
128  {
129  xercesc::XMLPlatformUtils::Terminate(); // Terminate after release of memory
130  }
131  catch(xercesc::XMLException& e)
132  {
133  __MOUT_ERR__ << "XML ttolkit teardown error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
134  }
135 }
136 
137 //==============================================================================
138 bool ConfigurationHandler::validateNode(XMLCh* tagName, xercesc::DOMNode* node, const std::string& expectedValue)
139 {
140  if(node->getFirstChild() == 0)
141  {
142  __COUT__ << "Tag " << XML_TO_CHAR(tagName) << " doesn't have a value!" << std::endl;
143  return false;
144  }
145 
146  if(XML_TO_STRING(node->getFirstChild()->getNodeValue()) != expectedValue)
147  {
148  __COUT__ << "The tag " << XML_TO_CHAR(tagName) << " with value " << XML_TO_CHAR(node->getFirstChild()->getNodeValue())
149  << " doesn't match the expected value " << expectedValue << std::endl;
150  return false;
151  }
152 
153  return true;
154 }
155 
156 //==============================================================================
157 xercesc::DOMNode* ConfigurationHandler::getNode(XMLCh* tagName, xercesc::DOMNode* parent, unsigned int itemNumber)
158 {
159  return getNode(tagName, dynamic_cast<xercesc::DOMElement*>(parent), itemNumber);
160 }
161 
162 //==============================================================================
163 xercesc::DOMNode* ConfigurationHandler::getNode(XMLCh* tagName, xercesc::DOMElement* parent, unsigned int itemNumber)
164 {
165  xercesc::DOMNodeList* nodeList = parent->getElementsByTagName(tagName);
166 
167  if(!nodeList)
168  {
169  throw(std::runtime_error(std::string("Can't find ") + XML_TO_STRING(tagName) + " tag!"));
170  __COUT__ << (std::string("Can't find ") + XML_TO_STRING(tagName) + " tag!") << std::endl;
171  }
172 
173  // __COUT__<< "Name: " << XML_TO_CHAR(nodeList->item(itemNumber)->getNodeName())
174  // << std::endl; if( nodeList->item(itemNumber)->getFirstChild() != 0 )
175  // __COUT__<< "Value: " <<
176  // XML_TO_CHAR(nodeList->item(itemNumber)->getFirstChild()->getNodeValue()) <<
177  // std::endl;
178  return nodeList->item(itemNumber);
179 }
180 
181 //==============================================================================
182 xercesc::DOMElement* ConfigurationHandler::getElement(XMLCh* tagName, xercesc::DOMNode* parent, unsigned int itemNumber)
183 {
184  return dynamic_cast<xercesc::DOMElement*>(getNode(tagName, parent, itemNumber));
185 }
186 
187 //==============================================================================
188 xercesc::DOMElement* ConfigurationHandler::getElement(XMLCh* tagName, xercesc::DOMElement* parent, unsigned int itemNumber)
189 {
190  return dynamic_cast<xercesc::DOMElement*>(getNode(tagName, parent, itemNumber));
191 }
192 
193 //==============================================================================
194 void ConfigurationHandler::readXML(TableBase* table, TableVersion version) { readXML(*table, version); }
195 
196 //==============================================================================
197 void ConfigurationHandler::readXML(TableBase& table, TableVersion version)
198 {
199  initPlatform();
200  std::string configFile = getXMLFileName(table, version);
201 
202  __COUT__ << "Reading: " << configFile << std::endl;
203  __COUT__ << "Into View with Table Name: " << table.getViewP()->getTableName() << std::endl;
204  __COUT__ << "Into View with version: " << table.getViewP()->getVersion() << " and version-to-read: " << version << std::endl;
205 
206  struct stat fileStatus;
207  // stat returns -1 on error, status in errno
208  if(stat(configFile.c_str(), &fileStatus) < 0)
209  {
210  __COUT__ << "Error reading path: " << configFile << std::endl;
211  std::stringstream ss;
212  ss << __COUT_HDR__;
213  if(errno == ENOENT)
214  ss << ("Path file_name does not exist.");
215  else if(errno == ENOTDIR)
216  ss << ("A component of the path is not a directory.");
217  else if(errno == ELOOP)
218  ss << ("Too many symbolic links encountered while traversing the path.");
219  else if(errno == EACCES)
220  ss << ("Permission denied.");
221  else if(errno == ENAMETOOLONG)
222  ss << ("File name too long.");
223  else
224  ss << ("File can not be read.");
225  ss << std::endl;
226  __COUT_ERR__ << ss.str();
227  __SS_THROW__;
228  }
229 
230  xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser;
231 
232  // Configure DOM parser.
233  parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto); // Val_Never
234  parser->setDoNamespaces(true);
235  parser->setDoSchema(false); // RAR set to false to get rid of "error reading primary document *.xsd"
236  // uses if true:
237  // rootElement->setAttribute(CONVERT_TO_XML("xsi:noNamespaceSchemaLocation"),CONVERT_TO_XML("TableBase.xsd"));
238  parser->useCachedGrammarInParse(false);
239  DOMTreeErrorReporter* errorHandler = new DOMTreeErrorReporter();
240  parser->setErrorHandler(errorHandler);
241 
242  //__COUT__ << configFile << std::endl;
243  try
244  {
245  //__COUT__ << "Parsing" << std::endl;
246  parser->parse(configFile.c_str());
247  //__COUT__ << "Parsed" << std::endl;
248 
249  // no need to free this pointer - owned by the parent parser object
250  xercesc::DOMDocument* document = parser->getDocument();
251 
252  // Get the top-level element: Name is "root". No attributes for "root"
253  xercesc::DOMElement* elementRoot = document->getDocumentElement();
254 
255  if(!elementRoot)
256  throw(std::runtime_error("empty XML document"));
257  //<HEADER>
258  //__COUT__ << "Reading header" << std::endl;
259  xercesc::DOMNode* headerNode = getNode(headerTag_, elementRoot, 0);
260  if(!headerNode)
261  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(headerTag_)));
262 
263  //<TYPE>
264  //__COUT__ << "Reading type" << std::endl;
265  xercesc::DOMElement* typeElement = getElement(typeTag_, headerNode, 0);
266  if(!typeElement)
267  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(typeTag_)));
268  xercesc::DOMNode* extensionTableNameNode = getNode(extensionTableNameTag_, typeElement, 0);
269  if(!validateNode(extensionTableNameTag_, extensionTableNameNode, table.getView().getTableName()))
270  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(extensionTableNameTag_)));
271  xercesc::DOMNode* nameNode = getNode(nameTag_, typeElement, 0);
272  if(!validateNode(nameTag_, nameNode, table.getTableName()))
273  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(nameTag_)));
274 
275  //__COUT__ << configFile << std::endl;
276  //</TYPE>
277  //<RUN>
278  //__COUT__ << "Reading run" << std::endl;
279  xercesc::DOMElement* runElement = getElement(runTag_, headerNode, 0);
280  if(!runElement)
281  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(runTag_)));
282  [[maybe_unused]] xercesc::DOMNode* runTypeNode = getNode(runTypeTag_, runElement, 0);
283  assert(validateNode(runTypeTag_, runTypeNode, table.getTableName()));
284  xercesc::DOMNode* runNumberNode = getNode(runNumberTag_, runElement, 0);
285  if(!runNumberNode)
286  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(runNumberTag_)));
287  xercesc::DOMNode* runBeginTimestampNode = getNode(runBeginTimestampTag_, runElement, 0);
288  if(!runBeginTimestampNode)
289  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(runBeginTimestampTag_)));
290  xercesc::DOMNode* locationNode = getNode(locationTag_, runElement, 0);
291  if(!locationNode)
292  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(locationTag_)));
293 
294  //__COUT__ << configFile << std::endl;
295  //</RUN>
296  //</HEADER>
297 
298  //<DATA_SET>
299  //__COUT__ << "Reading Data Set" << std::endl;
300  xercesc::DOMElement* datasetElement = getElement(datasetTag_, elementRoot, 0);
301  if(!datasetElement)
302  throw(std::runtime_error(std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(datasetTag_)));
303 
304  // <PART>
305  //__COUT__ << "Reading Part" << std::endl;
306  //xercesc::DOMNode* partNode = getNode(partTag_, datasetElement, 0);
307  //xercesc::DOMNode* nameLabelNode = getNode(nameLabelTag_, partNode, 0);
308  //xercesc::DOMNode* kindOfPartNode = getNode(kindOfPartTag_, partNode, 0);
309 
310  // </PART>
311  xercesc::DOMNode* versionNode = getNode(versionTag_, datasetElement, 0);
312 
313  if(versionNode->getFirstChild() == 0) // if version tag is missing
314  {
315  throw(std::runtime_error(std::string("Missing version tag: ") + XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue())));
316  }
317  else // else verify version tag matches parameter version
318  {
319  char tmpVersionStr[100];
320  sprintf(tmpVersionStr, "%d", version.version());
321  __COUT__ << version << "-" << XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()) << std::endl;
322  if(strcmp(tmpVersionStr, XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue())) != 0)
323  throw(std::runtime_error(std::string("Mis-matched version tag: ") + XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()) + " vs " +
324  tmpVersionStr));
325  }
326  // version is valid
327  table.getViewP()->setVersion(XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()));
328 
329  xercesc::DOMNode* commentDescriptionNode = getNode(commentDescriptionTag_, datasetElement, 0);
330  if(commentDescriptionNode->getFirstChild() != 0)
331  table.getViewP()->setComment(XML_TO_CHAR(commentDescriptionNode->getFirstChild()->getNodeValue()));
332 
333  xercesc::DOMNode* createdByUserNode = getNode(createdByUserTag_, datasetElement, 0);
334  if(createdByUserNode->getFirstChild() != 0)
335  table.getViewP()->setAuthor(XML_TO_CHAR(createdByUserNode->getFirstChild()->getNodeValue()));
336 
337  //<DATA>
338  //__COUT__ << "Reading Data" << std::endl;
339  xercesc::DOMNodeList* dataNodeList = datasetElement->getElementsByTagName(dataTag_);
340 
341  if(!dataNodeList)
342  throw(std::runtime_error(std::string("Can't find ") + XML_TO_STRING(dataTag_) + " tag!"));
343 
344  //__COUT__ << "Number of data nodes: " << dataNodeList->getLength() << std::endl;
345  // First I need to setup the data container which is a [row][col] matrix where
346  // each <dataTag_> is a row and row 0 has the names of the column which will go
347  // in the columnInfo container
348  if(!dataNodeList->getLength()) // I must have at least 1 data!
349  {
350  __SS__ << "Must be non-empty data set!";
351  __SS_THROW__;
352  }
353 
354  //__COUT__ << table.getView().getColumnsInfo().size() << std::endl;
355  // First I can build the matrix and then fill it since I know the number of rows
356  // and columns
357  table.getViewP()->resizeDataView(dataNodeList->getLength(), table.getView().getNumberOfColumns());
358 
359  for(XMLSize_t row = 0; row < dataNodeList->getLength(); row++)
360  {
361  // DOMElement* dataElement = dynamic_cast< xercesc::DOMElement* >(
362  // dataNodeList->item(row) );
363  xercesc::DOMNodeList* columnNodeList = dataNodeList->item(row)->getChildNodes();
364  unsigned int colNumber = 0;
365 
366  //__COUT__ << "Row: " << row << " w " << columnNodeList->getLength() <<
367  // std::endl;
368  for(XMLSize_t col = 0; col < columnNodeList->getLength(); col++)
369  {
370  //__COUT__ << "Col: " << col << std::endl;
371 
372  if(!columnNodeList->item(col)->getNodeType() ||
373  columnNodeList->item(col)->getNodeType() != xercesc::DOMNode::ELEMENT_NODE) // true is not 0 && is element
374  continue;
375 
376  xercesc::DOMElement* columnElement = dynamic_cast<xercesc::DOMElement*>(columnNodeList->item(col));
377 
378  if(table.getView().getColumnInfo(colNumber).getStorageName() != XML_TO_STRING(columnElement->getTagName()))
379  {
380  std::stringstream error;
381  error << __COUT_HDR__ << std::endl
382  << "The column number " << colNumber << " named " << table.getView().getColumnInfo(colNumber).getStorageName()
383  << " defined in the view " << table.getView().getTableName() << " doesn't match the file column order, since the " << colNumber + 1
384  << (colNumber == 0 ? "st" : (colNumber == 1 ? "nd" : (colNumber == 2 ? "rd" : "th"))) << " element found in the file at "
385  << XML_TO_CHAR(dataTag_) << " tag number " << row << " is " << XML_TO_CHAR(columnElement->getTagName());
386  __MOUT_ERR__ << error.str();
387  throw(std::runtime_error(error.str()));
388  }
389 
390  // if( row==0 )
391  // {
392  // table.getViewP()->getDataViewP()->push_back(vector<string>(dataNodeList->getLength()+1));//#
393  // of data + names
394  // (*table.getViewP()->getDataViewP())[colNumber][0]
395  // = XML_TO_STRING(columnElement->getTagName());
396  // }
397  table.getViewP()->setValueAsString(XML_TO_STRING(columnNodeList->item(col)->getFirstChild()->getNodeValue()), row, colNumber);
398  //(*table.getViewP()->getDataViewP())[row][colNumber] =
399  // XML_TO_STRING(columnNodeList->item(col)->getFirstChild()->getNodeValue());
400  ++colNumber;
401  }
402  }
403  }
404  catch(xercesc::XMLException& e)
405  {
406  __COUT__ << "Error parsing file: " << configFile << std::endl;
407  std::ostringstream errBuf;
408  errBuf << "Error parsing file: " << XML_TO_CHAR(e.getMessage()) << std::flush;
409  }
410 
411  __COUT__ << "Done with table file: " << configFile << std::endl;
412 
413  delete parser;
414  delete errorHandler;
415  terminatePlatform();
416 }
417 
418 //==============================================================================
419 std::string ConfigurationHandler::writeXML(const TableBase& table)
420 {
421  initPlatform();
422 
423  std::string configFile = getXMLFileName(table,
424  table.getViewVersion()); // std::string(__ENV__("CONFIGURATION_DATA_PATH")) + "/"
425  // + table.getTableName() + "_write.xml";
426 
427  xercesc::DOMImplementation* implementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML("Core"));
428  if(implementation != 0)
429  {
430  try
431  {
432  //<ROOT>
433  xercesc::DOMDocument* document = implementation->createDocument(0, // root element namespace URI.
434  rootTag_, // root element name
435  0); // document type object (DTD).
436 
437  xercesc::DOMElement* rootElement = document->getDocumentElement();
438  rootElement->setAttribute(CONVERT_TO_XML("xmlns:xsi"), CONVERT_TO_XML("http://www.w3.org/2001/XMLSchema-instance"));
439  rootElement->setAttribute(CONVERT_TO_XML("xsi:noNamespaceSchemaLocation"),
440  CONVERT_TO_XML("TableBase.xsd")); // configFile.substr(configFile.rfind("/")+1).c_str()));
441  // //put the file name here..? TableBase.xsd"));
442  //${OTSDAQ_DIR}/otsdaq/ConfigurationDataFormats/TableInfo.xsd
443  // now moved to $USER_DATA/TableInfo/TableInfo.xsd
444 
445  //<HEADER>
446  xercesc::DOMElement* headerElement = document->createElement(headerTag_);
447  rootElement->appendChild(headerElement);
448 
449  //<TYPE>
450  xercesc::DOMElement* typeElement = document->createElement(typeTag_);
451  headerElement->appendChild(typeElement);
452 
453  xercesc::DOMElement* extensionTableNameElement = document->createElement(extensionTableNameTag_);
454  typeElement->appendChild(extensionTableNameElement);
455  xercesc::DOMText* extensionTableNameValue = document->createTextNode(CONVERT_TO_XML(table.getView().getTableName().c_str()));
456  extensionTableNameElement->appendChild(extensionTableNameValue);
457 
458  xercesc::DOMElement* nameElement = document->createElement(nameTag_);
459  typeElement->appendChild(nameElement);
460  xercesc::DOMText* nameValue = document->createTextNode(CONVERT_TO_XML(table.getTableName().c_str()));
461  nameElement->appendChild(nameValue);
462  //</TYPE>
463 
464  //<RUN>
465  xercesc::DOMElement* runElement = document->createElement(runTag_);
466  headerElement->appendChild(runElement);
467 
468  xercesc::DOMElement* runTypeElement = document->createElement(runTypeTag_);
469  runElement->appendChild(runTypeElement);
470  xercesc::DOMText* runTypeValue = document->createTextNode(CONVERT_TO_XML(table.getTableName().c_str()));
471  runTypeElement->appendChild(runTypeValue);
472 
473  xercesc::DOMElement* runNumberElement = document->createElement(runNumberTag_);
474  runElement->appendChild(runNumberElement);
475  xercesc::DOMText* runNumberValue = document->createTextNode(CONVERT_TO_XML("1")); // This is dynamic and need to be created when I write the file
476  runNumberElement->appendChild(runNumberValue);
477 
478  xercesc::DOMElement* runBeginTimestampElement = document->createElement(runBeginTimestampTag_);
479  runElement->appendChild(runBeginTimestampElement);
480  xercesc::DOMText* runBeginTimestampValue = document->createTextNode(CONVERT_TO_XML(TimeFormatter::getTime().c_str())); // This is dynamic and
481  // need to be created
482  // when I write the
483  // files
484  runBeginTimestampElement->appendChild(runBeginTimestampValue);
485 
486  xercesc::DOMElement* locationElement = document->createElement(locationTag_);
487  runElement->appendChild(locationElement);
488  xercesc::DOMText* locationValue = document->createTextNode(CONVERT_TO_XML("CERN P5")); // This is dynamic and need to be created
489  // when I write the file
490  locationElement->appendChild(locationValue);
491  //</RUN>
492 
493  xercesc::DOMElement* datasetElement = document->createElement(datasetTag_);
494  rootElement->appendChild(datasetElement);
495  //<PART>
496  xercesc::DOMElement* partElement = document->createElement(partTag_);
497  datasetElement->appendChild(partElement);
498 
499  xercesc::DOMElement* nameLabelElement = document->createElement(nameLabelTag_);
500  partElement->appendChild(nameLabelElement);
501  xercesc::DOMText* nameLabelValue = document->createTextNode(CONVERT_TO_XML("CMS--ROOT"));
502  nameLabelElement->appendChild(nameLabelValue);
503 
504  xercesc::DOMElement* kindOfPartElement = document->createElement(kindOfPartTag_);
505  partElement->appendChild(kindOfPartElement);
506  xercesc::DOMText* kindOfPartValue = document->createTextNode(CONVERT_TO_XML("Detector ROOT"));
507  kindOfPartElement->appendChild(kindOfPartValue);
508 
509  xercesc::DOMElement* versionElement = document->createElement(versionTag_);
510  datasetElement->appendChild(versionElement);
511  xercesc::DOMText* versionValue = document->createTextNode(CONVERT_TO_XML(table.getView().getVersion().version()));
512  versionElement->appendChild(versionValue);
513 
514  xercesc::DOMElement* commentDescriptionElement = document->createElement(commentDescriptionTag_);
515  datasetElement->appendChild(commentDescriptionElement);
516  xercesc::DOMText* commentDescriptionValue = document->createTextNode(CONVERT_TO_XML(table.getView().getComment().c_str()));
517  commentDescriptionElement->appendChild(commentDescriptionValue);
518 
519  xercesc::DOMElement* createdByUserElement = document->createElement(createdByUserTag_);
520  datasetElement->appendChild(createdByUserElement);
521  xercesc::DOMText* createdByUserValue = document->createTextNode(CONVERT_TO_XML(table.getView().getAuthor().c_str()));
522  createdByUserElement->appendChild(createdByUserValue);
523  // for(TableView::iterator it=table.getView().begin();
524  // it!=table.getView().end(); it++)
525 
526  for(unsigned int row = 0; row < table.getView().getNumberOfRows(); row++)
527  {
528  xercesc::DOMElement* dataElement = document->createElement(dataTag_);
529  datasetElement->appendChild(dataElement);
530 
531  for(unsigned int col = 0; col < table.getView().getNumberOfColumns(); col++)
532  {
533  xercesc::DOMElement* element = document->createElement(CONVERT_TO_XML(table.getView().getColumnInfo(col).getStorageName().c_str()));
534  dataElement->appendChild(element);
535  xercesc::DOMText* value = document->createTextNode(CONVERT_TO_XML(table.getView().getDataView()[row][col].c_str()));
536  element->appendChild(value);
537  }
538  }
539 
540  outputXML(document, configFile);
541 
542  document->release();
543  }
544  catch(const xercesc::OutOfMemoryException&)
545  {
546  XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
547  // errorCode = 5;
548  }
549  catch(const xercesc::DOMException& e)
550  {
551  XERCES_STD_QUALIFIER cerr << "DOMException code is: " << e.code << XERCES_STD_QUALIFIER endl;
552  // errorCode = 2;
553  }
554  catch(const xercesc::XMLException& e)
555  {
556  std::string message = XML_TO_STRING(e.getMessage());
557  __COUT__ << "Error Message: " << message << std::endl;
558  // return 1;
559  return message;
560  }
561  catch(...)
562  {
563  XERCES_STD_QUALIFIER cerr << "An error occurred creating the document" << XERCES_STD_QUALIFIER endl;
564  // errorCode = 3;
565  }
566  } // (inpl != 0)
567  else
568  {
569  XERCES_STD_QUALIFIER cerr << "Requested implementation is not supported" << XERCES_STD_QUALIFIER endl;
570  // errorCode = 4;
571  }
572 
573  terminatePlatform();
574  return configFile;
575 }
576 
577 // return errorCode;
578 
579 //==============================================================================
580 void ConfigurationHandler::outputXML(xercesc::DOMDocument* pmyDOMDocument, std::string fileName)
581 {
582  std::string directory = fileName.substr(0, fileName.rfind("/") + 1);
583  __COUT__ << "Saving XML to " << fileName << " in directory: " << directory << std::endl;
584 
585  mkdir(directory.c_str(), 0755);
586 
587  // Return the first registered implementation that has the desired features. In this
588  // case, we are after a DOM implementation that has the LS feature... or Load/Save.
589  // DOMImplementation *implementation =
590  // DOMImplementationRegistry::getDOMImplementation(L"LS");
591  xercesc::DOMImplementation* implementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML("LS"));
592 
593 #if _XERCES_VERSION >= 30000
594  // Create a DOMLSSerializer which is used to serialize a DOM tree into an XML
595  // document.
596  xercesc::DOMLSSerializer* serializer = ((xercesc::DOMImplementationLS*)implementation)->createLSSerializer();
597 
598  // Make the output more human readable by inserting line feeds.
599 
600  if(serializer->getDomConfig()->canSetParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true))
601  serializer->getDomConfig()->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
602 
603  // The end-of-line sequence of characters to be used in the XML being written out.
604  // serializer->setNewLine(CONVERT_TO_XML("\r\n"));
605 
606  // Convert the path into Xerces compatible XMLCh*.
607 
608  // Specify the target for the XML output.
609  xercesc::XMLFormatTarget* formatTarget = new xercesc::LocalFileFormatTarget(CONVERT_TO_XML(fileName));
610 
611  // Create a new empty output destination object.
612  xercesc::DOMLSOutput* output = ((xercesc::DOMImplementationLS*)implementation)->createLSOutput();
613 
614  // Set the stream to our target.
615  output->setByteStream(formatTarget);
616 
617  // Write the serialized output to the destination.
618  serializer->write(pmyDOMDocument, output);
619 
620 #else
621  xercesc::DOMWriter* serializer = ((xercesc::DOMImplementationLS*)implementation)->createDOMWriter();
622 
623  serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
624 
625  /*
626  Choose a location for the serialized output. The 3 options are:
627  1) StdOutFormatTarget (std output stream - good for debugging)
628  2) MemBufFormatTarget (to Memory)
629  3) LocalFileFormatTarget (save to file)
630  (Note: You'll need a different header file for each one)
631  */
632  // XMLFormatTarget* pTarget = new StdOutFormatTarget();
633  // Convert the path into Xerces compatible XMLCh*.
634 
635  xercesc::XMLFormatTarget* formatTarget = new xercesc::LocalFileFormatTarget(CONVERT_TO_XML(fileName.c_str()));
636 
637  // Write the serialized output to the target.
638  serializer->writeNode(formatTarget, *pmyDOMDocument);
639 
640 #endif
641 
642  // Cleanup.
643  serializer->release();
644 
645  delete formatTarget;
646 
647 #if _XERCES_VERSION >= 30000
648 
649  output->release();
650 
651 #endif
652  __COUT__ << "Done writing " << std::endl;
653 }
654 
655 //==============================================================================
656 std::string ConfigurationHandler::writeXML(const TableBase* table) { return writeXML(*table); }
657 
658 //==============================================================================
659 std::string ConfigurationHandler::getXMLFileName(const TableBase& table, TableVersion version)
660 {
661  std::stringstream fileName;
662  fileName << getXMLDir(&table) << version << '/' << table.getTableName() << "_v" << version << ".xml";
663  return fileName.str();
664 }
665 
666 //==============================================================================
667 std::string ConfigurationHandler::getXMLDir(const TableBase* table)
668 {
669  return std::string(__ENV__("CONFIGURATION_DATA_PATH")) + '/' + table->getTableName() + '/';
670 }