src/cm/media/js/lib/yui/yui3-3.15.0/build/cache-base/cache-base.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('cache-base', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4  * The Cache utility provides a common configurable interface for components to
       
     5  * cache and retrieve data from a local JavaScript struct.
       
     6  *
       
     7  * @module cache
       
     8  * @main
       
     9  */
       
    10 
       
    11 /**
       
    12  * Provides the base class for the YUI Cache utility.
       
    13  *
       
    14  * @submodule cache-base
       
    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 {EventFacade} 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 {EventFacade} 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 {EventFacade} 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 {EventFacade} 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 {EventFacade} 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             entry   = e.entry,
       
   255             max     = this.get("max"),
       
   256             pos;
       
   257 
       
   258         // If uniqueKeys is true and item exists with this key, then remove it.
       
   259         if (this.get("uniqueKeys")) {
       
   260             pos = this._position(e.entry.request);
       
   261             if (LANG.isValue(pos)) {
       
   262                 entries.splice(pos, 1);
       
   263             }
       
   264         }
       
   265 
       
   266         // If the cache at or over capacity, make room by removing stalest
       
   267         // element(s) starting at index-0.
       
   268         while (max && entries.length >= max) {
       
   269             entries.shift();
       
   270         }
       
   271 
       
   272         // Add entry to cache in the newest position, at the end of the array
       
   273         entries[entries.length] = entry;
       
   274     },
       
   275 
       
   276     /**
       
   277      * Flushes cache.
       
   278      *
       
   279      * @method _defFlushFn
       
   280      * @param e {EventFacade} Event Facade object.
       
   281      * @protected
       
   282      */
       
   283     _defFlushFn: function(e) {
       
   284         var entries = this._entries,
       
   285             details = e.details[0],
       
   286             pos;
       
   287 
       
   288         //passed an item, flush only that
       
   289         if(details && LANG.isValue(details.request)) {
       
   290             pos = this._position(details.request);
       
   291 
       
   292             if(LANG.isValue(pos)) {
       
   293                 entries.splice(pos,1);
       
   294 
       
   295             }
       
   296         }
       
   297         //no item, flush everything
       
   298         else {
       
   299             this._entries = [];
       
   300         }
       
   301     },
       
   302 
       
   303     /**
       
   304      * Default overridable method compares current request with given cache entry.
       
   305      * Returns true if current request matches the cached request, otherwise
       
   306      * false. Implementers should override this method to customize the
       
   307      * cache-matching algorithm.
       
   308      *
       
   309      * @method _isMatch
       
   310      * @param request {Object} Request object.
       
   311      * @param entry {Object} Cached entry.
       
   312      * @return {Boolean} True if current request matches given cached request, false otherwise.
       
   313      * @protected
       
   314      */
       
   315     _isMatch: function(request, entry) {
       
   316         if(!entry.expires || new Date() < entry.expires) {
       
   317             return (request === entry.request);
       
   318         }
       
   319         return false;
       
   320     },
       
   321 
       
   322     /**
       
   323      * Returns position of a request in the entries array, otherwise null.
       
   324      *
       
   325      * @method _position
       
   326      * @param request {Object} Request object.
       
   327      * @return {Number} Array position if found, null otherwise.
       
   328      * @protected
       
   329      */
       
   330     _position: function(request) {
       
   331         // If cache is enabled...
       
   332         var entries = this._entries,
       
   333             length = entries.length,
       
   334             i = length-1;
       
   335 
       
   336         if((this.get("max") === null) || this.get("max") > 0) {
       
   337             // Loop through each cached entry starting from the newest
       
   338             for(; i >= 0; i--) {
       
   339                 // Execute matching function
       
   340                 if(this._isMatch(request, entries[i])) {
       
   341                     return i;
       
   342                 }
       
   343             }
       
   344         }
       
   345 
       
   346         return null;
       
   347     },
       
   348 
       
   349     /////////////////////////////////////////////////////////////////////////////
       
   350     //
       
   351     // Cache public methods
       
   352     //
       
   353     /////////////////////////////////////////////////////////////////////////////
       
   354 
       
   355     /**
       
   356      * Adds a new entry to the cache of the format
       
   357      * {request:request, response:response, cached:cached, expires:expires}.
       
   358      * If cache is full, evicts the stalest entry before adding the new one.
       
   359      *
       
   360      * @method add
       
   361      * @param request {Object} Request value.
       
   362      * @param response {Object} Response value.
       
   363      */
       
   364     add: function(request, response) {
       
   365         var expires = this.get("expires");
       
   366         if(this.get("initialized") && ((this.get("max") === null) || this.get("max") > 0) &&
       
   367                 (LANG.isValue(request) || LANG.isNull(request) || LANG.isUndefined(request))) {
       
   368             this.fire("add", {entry: {
       
   369                 request:request,
       
   370                 response:response,
       
   371                 cached: new Date(),
       
   372                 expires: isDate(expires) ? expires :
       
   373             (expires ? new Date(new Date().getTime() + this.get("expires")) : null)
       
   374             }});
       
   375         }
       
   376         else {
       
   377         }
       
   378     },
       
   379 
       
   380     /**
       
   381      * Flushes cache.
       
   382      *
       
   383      * @method flush
       
   384      */
       
   385     flush: function(request) {
       
   386         this.fire("flush", { request: (LANG.isValue(request) ? request : null) });
       
   387     },
       
   388 
       
   389     /**
       
   390      * Retrieves cached object for given request, if available, and refreshes
       
   391      * entry in the cache. Returns null if there is no cache match.
       
   392      *
       
   393      * @method retrieve
       
   394      * @param request {Object} Request object.
       
   395      * @return {Object} Cached object with the properties request and response, or null.
       
   396      */
       
   397     retrieve: function(request) {
       
   398         // If cache is enabled...
       
   399         var entries = this._entries,
       
   400             length = entries.length,
       
   401             entry = null,
       
   402             pos;
       
   403 
       
   404         if((length > 0) && ((this.get("max") === null) || (this.get("max") > 0))) {
       
   405             this.fire("request", {request: request});
       
   406 
       
   407             pos = this._position(request);
       
   408 
       
   409             if(LANG.isValue(pos)) {
       
   410                 entry = entries[pos];
       
   411 
       
   412                 this.fire("retrieve", {entry: entry});
       
   413 
       
   414                 // Refresh the position of the cache hit
       
   415                 if(pos < length-1) {
       
   416                     // Remove element from its original location
       
   417                     entries.splice(pos,1);
       
   418                     // Add as newest
       
   419                     entries[entries.length] = entry;
       
   420                 }
       
   421 
       
   422                 return entry;
       
   423             }
       
   424         }
       
   425         return null;
       
   426     }
       
   427 });
       
   428 
       
   429 Y.Cache = Cache;
       
   430 
       
   431 
       
   432 }, '@VERSION@', {"requires": ["base"]});