00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <fstream>
00015 #include <string>
00016 #include <iomanip>
00017 #include <map>
00018 #include <sstream>
00019 #include <algorithm>
00020
00021 #include "Reflex/Base.h"
00022 #include "Reflex/Member.h"
00023
00024 #include "FWCore/Framework/interface/Event.h"
00025 #include "DataFormats/Provenance/interface/BranchDescription.h"
00026 #include "DataFormats/Provenance/interface/Selections.h"
00027
00028 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00029 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00030 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00031
00032 #include "FWCore/Framework/interface/Frameworkfwd.h"
00033 #include "FWCore/Framework/interface/OutputModule.h"
00034 #include "FWCore/Framework/interface/GenericHandle.h"
00035 #include "FWCore/Framework/interface/MakerMacros.h"
00036
00037
00038
00039
00040
00041
00042
00043 namespace edm {
00044 class XMLOutputModule : public OutputModule {
00045
00046 public:
00047 XMLOutputModule(ParameterSet const&);
00048 virtual ~XMLOutputModule();
00049 static void fillDescriptions(ConfigurationDescriptions& descriptions);
00050
00051
00052
00053
00054
00055
00056
00057 private:
00058 virtual void write(EventPrincipal const& e);
00059 virtual void writeLuminosityBlock(LuminosityBlockPrincipal const&) {}
00060 virtual void writeRun(RunPrincipal const&) {}
00061
00062 XMLOutputModule(XMLOutputModule const&);
00063
00064 XMLOutputModule const& operator=(XMLOutputModule const&);
00065
00066
00067 std::ofstream stream_;
00068 std::string indentation_;
00069 };
00070
00071 namespace {
00072 void doNotDelete(void*) {}
00073 void callDestruct(Reflex::Object* iObj) {
00074 iObj->Destruct();
00075 }
00076
00077
00078
00079 boost::shared_ptr<Reflex::Object> initReturnValue(Reflex::Member const& iMember,
00080 Reflex::Object* iObj,
00081 void** iRefBuffer) {
00082 Reflex::Type returnType = iMember.TypeOf().ReturnType();
00083 if(returnType.IsReference()) {
00084 *iObj = Reflex::Object(returnType, iRefBuffer);
00085 return boost::shared_ptr<Reflex::Object>(iObj, doNotDelete);
00086 }
00087 *iObj = returnType.Construct();
00088 return boost::shared_ptr<Reflex::Object>(iObj, callDestruct);
00089 }
00090
00091
00092 std::string formatXML(std::string const& iO) {
00093 std::string result(iO);
00094 static std::string const kSubs("<>&");
00095 static std::string const kLeft("<");
00096 static std::string const kRight(">");
00097 static std::string const kAmp("&");
00098
00099 std::string::size_type i = 0;
00100 while(std::string::npos != (i = result.find_first_of(kSubs, i))) {
00101 switch(result.at(i)) {
00102 case '<':
00103 result.replace(i, 1, kLeft);
00104 break;
00105 case '>':
00106 result.replace(i, 1, kRight);
00107 break;
00108 case '&':
00109 result.replace(i, 1, kAmp);
00110 }
00111 ++i;
00112 }
00113 return result;
00114 }
00115
00116 char const* kNameValueSep = "\">";
00117 char const* kContainerOpen = "<container size=\"";
00118 char const* kContainerClose = "</container>";
00119 std::string const kObjectOpen = "<object type=\"";
00120 std::string const kObjectClose = "</object>";
00122 #define FILLNAME(_type_) s_toName[typeid(_type_).name()]= #_type_;
00123 std::string const& typeidToName(std::type_info const& iID) {
00124 static std::map<std::string, std::string> s_toName;
00125 if(s_toName.empty()) {
00126 FILLNAME(short);
00127 FILLNAME(int);
00128 FILLNAME(long);
00129 FILLNAME(long long);
00130
00131 FILLNAME(unsigned short);
00132 FILLNAME(unsigned int);
00133 FILLNAME(unsigned long);
00134 FILLNAME(unsigned long long);
00135
00136 FILLNAME(double);
00137 FILLNAME(float);
00138 }
00139 return s_toName[iID.name()];
00140 }
00141
00142 template<typename T>
00143 void doPrint(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
00144 oStream << iIndent << iPrefix << typeidToName(typeid(T)) << kNameValueSep
00145 << *reinterpret_cast<T*>(iObject.Address()) << iPostfix << "\n";
00146 }
00147
00148 template<>
00149 void doPrint<char>(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
00150 oStream << iIndent << iPrefix << "char" << kNameValueSep
00151 << static_cast<int>(*reinterpret_cast<char*>(iObject.Address())) << iPostfix << "\n";
00152 }
00153
00154 template<>
00155 void doPrint<unsigned char>(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
00156 oStream << iIndent << iPrefix << "unsigned char" << kNameValueSep << static_cast<unsigned int>(*reinterpret_cast<unsigned char*>(iObject.Address())) << iPostfix << "\n";
00157 }
00158
00159 template<>
00160 void doPrint<bool>(std::ostream& oStream, std::string const& iPrefix, std::string const& iPostfix, Reflex::Object const& iObject, std::string const& iIndent) {
00161 oStream << iIndent << iPrefix << "bool" << kNameValueSep
00162 << ((*reinterpret_cast<bool*>(iObject.Address()))?"true":"false") << iPostfix << "\n";
00163 }
00164
00165
00166 typedef void(*FunctionType)(std::ostream&, std::string const&,
00167 std::string const&, Reflex::Object const&, std::string const&);
00168 typedef std::map<std::string, FunctionType> TypeToPrintMap;
00169
00170 template<typename T>
00171 void addToMap(TypeToPrintMap& iMap){
00172 iMap[typeid(T).name()]=doPrint<T>;
00173 }
00174
00175 bool printAsBuiltin(std::ostream& oStream,
00176 std::string const& iPrefix,
00177 std::string const& iPostfix,
00178 Reflex::Object const iObject,
00179 std::string const& iIndent){
00180 typedef void(*FunctionType)(std::ostream&, std::string const&, std::string const&, Reflex::Object const&, std::string const&);
00181 typedef std::map<std::string, FunctionType> TypeToPrintMap;
00182 static TypeToPrintMap s_map;
00183 static bool isFirst = true;
00184 if(isFirst){
00185 addToMap<bool>(s_map);
00186 addToMap<char>(s_map);
00187 addToMap<short>(s_map);
00188 addToMap<int>(s_map);
00189 addToMap<long>(s_map);
00190 addToMap<unsigned char>(s_map);
00191 addToMap<unsigned short>(s_map);
00192 addToMap<unsigned int>(s_map);
00193 addToMap<unsigned long>(s_map);
00194 addToMap<float>(s_map);
00195 addToMap<double>(s_map);
00196 isFirst=false;
00197 }
00198 TypeToPrintMap::iterator itFound =s_map.find(iObject.TypeOf().TypeInfo().name());
00199 if(itFound == s_map.end()){
00200
00201 return false;
00202 }
00203 itFound->second(oStream, iPrefix, iPostfix, iObject, iIndent);
00204 return true;
00205 }
00206
00207 bool printAsContainer(std::ostream& oStream,
00208 std::string const& iPrefix,
00209 std::string const& iPostfix,
00210 Reflex::Object const& iObject,
00211 std::string const& iIndent,
00212 std::string const& iIndentDelta);
00213
00214 void printDataMembers(std::ostream& oStream,
00215 Reflex::Object const& iObject,
00216 Reflex::Type const& iType,
00217 std::string const& iIndent,
00218 std::string const& iIndentDelta);
00219
00220 void printObject(std::ostream& oStream,
00221 std::string const& iPrefix,
00222 std::string const& iPostfix,
00223 Reflex::Object const& iObject,
00224 std::string const& iIndent,
00225 std::string const& iIndentDelta) {
00226 Reflex::Object objectToPrint = iObject;
00227 std::string indent(iIndent);
00228 if(iObject.TypeOf().IsPointer()) {
00229 oStream << iIndent << iPrefix << formatXML(iObject.TypeOf().Name(Reflex::SCOPED)) << "\">\n";
00230 indent +=iIndentDelta;
00231 int size = (0!=iObject.Address()) ? (0!=*reinterpret_cast<void**>(iObject.Address())?1:0) : 0;
00232 oStream << indent << kContainerOpen << size << "\">\n";
00233 if(size) {
00234 std::string indent2 = indent + iIndentDelta;
00235 Reflex::Object obj(iObject.TypeOf().ToType(), *reinterpret_cast<void**>(iObject.Address()));
00236 obj = obj.CastObject(obj.DynamicType());
00237 printObject(oStream, kObjectOpen, kObjectClose, obj, indent2, iIndentDelta);
00238 }
00239 oStream << indent << kContainerClose << "\n";
00240 oStream << iIndent << iPostfix << "\n";
00241 Reflex::Type pointedType = iObject.TypeOf().ToType();
00242 if(Reflex::Type::ByName("void") == pointedType || pointedType.IsPointer() || iObject.Address()==0) {
00243 return;
00244 }
00245 return;
00246
00247
00248
00249
00250
00251
00252
00253 }
00254 std::string typeName(objectToPrint.TypeOf().Name(Reflex::SCOPED));
00255 if(typeName.empty()){
00256 typeName="{unknown}";
00257 }
00258
00259
00260 Reflex::Type objectType = objectToPrint.TypeOf();
00261 bool wasTypedef = false;
00262 while(objectType.IsTypedef()) {
00263 objectType = objectType.ToType();
00264 wasTypedef = true;
00265 }
00266 if(wasTypedef){
00267 Reflex::Object tmp(objectType, objectToPrint.Address());
00268 objectToPrint = tmp;
00269 }
00270 if(printAsBuiltin(oStream, iPrefix, iPostfix, objectToPrint, indent)) {
00271 return;
00272 }
00273 if(printAsContainer(oStream, iPrefix, iPostfix, objectToPrint, indent, iIndentDelta)){
00274 return;
00275 }
00276
00277 oStream << indent << iPrefix << formatXML(typeName) << "\">\n";
00278 printDataMembers(oStream, objectToPrint, objectType, indent+iIndentDelta, iIndentDelta);
00279 oStream << indent << iPostfix << "\n";
00280
00281 }
00282
00283 void printDataMembers(std::ostream& oStream,
00284 Reflex::Object const& iObject,
00285 Reflex::Type const& iType,
00286 std::string const& iIndent,
00287 std::string const& iIndentDelta) {
00288
00289 for(Reflex::Base_Iterator itBase = iType.Base_Begin();
00290 itBase != iType.Base_End();
00291 ++itBase) {
00292 printDataMembers(oStream, iObject.CastObject(itBase->ToType()), itBase->ToType(), iIndent, iIndentDelta);
00293 }
00294 static std::string const kPrefix("<datamember name=\"");
00295 static std::string const ktype("\" type=\"");
00296 static std::string const kPostfix("</datamember>");
00297
00298 for(Reflex::Member_Iterator itMember = iType.DataMember_Begin();
00299 itMember != iType.DataMember_End();
00300 ++itMember){
00301
00302 if (itMember->IsTransient()) {
00303 continue;
00304 }
00305 try {
00306 std::string prefix = kPrefix + itMember->Name() + ktype;
00307 printObject(oStream,
00308 prefix,
00309 kPostfix,
00310 itMember->Get(iObject),
00311 iIndent,
00312 iIndentDelta);
00313 }catch(std::exception& iEx) {
00314 std::cout << iIndent << itMember->Name() << " <exception caught("
00315 << iEx.what() << ")>\n";
00316 }
00317 }
00318 }
00319
00320 bool printContentsOfStdContainer(std::ostream& oStream,
00321 std::string const& iPrefix,
00322 std::string const& iPostfix,
00323 Reflex::Object iBegin,
00324 Reflex::Object const& iEnd,
00325 std::string const& iIndent,
00326 std::string const& iIndentDelta){
00327 size_t size = 0;
00328 std::ostringstream sStream;
00329 if(iBegin.TypeOf() != iEnd.TypeOf()) {
00330 std::cerr << " begin (" << iBegin.TypeOf().Name(Reflex::SCOPED) << ") and end ("
00331 << iEnd.TypeOf().Name(Reflex::SCOPED) << ") are not the same type" << std::endl;
00332 throw std::exception();
00333 }
00334 try {
00335 Reflex::Member compare(iBegin.TypeOf().MemberByName("operator!="));
00336 if(!compare) {
00337
00338 return false;
00339 }
00340 Reflex::Member incr(iBegin.TypeOf().MemberByName("operator++"));
00341 if(!incr) {
00342
00343 return false;
00344 }
00345 Reflex::Member deref(iBegin.TypeOf().MemberByName("operator*"));
00346 if(!deref) {
00347
00348 return false;
00349 }
00350
00351 std::string indexIndent = iIndent+iIndentDelta;
00352 int dummy=0;
00353
00354
00355 std::vector<void*> compareArgs = Reflex::Tools::MakeVector((iEnd.Address()));
00356 std::vector<void*> incrArgs = Reflex::Tools::MakeVector(static_cast<void*>(&dummy));
00357 bool compareResult;
00358 Reflex::Object objCompareResult(Reflex::Type::ByTypeInfo(typeid(bool)), &compareResult);
00359 Reflex::Object objIncr;
00360 void* objIncrRefBuffer;
00361 boost::shared_ptr<Reflex::Object> incrMemHolder = initReturnValue(incr, &objIncr, &objIncrRefBuffer);
00362 for(;
00363 compare.Invoke(iBegin, &objCompareResult, compareArgs), compareResult;
00364 incr.Invoke(iBegin, &objIncr, incrArgs), ++size) {
00365
00366 Reflex::Object iTemp;
00367 void* derefRefBuffer;
00368 boost::shared_ptr<Reflex::Object> derefMemHolder = initReturnValue(deref, &iTemp, &derefRefBuffer);
00369 deref.Invoke(iBegin, &iTemp);
00370 if(iTemp.TypeOf().IsReference()) {
00371 iTemp = Reflex::Object(iTemp.TypeOf(), derefRefBuffer);
00372 }
00373 printObject(sStream, kObjectOpen, kObjectClose, iTemp, indexIndent, iIndentDelta);
00374
00375 }
00376 } catch(std::exception const& iE) {
00377 std::cerr << "while printing std container caught exception " << iE.what() << std::endl;
00378 return false;
00379 }
00380 oStream << iPrefix << iIndent << kContainerOpen << size << "\">\n";
00381 oStream << sStream.str();
00382 oStream << iIndent << kContainerClose << std::endl;
00383 oStream << iPostfix;
00384
00385 return true;
00386 }
00387
00388 bool printAsContainer(std::ostream& oStream,
00389 std::string const& iPrefix, std::string const& iPostfix,
00390 Reflex::Object const& iObject,
00391 std::string const& iIndent,
00392 std::string const& iIndentDelta) {
00393 Reflex::Object sizeObj;
00394 try {
00395 size_t temp;
00396 sizeObj = Reflex::Object(Reflex::Type::ByTypeInfo(typeid(size_t)), &temp);
00397 iObject.Invoke("size", &sizeObj);
00398
00399 if(sizeObj.TypeOf().TypeInfo() != typeid(size_t)) {
00400 throw std::exception();
00401 }
00402 size_t size = *reinterpret_cast<size_t*>(sizeObj.Address());
00403 Reflex::Member atMember;
00404 atMember = iObject.TypeOf().MemberByName("at");
00405 if(!atMember) {
00406 throw std::exception();
00407 }
00408 std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
00409 if(typeName.empty()){
00410 typeName="{unknown}";
00411 }
00412
00413 oStream << iIndent << iPrefix << formatXML(typeName) << "\">\n"
00414 << iIndent << kContainerOpen << size << "\">\n";
00415 Reflex::Object contained;
00416 std::string indexIndent=iIndent+iIndentDelta;
00417 for(size_t index = 0; index != size; ++index) {
00418 void* atRefBuffer;
00419 boost::shared_ptr<Reflex::Object> atMemHolder = initReturnValue(atMember, &contained, &atRefBuffer);
00420
00421 atMember.Invoke(iObject, &contained, Reflex::Tools::MakeVector(static_cast<void*>(&index)));
00422 if(contained.TypeOf().IsReference()) {
00423 contained = Reflex::Object(contained.TypeOf(), atRefBuffer);
00424 }
00425
00426 try {
00427 printObject(oStream, kObjectOpen, kObjectClose, contained, indexIndent, iIndentDelta);
00428 }catch(std::exception& iEx) {
00429 std::cout << iIndent << " <exception caught("
00430 << iEx.what() << ")>\n";
00431 }
00432 }
00433 oStream << iIndent << kContainerClose << std::endl;
00434 oStream << iIndent << iPostfix << std::endl;
00435 return true;
00436 } catch(std::exception const& x){
00437
00438 try {
00439
00440 std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
00441 if(typeName.empty()){
00442 typeName="{unknown}";
00443 }
00444 Reflex::Object iObjBegin;
00445 void* beginRefBuffer;
00446 Reflex::Member beginMember = iObject.TypeOf().MemberByName("begin");
00447 boost::shared_ptr<Reflex::Object> beginMemHolder = initReturnValue(beginMember, &iObjBegin, &beginRefBuffer);
00448 Reflex::Object iObjEnd;
00449 void* endRefBuffer;
00450 Reflex::Member endMember = iObject.TypeOf().MemberByName("end");
00451 boost::shared_ptr<Reflex::Object> endMemHolder = initReturnValue(endMember, &iObjEnd, &endRefBuffer);
00452
00453 beginMember.Invoke(iObject, &iObjBegin);
00454 endMember.Invoke(iObject, &iObjEnd);
00455 if(printContentsOfStdContainer(oStream,
00456 iIndent+iPrefix+formatXML(typeName)+"\">\n",
00457 iIndent+iPostfix,
00458 iObjBegin,
00459 iObjEnd,
00460 iIndent,
00461 iIndentDelta)) {
00462 if(typeName.empty()){
00463 typeName="{unknown}";
00464 }
00465 return true;
00466 }
00467 } catch(std::exception const& x) {
00468 }
00469 return false;
00470 }
00471 return false;
00472 }
00473
00474 void printObject(std::ostream& oStream,
00475 Event const& iEvent,
00476 std::string const& iClassName,
00477 std::string const& iModuleLabel,
00478 std::string const& iInstanceLabel,
00479 std::string const& iIndent,
00480 std::string const& iIndentDelta) {
00481 try {
00482 GenericHandle handle(iClassName);
00483 }catch(edm::Exception const&) {
00484 std::cout << iIndent << " \"" << iClassName << "\"" << " is an unknown type" << std::endl;
00485 return;
00486 }
00487 GenericHandle handle(iClassName);
00488 iEvent.getByLabel(iModuleLabel, iInstanceLabel, handle);
00489 std::string className = formatXML(iClassName);
00490 printObject(oStream, kObjectOpen, kObjectClose, *handle, iIndent, iIndentDelta);
00491 }
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501 XMLOutputModule::XMLOutputModule(ParameterSet const& iPSet) :
00502 OutputModule(iPSet),
00503 stream_(iPSet.getUntrackedParameter<std::string>("fileName").c_str()),
00504 indentation_(" ") {
00505 if(!stream_){
00506 throw edm::Exception(errors::Configuration) << "failed to open file " << iPSet.getUntrackedParameter<std::string>("fileName");
00507 }
00508 stream_ << "<cmsdata>" << std::endl;
00509 }
00510
00511
00512
00513
00514
00515
00516 XMLOutputModule::~XMLOutputModule() {
00517 stream_ << "</cmsdata>" << std::endl;
00518 }
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 void
00536 XMLOutputModule::write(EventPrincipal const& iEP) {
00537 ModuleDescription desc;
00538 Event event(const_cast<EventPrincipal&>(iEP), desc);
00539 stream_ << "<event run=\"" << event.id().run() << "\" number=\"" << event.id().event() << "\" >\n";
00540 std::string startIndent = indentation_;
00541 for(Selections::const_iterator itBD = keptProducts()[InEvent].begin(), itBDEnd = keptProducts()[InEvent].end();
00542 itBD != itBDEnd;
00543 ++itBD) {
00544 stream_ << "<product type=\"" << (*itBD)->friendlyClassName()
00545 << "\" module=\"" << (*itBD)->moduleLabel()
00546 << "\" productInstance=\"" << (*itBD)->productInstanceName() << "\">\n";
00547 printObject(stream_,
00548 event,
00549 (*itBD)->className(),
00550 (*itBD)->moduleLabel(),
00551 (*itBD)->productInstanceName(),
00552 startIndent,
00553 indentation_);
00554 stream_ << "</product>\n";
00555 }
00556 stream_ << "</event>" << std::endl;
00557 }
00558
00559 void
00560 XMLOutputModule::fillDescriptions(ConfigurationDescriptions& descriptions) {
00561 ParameterSetDescription desc;
00562 desc.setComment("Prints event information into a file in XML format.");
00563 desc.addUntracked<std::string>("fileName");
00564 OutputModule::fillDescription(desc);
00565 descriptions.add("XMLoutput", desc);
00566 }
00567 }
00568 using edm::XMLOutputModule;
00569 DEFINE_FWK_MODULE(XMLOutputModule);