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