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 objectToPrint = Reflex::Object(pointedType, iObject.Address());
00249
00250 objectToPrint = Reflex::Object(objectToPrint.CastObject(objectToPrint.DynamicType()));
00251 indent +=iIndentDelta;
00252 }
00253 std::string typeName(objectToPrint.TypeOf().Name(Reflex::SCOPED));
00254 if(typeName.empty()){
00255 typeName="{unknown}";
00256 }
00257
00258
00259 Reflex::Type objectType = objectToPrint.TypeOf();
00260 bool wasTypedef = false;
00261 while(objectType.IsTypedef()) {
00262 objectType = objectType.ToType();
00263 wasTypedef = true;
00264 }
00265 if(wasTypedef){
00266 Reflex::Object tmp(objectType, objectToPrint.Address());
00267 objectToPrint = tmp;
00268 }
00269 if(printAsBuiltin(oStream, iPrefix, iPostfix, objectToPrint, indent)) {
00270 return;
00271 }
00272 if(printAsContainer(oStream, iPrefix, iPostfix, objectToPrint, indent, iIndentDelta)){
00273 return;
00274 }
00275
00276 oStream << indent << iPrefix << formatXML(typeName) << "\">\n";
00277 printDataMembers(oStream, objectToPrint, objectType, indent+iIndentDelta, iIndentDelta);
00278 oStream << indent << iPostfix << "\n";
00279
00280 }
00281
00282 void printDataMembers(std::ostream& oStream,
00283 Reflex::Object const& iObject,
00284 Reflex::Type const& iType,
00285 std::string const& iIndent,
00286 std::string const& iIndentDelta) {
00287
00288 for(Reflex::Base_Iterator itBase = iType.Base_Begin();
00289 itBase != iType.Base_End();
00290 ++itBase) {
00291 printDataMembers(oStream, iObject.CastObject(itBase->ToType()), itBase->ToType(), iIndent, iIndentDelta);
00292 }
00293 static std::string const kPrefix("<datamember name=\"");
00294 static std::string const ktype("\" type=\"");
00295 static std::string const kPostfix("</datamember>");
00296
00297 for(Reflex::Member_Iterator itMember = iType.DataMember_Begin();
00298 itMember != iType.DataMember_End();
00299 ++itMember){
00300
00301 if (itMember->IsTransient()) {
00302 continue;
00303 }
00304 try {
00305 std::string prefix = kPrefix + itMember->Name() + ktype;
00306 printObject(oStream,
00307 prefix,
00308 kPostfix,
00309 itMember->Get(iObject),
00310 iIndent,
00311 iIndentDelta);
00312 }catch(std::exception& iEx) {
00313 std::cout << iIndent << itMember->Name() << " <exception caught("
00314 << iEx.what() << ")>\n";
00315 }
00316 }
00317 }
00318
00319 bool printContentsOfStdContainer(std::ostream& oStream,
00320 std::string const& iPrefix,
00321 std::string const& iPostfix,
00322 Reflex::Object iBegin,
00323 Reflex::Object const& iEnd,
00324 std::string const& iIndent,
00325 std::string const& iIndentDelta){
00326 size_t size = 0;
00327 std::ostringstream sStream;
00328 if(iBegin.TypeOf() != iEnd.TypeOf()) {
00329 std::cerr << " begin (" << iBegin.TypeOf().Name(Reflex::SCOPED) << ") and end ("
00330 << iEnd.TypeOf().Name(Reflex::SCOPED) << ") are not the same type" << std::endl;
00331 throw std::exception();
00332 }
00333 try {
00334 Reflex::Member compare(iBegin.TypeOf().MemberByName("operator!="));
00335 if(!compare) {
00336
00337 return false;
00338 }
00339 Reflex::Member incr(iBegin.TypeOf().MemberByName("operator++"));
00340 if(!incr) {
00341
00342 return false;
00343 }
00344 Reflex::Member deref(iBegin.TypeOf().MemberByName("operator*"));
00345 if(!deref) {
00346
00347 return false;
00348 }
00349
00350 std::string indexIndent = iIndent+iIndentDelta;
00351 int dummy=0;
00352
00353
00354 std::vector<void*> compareArgs = Reflex::Tools::MakeVector((iEnd.Address()));
00355 std::vector<void*> incrArgs = Reflex::Tools::MakeVector(static_cast<void*>(&dummy));
00356 bool compareResult;
00357 Reflex::Object objCompareResult(Reflex::Type::ByTypeInfo(typeid(bool)), &compareResult);
00358 Reflex::Object objIncr;
00359 void* objIncrRefBuffer;
00360 boost::shared_ptr<Reflex::Object> incrMemHolder = initReturnValue(incr, &objIncr, &objIncrRefBuffer);
00361 for(;
00362 compare.Invoke(iBegin, &objCompareResult, compareArgs), compareResult;
00363 incr.Invoke(iBegin, &objIncr, incrArgs), ++size) {
00364
00365 Reflex::Object iTemp;
00366 void* derefRefBuffer;
00367 boost::shared_ptr<Reflex::Object> derefMemHolder = initReturnValue(deref, &iTemp, &derefRefBuffer);
00368 deref.Invoke(iBegin, &iTemp);
00369 if(iTemp.TypeOf().IsReference()) {
00370 iTemp = Reflex::Object(iTemp.TypeOf(), derefRefBuffer);
00371 }
00372 printObject(sStream, kObjectOpen, kObjectClose, iTemp, indexIndent, iIndentDelta);
00373
00374 }
00375 } catch(std::exception const& iE) {
00376 std::cerr << "while printing std container caught exception " << iE.what() << std::endl;
00377 return false;
00378 }
00379 oStream << iPrefix << iIndent << kContainerOpen << size << "\">\n";
00380 oStream << sStream.str();
00381 oStream << iIndent << kContainerClose << std::endl;
00382 oStream << iPostfix;
00383
00384 return true;
00385 }
00386
00387 bool printAsContainer(std::ostream& oStream,
00388 std::string const& iPrefix, std::string const& iPostfix,
00389 Reflex::Object const& iObject,
00390 std::string const& iIndent,
00391 std::string const& iIndentDelta) {
00392 Reflex::Object sizeObj;
00393 try {
00394 size_t temp;
00395 sizeObj = Reflex::Object(Reflex::Type::ByTypeInfo(typeid(size_t)), &temp);
00396 iObject.Invoke("size", &sizeObj);
00397
00398 if(sizeObj.TypeOf().TypeInfo() != typeid(size_t)) {
00399 throw std::exception();
00400 }
00401 size_t size = *reinterpret_cast<size_t*>(sizeObj.Address());
00402 Reflex::Member atMember;
00403 atMember = iObject.TypeOf().MemberByName("at");
00404 if(!atMember) {
00405 throw std::exception();
00406 }
00407 std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
00408 if(typeName.empty()){
00409 typeName="{unknown}";
00410 }
00411
00412 oStream << iIndent << iPrefix << formatXML(typeName) << "\">\n"
00413 << iIndent << kContainerOpen << size << "\">\n";
00414 Reflex::Object contained;
00415 std::string indexIndent=iIndent+iIndentDelta;
00416 for(size_t index = 0; index != size; ++index) {
00417 void* atRefBuffer;
00418 boost::shared_ptr<Reflex::Object> atMemHolder = initReturnValue(atMember, &contained, &atRefBuffer);
00419
00420 atMember.Invoke(iObject, &contained, Reflex::Tools::MakeVector(static_cast<void*>(&index)));
00421 if(contained.TypeOf().IsReference()) {
00422 contained = Reflex::Object(contained.TypeOf(), atRefBuffer);
00423 }
00424
00425 try {
00426 printObject(oStream, kObjectOpen, kObjectClose, contained, indexIndent, iIndentDelta);
00427 }catch(std::exception& iEx) {
00428 std::cout << iIndent << " <exception caught("
00429 << iEx.what() << ")>\n";
00430 }
00431 }
00432 oStream << iIndent << kContainerClose << std::endl;
00433 oStream << iIndent << iPostfix << std::endl;
00434 return true;
00435 } catch(std::exception const& x){
00436
00437 try {
00438
00439 std::string typeName(iObject.TypeOf().Name(Reflex::SCOPED));
00440 if(typeName.empty()){
00441 typeName="{unknown}";
00442 }
00443 Reflex::Object iObjBegin;
00444 void* beginRefBuffer;
00445 Reflex::Member beginMember = iObject.TypeOf().MemberByName("begin");
00446 boost::shared_ptr<Reflex::Object> beginMemHolder = initReturnValue(beginMember, &iObjBegin, &beginRefBuffer);
00447 Reflex::Object iObjEnd;
00448 void* endRefBuffer;
00449 Reflex::Member endMember = iObject.TypeOf().MemberByName("end");
00450 boost::shared_ptr<Reflex::Object> endMemHolder = initReturnValue(endMember, &iObjEnd, &endRefBuffer);
00451
00452 beginMember.Invoke(iObject, &iObjBegin);
00453 endMember.Invoke(iObject, &iObjEnd);
00454 if(printContentsOfStdContainer(oStream,
00455 iIndent+iPrefix+formatXML(typeName)+"\">\n",
00456 iIndent+iPostfix,
00457 iObjBegin,
00458 iObjEnd,
00459 iIndent,
00460 iIndentDelta)) {
00461 if(typeName.empty()){
00462 typeName="{unknown}";
00463 }
00464 return true;
00465 }
00466 } catch(std::exception const& x) {
00467 }
00468 return false;
00469 }
00470 return false;
00471 }
00472
00473 void printObject(std::ostream& oStream,
00474 Event const& iEvent,
00475 std::string const& iClassName,
00476 std::string const& iModuleLabel,
00477 std::string const& iInstanceLabel,
00478 std::string const& iIndent,
00479 std::string const& iIndentDelta) {
00480 try {
00481 GenericHandle handle(iClassName);
00482 }catch(edm::Exception const&) {
00483 std::cout << iIndent << " \"" << iClassName << "\"" << " is an unknown type" << std::endl;
00484 return;
00485 }
00486 GenericHandle handle(iClassName);
00487 iEvent.getByLabel(iModuleLabel, iInstanceLabel, handle);
00488 std::string className = formatXML(iClassName);
00489 printObject(oStream, kObjectOpen, kObjectClose, *handle, iIndent, iIndentDelta);
00490 }
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500 XMLOutputModule::XMLOutputModule(ParameterSet const& iPSet) :
00501 OutputModule(iPSet),
00502 stream_(iPSet.getUntrackedParameter<std::string>("fileName").c_str()),
00503 indentation_(" ") {
00504 if(!stream_){
00505 throw edm::Exception(errors::Configuration) << "failed to open file " << iPSet.getUntrackedParameter<std::string>("fileName");
00506 }
00507 stream_ << "<cmsdata>" << std::endl;
00508 }
00509
00510
00511
00512
00513
00514
00515 XMLOutputModule::~XMLOutputModule() {
00516 stream_ << "</cmsdata>" << std::endl;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 void
00535 XMLOutputModule::write(EventPrincipal const& iEP) {
00536 ModuleDescription desc;
00537 Event event(const_cast<EventPrincipal&>(iEP), desc);
00538 stream_ << "<event run=\"" << event.id().run() << "\" number=\"" << event.id().event() << "\" >\n";
00539 std::string startIndent = indentation_;
00540 for(Selections::const_iterator itBD = keptProducts()[InEvent].begin(), itBDEnd = keptProducts()[InEvent].end();
00541 itBD != itBDEnd;
00542 ++itBD) {
00543 stream_ << "<product type=\"" << (*itBD)->friendlyClassName()
00544 << "\" module=\"" << (*itBD)->moduleLabel()
00545 << "\" productInstance=\"" << (*itBD)->productInstanceName() << "\">\n";
00546 printObject(stream_,
00547 event,
00548 (*itBD)->className(),
00549 (*itBD)->moduleLabel(),
00550 (*itBD)->productInstanceName(),
00551 startIndent,
00552 indentation_);
00553 stream_ << "</product>\n";
00554 }
00555 stream_ << "</event>" << std::endl;
00556 }
00557
00558 void
00559 XMLOutputModule::fillDescriptions(ConfigurationDescriptions& descriptions) {
00560 ParameterSetDescription desc;
00561 desc.setComment("Prints event information into a file in XML format.");
00562 desc.addUntracked<std::string>("fileName");
00563 OutputModule::fillDescription(desc);
00564 descriptions.add("XMLoutput", desc);
00565 }
00566 }
00567 using edm::XMLOutputModule;
00568 DEFINE_FWK_MODULE(XMLOutputModule);