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