CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/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 = "http://code.jquery.com/jquery-1.6.2.min.js"
00035 LXR = "http://cmslxr.fnal.gov/lxr/ident?"
00036 CVS = "http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/"
00037 CMSLOGO = "http://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                 v_it = []
00704                 for vv in v:
00705                    if type(vv) == cms.InputTag:
00706                      v_it.append(vv)
00707                    elif type(vv) == str:
00708                      v_it.append(cms.InputTag(vv))
00709                    else:
00710                       raise "Unsupported type in VInputTag", type(vv)
00711                 item['value'] = [(vv.moduleLabel, vv.productInstanceLabel, vv.processName) for vv in v_it]
00712                 item['list'] = True
00713             elif typename == 'InputTag':
00714                 item['value'] = [v.moduleLabel, v.productInstanceLabel, v.processName]
00715             elif isinstance(v, mix._ValidatingListBase):
00716                 item['value'] = [str(vv) for vv in v]
00717                 item['list'] = True
00718             else:
00719                 item['value'] = v.pythonValue()
00720             result += [item]
00721         return result
00722 
00723     def module_to_json(self, data, module):
00724         return {
00725             'label':data.label(module),
00726             'class':data.classname(module),
00727             'file':data.pypath(module),
00728             'line':data.lineNumber(module),
00729             #'package':data.pypackage(module),
00730             'pset':self.pset_to_json(module.parameters_()),
00731             'type':data.type(module),
00732             'uses':data.uses(module),
00733             'usedby':data.usedBy(module),
00734             'memberof':data.foundIn(module)
00735         }
00736 
00737     def path_to_json(self, data, path):
00738         children = data.children(path)
00739         if data.isContainer(path):
00740             json_children = [self.path_to_json(data, child) for child in children]
00741             return {'type':data.type(path), 'label':data.label(path), 
00742                     'path':json_children, 'memberof': data.foundIn(path),
00743                     'file': data.pypath(path), 'line': data.lineNumber(path)}
00744                     #'package': data.pypackage(path)}
00745         else:
00746             return self.module_to_json(data, path)
00747             
00748             
00749                             
00750 
00751 class HTMLExportStatic(FileExportPlugin):
00752   options_types={}
00753   plugin_name='HTML Export (Static)'
00754   file_types=('html',)
00755   def __init__(self):
00756     FileExportPlugin.__init__(self)
00757   
00758   def produce(self,data):
00759     def elem(elemtype,innerHTML='',html_class='',**kwargs):
00760       if html_class:
00761         kwargs['class']=html_class
00762       return "<%s %s>%s</%s>\n" % (elemtype,' '.join(['%s="%s"'%(k,v) for k,v in kwargs.items()]),innerHTML,elemtype)
00763     def div(innerHTML='',html_class='',**kwargs):
00764       return elem('div',innerHTML,html_class,**kwargs)
00765     
00766     def htmlPSet(pset):
00767       def linkInputTag(tag):
00768         inputtag=''
00769         if isinstance(tag,typ.InputTag):
00770           inputtag = tag.pythonValue()
00771         else:
00772           inputtag = tag
00773         if len(str(tag))==0:
00774           inputtag = '""'
00775         return inputtag
00776 
00777       pset_items_html=''
00778       for k,v in pset.items():
00779         if isinstance(v,mix._ParameterTypeBase):
00780           if isinstance(v,mix._SimpleParameterTypeBase):
00781             item_class='other'
00782             if isinstance(v,typ.bool):
00783               item_class='bool'
00784             if isinstance(v,typ.double):
00785               item_class='double'
00786             if isinstance(v,typ.string):
00787               item_class='string'
00788             if isinstance(v,(typ.int32, typ.uint32, typ.int64, typ.uint64)):
00789               item_class='int'
00790             pset_items_html+=elem('tr',
00791               elem('td',k,'param-name')
00792              +elem('td',v.pythonTypeName(),'param-class')
00793              +elem('td',v.pythonValue(),'param-value-%s'%item_class),
00794              'pset-item'
00795             )
00796           if isinstance(v,typ.InputTag):
00797             pset_items_html+=elem('tr',
00798               elem('td',k,'param-name')
00799              +elem('td',v.pythonTypeName(),'param-class')
00800              +elem('td',linkInputTag(v),'param-value-inputtag'),
00801              'pset-item'
00802             )
00803           if isinstance(v,typ.PSet):
00804             pset_html = ''
00805             if len(v.parameters_())==0:
00806               pset_items_html+=elem('tr',
00807                 elem('td',k,'param-name')
00808                +elem('td',v.pythonTypeName(),'param-class')
00809                +elem('td','(empty)','label'),
00810                'pset-item'
00811               )
00812             else:
00813               pset_items_html+=elem('tr',
00814                 elem('td',k,'param-name')
00815                +elem('td',v.pythonTypeName(),'param-class')
00816                +elem('td',htmlPSet(v.parameters_())),
00817                'pset-item'
00818               )
00819           if isinstance(v,mix._ValidatingListBase):
00820             list_html = ''
00821             if len(v)==0:
00822               list_html = elem('li','(empty)','label')
00823             else:
00824               if isinstance(v,typ.VInputTag):
00825                 for vv in v:
00826                   list_html += elem('li',linkInputTag(vv),'param-value-inputtag pset-list-item')
00827               elif isinstance(v,typ.VPSet):
00828                 for vv in v:
00829                   list_html += elem('li',htmlPSet(vv.parameters_()),'pset-list-item')
00830               else:
00831                 item_class='other'
00832                 if isinstance(v,typ.vbool):
00833                   item_class='bool'
00834                 if isinstance(v,typ.vdouble):
00835                   item_class='double'
00836                 if isinstance(v,typ.vstring):
00837                   item_class='string'
00838                 if isinstance(v,(typ.vint32,typ.vuint32,typ.vint64,typ.vuint64)):
00839                   item_class='int'
00840                 for vv in v:
00841                   if len(str(vv))==0:
00842                     vv = "''"
00843                   list_html += elem('li',vv,'pset-list-item param-value-%s'%item_class)
00844             pset_items_html+=elem('tr',
00845               elem('td',k,'param-name')
00846              +elem('td','%s[%s]'%(v.pythonTypeName(),len(v)),'param-class')
00847              +elem('td',elem('ol',list_html,'pset-list')),
00848              'pset-item'
00849             )
00850               
00851             
00852       return elem('table',pset_items_html,'pset')
00853       
00854     def htmlModule(mod):
00855       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))))
00856       
00857       mod_table = elem('table',
00858         elem('tr',elem('td','Type','label')+elem('td',data.type(mod)))
00859        +elem('tr',elem('td','Class','label')+elem('td',data.classname(mod))),
00860         'module_table')
00861         
00862       mod_pset = htmlPSet(mod.parameters_())
00863       
00864       mod_content_html = div(mod_table+mod_pset,'module_area',id='mod_%s'%data.label(mod))
00865       return div(mod_label_html+mod_content_html,'module',id='module_'+data.label(mod))
00866       
00867     def htmlPathRecursive(p):
00868       children = data.children(p)
00869       if children:
00870         seq_name='Sequence'
00871         if isinstance(p,sqt.Path):
00872           seq_name='Path'
00873         if isinstance(p,sqt.EndPath):
00874           seq_name='EndPath'
00875         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))
00876         seq_inner_content_html = ''.join([htmlPathRecursive(c) for c in children])
00877         seq_content_html = div(seq_inner_content_html,'sequence_area',id='seq_%s'%data.label(p))
00878         return div(seq_label_html+seq_content_html,'sequence')
00879       else:
00880         return htmlModule(p)
00881         
00882     toplevel={}
00883     
00884     
00885     
00886     filter_html = elem('span','Filter  '+
00887                         elem('input',type='text',width=50,onkeyup="return doFilter();",id='input-filter'),
00888                         'right label')
00889     
00890     header_html = div('Config File Visualisation'+filter_html,'header')
00891     
00892     if data.process():
00893       for tlo in data.children(data.topLevelObjects()[0]):
00894         children = data.children(tlo)
00895         if children:
00896           toplevel[tlo._label]=children    
00897       path_html=''
00898       if 'paths' in toplevel:
00899         for path in toplevel['paths']:
00900           path_html += div(htmlPathRecursive(path),'path')
00901     
00902       file_html = div(elem('span','Process:')
00903                    +elem('span',data.process().name_(),'title')
00904                    +elem('span',data._filename,'right'),
00905                 'file')
00906       head_html = elem('head',elem('title',data.process().name_()))
00907     else:
00908       toplevel['sequences']=[]
00909       toplevel['paths']=[]
00910       toplevel['modules']=[]
00911       for tlo in data.topLevelObjects():
00912         if data.type(tlo)=='Sequence':
00913           toplevel['sequences']+=[tlo]
00914         if data.type(tlo)=='Path':
00915           toplevel['paths']+=[tlo]
00916         if data.type(tlo) in ('EDAnalyzer','EDFilter','EDProducer','OutputModule'):
00917           toplevel['modules']+=[tlo]
00918       
00919       path_html = ''
00920       sequence_html = ''
00921       module_html = ''
00922       for path in toplevel['paths']:
00923         path_html += div(htmlPathRecursive(path),'path')
00924       for sequence in toplevel['sequences']:
00925         sequence_html += htmlPathRecursive(sequence)
00926       for module in toplevel['modules']:
00927         module_html += htmlModule(module)
00928       file_html = div(elem('span',data._filename,'right'),'file')
00929       path_html += sequence_html
00930       path_html += module_html
00931       head_html = elem('head',elem('title',data._filename))
00932     footer_html = div('gordon.ball','footer')
00933     
00934     
00935     
00936     style_html = elem('style',
00937     """
00938     .title{font-weight:bold}
00939     .label{color:grey}
00940     .header{position:fixed;top:0px;left:0px;width:100%;background:#33cc00;font-weight:bold;font-size:120%}
00941     .footer{position:fixed;bottom:0px;left:0px;width:100%;background:#33cc00;text-align:right}
00942     .canvas{padding:40px 10px 40px 10px}
00943     .file{position:relative;background:#bbb;width:100%;padding-left:5px}
00944     .right{position:absolute;right:5px}
00945     .sequence{border:1px solid #aaa}
00946     .sequence:hover{border 1px solid #00ffff}
00947     .sequence_label{background:lightskyblue;padding-left:5px}
00948     .sequence_label:hover{background:#fff}
00949     .sequence_label_hidden{background:grey;padding-left:5px}
00950     .sequence_area{padding:5px 0px 5px 5px}
00951     .edproducer{border:1px solid red;background-image:url('edproducer.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00952     .edfilter{border:1px solid green;background-image:url('edfilter.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00953     .edanalyzer{border:1px solid blue;background-image:url('edanalyzer.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00954     .outputmodule{border:1px solid green;background-image:url('outputmodule.png');background-position:center left;background-repeat:no-repeat;padding:0px 0px 0px 40px}
00955     .module{}
00956     .module_label:hover{background:#ccc;position:relative}
00957     .module_area{display:none;padding:5px 0px 15px 15px;background:beige}
00958     .pset{border-spacing:10px 1px;border:1px solid black}
00959     .pset-item{}
00960     .pset-list{list-style-type:none;margin:0px;padding:2px 2px 2px 2px;border:1px solid grey}
00961     .pset-list-item{border-top:1px solid lightgrey;border-bottom:1px solid lightgrey}
00962     .param-name{font-weight:bold}
00963     .param-class{color:grey}
00964     .param-value-int{font-family:courier;color:blue}
00965     .param-value-double{font-family:courier;color:purple}
00966     .param-value-string{font-family:courier;color:brown}
00967     .param-value-bool{font-family:courier;color:#f0f}
00968     .param-value-inputtag{font-family:courier;color:red}
00969     .param-value-other{font-family:courier}
00970     .path{}
00971     .hidden{display:none}
00972     """,
00973     type='text/css')
00974     
00975     script_html = elem('script',
00976     """
00977     function toggleModuleVisible(id) {
00978       var elem = document.getElementById(id);
00979       if (elem.style.display=='block') {
00980         elem.style.display='none';
00981       } else {
00982         elem.style.display='block';      
00983       }
00984     }
00985     
00986     function toggleSequenceVisible(id) {
00987       var area_elem = document.getElementById('seq_'+id);
00988       var hidden_elem = document.getElementById('seq_hidden_'+id);
00989       var label_elem = document.getElementById('seq_label_'+id);
00990       if (area_elem.style.display=='none') {
00991         area_elem.style.display='block';      
00992         hidden_elem.style.display='none';
00993         label_elem.className = 'sequence_label';
00994       } else {
00995         area_elem.style.display='none';
00996         hidden_elem.style.display='block';
00997         label_elem.className = 'sequence_label_hidden';
00998       }
00999     }
01000     
01001     function doFilter() {
01002       var text = document.getElementById('input-filter').value;
01003       var regex = new RegExp(text);
01004       for (var i=0;i<document.all.length;i++) {
01005         if (document.all(i).id.substr(0,7)=="module_") {
01006           var elem = document.all(i);
01007           var elem_name = elem.id.substr(7);
01008           if (regex.test(elem_name)) {
01009             elem.style.display='block';
01010           } else {
01011             elem.style.display='none';
01012           }
01013         }
01014       }
01015     }
01016     """,
01017     type='text/javascript')
01018     
01019     body_html = elem('body',script_html+header_html+footer_html+div(file_html+path_html,'canvas'))
01020     
01021     return elem('html',head_html+style_html+body_html)
01022     
01023   def export(self,data,filename,filetype):
01024     #if not data.process():
01025     #  raise "HTMLExport requires a cms.Process object"
01026     
01027     html = self.produce(data)
01028     
01029     if filetype=='html':
01030       htmlfile = open(filename,'w')
01031       htmlfile.write(html)
01032       htmlfile.close()