'use strict';
/**
* @author Marco Lehmann <marco.lehmann@kiwigrid.com>
* @copyright Kiwigrid GmbH 2014-2015
* @module keta.services.DeviceSet
* @description DeviceSet Provider
*/
angular.module('keta.services.DeviceSet',
[
'keta.services.Device',
'keta.services.DeviceEvent'
])
/**
* @class ketaDeviceSetProvider
* @propertyOf keta.services.DeviceSet
* @description DeviceSet Provider
*/
.provider('ketaDeviceSet', function DeviceSetProvider() {
var DEFAULT_OFFSET = 0;
var DEFAULT_LIMIT = 50;
this.$get = function DeviceSetService(
$q, $rootScope, $log,
ketaDevice, ketaDeviceEvent, ketaEventBusDispatcher, ketaEventBusManager) {
// api reference
var api;
/**
* @class DeviceSetInstance
* @propertyOf DeviceSetProvider
* @description DeviceSet Instance
* @param {EventBus} givenEventBus eventBus to use for DeviceSetInstance
*/
var DeviceSetInstance = function(givenEventBus) {
// keep reference
var that = this;
// save EventBus instance
var eventBus = givenEventBus;
// internal params object
var params = {};
// automatically register device set listener
var registerListener = false;
// internal set object
var set = {};
/**
* @name filter
* @function
* @description
* <p>
* Adds a filter before DeviceSet query is sent to EventBus.
* </p>
* @param {Object} filter filter to use
* @returns {DeviceSetInstance} DeviceSetInstance to chain
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus)
* .filter({
* guid: 'guid'
* })
* .query()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
* });
*/
that.filter = function(filter) {
params.filter = filter;
return that;
};
/**
* @name project
* @function
* @description
* <p>
* Adds a projection before DeviceSet query is sent to EventBus.
* </p>
* @param {Object} projection projection to use
* @returns {DeviceSetInstance} DeviceSetInstance to chain
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus)
* .project({
* guid: 1,
* tagValues: {
* IdName: 1
* }
* })
* .query()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
* });
*/
that.project = function(projection) {
params.projection = projection;
return that;
};
/**
* @name sort
* @function
* @description
* <p>
* Adds a sorting before DeviceSet query is sent to EventBus.
* </p>
* @param {Object} sorting sorting to use
* @returns {DeviceSetInstance} DeviceSetInstance to chain
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus)
* .sort({
* 'tagValue.IdName.value': 1
* })
* .query()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
* });
*/
that.sort = function(sorting) {
params.sorting = sorting;
return that;
};
/**
* @name paginate
* @function
* @description
* <p>
* Adds a pagination before DeviceSet query is sent to EventBus.
* </p>
* @param {Object} pagination pagination to use
* @returns {DeviceSetInstance} DeviceSetInstance to chain
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus)
* .paginate({
* offset: 0,
* limit: 50
* })
* .query()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
* });
*/
that.paginate = function(pagination) {
if (angular.isDefined(pagination)) {
params.offset = angular.isDefined(pagination.offset) ? pagination.offset : DEFAULT_OFFSET;
params.limit = angular.isDefined(pagination.limit) ? pagination.limit : DEFAULT_LIMIT;
} else {
params.offset = DEFAULT_OFFSET;
params.limit = DEFAULT_LIMIT;
}
return that;
};
/**
* @name live
* @function
* @description
* <p>
* Adds live update capabilities by registering a DeviceSetListener.
* </p>
* @returns {promise} DeviceSetInstance to chain
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus)
* .live()
* .query()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
*/
that.live = function() {
registerListener = true;
return that;
};
/**
* @name query
* @function
* @description
* <p>
* Finally executes DeviceSet query by sending it to the associated EventBus instance.
* </p>
* @returns {promise} Promise which is resolved when query is returned
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus)
* .query()
* .then(function(reply) {
* // success handler
* // ...
* }, function(reply) {
* // error handler
* // ...
* });
* });
*/
that.query = function() {
var deferred = $q.defer();
// register device set listener if configured
if (registerListener) {
// generate UUID
var liveHandlerUUID = 'CLIENT_' + ketaEventBusDispatcher.generateUUID();
// register handler under created UUID
ketaEventBusDispatcher.registerHandler(eventBus, liveHandlerUUID, function(event) {
// inject guid if missing
if (!angular.isDefined(event.value.guid) &&
angular.isDefined(event.value.tagValues)) {
var tagValueKeys = Object.keys(event.value.tagValues);
event.value.guid = event.value.tagValues[tagValueKeys[0]].guid;
}
// process event using sync
api.sync(set, ketaDeviceEvent.create(event.type, event.value), eventBus);
// log if in debug mode
if (ketaEventBusManager.inDebugMode()) {
$log.event([event], $log.ADVANCED_FORMATTER);
}
});
// register device set listener
ketaEventBusDispatcher.send(eventBus, 'deviceservice', {
action: 'registerDeviceSetListener',
body: {
filter: params.filter,
projection: params.projection,
replyAddress: liveHandlerUUID
}
}, function(reply) {
// log if in debug mode
if (ketaEventBusManager.inDebugMode()) {
$log.request(['deviceservice', {
action: 'registerDeviceSetListener',
body: {
filter: params.filter,
projection: params.projection,
replyAddress: liveHandlerUUID
}
}, reply], $log.ADVANCED_FORMATTER);
}
});
}
ketaEventBusDispatcher.send(eventBus, 'deviceservice', {
action: 'getDevices',
params: params
}, function(reply) {
if (reply) {
// inject used params
reply.params = params;
if (reply.code === ketaEventBusDispatcher.RESPONSE_CODE_OK) {
// create DeviceInstances
if (angular.isDefined(reply.result) &&
angular.isDefined(reply.result.items)) {
angular.forEach(reply.result.items, function(item, index) {
reply.result.items[index] = ketaDevice.create(eventBus, item);
});
set = reply;
} else {
set = {};
}
// log if in debug mode
if (ketaEventBusManager.inDebugMode()) {
$log.request(['deviceservice', {
action: 'getDevices',
params: params
}, reply], $log.ADVANCED_FORMATTER);
}
deferred.resolve(reply);
$rootScope.$digest();
} else {
deferred.reject(reply);
}
} else {
deferred.reject('Something bad happened. Got no reply.');
}
});
return deferred.promise;
};
};
/**
* @class DeviceSet
* @propertyOf DeviceSetProvider
* @description DeviceSet Service
*/
api = {
/**
* @name create
* @function
* @description
* <p>
* Creates a DeviceSetInstance with given EventBus instance.
* </p>
* @param {EventBus} eventBus EventBus instance to use for communication
* @returns {DeviceSetInstance} DeviceSetInstance created
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* var deviceSet = ketaDeviceSet.create(eventBus);
* });
*/
create: function(eventBus) {
return new DeviceSetInstance(eventBus);
},
/**
* @name indexOf
* @function
* @description
* <p>
* Returns index of given Device in DeviceSet by comparing GUIDs.
* </p>
* @param {DeviceSetInstance} set DeviceSetInstance to search in
* @param {DeviceInstance} device DeviceInstance to search for
* @returns {number} index
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus).query()
* .then(function(reply) {
* // index equals 0 after the call
* var index = ketaDeviceSet.indexOf(reply, reply.result.items[0]);
* });
* });
*/
indexOf: function(set, device) {
var index = -1;
if (angular.isDefined(set.result) &&
angular.isDefined(set.result.items)) {
angular.forEach(set.result.items, function(item, key) {
if (item.guid === device.guid) {
index = key;
}
});
}
return index;
},
/**
* @name length
* @function
* @description
* <p>
* Returns number of devices in given DeviceSet.
* </p>
* @param {DeviceSetInstance} set DeviceSetInstance to search in
* @returns {number} number of devices
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus).query()
* .then(function(reply) {
* // length equals number of devices in DeviceSet
* var length = ketaDeviceSet.length(reply);
* });
* });
*/
length: function(set) {
var length =
angular.isDefined(set.result) &&
angular.isDefined(set.result.items) &&
angular.isArray(set.result.items) ? set.result.items.length : 0;
return length;
},
/**
* @name get
* @function
* @description
* <p>
* Returns device in given DeviceSet by specified index.
* </p>
* @param {DeviceSetInstance} set DeviceSetInstance to search in
* @param {number} index Index of device to return
* @returns {DeviceInstance} DeviceInstance retrieved from set
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus).query()
* .then(function(reply) {
* // device equals first item after the call
* var device = ketaDeviceSet.get(reply, 0);
* });
* });
*/
get: function(set, index) {
var device =
angular.isDefined(set.result) &&
angular.isDefined(set.result.items) &&
angular.isDefined(set.result.items[index]) ? set.result.items[index] : null;
return device;
},
/**
* @name getAll
* @function
* @description
* <p>
* Returns all devices in given DeviceSet.
* </p>
* @param {DeviceSetInstance} set DeviceSetInstance to search in
* @returns {Array} All DeviceInstances retrieved from set
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet) {
* ketaDeviceSet.create(eventBus).query()
* .then(function(reply) {
* var devices = ketaDeviceSet.getAll(reply);
* });
* });
*/
getAll: function(set) {
var devices =
angular.isDefined(set.result) &&
angular.isDefined(set.result.items) ? set.result.items : [];
return devices;
},
/**
* @name sync
* @function
* @description
* <p>
* Synchronizes given DeviceSet with given DeviceEvent.
* </p>
* @param {DeviceSetInstance} set DeviceSetInstance to sync
* @param {DeviceEventInstance} event DeviceEventInstance to process
* @param {EventBus} eventBus EventBus instance to use for communication
* @returns {void} returns nothing
* @example
* angular.module('exampleApp', ['keta.services.DeviceSet'])
* .controller('ExampleController', function(ketaDeviceSet, ketaDeviceEvent, ketaDevice) {
* ketaDeviceSet.sync(
* ketaDeviceSet.create().query(),
* ketaDeviceEvent.create({
* type: ketaDeviceEvent.CREATED,
* device: ketaDevice.create(eventBus, {
* guid: 'guid'
* });
* });
* );
* });
*/
sync: function(set, event, eventBus) {
var modified = false;
var device = ketaDevice.create(eventBus, event.getDevice());
if (event.getType() === ketaDeviceEvent.CREATED) {
set.result.items.push(device);
modified = true;
} else if (event.getType() === ketaDeviceEvent.DELETED) {
set.result.items.splice(api.indexOf(set, device), 1);
modified = true;
} else if (event.getType() === ketaDeviceEvent.UPDATED) {
var index = api.indexOf(set, device);
if (index !== -1) {
angular.extend(api.get(set, index), device);
modified = true;
}
}
// trigger scope digest if anything was modified and not automatically triggered
if (modified && !$rootScope.$$phase) {
$rootScope.$apply();
}
}
};
return api;
};
});