blob: cd2af1d5c9fddbd73f9d31bc58520c812504276d [file] [log] [blame]
Valentin Pavlov Valcheva7732f52011-09-12 14:45:53 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18var repoTable = false;
19var repoTableTemplate = false;
20var addRepoUri = false;
21var resTable = false;
22var searchField = false;
23var ifStatusOK = false;
24
25//This prototype is provided by the Mozilla foundation and
26//is distributed under the MIT license.
27//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
28if (!Array.prototype.map)
29{
30 Array.prototype.map = function(fun /*, thisp*/)
31 {
32 var len = this.length;
33 if (typeof fun != "function")
34 throw new TypeError();
35
36 var res = new Array(len);
37 var thisp = arguments[1];
38 for (var i = 0; i < len; i++)
39 {
40 if (i in this)
41 res[i] = fun.call(thisp, this[i], i, this);
42 }
43
44 return res;
45 };
46}
47
48var uid = 0;
49function guid() {
50 uid = uid + 1;
51 return (0x10000 + uid).toString(16).substring(1) + (((1+Math.random())*0x10000)|0).toString(16).substring(1);
52}
53
54/* displays a date in the user's local timezone */
55function localTm(time) {
56 return (time ? new Date(time) : new Date()).toLocaleString();
57}
58
59function doRepoAction(action, url) {
60 if ( !url ) {
61 Xalert('Invalid URI: ' + url, 'Error');
62 } else {
63 $.post(pluginRoot, {
64 'action' : action,
65 'url' : url
66 }, renderData, 'json');
67 }
68}
69
70function showDetails( symbolicname, version ) {
71 window.location.href = pluginRoot + '/' + symbolicname + '/' + version;
72}
73
74function showVersions( symbolicname ) {
75 var _id = symbolicname.replace(/\./g, '_');
76 $("#block" + _id).append("<div id='pluginInlineVersions" + _id + "' style='margin-left: 4em'><ul/></div>");
77 $("#img" + _id).each(function() {
78 $(this).
79 removeClass('ui-icon-triangle-1-e').//right
80 addClass('ui-icon-triangle-1-s');//down
81 });
82 $("#entry" + _id).each(function() {
83 $(this).
84 unbind('click').
85 click(function() {hideVersions(symbolicname)}).
86 attr("title", "Hide Versions");
87 });
88 var versions = [];
89 for (var i in obrData.resources ) {
90 if (obrData.resources[i].symbolicname == symbolicname) {
91 versions.push(obrData.resources[i].version);
92 }
93 }
94 versions.sort();
95 for (var i in versions) {
96 var txt = "<li><a href='javascript: showDetails(\"" + symbolicname + "\",\"" + versions[i] + "\")'>" + versions[i] + "</a></li>";
97 $("#pluginInlineVersions" + _id + " > ul").append(txt);
98 }
99}
100
101function hideVersions( symbolicname ) {
102 var _id = symbolicname.replace(/\./g, '_');
103 $("#img" + _id).each(function() {
104 $(this).
105 removeClass('ui-icon-triangle-1-s').//down
106 addClass('ui-icon-triangle-1-e');//right
107 });
108 $("#pluginInlineVersions" + _id).each(function() {
109 $(this).
110 remove();
111 });
112 $("#entry" + _id).each(function() {
113 $(this).
114 unbind('click').
115 click(function() {showVersions(symbolicname)}).
116 attr("title", "Show Versions");
117 });
118}
119
120function renderResource(res) {
121 // proceed with resource
122 var _id = res.symbolicname.replace(/\./g, '_');
123 var _tr = resTable.find('#row' + _id);
124
125 if (_tr.length == 0) { // not created yet, create it
126 var blockElement = createElement('span', '', {
127 id: 'block' + _id
128 });
129 var titleElement = createElement('span', '', {
130 id: 'entry' + _id,
131 title: "Show Versions"
132 });
133 var inputElement = createElement('span', 'ui-icon ui-icon-triangle-1-e', {
134 id: 'img' + _id,
135 style: {display: "inline-block"}
136 });
137 blockElement.appendChild(titleElement);
138 titleElement.appendChild(inputElement);
139 titleElement.appendChild(text(" "));
140 if (res.presentationname) {
141 titleElement.appendChild(text(res.presentationname));
142 titleElement.appendChild(text(" ("));
143 titleElement.appendChild(text(res.symbolicname));
144 titleElement.appendChild(text(")"));
145 } else {
146 titleElement.appendChild(text(res.symbolicname));
147 }
148 $(titleElement).click(function() {showVersions(res.symbolicname)});
149
150 _tr = tr( null, { 'id' : 'row' + _id } , [
151 td( null, null, [ blockElement ] ),
152 td( null, null, [ text(res.installed ? res.version : '') ] )
153 ]);
154 resTable.append( _tr );
155 }
156}
157
158function getCapabilitiesByName(res, name) {
159 var caps = [];
160 for (var v in res.capabilities) {
161 if (res.capabilities[v].name == name) {
162 caps.push(res.capabilities[v]);
163 }
164 }
165 return caps;
166}
167
168function getRequirementsByName(res, name) {
169 var caps = [];
170 for (var v in res.requirements) {
171 if (res.requirements[v].name == name) {
172 caps.push(res.requirements[v]);
173 }
174 }
175 return caps;
176}
177
178function createDetailedTable(enclosing, name, headers, rows, callback) {
179 if (rows && rows.length > 0) {
180 var uuid = guid();
181 var title = createElement('span', null, null, [
182 createElement('span', 'ui-icon ui-icon-triangle-1-e', { id: "img"+uuid, style: {display: "inline-block"} }),
183 text(" "),
184 text(name)
185 ]);
186 enclosing.append(tr(null, null, [
187 td(null, null, [ title ]),
188 td(null, null, [ createElement('table', 'nicetable ui-widget ui-helper-hidden', { id: "alt1"+uuid }, [
189 createElement('thead', null, null, [
190 tr(null, null, headers.map(function(x) {
191 return th('ui-widget-header', null, [text(x)]);
192 }))
193 ]),
194 createElement('tbody', null, null,
195 rows.map(function(x) {
196 var values = callback(x);
197 var tds = values.map(function(x) {
198 return td(null, null, [x]);
199 });
200 return tr(null, null, tds);
201 })
202 )
203 ]),
204 createElement('span', null, { id: "alt2"+uuid }, [
205 text(rows.length)
206 ])
207 ])
208 ]));
209 $(title).
210 unbind('click').
211 click(function(event) {
212 event.preventDefault();
213 $("#img"+uuid).toggleClass('ui-icon-triangle-1-s').//down
214 toggleClass('ui-icon-triangle-1-e');//right
215 $("#alt1"+uuid).toggle();
216 $("#alt2"+uuid).toggle();
217 });
218 }
219}
220
221function trim(stringToTrim) {
222 return stringToTrim.replace(/^\s+|\s+$/g,"");
223}
224
225function parseSimpleFilter(filter) {
226 filter = filter.substring(1, filter.length-1);
227 var start = 0;
228 var pos = 0;
229 var c = filter.charAt(pos);
230 while (c != '~' && c != '<' && c != '>' && c != '=' && c != '(' && c != ')') {
231 if (c == '<' && filterChars[pos+1] == '*') {
232 break;
233 }
234 if (c == '*' && filterChars[pos+1] == '>') {
235 break;
236 }
237 pos++;
238 c = filter.charAt(pos);
239 }
240 if (pos == start) {
241 throw ("Missing attr: " + filter.substring(pos));
242 }
243
244 var attr = trim(filter.substring(start, pos));
245 var oper = filter.substring(pos, pos+2);
246 var value;
247 if (oper == '*>' || oper == '~=' || oper == '>=' || oper == '<=' || oper == '<*') {
248 value = trim(filter.substring(pos+2));
249 if (value == '') {
250 throw ("Missing value: " + filter.substring(pos));
251 }
252
253 return { operator: oper, operands: [ attr, value ]};
254 } else {
255 if (c != '=') {
256 throw ("Invalid operator: " + filter.substring(pos));
257 }
258 oper = '=';
259 value = filter.substring(pos+1);
260 if (value == '*' ) {
261 return { operator: '=*', operands: [ attr ]};
262 }
263 return { operator: '=', operands: [ attr, value ]};
264 }
265}
266
267function parseFilter(filter) {
268 if (filter.charAt(0) != "(" || filter.charAt(filter.length-1) != ")") {
269 throw "Wrong parenthesis: " + filter;
270 }
271 if (filter.charAt(1) == "!") {
272 return { operator: filter.charAt(1), operands: [ parseFilter(filter.substring(2, filter.length-1)) ] };
273 }
274 if (filter.charAt(1) == "|" || filter.charAt(1) == "&") {
275 var inner = filter.substring(2, filter.length-1);
276 var flts = inner.match(/\([^\(\)]*(\([^\(\)]*(\([^\(\)]*(\([^\(\)]*\))*[^\(\)]*\))*[^\(\)]*\))*[^\(\)]*\)/g);
277 return { operator: filter.charAt(1), operands: flts.map(function(x) { return parseFilter(x); }) };
278 }
279 return parseSimpleFilter(filter);
280}
281
282function simplify(filter) {
283 if (filter.operator == '&' || filter.operator == '|') {
284 filter.operands = filter.operands.map(function(x) { return simplify(x); });
285 } else if (filter.operator == '!') {
286 if (filter.operands[0].operator == '<=') {
287 filter.operator = '>';
288 filter.operands = filter.operands[0].operands;
289 } else if (filter.operands[0].operator == '>=') {
290 filter.operator = '<';
291 filter.operands = filter.operands[0].operands;
292 }
293 }
294 return filter;
295}
296
297function addRow(tbody, key, value) {
298 if (value) {
299 tbody.append( tr(null, null, [
300 td(null, null, [ text(key) ]),
301 td(null, null, [ text(value) ])
302 ]));
303 }
304}
305
306function renderDetailedResource(res) {
307 var tbody = $('#detailsTableBody');
308
309 tbody.append( tr(null, null, [
310 th('ui-widget-header', null, [
311 text("Resource")
312 ]),
313 th('ui-widget-header', null, [
314 createElement('form', 'button-group', { method: "post"}, [
315 createElement('input', null, { type: "hidden", name: "bundle", value: res.id}),
316 createElement('input', 'ui-state-default ui-corner-all', { type: "submit", name: "deploy", value: "Deploy" }, [ text("dummy")]),
317 createElement('input', 'ui-state-default ui-corner-all', { type: "submit", name: "deploystart", value: "Deploy and Start" }, [ text("dummy")]),
318 text(" "),
319 createElement('input', 'ui-state-default ui-corner-all', { id: "optional", type: "checkbox", name: "optional" }),
320 text(" "),
321 createElement('label', 'ui-widget', { 'for': "optional" }, [ text("deploy optional dependencies") ])
322 ])
323 ])
324 ]));
325
326 addRow(tbody, "Name", res.presentationname);
327 addRow(tbody, "Description", res.description);
328 addRow(tbody, "Symbolic name", res.symbolicname);
329 addRow(tbody, "Version", res.version);
330 addRow(tbody, "URI", res.uri);
331 addRow(tbody, "Documentation", res.documentation);
332 addRow(tbody, "Javadoc", res.javadoc);
333 addRow(tbody, "Source", res.source);
334 addRow(tbody, "License", res.license);
335 addRow(tbody, "Copyright", res.copyright);
336 addRow(tbody, "Size", res.size);
337
338 // Exported packages
339 createDetailedTable(tbody, "Exported packages", ["Package", "Version"],
340 getCapabilitiesByName(res, "package").sort(function(a,b) {
341 var pa = a.properties['package'], pb = b.properties['package']; return pa == pb ? 0 : pa < pb ? -1 : +1;
342 }),
343 function(p) {
344 return [ text(p.properties['package']), text(p.properties['version']) ];
345 });
346 // Exported services
347 createDetailedTable(tbody, "Exported services", ["Service"], getCapabilitiesByName(res, "service"), function(p) {
348 return [ text(p.properties['service']) ];
349 });
350 // Imported packages
351 createDetailedTable(tbody, "Imported packages", ["Package", "Version", "Optional"], getRequirementsByName(res, "package"), function(p) {
352 var f = parseFilter(p.filter);
353 simplify(f);
354 var n, vmin = "[0.0.0", vmax = "infinity)";
355 if (f.operator == '&') {
356 for (var i in f.operands) {
357 var fi = f.operands[i];
358 if (fi.operands[0] == 'package' && fi.operator == '=') {
359 n = fi.operands[1];
360 }
361 if (fi.operands[0] == 'version') {
362 if (fi.operator == '>=') {
363 vmin = '[' + fi.operands[1];
364 }
365 if (fi.operator == '>') {
366 vmin = '(' + fi.operands[1];
367 }
368 if (fi.operator == '<=') {
369 vmax = fi.operands[1] + "]";
370 }
371 if (fi.operator == '<') {
372 vmax = fi.operands[1] + ")";
373 }
374 }
375 }
376 }
377 return [ text(n ? n : p.filter), text(vmin + ", " + vmax), text(p.optional) ];
378 });
379 // Imported bundles
380 createDetailedTable(tbody, "Imported bundles", ["Bundle", "Version", "Optional"], getRequirementsByName(res, "bundle"), function(p) {
381 return [ text(p.filter), text(""), text(p.optional) ];
382 });
383 // Imported services
384 createDetailedTable(tbody, "Imported services", ["Service", "Optional"], getRequirementsByName(res, "service"), function(p) {
385 return [ text(p.filter), text(p.optional) ];
386 });
387 // Required dependencies
388 createDetailedTable(tbody, "Dependencies", ["Name", "Version"], res.required, function(p) {
389 var a = createElement('a', null, { href: (pluginRoot + '/' + p.symbolicname + '/' + p.version) });
390 a.appendChild(text(p.presentationname ? p.presentationname : p.symbolicname));
391 return [ a, text(p.version) ];
392 });
393 // Optional dependencies
394 createDetailedTable(tbody, "Optional Dependencies", ["Name", "Version"], res.optional, function(p) {
395 var a = createElement('a', null, { href: (pluginRoot + '/' + p.symbolicname + '/' + p.version) });
396 a.appendChild(text(p.presentationname ? p.presentationname : p.symbolicname));
397 return [ a, text(p.version) ];
398 });
399 // Unsatisfied requirements
400 createDetailedTable(tbody, "Unsatisfied Requirements", ["Requirement", "Optional"], res.unsatisfied, function(p) {
401 return [ text(p.filter), text(p.optional) ];
402 });
403
404// $('#detailsTableBody').append( tr(null, null, [ th('ui-widget-header', { colspan: 2 }, [ text("Resource") ]) ]) );
405// $('#detailsTableBody').append( tbody );
406}
407
408function renderRepository(repo) {
409 var _tr = repoTableTemplate.clone();
410 _tr.find('td:eq(0)').text( repo.name );
411 _tr.find('td:eq(1)').text( repo.url );
412 _tr.find('td:eq(2)').text( localTm(repo.lastModified) );
413 _tr.find('li:eq(0)').click(function() {
414 doRepoAction('refresh', repo.url);
415 });
416 _tr.find('li:eq(1)').click(function() {
417 doRepoAction('delete', repo.url);
418 });
419 repoTable.append(_tr);
420}
421
Valentin Pavlov Valchevffe148c2012-05-29 10:59:38 +0000422function renderData(data) {
Valentin Pavlov Valcheva7732f52011-09-12 14:45:53 +0000423 repoTable.empty();
424 resTable.empty();
Valentin Pavlov Valchevffe148c2012-05-29 10:59:38 +0000425 $.extend ( obrData, data );
Valentin Pavlov Valcheva7732f52011-09-12 14:45:53 +0000426 if ( obrData.status ) {
427 $('.statline').html(i18n.status_ok);
428 ifStatusOK.removeClass('ui-helper-hidden');
429 for (var i in obrData.repositories ) {
430 renderRepository( obrData.repositories[i] );
431 }
432 if (obrData.details) {
433 $('#resTable').addClass('ui-helper-hidden');
434 $('#detailsTable').removeClass('ui-helper-hidden');
435 for (var i in obrData.resources ) {
436 renderDetailedResource( obrData.resources[i] );
437 }
438 } else if (obrData.resources) {
439 for (var i in obrData.resources ) {
440 renderResource( obrData.resources[i] );
441 }
442 } else if (obrData.error) {
443 _tr = tr( "ui-state-error", null , [
444 td( "ui-state-error-text", { 'colspan': '2' },
445 [ text(i18n.error + ": " + obrData.error) ] )
446 ]);
447 resTable.append( _tr );
448 }
449 } else {
450 $('.statline').html(i18n.status_no);
451 ifStatusOK.addClass('ui-helper-hidden');
452 }
453}
454
455
456$.extend({
457 getUrlVars: function(){
458 var vars = [], hash;
459 var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
460 for(var i = 0; i < hashes.length; i++)
461 {
462 var j = hashes[i].indexOf('=');
463 if (j > 0) {
464 var k = hashes[i].slice(0, j);
465 var v = hashes[i].slice(j + 1);
466 vars.push(k);
467 vars[k] = v;
468 } else {
469 vars.push(hashes[i]);
470 vars[hashes[i]] = true;
471 }
472 }
473 return vars;
474 },
475 getUrlVar: function(name){
476 return $.getUrlVars()[name];
477 }
478});
479
480$(document).ready( function() {
481 repoTable = $('#repoTable tbody');
482 repoTableTemplate = repoTable.find('tr').clone();
483 addRepoUri = $('#addRepoUri');
484 resTable = $('#resTable tbody').empty();
485 searchField = $('#searchField');
486 ifStatusOK = $('#ifStatusOK');
487
488 var query = $.getUrlVar('query');
489 if (query) {
490 searchField.val(decodeURIComponent(query));
491 }
492
493 $('#addRepoBtn').click(function(event) {
494 event.preventDefault();
495 doRepoAction('add', addRepoUri.val());
496 });
497 $('#searchBtn').click(function(event) {
498 event.preventDefault();
499 window.location.href = pluginRoot + '?query=' + encodeURIComponent(searchField.val());
500 });
501 searchField.keypress(function(event) {
502 if (event.keyCode == 13) {
503 event.preventDefault();
504 $('#searchBtn').click();
505 }
506 });
507
508 renderData();
509 initStaticWidgets();
510});
511