'use strict';
/**
* @module providers
*/
var util = require('util');
var shortid = require('shortid');
var Provider = process.requireApi('lib/providers/Provider.js');
var ResourceFilter = process.requireApi('lib/storages/ResourceFilter.js');
/**
* Defines a provider holding a single type of resources.
*
* An entity provider manages a single type of resources. These resources are stored into the given storage / location.
* Each entity must have an identification number held in the "id" property. An entity may also have a "locked"
* property to make it immutable.
*
* @class EntityProvider
* @extends Provider
* @constructor
* @param {Storage} storage The storage to use to store provider entities
* @param {String} location The location of the entities in the storage
* @throws {TypeError} If storage and / or location is not valid
*/
function EntityProvider(storage, location) {
EntityProvider.super_.call(this, storage);
Object.defineProperties(this, {
/**
* The location of the entities in the storage.
*
* @property location
* @type String
* @final
*/
location: {value: location}
});
if (Object.prototype.toString.call(this.location) !== '[object String]')
throw new TypeError('location must be a string');
}
module.exports = EntityProvider;
util.inherits(EntityProvider, Provider);
/**
* Fetches an entity by its id.
*
* @method getOne
* @async
* @param {String} id The entity id
* @param {Object} [fields] Fields to be included or excluded from the response, by default all
* fields are returned. Only "exclude" or "include" can be specified, not both
* @param {Array} [fields.include] The list of fields to include in the response, all other fields are excluded
* @param {Array} [fields.exclude] The list of fields to exclude from response, all other fields are included. Ignored
* if include is also specified.
* @param {Function} callback The function to call when it's done
* - **Error** The error if an error occurred, null otherwise
* - **Object** The entity
*/
EntityProvider.prototype.getOne = function(id, fields, callback) {
var filter = new ResourceFilter().equal('id', id);
this.storage.getOne(this.location, filter, fields, callback);
};
/**
* Fetches entities.
*
* @method get
* @async
* @param {ResourceFilter} [filter] Rules to filter entities
* @param {Object} [fields] Fields to be included or excluded from the response, by default all
* fields are returned. Only "exclude" or "include" can be specified, not both
* @param {Array} [fields.include] The list of fields to include in the response, all other fields are excluded
* @param {Array} [fields.exclude] The list of fields to exclude from response, all other fields are included. Ignored
* if include is also specified.
* @param {Number} [limit] A limit number of entities to retrieve (10 by default)
* @param {Number} [page] The page number started at 0 for the first page
* @param {Object} [sort] The list of fields to sort by with the field name as key and the sort order as
* value (e.g. {field1: 'asc', field2: 'desc'})
* @param {Function} callback The function to call when it's done
* - **Error** The error if an error occurred, null otherwise
* - **Array** The list of retrieved entities
* - **Object** Pagination information
* - **Number** limit The specified limit
* - **Number** page The actual page
* - **Number** pages The total number of pages
* - **Number** size The total number of entities
*/
EntityProvider.prototype.get = function(filter, fields, limit, page, sort, callback) {
this.storage.get(this.location, filter, fields, limit, page, sort, callback);
};
/**
* Adds entities.
*
* @method add
* @async
* @param {Array} entities The list of entities to store
* @param {Function} [callback] The function to call when it's done
* - **Error** The error if an error occurred, null otherwise
* - **Number** The total amount of entities inserted
*/
EntityProvider.prototype.add = function(entities, callback) {
entities.forEach(function(entity) {
entity.id = entity.id || shortid.generate();
});
this.storage.add(this.location, entities, callback || function(error) {
if (error)
process.logger.error('Error while inserting entities with message: ' + error.message);
});
};
/**
* Updates entities.
*
* @method update
* @async
* @param {ResourceFilter} [filter] Rules to filter entities to update
* @param {Object} data The modifications to perform
* @param {Function} [callback] The function to call when it's done
* - **Error** The error if an error occurred, null otherwise
* - **Number** The number of updated entities
*/
EntityProvider.prototype.update = function(filter, data, callback) {
if (!filter) filter = new ResourceFilter();
filter.notEqual('locked', true);
this.storage.update(this.location, filter, data, callback || function(error) {
if (error)
process.logger.error('Error while updating entities with message: ' + error.message, filter);
});
};
/**
* Removes entities.
*
* @method remove
* @async
* @param {ResourceFilter} [filter] Rules to filter entities to remove
* @param {Function} [callback] The function to call when it's done
* - **Error** The error if an error occurred, null otherwise
* - **Number** The number of removed entities
*/
EntityProvider.prototype.remove = function(filter, callback) {
if (!filter) filter = new ResourceFilter();
filter.notEqual('locked', true);
this.storage.remove(this.location, filter, callback || function(error) {
if (error)
process.logger.error('Error while removing entities with message: ' + error.message, filter);
});
};
/**
* Removes a field from entities.
*
* @method removeField
* @async
* @param {String} field The field to remove from entities
* @param {ResourceFilter} [filter] Rules to filter entities to update
* @param {Function} [callback] The function to call when it's done
* - **Error** The error if an error occurred, null otherwise
* - **Number** The number of updated entities
*/
EntityProvider.prototype.removeField = function(field, filter, callback) {
if (!filter) filter = new ResourceFilter();
filter.notEqual('locked', true);
this.storage.removeField(this.location, field, filter, callback || function(error) {
if (error)
process.logger.error('Error while removing field from entities with message: ' + error.message, field);
});
};