src/cm/media/js/lib/yui/yui_3.10.3/build/cache-base/cache-base-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     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         Y.log("Cache initialized", "info", "cache");
       
   189     },
       
   190 
       
   191     /**
       
   192     * @method destructor
       
   193     * @description Internal destroy() handler.
       
   194     * @private
       
   195     */
       
   196     destructor: function() {
       
   197         this._entries = [];
       
   198         Y.log("Cache destroyed", "info", "cache");
       
   199     },
       
   200 
       
   201     /////////////////////////////////////////////////////////////////////////////
       
   202     //
       
   203     // Cache protected methods
       
   204     //
       
   205     /////////////////////////////////////////////////////////////////////////////
       
   206 
       
   207     /**
       
   208      * Sets max.
       
   209      *
       
   210      * @method _setMax
       
   211      * @protected
       
   212      */
       
   213     _setMax: function(value) {
       
   214         // If the cache is full, make room by removing stalest element (index=0)
       
   215         var entries = this._entries;
       
   216         if(value > 0) {
       
   217             if(entries) {
       
   218                 while(entries.length > value) {
       
   219                     entries.shift();
       
   220                 }
       
   221             }
       
   222         }
       
   223         else {
       
   224             value = 0;
       
   225             this._entries = [];
       
   226         }
       
   227         return value;
       
   228     },
       
   229 
       
   230     /**
       
   231      * Gets size.
       
   232      *
       
   233      * @method _getSize
       
   234      * @protected
       
   235      */
       
   236     _getSize: function() {
       
   237         return this._entries.length;
       
   238     },
       
   239 
       
   240     /**
       
   241      * Gets all entries.
       
   242      *
       
   243      * @method _getEntries
       
   244      * @protected
       
   245      */
       
   246     _getEntries: function() {
       
   247         return this._entries;
       
   248     },
       
   249 
       
   250 
       
   251     /**
       
   252      * Adds entry to cache.
       
   253      *
       
   254      * @method _defAddFn
       
   255      * @param e {Event.Facade} Event Facade with the following properties:
       
   256      * <dl>
       
   257      * <dt>entry (Object)</dt> <dd>The cached entry.</dd>
       
   258      * </dl>
       
   259      * @protected
       
   260      */
       
   261     _defAddFn: function(e) {
       
   262         var entries = this._entries,
       
   263             entry   = e.entry,
       
   264             max     = this.get("max"),
       
   265             pos;
       
   266 
       
   267         // If uniqueKeys is true and item exists with this key, then remove it.
       
   268         if (this.get("uniqueKeys")) {
       
   269             pos = this._position(e.entry.request);
       
   270             if (LANG.isValue(pos)) {
       
   271                 entries.splice(pos, 1);
       
   272             }
       
   273         }
       
   274 
       
   275         // If the cache at or over capacity, make room by removing stalest
       
   276         // element(s) starting at index-0.
       
   277         while (max && entries.length >= max) {
       
   278             entries.shift();
       
   279         }
       
   280 
       
   281         // Add entry to cache in the newest position, at the end of the array
       
   282         entries[entries.length] = entry;
       
   283         Y.log("Cached entry: " + Y.dump(entry), "info", "cache");
       
   284     },
       
   285 
       
   286     /**
       
   287      * Flushes cache.
       
   288      *
       
   289      * @method _defFlushFn
       
   290      * @param e {Event.Facade} Event Facade object.
       
   291      * @protected
       
   292      */
       
   293     _defFlushFn: function(e) {
       
   294         var entries = this._entries,
       
   295             details = e.details[0],
       
   296             pos;
       
   297 
       
   298         //passed an item, flush only that
       
   299         if(details && LANG.isValue(details.request)) {
       
   300             pos = this._position(details.request);
       
   301 
       
   302             if(LANG.isValue(pos)) {
       
   303                 entries.splice(pos,1);
       
   304 
       
   305                 Y.log("Flushed cache item " + Y.dump(details.request), "info", "cache");
       
   306             }
       
   307         }
       
   308         //no item, flush everything
       
   309         else {
       
   310             this._entries = [];
       
   311             Y.log("Cache flushed", "info", "cache");
       
   312         }
       
   313     },
       
   314 
       
   315     /**
       
   316      * Default overridable method compares current request with given cache entry.
       
   317      * Returns true if current request matches the cached request, otherwise
       
   318      * false. Implementers should override this method to customize the
       
   319      * cache-matching algorithm.
       
   320      *
       
   321      * @method _isMatch
       
   322      * @param request {Object} Request object.
       
   323      * @param entry {Object} Cached entry.
       
   324      * @return {Boolean} True if current request matches given cached request, false otherwise.
       
   325      * @protected
       
   326      */
       
   327     _isMatch: function(request, entry) {
       
   328         if(!entry.expires || new Date() < entry.expires) {
       
   329             return (request === entry.request);
       
   330         }
       
   331         return false;
       
   332     },
       
   333 
       
   334     /**
       
   335      * Returns position of a request in the entries array, otherwise null.
       
   336      *
       
   337      * @method _position
       
   338      * @param request {Object} Request object.
       
   339      * @return {Number} Array position if found, null otherwise.
       
   340      * @protected
       
   341      */
       
   342     _position: function(request) {
       
   343         // If cache is enabled...
       
   344         var entries = this._entries,
       
   345             length = entries.length,
       
   346             i = length-1;
       
   347 
       
   348         if((this.get("max") === null) || this.get("max") > 0) {
       
   349             // Loop through each cached entry starting from the newest
       
   350             for(; i >= 0; i--) {
       
   351                 // Execute matching function
       
   352                 if(this._isMatch(request, entries[i])) {
       
   353                     return i;
       
   354                 }
       
   355             }
       
   356         }
       
   357 
       
   358         return null;
       
   359     },
       
   360 
       
   361     /////////////////////////////////////////////////////////////////////////////
       
   362     //
       
   363     // Cache public methods
       
   364     //
       
   365     /////////////////////////////////////////////////////////////////////////////
       
   366 
       
   367     /**
       
   368      * Adds a new entry to the cache of the format
       
   369      * {request:request, response:response, cached:cached, expires:expires}.
       
   370      * If cache is full, evicts the stalest entry before adding the new one.
       
   371      *
       
   372      * @method add
       
   373      * @param request {Object} Request value.
       
   374      * @param response {Object} Response value.
       
   375      */
       
   376     add: function(request, response) {
       
   377         var expires = this.get("expires");
       
   378         if(this.get("initialized") && ((this.get("max") === null) || this.get("max") > 0) &&
       
   379                 (LANG.isValue(request) || LANG.isNull(request) || LANG.isUndefined(request))) {
       
   380             this.fire("add", {entry: {
       
   381                 request:request,
       
   382                 response:response,
       
   383                 cached: new Date(),
       
   384                 expires: isDate(expires) ? expires :
       
   385             (expires ? new Date(new Date().getTime() + this.get("expires")) : null)
       
   386             }});
       
   387         }
       
   388         else {
       
   389             Y.log("Could not add " + Y.dump(response) + " to cache for " + Y.dump(request), "info", "cache");
       
   390         }
       
   391     },
       
   392 
       
   393     /**
       
   394      * Flushes cache.
       
   395      *
       
   396      * @method flush
       
   397      */
       
   398     flush: function(request) {
       
   399         this.fire("flush", { request: (LANG.isValue(request) ? request : null) });
       
   400     },
       
   401 
       
   402     /**
       
   403      * Retrieves cached object for given request, if available, and refreshes
       
   404      * entry in the cache. Returns null if there is no cache match.
       
   405      *
       
   406      * @method retrieve
       
   407      * @param request {Object} Request object.
       
   408      * @return {Object} Cached object with the properties request and response, or null.
       
   409      */
       
   410     retrieve: function(request) {
       
   411         // If cache is enabled...
       
   412         var entries = this._entries,
       
   413             length = entries.length,
       
   414             entry = null,
       
   415             pos;
       
   416 
       
   417         if((length > 0) && ((this.get("max") === null) || (this.get("max") > 0))) {
       
   418             this.fire("request", {request: request});
       
   419 
       
   420             pos = this._position(request);
       
   421 
       
   422             if(LANG.isValue(pos)) {
       
   423                 entry = entries[pos];
       
   424 
       
   425                 this.fire("retrieve", {entry: entry});
       
   426 
       
   427                 // Refresh the position of the cache hit
       
   428                 if(pos < length-1) {
       
   429                     // Remove element from its original location
       
   430                     entries.splice(pos,1);
       
   431                     // Add as newest
       
   432                     entries[entries.length] = entry;
       
   433                     Y.log("Refreshed cache entry: " + Y.dump(entry) +
       
   434                             " for request: " +  Y.dump(request), "info", "cache");
       
   435                 }
       
   436 
       
   437                 Y.log("Retrieved cached response: " + Y.dump(entry) +
       
   438                         " for request: " + Y.dump(request), "info", "cache");
       
   439                 return entry;
       
   440             }
       
   441         }
       
   442         return null;
       
   443     }
       
   444 });
       
   445 
       
   446 Y.Cache = Cache;
       
   447 
       
   448 
       
   449 }, '3.10.3', {"requires": ["base"]});