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