CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/FWCore/GuiBrowsers/python/HTMLExport.py

Go to the documentation of this file.
00001 import sys
00002 import os
00003 import os.path
00004 import logging
00005 import random
00006 import json
00007 
00008 import FWCore.ParameterSet.SequenceTypes as sqt
00009 import FWCore.ParameterSet.Config as cms
00010 import FWCore.ParameterSet.Modules as mod
00011 import FWCore.ParameterSet.Types as typ
00012 import FWCore.ParameterSet.Mixins as mix
00013 
00014 from Vispa.Plugins.ConfigEditor.ConfigDataAccessor import ConfigDataAccessor
00015 from FWCore.GuiBrowsers.FileExportPlugin import FileExportPlugin
00016 
00017 
00018 def elem(elemtype, innerHTML='', html_class='', **kwargs):
00019     if html_class: #since 'class' cannot be used as a kwarg
00020         kwargs['class'] = html_class
00021     args = ' '.join(['%s="%s"' % i for i in kwargs.items()])
00022     if args:
00023         return "<%s %s>%s</%s>\n" % (elemtype, args, innerHTML, elemtype)
00024     else:
00025         return "<%s>%s</%s>\n" % (elemtype, innerHTML, elemtype)
00026 
00027 def get_jquery():
00028     jquery_file = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'jquery-1.6.2.min.js')
00029     if os.path.exists(jquery_file):
00030         return elem('script', open(jquery_file).read(), type='text/javascript')
00031     else:
00032         return elem('script', type='text/javascript', src=JQUERY)
00033 
00034 JQUERY = "https://code.jquery.com/jquery-1.6.2.min.js"
00035 LXR = "https://cmslxr.fnal.gov/lxr/ident?"
00036 CVS = "https://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/"
00037 CMSLOGO = "https://cms.cern.ch/iCMS/imgs/icms/CMSheader_left.gif"
00038 
00039 CSS_TEMPLATE =\
00040 """
00041 body {border-width:0;margin:0}
00042 #header {width:100%;height:10%;background-color:#000}
00043 #mlist {position:absolute;width:32%;top:10%;left:0;height:85%;overflow:auto;padding-left:20px}
00044 #mview {position:absolute;width:65%;height:85%;top:10%;left:35%;overflow:auto}
00045 #footer {position:absolute;top:95%;width:100%;height:5%;background-color:#000}
00046 #cmslogo {float:left;vertical-align:middle;margin:5px}
00047 #head_filedir {float:left;vertical-align:middle;margin:5px}
00048 #searcharea {float:right;vertical-align:middle;margin-top:3px;margin-right:5px;position:relative}
00049 #head_dirname {color:#ccc;font-size:12}
00050 #head_filename {color:#fff;font-weight:bold;font-size:16}
00051 #searchhider {display:none;position:relative;top:-10px}
00052 #searchhider a {color:#fff;text-decoration:none}
00053 #searchresult {display:none;-moz-border-radius:10px;border-radius:10px;border:2px solid #999;background-color:#ccc;padding:5px;z-index:1000;position:relative;height:700%}
00054 #searchscroll {overflow:scroll;height:100%;width:100%}
00055 #searchresult div {margin:3px;padding:2px}
00056 .searchfrom {color:#999;font-size:small}
00057 
00058 #mview_header {font-weight:bold;font-size:16;background-color:#cc6;-moz-border-radius:10px;border-radius:10px;margin-top:3px;padding:5px}
00059 #mview_header span {border-radius:5px;-moz-border-radius:5px;padding-left:5px;padding-top:2px;margin-top:2px;margin-left:5px}
00060 #mview_subheader {background-color:#ffffcc;-moz-border-radius:10px;border-radius:10px;margin-top:3px;padding:5px}
00061 #mview_pset {background-color:#ffffcc;-moz-border-radius:10px;border-radius:10px;margin-top:3px;padding:5px}
00062 .mview_label {color:#999}
00063 .mview_value {border-radius:5px;-moz-border-radius:5px;padding-left:5px;padding-top:2px;margin-top:2px;margin-left:5px;background-color:#cc6}
00064 .mview_value a {text-decoration:none}
00065 .mview_value span {display:inline-block}
00066 
00067 #footer_crumbs {float:left;font-size:small;font-weight:bold;color:#fff}
00068 #footer_crumbs span {color:#000}
00069 #footer_about {float:right}
00070 #footer_about a {text-decoration:none;font-weight:bold;color:#fff}
00071 
00072 .csearch {background-color:#fff}
00073 
00074 .seq_contain {position:relative;left:-20px}
00075 .seq_toggle {position:absolute;left:5px;top:2px;width:15px;vertical-align:middle;text-align:center;font-weight:bold;font-size:20}
00076 .seq_right {position:relative;left:20px;border-radius:5px;-moz-border-radius:5px;padding-left:5px;padding-top:3px;margin-top:3px;width:auto;display:inline-block}
00077 .seq_label {font-weight:bold;border-radius:5px;-moz-border-radius:5px;padding:3px 1px;display:inline-block;border-width:1px;border-style:solid}
00078 .seq_expand {display:none;padding-left:20px}
00079 
00080 .module {position:relative;border-radius:5px;-moz-border-radius:5px;padding-left:3px;padding-top:1px;margin-top:2px;padding-right:3px;padding-bottom:1px;margin-right:2px;display:inline-block;border-width:1px;border-style:solid}
00081 
00082 .path {background-color:#3cf;border-color:#3cf}
00083 .endpath {background-color:#9cf;border-color:#9cf}
00084 .sequence {background-color:#99f;border-color:#99f}
00085 .edanalyzer {background-color:#f00;border-color:#f00}
00086 .edproducer {background-color:#0f0;border-color:#0f0}
00087 .edfilter {background-color:#ff0;border-color:#ff0}
00088 .outputmodule {background-color:#f0f;border-color:#f0f}
00089 .source {background-color:#f9c;border-color:#f9c}
00090 .service {background-color:#f96;border-color:#f96}
00091 .sources {background-color:#fcc;border-color:#fcc}
00092 .services {background-color:#fc6;border-color:#fc6}
00093 .essource {background-color:#9cc;border-color:#9cc}
00094 .esproducer {background-color:#3c9;border-color:#3c9}
00095 .esprefer {background-color:#096;border-color:#096}
00096 .essources {background-color:#9fc;border-color:#9fc}
00097 .esproducers {background-color:#3f9;border-color:#3f9}
00098 .esprefers {background-color:#0c6;border-color:#0c6}
00099 .unknown_type {background-color:#ccc;border-color:#ccc}
00100 
00101 .used {border-radius:5px;-moz-border-radius:5px;padding:2px 5px;margin-top:2px;margin-right:5px;border-width:1px;border-style:solid}
00102 .member {border-radius:5px;-moz-border-radius:5px;padding:2px 5px;margin-top:2px;margin-right:5px;border-width:1px;border-style:solid}
00103 
00104 .clickable {cursor:pointer}
00105 span.clickable:hover {border-color:#fff}
00106 div.module.clickable:hover {border-color:#fff}
00107 div.seq_label.clickable:hover {border-color:#fff}
00108 
00109 .pset {border:2px solid #000;background-color:#ffffcc;font-size:small;border-collapse:collapse}
00110 .pset td {border-width:1px;border-color:#ccc; border-style:solid none;margin:0;padding:2px 4px}
00111 .pset_label {font-weight:bold}
00112 .pset_type {color:#aaa}
00113 
00114 .pset_vector {list-style-type:none;border:1px solid #000;padding-left:5px;margin:1px}
00115 .pset_int {font-family:courier;color:blue}
00116 .pset_double {font-family:courier;color:purple}
00117 .pset_string {font-family:courier;color:brown}
00118 .pset_bool {font-family:courier;color:#f0f}
00119 .pset_inputtag {font-family:courier}
00120 .pset_othertype {font-family:courier}
00121 .pset_placehold {display:none;color:#aaa}
00122 
00123 #about_dialog {position:absolute;width:60%;height:40%;top:30%;left:20%;border-radius:10px;-moz-border-radius:10px;color:#fff;background-color:#00f;border:5px solid #003;display:none;text-align:center}
00124 """
00125 
00126 JS_TEMPLATE =\
00127 """
00128 var modules = {};
00129 var sequences = {};
00130 var pset_keys = {};
00131 var pset_values = {};
00132 var crumbs = [];
00133 var n_results = 0;
00134 var last_search = "";
00135 
00136 var cvsroot = "%(cvs)s";
00137 var lxrroot = "%(lxr)s";
00138 if (data.process.cmssw) {
00139     lxrroot = lxrroot + "v=" + data.process.cmssw + ";";
00140 }
00141 
00142 function parse_data() {
00143     function _pset_visitor(pset, context) {
00144         var keys = [];
00145         var values = [];
00146         for (var i in pset) {
00147             var item = pset[i];
00148             var name = context + item.label;
00149             if (item.type == 'PSet') {
00150                 result = _pset_visitor(item.value, name+'.');
00151                 keys.concat(result.keys);
00152                 values.concat(result.values);
00153             } else if (item.type == 'VPSet') {
00154                 for (var j in item.value) {
00155                     result = _pset_visitor(item.value[j], name+'.');
00156                     if (j==0) {
00157                         keys.concat(result.keys); //assume they all have equivalent structure
00158                     }
00159                     values.concat(result.values);
00160                 }
00161             } else if (item.type == 'VInputTag') {
00162                 keys.push(name);
00163                 for (var j in item.value) {
00164                     values.push(item.value[j][0].toString()); //only modulename
00165                 }
00166             } else if (item.type == 'InputTag') {
00167                 keys.push(name);
00168                 values.push(item.value[0].toString());
00169             } else if (item.list) {
00170                 keys.push(name);
00171                 for (var j in item.value) {
00172                     values.push(item.value[j].toString());
00173                 }
00174             } else {
00175                 keys.push(name);
00176                 values.push(item.value.toString());
00177             }   
00178         }
00179         return {keys:keys, values:values};
00180     }
00181     function _path_visitor(path) {
00182         if (path.path) {
00183             sequences[path.label] = path;
00184             for (var child in path.path) {
00185                 _path_visitor(path.path[child]);
00186             }
00187         } else {
00188             _module_visitor(path);
00189         }                 
00190     }
00191     function _module_visitor(module) {
00192         modules[module.label] = module;
00193         if (module.pset) {
00194             var result = _pset_visitor(module.pset, '');
00195             pset_keys[module.label] = result.keys;
00196             pset_values[module.label] = result.values;
00197         }
00198     }
00199     function _handle_flat(modlist) {
00200         for (var i in modlist) {
00201             _module_visitor(modlist[i]);
00202         }
00203     }
00204     _handle_flat(data.source);
00205     _handle_flat(data.services);
00206     _handle_flat(data.essources);
00207     _handle_flat(data.esproducers);
00208     _handle_flat(data.esprefers);
00209     for (var p in data.paths) {var path = data.paths[p]; _path_visitor(path);}
00210     for (var p in data.endpaths) {var path = data.paths[p]; _path_visitor(path);} 
00211 }
00212 
00213 function ensure_visible(name) {
00214     if (! $("#"+name).is(":visible")) {
00215         $("#"+name).parents(".seq_expand").each(function() {
00216             if (! $(this).is(":visible")) {
00217                 var id = $(this).attr("id").slice(7);
00218                 toggle_sequence(id);
00219             }
00220         });
00221     }
00222     $("#mlist").animate({"scrollTop": $("#"+name).position().top}, 1000);
00223 }
00224 
00225 function show_module(name) {
00226     var module = modules[name];
00227     if (module) {
00228         add_breadcrumb("module", name);
00229         ensure_visible(name);
00230         show_mview(module);
00231     }
00232 }
00233 
00234 function show_sequence(name) {
00235     var sequence = sequences[name];
00236     if (sequence) {
00237         add_breadcrumb("sequence", name);
00238         ensure_visible(name);
00239         show_mview(sequence);
00240     }
00241 }
00242 
00243 function show_mview(module) {
00244     function build_memberlist(memberof) {
00245         var new_html = "";
00246         for (var i in memberof) {
00247             var sequence = sequences[memberof[i]];
00248             if (sequence) {
00249                 new_html += "<span class='clickable member "+sequence.type.toLowerCase()+"' onclick='show_sequence(\\""+sequence.label+"\\");'>"+sequence.label+"</span>";
00250             } else {
00251                 new_html += "<span class='member unknown_type'>"+memberof[i]+"</span>";
00252             }
00253         }
00254         return new_html;
00255     }
00256     function build_uselist(uses) {
00257         var new_html = "";
00258         for (var i in uses) {
00259             var module = modules[uses[i]];
00260             if (module) {
00261                 new_html += "<span class='clickable used "+module.type.toLowerCase()+"' onclick='show_module(\\""+module.label+"\\");'>"+module.label+"</span>";
00262             } else {
00263                 new_html += "<span class='used unknown_type'>"+uses[i]+"</span>";
00264             }
00265         }
00266         return new_html;
00267     }
00268     function build_pset(pset, context, toplevel) {
00269         var typemap = {"string": "string", "double": "double", "int32": "int", "int64": "int", "uint32": "int", "uint64": "int", "bool": "bool"};
00270         if (! toplevel) {
00271             var new_html = "<span class='pset_placehold clickable' id='placehold_"+context+"' onclick='pset_toggle(\\""+context+"\\");'>("+pset.length.toString()+" hidden)</span><table id='content_"+context+"' class='pset'>";    
00272         } else {
00273             var new_html = "<table class='pset'>";
00274         }
00275         for (var i in pset) {
00276             var context2 = context + "_" + i.toString();
00277             var item = pset[i];
00278             if (item.untracked) {
00279                 var itemtype = "cms.untracked."+item.type;
00280             } else {
00281                 var itemtype = "cms."+item.type;
00282             }
00283             if (item.list) {
00284                 itemtype += "[" + item.value.length.toString() + "]";
00285                 new_html += "<tr><td class='pset_label'>"+item.label+"</td><td class='pset_type clickable'  onclick='pset_toggle(\\""+context2+"\\");'>"+itemtype+"</td><td>";
00286             } else if (item.type == 'PSet') {
00287                 new_html += "<tr><td class='pset_label'>"+item.label+"</td><td class='pset_type clickable'  onclick='pset_toggle(\\""+context2+"\\");'>"+itemtype+"</td><td>";
00288             } else {
00289                 new_html += "<tr><td class='pset_label'>"+item.label+"</td><td class='pset_type'>"+itemtype+"</td><td>";
00290             }
00291             
00292             if (item.type == 'PSet') {
00293                 new_html += build_pset(item.value, context2);
00294             } else if (item.type == 'VPSet') {
00295                 new_html += "<span class='pset_placehold clickable' id='placehold_"+context2+"' onclick='pset_toggle(\\""+context2+"\\");'>("+item.value.length.toString()+" hidden)</span><ul class='pset_vector' id='content_"+context2+"'>";
00296                 for (var j in item.value) {
00297                     new_html += "<li>"+build_pset(item.value[j], context2+"_"+j.toString())+"</li>";
00298                 }
00299                 new_html += "</ul>";
00300             } else if (item.type == 'VInputTag') {
00301                 new_html += "<span class='pset_placehold clickable' id='placehold_"+context2+"' onclick='pset_toggle(\\""+context2+"\\");'>("+item.value.length.toString()+" hidden)</span><ul class='pset_vector' id='content_"+context2+"'>";
00302                 for (var j in item.value) {
00303                     var tag = item.value[j];
00304                     var link = build_uselist([tag[0]]);
00305                     if (tag[1] || tag[2]) {
00306                         new_html += "<li><span class='pset_inputtag'>"+link+":"+tag[1]+":"+tag[2]+"</span></li>";
00307                     } else {
00308                         new_html += "<li><span class='pset_inputtag'>"+link+"</span></li>";
00309                     }
00310                 }
00311                 new_html += "</ul>";
00312             } else if (item.type == 'InputTag') {
00313                 var tag = item.value;
00314                 var link = build_uselist([tag[0]]);
00315                 if (tag[1] || tag[2]) {
00316                     new_html += "<span class='pset_inputtag'>"+link+":"+tag[1]+":"+tag[2]+"</span>";
00317                 } else {
00318                     new_html += "<span class='pset_inputtag'>"+link+"</span>";
00319                 }
00320             } else if (item.list) {
00321                 new_html += "<span class='pset_placehold clickable' id='placehold_"+context2+"' onclick='pset_toggle(\\""+context2+"\\");'>("+item.value.length.toString()+" hidden)</span><ul class='pset_vector' id='content_"+context2+"'>";
00322                 var cmstype = item.type.slice(1);
00323                 if (typemap[cmstype]) {
00324                     var css = typemap[cmstype];
00325                 } else {
00326                     var css = "othertype";
00327                 }
00328                 for (var j in item.value) {
00329                     new_html += "<li><span class='pset_"+css+"'>"+item.value[j]+"</span></li>";
00330                 }
00331                 new_html += "</ul>";                
00332             } else {
00333                 var cmstype = item.type;
00334                 if (typemap[cmstype]) {
00335                     var css = typemap[cmstype];
00336                 } else {
00337                     var css = "othertype";
00338                 }
00339                 new_html += "<span class='pset_"+css+"'>"+item.value+"</span>";
00340             }
00341             new_html += "</td></tr>";
00342         }
00343         new_html += "</table>";       
00344         return new_html;
00345     }        
00346     var header = "<span class='used "+module.type.toLowerCase()+"'>"+module.label+"</span>";
00347     $("#mview_header").html(header);
00348     var table_html = "<tr><td class='mview_label'>Module Type:</td><td class='mview_value'>"+module.type+"</td></tr>";
00349     if (module.file && module.line) {
00350         table_html += "<tr><td class='mview_label'>Defined in:</td><td class='mview_value'><a href='"+cvsroot+module.file+"'>"+module.file+"</a>:"+module.line+"</td></tr>";
00351     } else if (module.file) {
00352         table_html += "<tr><td class='mview_label'>Defined in:</td><td class='mview_value'><a href='"+cvsroot+module.file+"'>"+module.file+"</a></td></tr>";
00353     }
00354     if (module.class) {
00355         table_html += "<tr><td class='mview_label'>Module Class:</td><td class='mview_value'><a href='"+lxrroot+"i="+module.class+"'>"+module.class+"</a></td></tr>";
00356     }
00357     if (module.uses) {
00358         table_html += "<tr><td class='mview_label'>Uses:</td><td class='mview_value'>"+build_uselist(module.uses)+"</td></tr>";
00359     }
00360     if (module.usedby) {
00361         table_html += "<tr><td class='mview_label'>Used by:</td><td class='mview_value'>"+build_uselist(module.usedby)+"</td></tr>";
00362     }
00363     if (module.memberof) {
00364         table_html += "<tr><td class='mview_label'>Member of:</td><td class='mview_value'>"+build_memberlist(module.memberof)+"</td></tr>";
00365     }
00366     $("#mview_table").html(table_html);
00367     if (module.pset) {
00368         $("#mview_pset").html(build_pset(module.pset, "pset", true));
00369         $("#mview_pset").find("tr,li").filter(":even").css({"background-color": "#ffa"});
00370         $("#mview_pset").find("tr,li").filter(":odd").css({"background-color": "#ffc"});
00371         $("#mview_pset").find('[id^="content_"]').each(function() {
00372             var id = $(this).attr("id").slice(8);
00373             if ($(this).children().size() > 5) {
00374                 pset_toggle(id);
00375             }
00376         });
00377     } else {
00378         $("#mview_pset").html("");
00379     }
00380 }
00381 
00382 function pset_toggle(item) {
00383     if ($("#content_"+item).is(":visible")) {
00384         $("#content_"+item).hide("fast");
00385         $("#placehold_"+item).show("fast");
00386     } else {
00387         $("#content_"+item).show("fast");
00388         $("#placehold_"+item).hide("fast");
00389     }
00390 }
00391 
00392 function add_breadcrumb(itemtype, item) {
00393     if (crumbs.length > 0 && crumbs[crumbs.length-1][1] == item) {
00394 
00395     } else {
00396         if (crumbs.push([itemtype, item]) > 5) {
00397             crumbs = crumbs.slice(1);
00398         }
00399     }
00400     var new_html = "";
00401     for (var crumb in crumbs) {
00402         var c = crumbs[crumb];
00403         if (c[0] == "module") {
00404             var module = modules[c[1]];
00405             if (module) {
00406                 var css = "used clickable "+module.type.toLowerCase();
00407             } else {
00408                 var css = "used unknown_type";
00409             }
00410             new_html += "&lt; <span class='"+css+"' onclick='show_module(\\"" + c[1] + "\\");'>" + c[1] + "</span>";
00411         } else if (c[0] == "sequence") {
00412             var sequence = sequences[c[1]];
00413             if (sequences) {
00414                 var css = "used clickable "+sequence.type.toLowerCase();
00415             } else {
00416                 var css = "used unknown_type";
00417             }
00418             new_html += "&lt; <span class='"+css+"' onclick='show_sequence(\\"" + c[1] + "\\");'>" + c[1] + "</span>";
00419         } else if (c[0] == "search") {
00420             new_html += "&lt; <span class='used clickable csearch' onclick='do_search(\\"" + c[1] + "\\");'>\\"" + c[1] + "\\"?</span>";
00421         }
00422     }
00423     $("#footer_crumbs").html(new_html);    
00424 }
00425 
00426 function toggle_sequence(sequence) {
00427     if ($("#expand_"+sequence).is(":visible")) {
00428         $("#expand_"+sequence).hide("fast");
00429         $("#toggle_"+sequence).text("+");
00430     } else {
00431         $("#expand_"+sequence).show("fast");
00432         $("#toggle_"+sequence).text("-");
00433     }
00434 }
00435 
00436 function build_mlist() {
00437     function build_path(path) {
00438         if (path.path) {
00439             var new_html = "<div class='seq_contain'><div class='seq_toggle clickable' id='toggle_"+path.label+"'>+</div><div class='seq_right "+path.type.toLowerCase()+"'><div id='"+path.label+"' class='seq_label "+path.type.toLowerCase()+"'>"+path.label+"</div><div class='seq_expand' id='expand_"+path.label+"'>";
00440             for (var child in path.path) {
00441                 new_html += build_path(path.path[child]);
00442             }
00443             new_html += "</div></div></div>";
00444             return new_html;
00445         } else {
00446             return build_module(path);
00447         }
00448     }
00449     function build_module(module) {
00450         return "<div id='"+module.label+"' class='module "+module.type.toLowerCase()+"'>"+module.label+"</div>";   
00451     }
00452     var new_html = "";
00453     if (data.source) {
00454         new_html += build_path({"label":"Source", "type": "Sources", "path": data.source});
00455     }
00456     if (data.services) {
00457         new_html += build_path({"label":"Services", "type": "Services", "path": data.services});
00458     }
00459     if (data.paths) {
00460         for (var path in data.paths) {
00461             new_html += build_path(data.paths[path]);
00462         }
00463     }
00464     if (data.endpaths) {
00465         for (var path in data.endpaths) {
00466             new_html += build_path(data.endpaths[path]);
00467         }
00468     }
00469     if (data.essources) {
00470         new_html += build_path({"label":"ESSources", "type": "ESSources", "path": data.essources});
00471     }
00472     if (data.esproducers) {
00473         new_html += build_path({"label":"ESProducers", "type": "ESProducers", "path": data.esproducers});
00474     }
00475     if (data.esprefers) {
00476         new_html += build_path({"label":"ESPrefers", "type": "ESPrefers", "path": data.esprefers});
00477     }
00478     $("#mlist").html(new_html);
00479     $("#mlist").find(".seq_toggle").each(function() {
00480         $(this).click(function() {
00481             var id=$(this).attr("id").slice(7);
00482             toggle_sequence(id);
00483         });
00484     });
00485     $("#mlist").find(".seq_label").each(function() {
00486         $(this).click(function() {show_sequence($(this).attr("id"));});
00487         $(this).addClass("clickable");
00488     });
00489     $("#mlist").find(".module").each(function() {
00490         $(this).click(function() {show_module($(this).attr("id"));});
00491         $(this).addClass("clickable");
00492     });
00493 }
00494 
00495 function do_search(query) {
00496     if (! query) {return;}
00497     add_breadcrumb("search", query);
00498     var results = {modules:[], modclass:[], modfile:[], sequences:[], seqfile:[], keys:[], values:[]};
00499     var pattern = new RegExp(query, "gi");
00500     for (var i in modules) {
00501         if (i.search(pattern) != -1) {
00502             results.modules.push(i);
00503         }
00504         if (modules[i].class.search(pattern) != -1) {
00505             results.modclass.push(i);
00506         }
00507         if (modules[i].file) {
00508             if (modules[i].file.search(pattern) != -1) {
00509                 results.modfile.push(i);
00510             }
00511         }
00512     }
00513     for (var i in sequences) {
00514         if (i.search(pattern) != -1) {
00515             results.sequences.push(i);
00516         }
00517         if (sequences[i].file) {
00518             if (sequences[i].file.search(pattern) != -1) {
00519                 results.seqfile.push(i);
00520             }
00521         }
00522     }
00523     for (var i in pset_keys) {
00524         for (var j in pset_keys[i]) {
00525             if (pset_keys[i][j].search(pattern) != -1) {
00526                 results.keys.push(i);
00527             }
00528         }
00529     }
00530     for (var i in pset_values) {
00531         for (var j in pset_values[i]) {
00532             if (pset_values[i][j].search(pattern) != -1) {
00533                 results.values.push(i);
00534             }
00535         }
00536     }
00537     var new_html = '';
00538     function _module_div(name, extra) {
00539         var new_html = '';
00540         var module = modules[name];
00541         if (modules[name]) {
00542             var module = modules[name];
00543             var onclick = "show_module(\\""+module.label+"\\");toggle_search();";
00544         } else if (sequences[name]) {
00545             var module = sequences[name];
00546             var onclick = "show_sequence(\\""+module.label+"\\");toggle_search();";
00547         } else {
00548             return '';
00549         }
00550         var label = name.replace(pattern, "<b>$&</b>");
00551         new_html += "<div><span class='used clickable "+module.type.toLowerCase()+"' onclick='"+onclick+"'>"+label+"</span><span class='searchfrom'>("+extra+")</span></div>";
00552         return new_html;
00553     }
00554     var hitlist = [];
00555     var searchmap = {"module name":results.modules, "module class":results.modclass, "module file":results.modfile, "module pset key":results.keys, "module pset value":results.values, "sequence name":results.sequences, "sequence file":results.seqfiles};
00556     for (var i in searchmap) {
00557         for (var j in searchmap[i]) {
00558             if (hitlist.indexOf(searchmap[i][j]) == -1) {
00559                 new_html += _module_div(searchmap[i][j], i);
00560                 hitlist.push(searchmap[i][j]);
00561             }
00562         }
00563     }
00564     n_results = hitlist.length;
00565     last_search = query;
00566     $("#searchscroll").html(new_html);
00567     $("#searchinput").val("search");
00568     if ($("#searchhider").is(":hidden")) {$("#searchhider").show("fast");}
00569     toggle_search(true);
00570 }
00571 
00572 function toggle_search(force) {
00573     if ($("#searchresult").is(":hidden") || force==true) {
00574         $("#searchresult").show("slow");
00575         $("#searchhider a").html("Hide search results");
00576     } else {
00577         $("#searchresult").hide("slow");
00578         $("#searchhider a").html("Show results for <b>"+last_search+"</b> ("+n_results.toString()+")");
00579     }
00580 }
00581 
00582 function about() {
00583     $("#about_dialog").toggle("slow");
00584 }
00585 
00586 $(document).ready(function() {
00587     parse_data();
00588     build_mlist();
00589     $('#searchinput').focus(function() {if ($(this).val() == 'search') {$(this).val('');}});
00590     $('#searchsubmit').click(function(event) {event.preventDefault();do_search($('#searchinput').val());});
00591 });
00592 """ % dict(cvs=CVS, lxr=LXR)
00593 
00594 PAGE_TEMPLATE =\
00595 """
00596 <html>
00597 <head>
00598 <title>%(title)s</title>
00599 <style type="text/css">
00600 %(css)s
00601 </style>
00602 %(jquery)s
00603 <script type="text/javascript">
00604 var data = %(json)s;
00605 %(js)s
00606 </script>
00607 </head>
00608 <body>
00609 <div id="header">
00610     <div id="cmslogo"><img src="%(cmslogo)s" alt="CMS Logo" height=48 width=48></img></div>
00611     <div id="head_filedir">
00612         <div id="head_dirname">%(dirname)s</div>
00613         <div id="head_filename">%(filename)s</div>
00614     </div>
00615     <div id="searcharea">
00616         <div>
00617             <form id="searchform">
00618                 <input id="searchinput" type="text" value="search">
00619                 <input id="searchsubmit" type="submit" value="Search">
00620             </form>
00621         </div>
00622         <div id='searchhider'><a href='#' onclick='toggle_search();'></a></div>
00623         <div id='searchresult'>
00624             <div id='searchscroll'></div>
00625         </div>
00626     </div>
00627 </div>
00628 <div id="mlist"></div>
00629 <div id="mview">
00630     <div id="mview_header"></div>
00631     <div id="mview_subheader">
00632         <table id="mview_table"></table>
00633     </div>
00634     <div id="mview_pset"></div>
00635 </div>
00636 <div id="footer">
00637     <div id="footer_crumbs"></div>
00638     <div id="footer_about"><a href='#' onclick='about();'>About</a></div>    
00639 </div>
00640 <div id="about_dialog" onclick='about();'>
00641     <div><h2>CMSSW configuration-to-html converter</h2></div>
00642     <div>Written by Gordon Ball (Imperial College)</div>
00643     <div>Uses CMSSW Config Editor and jQuery</div>
00644 </div>
00645 </body>
00646 </html>
00647 """
00648 
00649     
00650 
00651 
00652 class HTMLExport(FileExportPlugin):
00653     
00654     plugin_name = 'HTML Export'
00655     file_types = ('html', )
00656 
00657     def __init__(self):
00658         FileExportPlugin.__init__(self)
00659 
00660     def export(self, data, filename, filetype):
00661         with open(filename, 'w') as f:
00662             f.write(self.produce(data))
00663 
00664     def produce(self, data):
00665         return PAGE_TEMPLATE % dict(title=data._filename, jquery=get_jquery(),
00666                                     css=CSS_TEMPLATE, js=JS_TEMPLATE, dirname='.',
00667                                     filename=data._filename, json=self.data_to_json(data),
00668                                     cmslogo=CMSLOGO)
00669         
00670             
00671     def data_to_json(self, data):
00672         cmssw = None
00673         if 'CMSSW_BASE' in os.environ:
00674             cmssw = os.environ['CMSSW_BASE'].split('/')[-1]
00675         elif 'CMSSW_RELEASE_BASE' in os.environ:
00676             cmssw = os.environ['CMSSW_RELEASE_BASE'].split('/')[-1]
00677         result = {'process': {'name': data.process().name_() if data.process() else '(no process)', 'src': data._filename, 'cmssw':cmssw}}
00678         toplevel = data.children(data.topLevelObjects()[0]) if data.process() else data.topLevelObjects()
00679         for tlo in toplevel:
00680             children = data.children(tlo)
00681             label = tlo._label
00682             if label in ('source', 'services'):
00683                 result[label] = [{'class':data.classname(child), 'pset':self.pset_to_json(child.parameters_()), 'type':data.type(child), 'label':data.classname(child)} for child in children]
00684             elif label in ('essources', 'esproducers', 'esprefers'):
00685                 result[label] = [self.module_to_json(data, child) for child in children]
00686             elif label in ('paths', 'endpaths'):
00687                 result[label] = [self.path_to_json(data, child) for child in children]
00688         return json.dumps(result, indent=4)
00689 
00690     def pset_to_json(self, pset):
00691         result = []
00692         for k, v in pset.items():
00693             typename = v.pythonTypeName().split('.')[-1]
00694             item = {'label': k, 'type': typename}
00695             if not v.isTracked():
00696                 item['untracked'] = True 
00697             if typename == 'PSet':
00698                 item['value'] = self.pset_to_json(v.parameters_())
00699             elif typename == 'VPSet':   
00700                 item['value'] = [self.pset_to_json(vv.parameters_()) for vv in v]
00701                 item['list'] = True
00702             elif typename == 'VInputTag':
00703                 item['value'] = [(vv.moduleLabel, vv.productInstanceLabel, vv.processName) for vv in v]
00704                 item['list'] = True
00705             elif typename == 'InputTag':
00706                 item['value'] = [v.moduleLabel, v.productInstanceLabel, v.processName]
00707             elif isinstance(v, mix._ValidatingListBase):
00708                 item['value'] = [str(vv) for vv in v]
00709                 item['list'] = True
00710             else:
00711                 item['value'] = v.pythonValue()
00712             result += [item]
00713         return result
00714 
00715     def module_to_json(self, data, module):
00716         return {
00717             'label':data.label(module),
00718             'class':data.classname(module),
00719             'file':data.pypath(module),
00720             'line':data.lineNumber(module),
00721             #'package':data.pypackage(module),
00722             'pset':self.pset_to_json(module.parameters_()),
00723             'type':data.type(module),
00724             'uses':data.uses(module),
00725             'usedby':data.usedBy(module),
00726             'memberof':data.foundIn(module)
00727         }
00728 
00729     def path_to_json(self, data, path):
00730         children = data.children(path)
00731         if data.isContainer(path):
00732             json_children = [self.path_to_json(data, child) for child in children]
00733             return {'type':data.type(path), 'label':data.label(path), 
00734                     'path':json_children, 'memberof': data.foundIn(path),
00735                     'file': data.pypath(path), 'line': data.lineNumber(path)}
00736                     #'package': data.pypackage(path)}
00737         else:
00738             return self.module_to_json(data, path)
00739             
00740             
00741                             
00742 
00743 class HTMLExportStatic(FileExportPlugin):
00744   options_types={}
00745   plugin_name='HTML Export (Static)'
00746   file_types=('html',)
00747   def __init__(self):
00748     FileExportPlugin.__init__(self)
00749   
00750   def produce(self,data):
00751     def elem(elemtype,innerHTML='',html_class='',**kwargs):
00752       if html_class:
00753         kwargs['class']=html_class
00754       return "<%s %s>%s</%s>\n" % (elemtype,' '.join(['%s="%s"'%(k,v) for k,v in kwargs.items()]),innerHTML,elemtype)
00755     def div(innerHTML='',html_class='',**kwargs):
00756       return elem('div',innerHTML,html_class,**kwargs)
00757     
00758     def htmlPSet(pset):
00759       def linkInputTag(tag):
00760         inputtag=''
00761         if isinstance(tag,typ.InputTag):
00762           inputtag = tag.pythonValue()
00763         else:
00764           inputtag = tag
00765         if len(str(tag))==0:
00766           inputtag = '""'
00767         return inputtag
00768 
00769       pset_items_html=''
00770       for k,v in pset.items():
00771         if isinstance(v,mix._ParameterTypeBase):
00772           if isinstance(v,mix._SimpleParameterTypeBase):
00773             item_class='other'
00774             if isinstance(v,typ.bool):
00775               item_class='bool'
00776             if isinstance(v,typ.double):
00777               item_class='double'
00778             if isinstance(v,typ.string):
00779               item_class='string'
00780             if isinstance(v,(typ.int32, typ.uint32, typ.int64, typ.uint64)):
00781               item_class='int'
00782             pset_items_html+=elem('tr',
00783               elem('td',k,'param-name')
00784              +elem('td',v.pythonTypeName(),'param-class')
00785              +elem('td',v.pythonValue(),'param-value-%s'%item_class),
00786              'pset-item'
00787             )
00788           if isinstance(v,typ.InputTag):
00789             pset_items_html+=elem('tr',
00790               elem('td',k,'param-name')
00791              +elem('td',v.pythonTypeName(),'param-class')
00792              +elem('td',linkInputTag(v),'param-value-inputtag'),
00793              'pset-item'
00794             )
00795           if isinstance(v,typ.PSet):
00796             pset_html = ''
00797             if len(v.parameters_())==0:
00798               pset_items_html+=elem('tr',
00799                 elem('td',k,'param-name')
00800                +elem('td',v.pythonTypeName(),'param-class')
00801                +elem('td','(empty)','label'),
00802                'pset-item'
00803               )
00804             else:
00805               pset_items_html+=elem('tr',
00806                 elem('td',k,'param-name')
00807                +elem('td',v.pythonTypeName(),'param-class')
00808                +elem('td',htmlPSet(v.parameters_())),
00809                'pset-item'
00810               )
00811           if isinstance(v,mix._ValidatingListBase):
00812             list_html = ''
00813             if len(v)==0:
00814               list_html = elem('li','(empty)','label')
00815             else:
00816               if isinstance(v,typ.VInputTag):
00817                 for vv in v:
00818                   list_html += elem('li',linkInputTag(vv),'param-value-inputtag pset-list-item')
00819               elif isinstance(v,typ.VPSet):
00820                 for vv in v:
00821                   list_html += elem('li',htmlPSet(vv.parameters_()),'pset-list-item')
00822               else:
00823                 item_class='other'
00824                 if isinstance(v,typ.vbool):
00825                   item_class='bool'
00826                 if isinstance(v,typ.vdouble):
00827                   item_class='double'
00828                 if isinstance(v,typ.vstring):
00829                   item_class='string'
00830                 if isinstance(v,(typ.vint32,typ.vuint32,typ.vint64,typ.vuint64)):
00831                   item_class='int'
00832                 for vv in v:
00833                   if len(str(vv))==0:
00834                     vv = "''"
00835                   list_html += elem('li',vv,'pset-list-item param-value-%s'%item_class)
00836             pset_items_html+=elem('tr',
00837               elem('td',k,'param-name')
00838              +elem('td','%s[%s]'%(v.pythonTypeName(),len(v)),'param-class')
00839              +elem('td',elem('ol',list_html,'pset-list')),
00840              'pset-item'
00841             )
00842               
00843             
00844       return elem('table',pset_items_html,'pset')
00845       
00846     def htmlModule(mod):
00847       mod_label_html = div(elem('a',data.label(mod),'title',name=data.label(mod)),'module_label '+data.type(mod),onClick='return toggleModuleVisible(\'%s\')'%('mod_%s'%(data.label(mod))))
00848       
00849       mod_table = elem('table',
00850         elem('tr',elem('td','Type','label')+elem('td',data.type(mod)))
00851        +elem('tr',elem('td','Class','label')+elem('td',data.classname(mod))),
00852         'module_table')
00853         
00854       mod_pset = htmlPSet(mod.parameters_())
00855       
00856       mod_content_html = div(mod_table+mod_pset,'module_area',id='mod_%s'%data.label(mod))
00857       return div(mod_label_html+mod_content_html,'module',id='module_'+data.label(mod))
00858       
00859     def htmlPathRecursive(p):
00860       children = data.children(p)
00861       if children:
00862         seq_name='Sequence'
00863         if isinstance(p,sqt.Path):
00864           seq_name='Path'
00865         if isinstance(p,sqt.EndPath):
00866           seq_name='EndPath'
00867         seq_label_html = div(seq_name+' '+elem('span',data.label(p),'title')+' '+elem('span','[%s children hidden]'%len(children),'hidden',id='seq_hidden_%s'%data.label(p)),'sequence_label',onClick='return toggleSequenceVisible(\'%s\')'%data.label(p),id='seq_label_%s'%data.label(p))
00868         seq_inner_content_html = ''.join([htmlPathRecursive(c) for c in children])
00869         seq_content_html = div(seq_inner_content_html,'sequence_area',id='seq_%s'%data.label(p))
00870         return div(seq_label_html+seq_content_html,'sequence')
00871       else:
00872         return htmlModule(p)
00873         
00874     toplevel={}
00875     
00876     
00877     
00878     filter_html = elem('span','Filter  '+
00879                         elem('input',type='text',width=50,onkeyup="return doFilter();",id='input-filter'),
00880                         'right label')
00881     
00882     header_html = div('Config File Visualisation'+filter_html,'header')
00883     
00884     if data.process():
00885       for tlo in data.children(data.topLevelObjects()[0]):
00886         children = data.children(tlo)
00887         if children:
00888           toplevel[tlo._label]=children    
00889       path_html=''
00890       if 'paths' in toplevel:
00891         for path in toplevel['paths']:
00892           path_html += div(htmlPathRecursive(path),'path')
00893     
00894       file_html = div(elem('span','Process:')
00895                    +elem('span',data.process().name_(),'title')
00896                    +elem('span',data._filename,'right'),
00897                 'file')
00898       head_html = elem('head',elem('title',data.process().name_()))
00899     else:
00900       toplevel['sequences']=[]
00901       toplevel['paths']=[]
00902       toplevel['modules']=[]
00903       for tlo in data.topLevelObjects():
00904         if data.type(tlo)=='Sequence':
00905           toplevel['sequences']+=[tlo]
00906         if data.type(tlo)=='Path':
00907           toplevel['paths']+=[tlo]
00908         if data.type(tlo) in ('EDAnalyzer','EDFilter','EDProducer','OutputModule'):
00909           toplevel['modules']+=[tlo]
00910       
00911       path_html = ''
00912       sequence_html = ''
00913       module_html = ''
00914       for path in toplevel['paths']:
00915         path_html += div(htmlPathRecursive(path),'path')
00916       for sequence in toplevel['sequences']:
00917         sequence_html += htmlPathRecursive(sequence)
00918       for module in toplevel['modules']:
00919         module_html += htmlModule(module)
00920       file_html = div(elem('span',data._filename,'right'),'file')
00921       path_html += sequence_html
00922       path_html += module_html
00923       head_html = elem('head',elem('title',data._filename))
00924     footer_html = div('gordon.ball','footer')
00925     
00926     
00927     
00928     style_html = elem('style',
00929     """
00930     .title{font-weight:bold}
00931     .label{color:grey}
00932     .header{position:fixed;top:0px;left:0px;width:100%;background:#33cc00;font-weight:bold;font-size:120%}
00933     .footer{position:fixed;bottom:0px;left:0px;width:100%;background:#33cc00;text-align:right}
00934     .canvas{padding:40px 10px 40px 10px}
00935     .file{position:relative;background:#bbb;width:100%;padding-left:5px}
00936     .right{position:absolute;right:5px}
00937     .sequence{border:1px solid #aaa}
00938     .sequence:hover{border 1px solid #00ffff}
00939     .sequence_label{background:lightskyblue;padding-left:5px}
00940     .sequence_label:hover{background:#fff}
00941     .sequence_label_hidden{background:grey;padding-left:5px}
00942     .sequence_area{padding:5px 0px 5px 5px}
00943     .edproducer{border:1px solid red;background-image:url('edproducer.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00944     .edfilter{border:1px solid green;background-image:url('edfilter.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00945     .edanalyzer{border:1px solid blue;background-image:url('edanalyzer.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00946     .outputmodule{border:1px solid green;background-image:url('outputmodule.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00947     .module{}
00948     .module_label:hover{background:#ccc;position:relative}
00949     .module_area{display:none;padding:5px 0px 15px 15px;background:beige}
00950     .pset{border-spacing:10px 1px;border:1px solid black}
00951     .pset-item{}
00952     .pset-list{list-style-type:none;margin:0px;padding:2px 2px 2px 2px;border:1px solid grey}
00953     .pset-list-item{border-top:1px solid lightgrey;border-bottom:1px solid lightgrey}
00954     .param-name{font-weight:bold}
00955     .param-class{color:grey}
00956     .param-value-int{font-family:courier;color:blue}
00957     .param-value-double{font-family:courier;color:purple}
00958     .param-value-string{font-family:courier;color:brown}
00959     .param-value-bool{font-family:courier;color:#f0f}
00960     .param-value-inputtag{font-family:courier;color:red}
00961     .param-value-other{font-family:courier}
00962     .path{}
00963     .hidden{display:none}
00964     """,
00965     type='text/css')
00966     
00967     script_html = elem('script',
00968     """
00969     function toggleModuleVisible(id) {
00970       var elem = document.getElementById(id);
00971       if (elem.style.display=='block') {
00972         elem.style.display='none';
00973       } else {
00974         elem.style.display='block';      
00975       }
00976     }
00977     
00978     function toggleSequenceVisible(id) {
00979       var area_elem = document.getElementById('seq_'+id);
00980       var hidden_elem = document.getElementById('seq_hidden_'+id);
00981       var label_elem = document.getElementById('seq_label_'+id);
00982       if (area_elem.style.display=='none') {
00983         area_elem.style.display='block';      
00984         hidden_elem.style.display='none';
00985         label_elem.className = 'sequence_label';
00986       } else {
00987         area_elem.style.display='none';
00988         hidden_elem.style.display='block';
00989         label_elem.className = 'sequence_label_hidden';
00990       }
00991     }
00992     
00993     function doFilter() {
00994       var text = document.getElementById('input-filter').value;
00995       var regex = new RegExp(text);
00996       for (var i=0;i<document.all.length;i++) {
00997         if (document.all(i).id.substr(0,7)=="module_") {
00998           var elem = document.all(i);
00999           var elem_name = elem.id.substr(7);
01000           if (regex.test(elem_name)) {
01001             elem.style.display='block';
01002           } else {
01003             elem.style.display='none';
01004           }
01005         }
01006       }
01007     }
01008     """,
01009     type='text/javascript')
01010     
01011     body_html = elem('body',script_html+header_html+footer_html+div(file_html+path_html,'canvas'))
01012     
01013     return elem('html',head_html+style_html+body_html)
01014     
01015   def export(self,data,filename,filetype):
01016     #if not data.process():
01017     #  raise "HTMLExport requires a cms.Process object"
01018     
01019     html = self.produce(data)
01020     
01021     if filetype=='html':
01022       htmlfile = open(filename,'w')
01023       htmlfile.write(html)
01024       htmlfile.close()