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