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 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
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
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
01017
01018
01019 html = self.produce(data)
01020
01021 if filetype=='html':
01022 htmlfile = open(filename,'w')
01023 htmlfile.write(html)
01024 htmlfile.close()