~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

Viewing changes to lib/yuilib/3.13.0/cache-base/cache-base.js

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
YUI 3.13.0 (build 508226d)
 
3
Copyright 2013 Yahoo! Inc. All rights reserved.
 
4
Licensed under the BSD License.
 
5
http://yuilibrary.com/license/
 
6
*/
 
7
 
 
8
YUI.add('cache-base', function (Y, NAME) {
 
9
 
 
10
/**
 
11
 * The Cache utility provides a common configurable interface for components to
 
12
 * cache and retrieve data from a local JavaScript struct.
 
13
 *
 
14
 * @module cache
 
15
 * @main
 
16
 */
 
17
 
 
18
/**
 
19
 * Provides the base class for the YUI Cache utility.
 
20
 *
 
21
 * @submodule cache-base
 
22
 */
 
23
var LANG = Y.Lang,
 
24
    isDate = Y.Lang.isDate,
 
25
 
 
26
/**
 
27
 * Base class for the YUI Cache utility.
 
28
 * @class Cache
 
29
 * @extends Base
 
30
 * @constructor
 
31
 */
 
32
Cache = function() {
 
33
    Cache.superclass.constructor.apply(this, arguments);
 
34
};
 
35
 
 
36
    /////////////////////////////////////////////////////////////////////////////
 
37
    //
 
38
    // Cache static properties
 
39
    //
 
40
    /////////////////////////////////////////////////////////////////////////////
 
41
Y.mix(Cache, {
 
42
    /**
 
43
     * Class name.
 
44
     *
 
45
     * @property NAME
 
46
     * @type String
 
47
     * @static
 
48
     * @final
 
49
     * @value "cache"
 
50
     */
 
51
    NAME: "cache",
 
52
 
 
53
 
 
54
    ATTRS: {
 
55
        /////////////////////////////////////////////////////////////////////////////
 
56
        //
 
57
        // Cache Attributes
 
58
        //
 
59
        /////////////////////////////////////////////////////////////////////////////
 
60
 
 
61
        /**
 
62
        * @attribute max
 
63
        * @description Maximum number of entries the Cache can hold.
 
64
        * Set to 0 to turn off caching.
 
65
        * @type Number
 
66
        * @default 0
 
67
        */
 
68
        max: {
 
69
            value: 0,
 
70
            setter: "_setMax"
 
71
        },
 
72
 
 
73
        /**
 
74
        * @attribute size
 
75
        * @description Number of entries currently cached.
 
76
        * @type Number
 
77
        */
 
78
        size: {
 
79
            readOnly: true,
 
80
            getter: "_getSize"
 
81
        },
 
82
 
 
83
        /**
 
84
        * @attribute uniqueKeys
 
85
        * @description Validate uniqueness of stored keys. Default is false and
 
86
        * is more performant.
 
87
        * @type Boolean
 
88
        */
 
89
        uniqueKeys: {
 
90
            value: false
 
91
        },
 
92
 
 
93
        /**
 
94
        * @attribute expires
 
95
        * @description Absolute Date when data expires or
 
96
        * relative number of milliseconds. Zero disables expiration.
 
97
        * @type Date | Number
 
98
        * @default 0
 
99
        */
 
100
        expires: {
 
101
            value: 0,
 
102
            validator: function(v) {
 
103
                return Y.Lang.isDate(v) || (Y.Lang.isNumber(v) && v >= 0);
 
104
            }
 
105
        },
 
106
 
 
107
        /**
 
108
         * @attribute entries
 
109
         * @description Cached entries.
 
110
         * @type Array
 
111
         */
 
112
        entries: {
 
113
            readOnly: true,
 
114
            getter: "_getEntries"
 
115
        }
 
116
    }
 
117
});
 
118
 
 
119
Y.extend(Cache, Y.Base, {
 
120
    /////////////////////////////////////////////////////////////////////////////
 
121
    //
 
122
    // Cache private properties
 
123
    //
 
124
    /////////////////////////////////////////////////////////////////////////////
 
125
 
 
126
    /**
 
127
     * Array of request/response objects indexed chronologically.
 
128
     *
 
129
     * @property _entries
 
130
     * @type Object[]
 
131
     * @private
 
132
     */
 
133
    _entries: null,
 
134
 
 
135
    /////////////////////////////////////////////////////////////////////////////
 
136
    //
 
137
    // Cache private methods
 
138
    //
 
139
    /////////////////////////////////////////////////////////////////////////////
 
140
 
 
141
    /**
 
142
    * @method initializer
 
143
    * @description Internal init() handler.
 
144
    * @param config {Object} Config object.
 
145
    * @private
 
146
    */
 
147
    initializer: function(config) {
 
148
 
 
149
        /**
 
150
        * @event add
 
151
        * @description Fired when an entry is added.
 
152
        * @param e {Event.Facade} Event Facade with the following properties:
 
153
         * <dl>
 
154
         * <dt>entry (Object)</dt> <dd>The cached entry.</dd>
 
155
         * </dl>
 
156
        * @preventable _defAddFn
 
157
        */
 
158
        this.publish("add", {defaultFn: this._defAddFn});
 
159
 
 
160
        /**
 
161
        * @event flush
 
162
        * @description Fired when the cache is flushed.
 
163
        * @param e {Event.Facade} Event Facade object.
 
164
        * @preventable _defFlushFn
 
165
        */
 
166
        this.publish("flush", {defaultFn: this._defFlushFn});
 
167
 
 
168
        /**
 
169
        * @event request
 
170
        * @description Fired when an entry is requested from the cache.
 
171
        * @param e {Event.Facade} Event Facade with the following properties:
 
172
        * <dl>
 
173
        * <dt>request (Object)</dt> <dd>The request object.</dd>
 
174
        * </dl>
 
175
        */
 
176
 
 
177
        /**
 
178
        * @event retrieve
 
179
        * @description Fired when an entry is retrieved from the cache.
 
180
        * @param e {Event.Facade} Event Facade with the following properties:
 
181
        * <dl>
 
182
        * <dt>entry (Object)</dt> <dd>The retrieved entry.</dd>
 
183
        * </dl>
 
184
        */
 
185
 
 
186
        // Initialize internal values
 
187
        this._entries = [];
 
188
    },
 
189
 
 
190
    /**
 
191
    * @method destructor
 
192
    * @description Internal destroy() handler.
 
193
    * @private
 
194
    */
 
195
    destructor: function() {
 
196
        this._entries = [];
 
197
    },
 
198
 
 
199
    /////////////////////////////////////////////////////////////////////////////
 
200
    //
 
201
    // Cache protected methods
 
202
    //
 
203
    /////////////////////////////////////////////////////////////////////////////
 
204
 
 
205
    /**
 
206
     * Sets max.
 
207
     *
 
208
     * @method _setMax
 
209
     * @protected
 
210
     */
 
211
    _setMax: function(value) {
 
212
        // If the cache is full, make room by removing stalest element (index=0)
 
213
        var entries = this._entries;
 
214
        if(value > 0) {
 
215
            if(entries) {
 
216
                while(entries.length > value) {
 
217
                    entries.shift();
 
218
                }
 
219
            }
 
220
        }
 
221
        else {
 
222
            value = 0;
 
223
            this._entries = [];
 
224
        }
 
225
        return value;
 
226
    },
 
227
 
 
228
    /**
 
229
     * Gets size.
 
230
     *
 
231
     * @method _getSize
 
232
     * @protected
 
233
     */
 
234
    _getSize: function() {
 
235
        return this._entries.length;
 
236
    },
 
237
 
 
238
    /**
 
239
     * Gets all entries.
 
240
     *
 
241
     * @method _getEntries
 
242
     * @protected
 
243
     */
 
244
    _getEntries: function() {
 
245
        return this._entries;
 
246
    },
 
247
 
 
248
 
 
249
    /**
 
250
     * Adds entry to cache.
 
251
     *
 
252
     * @method _defAddFn
 
253
     * @param e {Event.Facade} Event Facade with the following properties:
 
254
     * <dl>
 
255
     * <dt>entry (Object)</dt> <dd>The cached entry.</dd>
 
256
     * </dl>
 
257
     * @protected
 
258
     */
 
259
    _defAddFn: function(e) {
 
260
        var entries = this._entries,
 
261
            entry   = e.entry,
 
262
            max     = this.get("max"),
 
263
            pos;
 
264
 
 
265
        // If uniqueKeys is true and item exists with this key, then remove it.
 
266
        if (this.get("uniqueKeys")) {
 
267
            pos = this._position(e.entry.request);
 
268
            if (LANG.isValue(pos)) {
 
269
                entries.splice(pos, 1);
 
270
            }
 
271
        }
 
272
 
 
273
        // If the cache at or over capacity, make room by removing stalest
 
274
        // element(s) starting at index-0.
 
275
        while (max && entries.length >= max) {
 
276
            entries.shift();
 
277
        }
 
278
 
 
279
        // Add entry to cache in the newest position, at the end of the array
 
280
        entries[entries.length] = entry;
 
281
    },
 
282
 
 
283
    /**
 
284
     * Flushes cache.
 
285
     *
 
286
     * @method _defFlushFn
 
287
     * @param e {Event.Facade} Event Facade object.
 
288
     * @protected
 
289
     */
 
290
    _defFlushFn: function(e) {
 
291
        var entries = this._entries,
 
292
            details = e.details[0],
 
293
            pos;
 
294
 
 
295
        //passed an item, flush only that
 
296
        if(details && LANG.isValue(details.request)) {
 
297
            pos = this._position(details.request);
 
298
 
 
299
            if(LANG.isValue(pos)) {
 
300
                entries.splice(pos,1);
 
301
 
 
302
            }
 
303
        }
 
304
        //no item, flush everything
 
305
        else {
 
306
            this._entries = [];
 
307
        }
 
308
    },
 
309
 
 
310
    /**
 
311
     * Default overridable method compares current request with given cache entry.
 
312
     * Returns true if current request matches the cached request, otherwise
 
313
     * false. Implementers should override this method to customize the
 
314
     * cache-matching algorithm.
 
315
     *
 
316
     * @method _isMatch
 
317
     * @param request {Object} Request object.
 
318
     * @param entry {Object} Cached entry.
 
319
     * @return {Boolean} True if current request matches given cached request, false otherwise.
 
320
     * @protected
 
321
     */
 
322
    _isMatch: function(request, entry) {
 
323
        if(!entry.expires || new Date() < entry.expires) {
 
324
            return (request === entry.request);
 
325
        }
 
326
        return false;
 
327
    },
 
328
 
 
329
    /**
 
330
     * Returns position of a request in the entries array, otherwise null.
 
331
     *
 
332
     * @method _position
 
333
     * @param request {Object} Request object.
 
334
     * @return {Number} Array position if found, null otherwise.
 
335
     * @protected
 
336
     */
 
337
    _position: function(request) {
 
338
        // If cache is enabled...
 
339
        var entries = this._entries,
 
340
            length = entries.length,
 
341
            i = length-1;
 
342
 
 
343
        if((this.get("max") === null) || this.get("max") > 0) {
 
344
            // Loop through each cached entry starting from the newest
 
345
            for(; i >= 0; i--) {
 
346
                // Execute matching function
 
347
                if(this._isMatch(request, entries[i])) {
 
348
                    return i;
 
349
                }
 
350
            }
 
351
        }
 
352
 
 
353
        return null;
 
354
    },
 
355
 
 
356
    /////////////////////////////////////////////////////////////////////////////
 
357
    //
 
358
    // Cache public methods
 
359
    //
 
360
    /////////////////////////////////////////////////////////////////////////////
 
361
 
 
362
    /**
 
363
     * Adds a new entry to the cache of the format
 
364
     * {request:request, response:response, cached:cached, expires:expires}.
 
365
     * If cache is full, evicts the stalest entry before adding the new one.
 
366
     *
 
367
     * @method add
 
368
     * @param request {Object} Request value.
 
369
     * @param response {Object} Response value.
 
370
     */
 
371
    add: function(request, response) {
 
372
        var expires = this.get("expires");
 
373
        if(this.get("initialized") && ((this.get("max") === null) || this.get("max") > 0) &&
 
374
                (LANG.isValue(request) || LANG.isNull(request) || LANG.isUndefined(request))) {
 
375
            this.fire("add", {entry: {
 
376
                request:request,
 
377
                response:response,
 
378
                cached: new Date(),
 
379
                expires: isDate(expires) ? expires :
 
380
            (expires ? new Date(new Date().getTime() + this.get("expires")) : null)
 
381
            }});
 
382
        }
 
383
        else {
 
384
        }
 
385
    },
 
386
 
 
387
    /**
 
388
     * Flushes cache.
 
389
     *
 
390
     * @method flush
 
391
     */
 
392
    flush: function(request) {
 
393
        this.fire("flush", { request: (LANG.isValue(request) ? request : null) });
 
394
    },
 
395
 
 
396
    /**
 
397
     * Retrieves cached object for given request, if available, and refreshes
 
398
     * entry in the cache. Returns null if there is no cache match.
 
399
     *
 
400
     * @method retrieve
 
401
     * @param request {Object} Request object.
 
402
     * @return {Object} Cached object with the properties request and response, or null.
 
403
     */
 
404
    retrieve: function(request) {
 
405
        // If cache is enabled...
 
406
        var entries = this._entries,
 
407
            length = entries.length,
 
408
            entry = null,
 
409
            pos;
 
410
 
 
411
        if((length > 0) && ((this.get("max") === null) || (this.get("max") > 0))) {
 
412
            this.fire("request", {request: request});
 
413
 
 
414
            pos = this._position(request);
 
415
 
 
416
            if(LANG.isValue(pos)) {
 
417
                entry = entries[pos];
 
418
 
 
419
                this.fire("retrieve", {entry: entry});
 
420
 
 
421
                // Refresh the position of the cache hit
 
422
                if(pos < length-1) {
 
423
                    // Remove element from its original location
 
424
                    entries.splice(pos,1);
 
425
                    // Add as newest
 
426
                    entries[entries.length] = entry;
 
427
                }
 
428
 
 
429
                return entry;
 
430
            }
 
431
        }
 
432
        return null;
 
433
    }
 
434
});
 
435
 
 
436
Y.Cache = Cache;
 
437
 
 
438
 
 
439
}, '3.13.0', {"requires": ["base"]});