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