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:
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 += "< <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 += "< <span class='"+css+"' onclick='show_sequence(\\"" + c[1] + "\\");'>" + c[1] + "</span>";
00419 } else if (c[0] == "search") {
00420 new_html += "< <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
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
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
01025
01026
01027 html = self.produce(data)
01028
01029 if filetype=='html':
01030 htmlfile = open(filename,'w')
01031 htmlfile.write(html)
01032 htmlfile.close()