Source: apps/db.cache.js

/**
 * Mobizen - Mobizen/Apps/DB/Cache
 *
 * IMPORTANT NOTE: This file is licensed only for use in providing the RSUPPORT services,
 *
 * @copyright 2015 RSUPPORT CO., LTD. All rights reserved.
 * @license Dedicated to the public domain.
 * @author Sungyeol Yim <syyim@rsupport.com>
 *
 */

(function(exports) {
  "use strict";

  /**
   * @typedef {Mobizen}
   */
  var Mobizen = exports.Mobizen
  /**
   * @typedef {Mobizen.Inherits}
   */
    , inherits = Mobizen.Inherits
  /**
   * @typedef {Mobizen.Apps.DB}
   */
    , DB = Mobizen.Apps.DB
  /**
   * @typedef {Mobizen.Apps.DB.Utils}
   */
    , utils = DB.Utils;

  /**
   * A Base Class of Cache
   * @constructs Cache
   * @memberof Mobizen.Apps.DB
   * @author Sungyeol Yim <syyim@rsupport.com>
   *
   * @param {string} app - name of app
   * @param {string} channel - name of db channel
   *
   * @requires loki.js
   */
  function CacheBase(app, channel) {
    /** @type {string} */
    this.app = app;
    /** @type {string} */
    this.channel = channel;
    /** @typedef {loki} */
    this.db = new loki(app);
    /** @typedef {Mobizen.Apps.DB.CacheSchema} */
    this.indexes = DB.CacheSchema[app][channel];

    (function init(that) {
      var stores = that.stores = {};
      that.indexes.forEach(function(index) {
        stores[index] = that.db.addCollection(index, 'doc');
      });
    })(this);
  }

  CacheBase.prototype = /** @lends Mobizen.Apps.DB.Cache# */ {
    /**
     * @param {array} docs
     * @return {Promise}
     */
    set: function(docs) {
      if (this.app === 'calllog') return this.setCalllog(docs);

      var map = docs.map(function(doc) {
        this.indexes.forEach(function(index) {
          var store = this.stores[index]
            , group = store.find({id: doc[index.substring(0, index.length -1) + 'Id']}).slice(0)[0];
          if (group) {
            this['add_'+index](group, doc);
            store.update(group);
          } else {
            group = this['add_'+index](null, doc);
            store.insert(group);
          }
        }.bind(this));
        return doc;
      }.bind(this));

      return Promise.all(map).then(function(test) {
        return test;
      });
    },

    /**
     * @param {array} ids
     * @return {array}
     * @private
     */
    _removeInfo: function(ids) {
      return ids.filter(utils.valueUnique).map(function(groupId) {
        var store = this.stores[this.indexes[0]]
          , group = store.find({id: groupId}).slice(0)[0];
        return group? {id: group.id, count: group._count} : {id: groupId, count: 0};
      }.bind(this));
    },

    /**
     * @param {array} docs
     * @return {Promise}
     */
    remove: function(docs) {
      var index = this.indexes[0]
        , store = this.stores[index]
        , key = index.substring(0, index.length -1) + 'Id'
        , map = docs.map(function(doc) {
            var group = store.find({id: doc[key]}).slice(0)[0];
            if (group) {
              group._count--;
              if (group._count < 1) store.remove(group);
              else store.update(group);

              this.remove_subindex(doc, group._count);
            }
            return group? group.id : doc[key];
        }.bind(this));

      return Promise.all(map).then(this._removeInfo.bind(this)).then(function(groups) {
        return {items: docs, groups: groups};
      });
    },


    // _remove: function(index, doc, key) {
    //   var store = this.stores[index]
    //     , group = store.find({id: doc[key]}).slice(0)[0];

    //   if (group) {
    //     group._count--;
    //     if (group._count < 1) store.remove(group);
    //     else store.update(group);

    //     this.remove_subindex(doc, group._count);
    //   }
    //   return group? group.id : doc[key];
    // },

    /**
     * @return {Promise}
     */
    info: function() {
      var map = this.indexes.map(function(index) {
        var store = this.stores[index];
        return store.find().slice(0);
      }.bind(this));

      return Promise.all(map);
    },

    /**
     * @param {number} index
     * @return {Promise}
     */
    all: function(index) {
      return new Promise(function(resolve, reject) {
        try {
          var store = this.stores[index];
          resolve(store.find().slice(0));
        } catch(e) {
          reject(e);
        }
      }.bind(this));
    },

    /**
     * @param {string} id
     * @param {number} index
     * @return {Promise}
     */
    get: function(id, index) {
      return new Promise(function(resolve, reject) {
        try {
          var store = this.stores[index]
            , data = store.find({id: id}).slice(0)[0];
          resolve(data);
        } catch(e) {
          reject(e);
        }
      }.bind(this));
    },

    /**
     * @param {object} doc
     * @return {Promise}
     */
    add: function(doc) {
      return this.set([doc]);
    },

    /**
     * @return {Promise}
     */
    clear: function() {
      var map = this.stores.map(function(store) {
        return store.remove();
      });
      return Promise.all(map);
    }
  };


  /**
   * @constructs Music
   * @memberof Mobizen.Apps.DB.Cache~
   * @extends Mobizen.Apps.DB.Cache
   * @author Sungyeol Yim <syyim@rsupport.com>
   *
   * @param {string} app - name of app
   * @param {string} channel - name of db channel
   */
  function MusicCache(app, channel) {
    CacheBase.call(this, app, channel);
  }

  inherits(MusicCache, CacheBase, /** @lends Mobizen.Apps.DB.Cache~Music# */ {
    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_albums: function(group, doc) {
      if (group) group._count++;
      else return {id: doc.albumId, title: doc.album, artist: doc.artist, _type: doc.$channel, _count: 1};

    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_artists: function(group, doc) {
      if (group) {
        group._count++;
        group.albums.indexOf(doc.albumId) === -1 && group.albums.push(doc.albumId);
      } else return {id: doc.artistId, title: doc.artist, _type: doc.$channel, albums: [doc.albumId], _count: 1};
    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_genres: function(group, doc) {
      if (group) {
        group._count++;
        group.albums.indexOf(doc.albumId) === -1 && group.albums.push(doc.albumId);
      } else return {id: doc.genreId, title: doc.genre, _type: doc.$channel, albums: [doc.albumId], _count: 1};
    },

    /**
     * @param {object} doc
     * @param {boolean} hasAlbum
     * @return {Promise}
     */
    remove_subindex: function(doc, hasAlbum) {
      var map = this.indexes.slice(1, this.indexes.length).map(function(index) {
        var store = this.stores[index]
          , group = store.find({id: doc[index.substring(0, index.length -1) + 'Id']})[0];

        if (group) {
          group._count--;
          if (!hasAlbum) {
            var i = group.albums.indexOf(doc.albumId);
            i > -1 && group.albums.splice(i, 1);
          }
          if (group.albums.length < 1 || group._count < 1) store.remove(group);
          else store.update(group);
        }
        return doc;
      }.bind(this));

      return Promise.all(map);
    }
  });


  /**
   * @constructs Photo
   * @memberof Mobizen.Apps.DB.Cache~
   * @extends Mobizen.Apps.DB.Cache
   * @author Sungyeol Yim <syyim@rsupport.com>
   *
   * @param {string} app - name of app
   * @param {string} channel - name of db channel
   */
  function PhotoCache(app, channel) {
    CacheBase.call(this, app, channel);
  }

  inherits(PhotoCache, CacheBase, /** @lends Mobizen.Apps.DB.Cache~Photo# */ {
    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_events: function(group, doc) {
      if (group) group._count++;
      else {
        return {id: doc.eventId, title: doc.event, _type: doc.$channel, _count: 1, _drawed: 0, added: doc.added,
          events: [doc.eventId], month: doc.month, monthId: doc.monthId, year: doc.year, yearId: doc.yearId};
      }
    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_albums: function(group, doc) {
      if (group) {
        group._count++;
        group.evts.indexOf(doc.eventId) === -1 && group.evts.push(doc.eventId);
      } else {
        var splited = doc.path.split('/');
        return {id: doc.albumId, _count: 1, path: (splited[splited.length -1] = '') || splited.join('/'), _type: doc.$channel, title: doc.album, evts:[doc.eventId]};
      }
    },

    /**
     * @param {object} doc
     * @param {boolean} hasEvent
     * @return {Promise}
     */
    remove_subindex: function(doc, hasEvent) {
      var map = this.indexes.slice(1, this.indexes.length).map(function(index) {
        var store = this.stores[index]
          , group = store.find({id: doc[index.substring(0, index.length -1) + 'Id']})[0];

        if (group) {
          group._count--;
          if (!hasEvent) {
            var i = group.evts.indexOf(doc.eventId);
            i > -1 && group.evts.splice(i, 1);
          }
          if (group.evts.length < 1) store.remove(group);
          else store.update(group);
        }
        return doc;
      }.bind(this));

      return Promise.all(map);
    }
  });


  /**
   * @constructs Video
   * @memberof Mobizen.Apps.DB.Cache~
   * @extends Mobizen.Apps.DB.Cache
   * @author Sungyeol Yim <syyim@rsupport.com>
   *
   * @param {string} app - name of app
   * @param {string} channel - name of db channel
   */
  function VideoCache(app, channel) {
    CacheBase.call(this, app, channel);
  }

  inherits(VideoCache, CacheBase, /** @lends Mobizen.Apps.DB.Cache~Video# */ {
    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_albums: function(group, doc) {
      if (group) group._count++;
      else return {id: doc.albumId, _type: doc.$channel, added: doc.added, title: doc.album, _count: 1};
    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_records: function(group, doc) {
      if (group) {
        group._count = doc.recordId === 1? group._count +1 : 0;
      } else {
        return {id: doc.recordId, _type: doc.$channel, _count:  (doc.recordId ===1? 1: 0)};
      }
    },

    /**
     * @param {object} doc
     * @return {boolean} 응?
     */
    remove_subindex: function(doc) {
      if (!doc.recordId) return true;

      var store = this.stores.records
        , group = store.find({id: 1})[0];

      if (group) {
        group._count = group._count < 1? 0 : group._count -1;
        store.update(group);
      }
      return true;
    }
  });


  /**
   * @constructs CallLog
   * @memberof Mobizen.Apps.DB.Cache~
   * @extends Mobizen.Apps.DB.Cache
   * @author Sungyeol Yim <syyim@rsupport.com>
   *
   * @param {string} app - name of app
   * @param {string} channel - name of db channel
   */
  function CallLogCache(app, channel) {
    CacheBase.call(this, app, channel);
  }

  inherits(CallLogCache, CacheBase, /** @lends Mobizen.Apps.DB.Cache~CallLog# */ {
    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     * @private
     */
    _set: function(group, doc) {
      if (group) group._count++;
      else return {id: doc.eventId, _count: 1};
    },

    /**
     * @param {array} docs
     * @return {Promise}
     */
    setCalllog: function(docs) {
      var map = docs.map(function(doc) {
        [this.indexes[0], this.indexes[doc.logTypeId]].forEach(function(index) {
          var store = this.stores[index]
            , group = store.find({id: doc.eventId})[0];

          if (group) {
            this['add_'+index](group, doc);
            store.update(group);
          } else{
            group = this['add_'+index](null, doc);
            store.insert(group);
          }
        }.bind(this));
        return doc;
      }.bind(this));

      return Promise.all(map);
    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_events: function(group, doc) {
      return this._set(group, doc);
    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_incoming: function(group, doc) {
      return this._set(group, doc);
    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_outgoing: function(group, doc) {
      return this._set(group, doc);
    },

    /**
     * @param {object} group
     * @param {object} doc
     * @return {object} doc
     */
    add_missed: function(group, doc) {
      return this._set(group, doc);
    },

    /**
     * @param {object} doc
     */
    remove_subindex: function(doc) {
      var store = this.stores[this.indexes[doc.logTypeId]]
        , group = store.find({id: doc.eventId})[0];
      if (group) {
        group._count--;
        if (group._count < 1) store.remove(group);
        else store.update(group);
      }
    }
  });


  /*
   * Exporting modules
   */

  DB.Cache = {
    music: MusicCache,
    photos: PhotoCache,
    videos: VideoCache,
    calllog: CallLogCache
  };

})(this);
comments powered by Disqus