1 /** @namespace */
  2 var SequenceStore; if( !SequenceStore ) SequenceStore = {};
  3 
  4 /**
  5  * Storage backend for sequences broken up into chunks, stored and
  6  * served as static text files.
  7  * @class
  8  * @constructor
  9  * @extends Store
 10  */
 11 SequenceStore.StaticChunked = function(args) {
 12     Store.call( this, args );
 13 
 14     this.chunkCache  = {};
 15 
 16     this.compress    = args.compress;
 17     this.urlTemplate = args.urlTemplate;
 18     this.baseUrl     = args.baseUrl;
 19 };
 20 
 21 SequenceStore.StaticChunked.prototype = new Store('');
 22 
 23 /**
 24  * @param {Object} seq object describing the sequence to operate on
 25  * @param {Number} start start coord, in interbase
 26  * @param {Number} end end coord, in interbase
 27  * @param {Function} callback function that takes ( start, end, seq )
 28  */
 29 SequenceStore.StaticChunked.prototype.getRange = function( seq, start, end, callback) {
 30 
 31     var seqname    = seq.name;
 32     var chunkSize  = seq.seqChunkSize;
 33     var firstChunk = Math.floor( Math.max(0,start) / chunkSize );
 34     var lastChunk  = Math.floor( (end - 1)         / chunkSize );
 35     var chunk;
 36 
 37     // if a callback spans more than one chunk, we need to wrap the
 38     // callback in another one that will be passed to each chunk to
 39     // concatenate the different pieces from each chunk and *then*
 40     // call the main callback
 41     if( firstChunk != lastChunk ) {
 42         callback = (function() {
 43             var chunk_seqs = [],
 44                 chunks_still_needed = lastChunk-firstChunk+1,
 45                 orig_callback = callback;
 46             return function( start, end, seq, chunkNum) {
 47                 chunk_seqs[chunkNum] = seq;
 48                 if( --chunks_still_needed == 0 )
 49                     orig_callback( start, end, chunk_seqs.join("") );
 50             };
 51          })();
 52     }
 53 
 54     var callbackInfo = { start: start, end: end, callback: callback };
 55 
 56     if( !this.chunkCache[seqname] ) {
 57         this.chunkCache[seqname] = [];
 58     }
 59     var chunkCacheForSeq = this.chunkCache[seqname];
 60 
 61     for (var i = firstChunk; i <= lastChunk; i++) {
 62         //console.log("working on chunk %d for %d .. %d", i, start, end);
 63 
 64         chunk = chunkCacheForSeq[i];
 65         if (chunk) {
 66             if (chunk.loaded) {
 67                 callback( start,
 68                           end,
 69                           chunk.sequence.substring(
 70                               start - i*chunkSize,
 71                               end - i*chunkSize
 72                           ),
 73                           i
 74                         );
 75             } else {
 76                 //console.log("added callback for %d .. %d", start, end);
 77                 chunk.callbacks.push(callbackInfo);
 78             }
 79         } else {
 80             chunk = {
 81                 loaded: false,
 82                 num: i,
 83                 callbacks: [callbackInfo]
 84             };
 85             chunkCacheForSeq[i] = chunk;
 86 
 87             var sequrl = Util.resolveUrl( this.baseUrl,
 88                                           Util.fillTemplate( this.urlTemplate,
 89                                                      {'refseq': seq.name} ));
 90 
 91             dojo.xhrGet({
 92                             url: sequrl + i + ".txt" + ( this.compress ? 'z' : '' ),
 93                             load: function (response) {
 94                                 var ci;
 95                                 chunk.sequence = response;
 96                                 for (var c = 0; c < chunk.callbacks.length; c++) {
 97                                     ci = chunk.callbacks[c];
 98                                     ci.callback( ci.start,
 99                                                  ci.end,
100                                                  response.substring( ci.start - chunk.num*chunkSize,
101                                                                      ci.end   - chunk.num*chunkSize
102                                                                    ),
103                                                  i
104                                                );
105                                 }
106                                 chunk.callbacks = undefined;
107                                 chunk.loaded = true;
108                             }
109                         });
110         }
111     }
112 };
113