opencloud shell prototype; wip
[plstackapi.git] / planetstack / core / dashboard / shell / shell_utils.js
1 DB = function() {
2 }
3
4 print = function(msg) {
5   //console.log(msg);
6 }
7
8
9 friendlyEqual = function( a , b ){
10     if ( a == b )
11         return true;
12
13     if ( tojson( a ) == tojson( b ) )
14         return true;
15
16     return false;
17 }
18
19
20 doassert = function( msg ){
21     print( "assert: " + msg );
22     throw msg;
23 }
24
25 assert = function( b , msg ){
26     if ( assert._debug && msg ) print( "in assert for: " + msg );
27
28     if ( b )
29         return;
30     
31     doassert( "assert failed : " + msg );
32 }
33
34 assert.eq = function( a , b , msg ){
35     if ( assert._debug && msg ) print( "in assert for: " + msg );
36
37     if ( a == b )
38         return;
39
40     if ( ( a != null && b != null ) && friendlyEqual( a , b ) )
41         return;
42
43     doassert( "[" + tojson( a ) + "] != [" + tojson( b ) + "] are not equal : " + msg );
44 }
45
46 assert.neq = function( a , b , msg ){
47     if ( assert._debug && msg ) print( "in assert for: " + msg );
48     if ( a != b )
49         return;
50
51     doassert( "[" + a + "] != [" + b + "] are equal : " + msg );
52 }
53
54 assert.soon = function( f, msg, timeout, interval ) {
55     if ( assert._debug && msg ) print( "in assert for: " + msg );
56
57     var start = new Date();
58     timeout = timeout || 30000;
59     interval = interval || 200;
60     var last;
61     while( 1 ) {
62         
63         if ( typeof( f ) == "string" ){
64             if ( eval( f ) )
65                 return;
66         }
67         else {
68             if ( f() )
69                 return;
70         }
71         
72         if ( ( new Date() ).getTime() - start.getTime() > timeout )
73             doassert( "assert.soon failed: " + f + ", msg:" + msg );
74         sleep( interval );
75     }
76 }
77
78 assert.throws = function( func , params , msg ){
79     if ( assert._debug && msg ) print( "in assert for: " + msg );
80     try {
81         func.apply( null , params );
82     }
83     catch ( e ){
84         return e;
85     }
86
87     doassert( "did not throw exception: " + msg );
88 }
89
90 assert.commandWorked = function( res , msg ){
91     if ( assert._debug && msg ) print( "in assert for: " + msg );
92
93     if ( res.ok == 1 )
94         return;
95     
96     doassert( "command failed: " + tojson( res ) + " : " + msg );
97 }
98
99 assert.commandFailed = function( res , msg ){
100     if ( assert._debug && msg ) print( "in assert for: " + msg );
101
102     if ( res.ok == 0 )
103         return;
104     
105     doassert( "command worked when it should have failed: " + tojson( res ) + " : " + msg );
106 }
107
108 assert.isnull = function( what , msg ){
109     if ( assert._debug && msg ) print( "in assert for: " + msg );
110
111     if ( what == null )
112         return;
113     
114     doassert( "supposed to null (" + ( msg || "" ) + ") was: " + tojson( what ) );
115 }
116
117 assert.lt = function( a , b , msg ){
118     if ( assert._debug && msg ) print( "in assert for: " + msg );
119
120     if ( a < b )
121         return;
122     doassert( a + " is not less than " + b + " : " + msg );
123 }
124
125 assert.gt = function( a , b , msg ){
126     if ( assert._debug && msg ) print( "in assert for: " + msg );
127
128     if ( a > b )
129         return;
130     doassert( a + " is not greater than " + b + " : " + msg );
131 }
132
133 Object.extend = function( dst , src , deep ){
134     for ( var k in src ){
135         var v = src[k];
136         if ( deep && typeof(v) == "object" ){
137             v = Object.extend( typeof ( v.length ) == "number" ? [] : {} , v , true );
138         }
139         dst[k] = v;
140     }
141     return dst;
142 }
143
144 argumentsToArray = function( a ){
145     var arr = [];
146     for ( var i=0; i<a.length; i++ )
147         arr[i] = a[i];
148     return arr;
149 }
150
151 isString = function( x ){
152     return typeof( x ) == "string";
153 }
154
155 isNumber = function(x){
156     return typeof( x ) == "number";
157 }
158
159 isObject = function( x ){
160     return typeof( x ) == "object";
161 }
162
163 String.prototype.trim = function() {
164     return this.replace(/^\s+|\s+$/g,"");
165 }
166 String.prototype.ltrim = function() {
167     return this.replace(/^\s+/,"");
168 }
169 String.prototype.rtrim = function() {
170     return this.replace(/\s+$/,"");
171 }
172
173 Date.timeFunc = function( theFunc , numTimes ){
174
175     var start = new Date();
176     
177     numTimes = numTimes || 1;
178     for ( var i=0; i<numTimes; i++ ){
179         theFunc.apply( null , argumentsToArray( arguments ).slice( 2 ) );
180     }
181
182     return (new Date()).getTime() - start.getTime();
183 }
184
185 Date.prototype.tojson = function(){
186     return "\"" + this.toString() + "\"";
187 }
188
189 RegExp.prototype.tojson = RegExp.prototype.toString;
190
191 Array.contains = function( a  , x ){
192     for ( var i=0; i<a.length; i++ ){
193         if ( a[i] == x )
194             return true;
195     }
196     return false;
197 }
198
199 Array.unique = function( a ){
200     var u = [];
201     for ( var i=0; i<a.length; i++){
202         var o = a[i];
203         if ( ! Array.contains( u , o ) ){
204             u.push( o );
205         }
206     }
207     return u;
208 }
209
210 Array.shuffle = function( arr ){
211     for ( var i=0; i<arr.length-1; i++ ){
212         var pos = i+Math.floor(Math.random()*(arr.length-i));
213         var save = arr[i];
214         arr[i] = arr[pos];
215         arr[pos] = save;
216     }
217     return arr;
218 }
219
220
221 Array.tojson = function( a , indent , x , html){
222     if (!indent) 
223         indent = "";
224     var spacer = "";
225     if(html) {
226       spacer = "<br/>";
227       indent = " &nbsp; "
228     }
229
230     var s = spacer + "[ " + spacer;
231     indent += " ";
232     for ( var i=0; i<a.length; i++){
233         s += indent + tojson( a[i], indent );
234         if ( i < a.length - 1 ){
235             s += "," + spacer;
236         }
237     }
238     if ( a.length == 0 ) {
239         s += indent;
240     }
241
242     indent = indent.substring(1);
243     s += spacer + " "+"]";
244     return s;
245 }
246
247 Array.fetchRefs = function( arr , coll ){
248     var n = [];
249     for ( var i=0; i<arr.length; i ++){
250         var z = arr[i];
251         if ( coll && coll != z.getCollection() )
252             continue;
253         n.push( z.fetch() );
254     }
255     
256     return n;
257 }
258
259 Array.sum = function( arr ){
260     if ( arr.length == 0 )
261         return null;
262     var s = arr[0];
263     for ( var i=1; i<arr.length; i++ )
264         s += arr[i];
265     return s;
266 }
267
268 Array.avg = function( arr ){
269     if ( arr.length == 0 )
270         return null;
271     return Array.sum( arr ) / arr.length;
272 }
273
274 Array.stdDev = function( arr ){
275     var avg = Array.avg( arr );
276     var sum = 0;
277
278     for ( var i=0; i<arr.length; i++ ){
279         sum += Math.pow( arr[i] - avg , 2 );
280     }
281
282     return Math.sqrt( sum / arr.length );
283 }
284
285 if ( ! ObjectId.prototype )
286     ObjectId.prototype = {}
287
288 ObjectId.prototype.toString = function(){
289     return this.str;
290 }
291
292 ObjectId.prototype.tojson = function(){
293     return "ObjectId(\"" + this.str + "\")";
294 }
295
296 ObjectId.prototype.isObjectId = true;
297
298 tojson = function( x, indent , nolint , html){
299     if ( x == null )
300         return "null";
301     
302     if ( x == undefined )
303         return "undefined";
304     
305     if (!indent) 
306         indent = "";
307
308     switch ( typeof x ){
309         
310     case "string": {
311         var s = "\"";
312         for ( var i=0; i<x.length; i++ ){
313             if ( x[i] == '"' ){
314                 s += "\\\"";
315             }
316             else
317                 s += x[i];
318         }
319         return s + "\"";
320     }
321         
322     case "number": 
323     case "boolean":
324         return "" + x;
325             
326     case "object":{
327         var s = tojsonObject( x, indent , nolint , html);
328         if ( ( nolint == null || nolint == true ) && s.length < 80 && ( indent == null || indent.length == 0 ) ){
329             s = s.replace( /[\s\r\n ]+/gm , " " );
330         }
331         return s;
332     }
333         
334     case "function":
335         return x.toString();
336         
337
338     default:
339         throw "tojson can't handle type " + ( typeof x );
340     }
341     
342 }
343
344 tojsonObject = function( x, indent , nolint , html){
345     if(html) {
346       var lineEnding = "<br/>";
347       var tabSpace   = "&nbsp;";
348     }
349     else {
350       var lineEnding = nolint ? " " : "\n";
351       var tabSpace = nolint ? "" : "\t";
352     }
353     
354     assert.eq( ( typeof x ) , "object" , "tojsonObject needs object, not [" + ( typeof x ) + "]" );
355
356     if (!indent) 
357         indent = "";
358     
359     if ( typeof( x.tojson ) == "function" && x.tojson != tojson ) {
360         return x.tojson(indent,nolint,html);
361     }
362     
363     if ( typeof( x.constructor.tojson ) == "function" && x.constructor.tojson != tojson ) {
364         return x.constructor.tojson( x, indent , nolint, html );
365     }
366
367     if ( x.toString() == "[object MaxKey]" )
368         return "{ $maxKey : 1 }";
369     if ( x.toString() == "[object MinKey]" )
370         return "{ $minKey : 1 }";
371     
372     var s = "{" + lineEnding;
373
374     // push one level of indent
375     indent += tabSpace;
376     
377     var total = 0;
378     for ( var k in x ) total++;
379     if ( total == 0 ) {
380         s += indent + lineEnding;
381     }
382
383     var keys = x;
384     if ( typeof( x._simpleKeys ) == "function" )
385         keys = x._simpleKeys();
386     var num = 1;
387     for ( var k in keys ){
388         
389         var val = x[k];
390
391         s += indent + "\"" + k + "\" : " + tojson( val, indent , nolint );
392         if (num != total) {
393             s += ",";
394             num++;
395         }
396         s += lineEnding;
397     }
398
399     // pop one level of indent
400     indent = indent.substring(1);
401     return s + indent + "}";
402 }
403
404 shellPrint = function( x ){
405     it = x;
406     if ( x != undefined )
407         shellPrintHelper( x );
408 }
409
410 printjson = function(x){
411     print( tojson( x ) );
412 }
413
414 shellPrintHelper = function( x ){
415
416     if ( typeof( x ) == "undefined" ){
417
418         return;
419     }
420     
421     if ( x == null ){
422         print( "null" );
423         return;
424     }
425
426     if ( typeof x != "object" ) 
427         return print( x );
428     
429     var p = x.shellPrint;
430     if ( typeof p == "function" )
431         return x.shellPrint();
432
433     var p = x.tojson;
434     if ( typeof p == "function" )
435         print( x.tojson() );
436     else
437         print( tojson( x ) );
438 }
439
440 shellHelper = function( command , rest , shouldPrint ){
441     command = command.trim();
442     var args = rest.trim().replace(/;$/,"").split( "\s+" );
443     
444     if ( ! shellHelper[command] )
445         throw "no command [" + command + "]";
446     
447     var res = shellHelper[command].apply( null , args );
448     if ( shouldPrint ){
449         shellPrintHelper( res );
450     }
451     return res;
452 }
453
454 help = shellHelper.help = function(){
455     print( "HELP" );
456     print( "\t" + "show dbs                     show database names");
457     print( "\t" + "show collections             show collections in current database");
458     print( "\t" + "show users                   show users in current database");
459     print( "\t" + "show profile                 show most recent system.profile entries with time >= 1ms");
460     print( "\t" + "use <db name>                set curent database to <db name>" );
461     print( "\t" + "db.help()                    help on DB methods");
462     print( "\t" + "db.foo.help()                help on collection methods");
463     print( "\t" + "db.foo.find()                list objects in collection foo" );
464     print( "\t" + "db.foo.find( { a : 1 } )     list objects in foo where a == 1" );
465     print( "\t" + "it                           result of the last line evaluated; use to further iterate");
466 }
467
468 if ( typeof( Map ) == "undefined" ){
469     Map = function(){
470         this._data = {};
471     }
472 }
473
474 Map.hash = function( val ){
475     if ( ! val )
476         return val;
477
478     switch ( typeof( val ) ){
479     case 'string':
480     case 'number':
481     case 'date':
482         return val.toString();
483     case 'object':
484     case 'array':
485         var s = "";
486         for ( var k in val ){
487             s += k + val[k];
488         }
489         return s;
490     }
491
492     throw "can't hash : " + typeof( val );
493 }
494
495 Map.prototype.put = function( key , value ){
496     var o = this._get( key );
497     var old = o.value;
498     o.value = value;
499     return old;
500 }
501
502 Map.prototype.get = function( key ){
503     return this._get( key ).value;
504 }
505
506 Map.prototype._get = function( key ){
507     var h = Map.hash( key );
508     var a = this._data[h];
509     if ( ! a ){
510         a = [];
511         this._data[h] = a;
512     }
513     
514     for ( var i=0; i<a.length; i++ ){
515         if ( friendlyEqual( key , a[i].key ) ){
516             return a[i];
517         }
518     }
519     var o = { key : key , value : null };
520     a.push( o );
521     return o;
522 }
523
524 Map.prototype.values = function(){
525     var all = [];
526     for ( var k in this._data ){
527         this._data[k].forEach( function(z){ all.push( z.value ); } );
528     }
529     return all;
530 }
531
532 if ( typeof( gc ) == "undefined" ){
533     gc = function(){
534     }
535 }
536    
537
538 Math.sigFig = function( x , N ){
539     if ( ! N ){
540         N = 3;
541     }
542     var p = Math.pow( 10, N - Math.ceil( Math.log( Math.abs(x) ) / Math.log( 10 )) );
543     return Math.round(x*p)/p;
544 }
545