otsdaq  v1_01_02
 All Classes Namespaces Functions
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/CoutHeaderMacros.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 __MOUT_HDR__
36 #define __MOUT_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  __MOUT__<< "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  __MOUT__<< "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  __MOUT__ << (std::string("Can't find ") + XML_TO_STRING(tagName) + " tag!") << std::endl;
173  }
174 
175  // __MOUT__<< "Name: " << XML_TO_CHAR(nodeList->item(itemNumber)->getNodeName()) << std::endl;
176  // if( nodeList->item(itemNumber)->getFirstChild() != 0 )
177  // __MOUT__<< "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  __MOUT__ << "Reading: " << configFile << std::endl;
207  __MOUT__ << "Into View with Table Name: " <<
208  configuration.getViewP()->getTableName() << std::endl;
209  __MOUT__ << "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  __MOUT__ << "Error reading path: " << configFile << std::endl;
218  if( errno == ENOENT )
219  throw ( std::runtime_error("Path file_name does not exist.") );
220  else if( errno == ENOTDIR )
221  throw ( std::runtime_error("A component of the path is not a directory."));
222  else if( errno == ELOOP )
223  throw ( std::runtime_error("Too many symbolic links encountered while traversing the path."));
224  else if( errno == EACCES )
225  throw ( std::runtime_error("Permission denied."));
226  else if( errno == ENAMETOOLONG )
227  throw ( std::runtime_error("File name too long.\n"));
228  else
229  throw ( std::runtime_error("File can not be read.\n"));
230  }
231 
232  xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser;
233 
234  // Configure DOM parser.
235  parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);//Val_Never
236  parser->setDoNamespaces ( true );
237  parser->setDoSchema ( false ); //RAR set to false to get rid of "error reading primary document *.xsd"
238  //uses if true: rootElement->setAttribute(CONVERT_TO_XML("xsi:noNamespaceSchemaLocation"),CONVERT_TO_XML("ConfigurationBase.xsd"));
239  parser->useCachedGrammarInParse ( false );
240  DOMTreeErrorReporter* errorHandler = new DOMTreeErrorReporter() ;
241  parser->setErrorHandler(errorHandler);
242 
243  //__MOUT__ << configFile << std::endl;
244  try
245  {
246  //__MOUT__ << "Parsing" << std::endl;
247  parser->parse( configFile.c_str() );
248  //__MOUT__ << "Parsed" << std::endl;
249 
250  // no need to free this pointer - owned by the parent parser object
251  xercesc::DOMDocument* document = parser->getDocument();
252 
253  // Get the top-level element: Name is "root". No attributes for "root"
254  xercesc::DOMElement* elementRoot = document->getDocumentElement();
255 
256  if( !elementRoot ) throw(std::runtime_error( "empty XML document" ));
257  //<HEADER>
258  //__MOUT__ << "Reading header" << std::endl;
259  xercesc::DOMNode* headerNode = getNode(headerTag_, elementRoot, 0);
260  if( !headerNode ) throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(headerTag_ )));
261 
262  //<TYPE>
263  //__MOUT__ << "Reading type" << std::endl;
264  xercesc::DOMElement* typeElement = getElement(typeTag_, headerNode, 0);
265  if( !typeElement ) throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(typeTag_ )));
266  xercesc::DOMNode* extensionTableNameNode = getNode (extensionTableNameTag_, typeElement, 0);
267  if(!validateNode(extensionTableNameTag_,extensionTableNameNode,configuration.getView().getTableName()))
268  throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(extensionTableNameTag_ )));
269  xercesc::DOMNode* nameNode = getNode (nameTag_, typeElement, 0);
270  if(!validateNode(nameTag_,nameNode,configuration.getConfigurationName()))
271  throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(nameTag_ )));
272 
273  //__MOUT__ << configFile << std::endl;
274  //</TYPE>
275  //<RUN>
276  //__MOUT__ << "Reading run" << std::endl;
277  xercesc::DOMElement* runElement = getElement(runTag_, headerNode,0);
278  if( !runElement ) throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(runTag_ )));
279  xercesc::DOMNode* runTypeNode = getNode (runTypeTag_, runElement, 0);
280  assert(validateNode(runTypeTag_,runTypeNode,configuration.getConfigurationName()));
281  xercesc::DOMNode* runNumberNode = getNode (runNumberTag_, runElement, 0);
282  if( !runNumberNode ) throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(runNumberTag_ )));
283  xercesc::DOMNode* runBeginTimestampNode = getNode (runBeginTimestampTag_, runElement, 0);
284  if( !runBeginTimestampNode ) throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(runBeginTimestampTag_ )));
285  xercesc::DOMNode* locationNode = getNode (locationTag_, runElement, 0);
286  if( !locationNode ) throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(locationTag_ )));
287 
288  //__MOUT__ << configFile << std::endl;
289  //</RUN>
290  //</HEADER>
291 
292  //<DATA_SET>
293  //__MOUT__ << "Reading Data Set" << std::endl;
294  xercesc::DOMElement* datasetElement = getElement(datasetTag_, elementRoot, 0);
295  if( !datasetElement ) throw(std::runtime_error( std::string("The document is missing the mandatory tag: ") + XML_TO_STRING(datasetTag_ )));
296 
297  // <PART>
298  //__MOUT__ << "Reading Part" << std::endl;
299  xercesc::DOMNode* partNode = getNode (partTag_, datasetElement, 0);
300  xercesc::DOMNode* nameLabelNode = getNode (nameLabelTag_, partNode, 0);
301  xercesc::DOMNode* kindOfPartNode = getNode (kindOfPartTag_, partNode, 0);
302 
303  // </PART>
304  xercesc::DOMNode* versionNode = getNode (versionTag_, datasetElement, 0);
305 
306  if(versionNode->getFirstChild() == 0) //if version tag is missing
307  {
308  throw(std::runtime_error( std::string("Missing version tag: ") + XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue())));
309  }
310  else //else verify version tag matches parameter version
311  {
312  char tmpVersionStr[100];
313  sprintf(tmpVersionStr, "%d", version.version());
314  __MOUT__ << version << "-" << XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()) << std::endl;
315  if(strcmp(tmpVersionStr,XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue())) != 0)
316  throw(std::runtime_error( std::string("Mis-matched version tag: ") + XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()) +
317  " vs " + tmpVersionStr));
318  }
319  //version is valid
320  configuration.getViewP()->setVersion(XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()));
321 
322  xercesc::DOMNode* commentDescriptionNode = getNode (commentDescriptionTag_, datasetElement, 0);
323  if(commentDescriptionNode->getFirstChild() != 0)
324  configuration.getViewP()->setComment(XML_TO_CHAR(commentDescriptionNode->getFirstChild()->getNodeValue()));
325 
326  xercesc::DOMNode* createdByUserNode = getNode (createdByUserTag_, datasetElement, 0);
327  if(createdByUserNode->getFirstChild() != 0)
328  configuration.getViewP()->setAuthor(XML_TO_CHAR(createdByUserNode->getFirstChild()->getNodeValue()));
329 
330  //<DATA>
331  //__MOUT__ << "Reading Data" << std::endl;
332  xercesc::DOMNodeList* dataNodeList = datasetElement->getElementsByTagName(dataTag_);
333 
334  if( !dataNodeList )
335  throw(std::runtime_error( std::string("Can't find ") + XML_TO_STRING(dataTag_) + " tag!"));
336 
337  //__MOUT__ << "Number of data nodes: " << dataNodeList->getLength() << std::endl;
338  //First I need to setup the data container which is a [row][col] matrix where each <dataTag_> is a row
339  //and row 0 has the names of the column which will go in the columnInfo container
340  if(!dataNodeList->getLength())//I must have at least 1 data!
341  {
342  __SS__ << "Must be non-empty data set!";
343  throw std::runtime_error(ss.str());
344  }
345 
346  //__MOUT__ << configuration.getView().getColumnsInfo().size() << std::endl;
347  //First I can build the matrix and then fill it since I know the number of rows and columns
348  configuration.getViewP()->resizeDataView(dataNodeList->getLength(), configuration.getView().getNumberOfColumns());
349 
350  for( XMLSize_t row = 0; row < dataNodeList->getLength(); row++ )
351  {
352  //DOMElement* dataElement = dynamic_cast< xercesc::DOMElement* >( dataNodeList->item(row) );
353  xercesc::DOMNodeList* columnNodeList = dataNodeList->item(row)->getChildNodes();
354  unsigned int colNumber = 0;
355 
356  //__MOUT__ << "Row: " << row << " w " << columnNodeList->getLength() << std::endl;
357  for( XMLSize_t col = 0; col < columnNodeList->getLength(); col++ )
358  {
359  //__MOUT__ << "Col: " << col << std::endl;
360 
361  if( !columnNodeList->item(col)->getNodeType() || columnNodeList->item(col)->getNodeType() != xercesc::DOMNode::ELEMENT_NODE )//true is not 0 && is element
362  continue;
363 
364  xercesc::DOMElement* columnElement = dynamic_cast< xercesc::DOMElement* >( columnNodeList->item(col) );
365 
366  if( configuration.getView().getColumnInfo(colNumber).getStorageName() != XML_TO_STRING(columnElement->getTagName()))
367  {
368  std::stringstream error;
369  error << __COUT_HDR__ << std::endl
370  << "The column number " << colNumber
371  << " named " << configuration.getView().getColumnInfo(colNumber).getStorageName()
372  << " defined in the view " << configuration.getView().getTableName()
373  << " doesn't match the file column order, since the "
374  << colNumber+1 << (colNumber==0?"st":(colNumber==1?"nd":(colNumber==2?"rd":"th")))
375  << " element found in the file at " << XML_TO_CHAR(dataTag_) << " tag number " << row
376  << " is " << XML_TO_CHAR(columnElement->getTagName());
377  mf::LogError(__FILE__) << error.str();
378  throw(std::runtime_error( error.str() ));
379  }
380 
381  // if( row==0 )
382  // {
383  // configuration.getViewP()->getDataViewP()->push_back(vector<string>(dataNodeList->getLength()+1));//# of data + names
384  // (*configuration.getViewP()->getDataViewP())[colNumber][0] = XML_TO_STRING(columnElement->getTagName());
385  // }
386  configuration.getViewP()->setValueAsString(
387  XML_TO_STRING(columnNodeList->item(col)->getFirstChild()->getNodeValue())
388  , row
389  , colNumber);
390  //(*configuration.getViewP()->getDataViewP())[row][colNumber] = XML_TO_STRING(columnNodeList->item(col)->getFirstChild()->getNodeValue());
391  ++colNumber;
392  }
393  }
394  }
395  catch( xercesc::XMLException& e )
396  {
397  __MOUT__ << "Error parsing file: " << configFile << std::endl;
398  std::ostringstream errBuf;
399  errBuf << "Error parsing file: " << XML_TO_CHAR(e.getMessage()) << std::flush;
400  }
401 
402  __MOUT__ << "Done with configuration file: " << configFile << std::endl;
403 
404  delete parser;
405  delete errorHandler;
406  terminatePlatform();
407 }
408 
409 
410 //==============================================================================
411 std::string ConfigurationHandler::writeXML(const ConfigurationBase& configuration)
412 {
413  initPlatform();
414 
415  std::string configFile = getXMLFileName(configuration,configuration.getViewVersion()); // std::string(getenv("CONFIGURATION_DATA_PATH")) + "/" + configuration.getConfigurationName() + "_write.xml";
416 
417 
418  xercesc::DOMImplementation* implementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML("Core"));
419  if (implementation != 0)
420  {
421  try
422  {
423  //<ROOT>
424  xercesc::DOMDocument* document = implementation->createDocument(
425  0, // root element namespace URI.
426  rootTag_, // root element name
427  0); // document type object (DTD).
428 
429  xercesc::DOMElement* rootElement = document->getDocumentElement();
430  rootElement->setAttribute(CONVERT_TO_XML("xmlns:xsi"),CONVERT_TO_XML("http://www.w3.org/2001/XMLSchema-instance"));
431  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"));
432  //${OTSDAQ_DIR}/otsdaq/ConfigurationDataFormats/ConfigurationInfo.xsd
433 
434  //<HEADER>
435  xercesc::DOMElement* headerElement = document->createElement(headerTag_);
436  rootElement->appendChild(headerElement);
437 
438  //<TYPE>
439  xercesc::DOMElement* typeElement = document->createElement(typeTag_);
440  headerElement->appendChild(typeElement);
441 
442  xercesc::DOMElement* extensionTableNameElement = document->createElement(extensionTableNameTag_);
443  typeElement->appendChild(extensionTableNameElement);
444  xercesc::DOMText* extensionTableNameValue = document->createTextNode(CONVERT_TO_XML(configuration.getView().getTableName().c_str()));
445  extensionTableNameElement->appendChild(extensionTableNameValue);
446 
447  xercesc::DOMElement* nameElement = document->createElement(nameTag_);
448  typeElement->appendChild(nameElement);
449  xercesc::DOMText* nameValue = document->createTextNode(CONVERT_TO_XML(configuration.getConfigurationName().c_str()));
450  nameElement->appendChild(nameValue);
451  //</TYPE>
452 
453  //<RUN>
454  xercesc::DOMElement* runElement = document->createElement(runTag_);
455  headerElement->appendChild(runElement);
456 
457  xercesc::DOMElement* runTypeElement = document->createElement(runTypeTag_);
458  runElement->appendChild(runTypeElement);
459  xercesc::DOMText* runTypeValue = document->createTextNode(CONVERT_TO_XML(configuration.getConfigurationName().c_str()));
460  runTypeElement->appendChild(runTypeValue);
461 
462  xercesc::DOMElement* runNumberElement = document->createElement(runNumberTag_);
463  runElement->appendChild(runNumberElement);
464  xercesc::DOMText* runNumberValue = document->createTextNode(CONVERT_TO_XML("1"));//This is dynamic and need to be created when I write the file
465  runNumberElement->appendChild(runNumberValue);
466 
467  xercesc::DOMElement* runBeginTimestampElement = document->createElement(runBeginTimestampTag_);
468  runElement->appendChild(runBeginTimestampElement);
469  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
470  runBeginTimestampElement->appendChild(runBeginTimestampValue);
471 
472  xercesc::DOMElement* locationElement = document->createElement(locationTag_);
473  runElement->appendChild(locationElement);
474  xercesc::DOMText* locationValue = document->createTextNode(CONVERT_TO_XML("CERN P5"));//This is dynamic and need to be created when I write the file
475  locationElement->appendChild(locationValue);
476  //</RUN>
477 
478 
479  xercesc::DOMElement* datasetElement = document->createElement(datasetTag_);
480  rootElement->appendChild(datasetElement);
481  //<PART>
482  xercesc::DOMElement* partElement = document->createElement(partTag_);
483  datasetElement->appendChild(partElement);
484 
485  xercesc::DOMElement* nameLabelElement = document->createElement(nameLabelTag_);
486  partElement->appendChild(nameLabelElement);
487  xercesc::DOMText* nameLabelValue = document->createTextNode(CONVERT_TO_XML("CMS--ROOT"));
488  nameLabelElement->appendChild(nameLabelValue);
489 
490  xercesc::DOMElement* kindOfPartElement = document->createElement(kindOfPartTag_);
491  partElement->appendChild(kindOfPartElement);
492  xercesc::DOMText* kindOfPartValue = document->createTextNode(CONVERT_TO_XML("Detector ROOT"));
493  kindOfPartElement->appendChild(kindOfPartValue);
494 
495  xercesc::DOMElement* versionElement = document->createElement(versionTag_);
496  datasetElement->appendChild(versionElement);
497  xercesc::DOMText* versionValue = document->createTextNode(CONVERT_TO_XML(configuration.getView().getVersion().version()));
498  versionElement->appendChild(versionValue);
499 
500  xercesc::DOMElement* commentDescriptionElement = document->createElement(commentDescriptionTag_);
501  datasetElement->appendChild(commentDescriptionElement);
502  xercesc::DOMText* commentDescriptionValue = document->createTextNode(CONVERT_TO_XML(configuration.getView().getComment().c_str()));
503  commentDescriptionElement->appendChild(commentDescriptionValue);
504 
505  xercesc::DOMElement* createdByUserElement = document->createElement(createdByUserTag_);
506  datasetElement->appendChild(createdByUserElement);
507  xercesc::DOMText* createdByUserValue = document->createTextNode(CONVERT_TO_XML(configuration.getView().getAuthor().c_str()));
508  createdByUserElement->appendChild(createdByUserValue);
509  //for(ConfigurationView::iterator it=configuration.getView().begin(); it!=configuration.getView().end(); it++)
510 
511  for(unsigned int row=0; row<configuration.getView().getNumberOfRows(); row++)
512  {
513  xercesc::DOMElement* dataElement = document->createElement(dataTag_);
514  datasetElement->appendChild(dataElement);
515 
516  for(unsigned int col=0; col<configuration.getView().getNumberOfColumns(); col++)
517  {
518  xercesc::DOMElement* element = document->createElement(CONVERT_TO_XML(configuration.getView().getColumnInfo(col).getStorageName().c_str()));
519  dataElement->appendChild(element);
520  xercesc::DOMText* value = document->createTextNode(CONVERT_TO_XML(configuration.getView().getDataView()[row][col].c_str()));
521  element->appendChild(value);
522  }
523  }
524 
525  outputXML(document, configFile);
526 
527  document->release();
528  }
529  catch (const xercesc::OutOfMemoryException&)
530  {
531  XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
532  //errorCode = 5;
533  }
534  catch (const xercesc::DOMException& e)
535  {
536  XERCES_STD_QUALIFIER cerr << "DOMException code is: " << e.code << XERCES_STD_QUALIFIER endl;
537  //errorCode = 2;
538  }
539  catch(const xercesc::XMLException& e)
540  {
541  std::string message = XML_TO_STRING(e.getMessage());
542  __MOUT__ << "Error Message: " << message << std::endl;
543  //return 1;
544  return message;
545  }
546  catch (...)
547  {
548  XERCES_STD_QUALIFIER cerr << "An error occurred creating the document" << XERCES_STD_QUALIFIER endl;
549  //errorCode = 3;
550  }
551  } // (inpl != 0)
552  else
553  {
554  XERCES_STD_QUALIFIER cerr << "Requested implementation is not supported" << XERCES_STD_QUALIFIER endl;
555  //errorCode = 4;
556  }
557 
558  terminatePlatform();
559  return configFile;
560 }
561 
562 // return errorCode;
563 
564 //==============================================================================
565 void ConfigurationHandler::outputXML(xercesc::DOMDocument* pmyDOMDocument, std::string fileName)
566 {
567  std::string directory = fileName.substr(0,fileName.rfind("/")+1);
568  __MOUT__ << "Saving Configuration to " << fileName << " in directory: " << directory << std::endl;
569 
570  mkdir(directory.c_str(), 0755);
571 
572  //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.
573  //DOMImplementation *implementation = DOMImplementationRegistry::getDOMImplementation(L"LS");
574  xercesc::DOMImplementation *implementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML("LS"));
575 
576 #if _XERCES_VERSION >= 30000
577  // Create a DOMLSSerializer which is used to serialize a DOM tree into an XML document.
578  xercesc::DOMLSSerializer* serializer = ((xercesc::DOMImplementationLS*)implementation)->createLSSerializer();
579 
580  // Make the output more human readable by inserting line feeds.
581 
582  if (serializer->getDomConfig()->canSetParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true))
583  serializer->getDomConfig()->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
584 
585  // The end-of-line sequence of characters to be used in the XML being written out.
586  //serializer->setNewLine(CONVERT_TO_XML("\r\n"));
587 
588  // Convert the path into Xerces compatible XMLCh*.
589 
590  // Specify the target for the XML output.
591  xercesc::XMLFormatTarget* formatTarget = new xercesc::LocalFileFormatTarget(CONVERT_TO_XML(fileName));
592 
593  // Create a new empty output destination object.
594  xercesc::DOMLSOutput* output = ((xercesc::DOMImplementationLS*)implementation)->createLSOutput();
595 
596  // Set the stream to our target.
597  output->setByteStream(formatTarget);
598 
599  // Write the serialized output to the destination.
600  serializer->write(pmyDOMDocument, output);
601 
602 #else
603  xercesc::DOMWriter *serializer = ((xercesc::DOMImplementationLS*)implementation)->createDOMWriter();
604 
605  serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
606 
607  /*
608  Choose a location for the serialized output. The 3 options are:
609  1) StdOutFormatTarget (std output stream - good for debugging)
610  2) MemBufFormatTarget (to Memory)
611  3) LocalFileFormatTarget (save to file)
612  (Note: You'll need a different header file for each one)
613  */
614  //XMLFormatTarget* pTarget = new StdOutFormatTarget();
615  // Convert the path into Xerces compatible XMLCh*.
616 
617  xercesc::XMLFormatTarget* formatTarget = new xercesc::LocalFileFormatTarget(CONVERT_TO_XML(fileName.c_str()));
618 
619  // Write the serialized output to the target.
620  serializer->writeNode(formatTarget, *pmyDOMDocument);
621 
622 #endif
623 
624  // Cleanup.
625  serializer->release();
626 
627  delete formatTarget;
628 
629 #if _XERCES_VERSION >= 30000
630 
631  output->release();
632 
633 #endif
634  __MOUT__ << "Done writing " << std::endl;
635 }
636 
637 //==============================================================================
638 std::string ConfigurationHandler::writeXML(const ConfigurationBase* configuration)
639 {
640  return writeXML(*configuration);
641 }
642 
643 //==============================================================================
644 std::string ConfigurationHandler::getXMLFileName(const ConfigurationBase& configuration, ConfigurationVersion version)
645 {
646  std::stringstream fileName;
647  fileName << getXMLDir(&configuration)
648  << version << '/'
649  << configuration.getConfigurationName() << "_v" << version << ".xml";
650  return fileName.str();
651 
652 }
653 
654 //==============================================================================
655 std::string ConfigurationHandler::getXMLDir(const ConfigurationBase* configuration)
656 {
657  return std::string(getenv("CONFIGURATION_DATA_PATH")) + '/' + configuration->getConfigurationName() + '/';
658 }