UNPKG

diffusion

Version:

Diffusion JavaScript client

240 lines (201 loc) 8.09 kB
var _implements = require('util/interface')._implements; var Set = require('core-js/library/fn/set'); var Services = require('services/services'); var Emitter = require('events/emitter'); var Result = require('events/result'); var DataTypes = require('data/datatypes'); var logger = require('util/logger').create('diffusion.locks.SessionLocks'); var parseSelector = require('topics/topic-selector-parser'); var FetchResult = require('features/topics/fetch-result'); var FetchQuery = require('services/fetch-query/fetch-query'); var api = require('../../../topics/fetch-request'); var TopicType = require('../../../topics/topic-type'); var TIME_SERIES_DATA_TYPE = FetchResult.TIME_SERIES_DATA_TYPE; var Limit = function(path, includesPath) { this.path = path; this.includesPath = includesPath; }; var FetchRange = function(from, to) { this.from = from; this.to = to; this.isUnbounded = function() { return this.from===undefined && this.to===undefined; }; }; /** * Indicates whether a specified topic type can be read as a specified * data type. * * @param {TopicType} topicType the topic type * @param {diffusion.datatypes.DataType} dataType the data type * * @returns {Boolean} true if the topic type can be read as the data type * @function diffusion.topics.FetchRequestImpl#canReadAs */ function canReadAs(topicType, dataType) { if (topicType === TopicType.TIME_SERIES) { return TIME_SERIES_DATA_TYPE.canReadAs(dataType); } else { var topicDataType = DataTypes.getByValue(topicType); return topicDataType !== null && topicDataType.canReadAs(dataType.valueClass); } } var FetchRequestImpl = _implements( api.FetchRequest, function FetchRequestImpl(internal, opts) { var defaultOptions = { range: new FetchRange(), topicTypes: api.FetchRequest.getAllTypes(), dataType: undefined, withProperties: false, limit: 0, maximumResultSize: internal.getOptions().maxMessageSize }; var options = Object.assign(defaultOptions, opts); function copyOptions() { return { range: new FetchRange(options.range.from, options.range.to), topicTypes: new Set(options.topicTypes), dataType: options.dataType, withProperties: options.withProperties, limit: options.limit, maximumResultSize: options.maximumResultSize }; } this.from = function(topicPath) { var limit = new Limit(topicPath, true); return new FetchRequestImpl( internal, Object.assign(copyOptions(), {range: new FetchRange(limit, options.range.to)}) ); }; this.after = function(topicPath) { var limit = new Limit(topicPath, false); return new FetchRequestImpl( internal, Object.assign(copyOptions(), {range: new FetchRange(limit, options.range.to)}) ); }; this.to = function(topicPath) { var limit = new Limit(topicPath, true); return new FetchRequestImpl( internal, Object.assign(copyOptions(), {range: new FetchRange(options.range.from, limit)}) ); }; this.before = function(topicPath) { var limit = new Limit(topicPath, false); return new FetchRequestImpl( internal, Object.assign(copyOptions(), {range: new FetchRange(options.range.from, limit)}) ); }; this.topicTypes = function(topicTypes) { if (topicTypes.length===0) { throw new Error("No types specified"); } var allTypes = api.FetchRequest.getAllTypes(); // Ensure that those supplied are valid and if there is a value // class that the types can be read as the value class. topicTypes.forEach(function (topicType) { if (!allTypes.has(topicType)) { throw new Error("Invalid topic type " + topicType.id); } if (options.dataType !== undefined && !canReadAs(topicType, options.dataType)) { throw new Error("Topic type " + topicType.id + " cannot be read as " + options.dataType); } }); return new FetchRequestImpl( internal, Object.assign(copyOptions(), {topicTypes: new Set(topicTypes)}) ); }; this.withValues = function(dataType) { var selectedTopicTypes; if (dataType !== undefined) { selectedTopicTypes = new Set(options.topicTypes); options.topicTypes.forEach(function (topicType) { if (!canReadAs(topicType, dataType)) { selectedTopicTypes.delete(topicType); } }); if (selectedTopicTypes.size===0) { throw new Error("No selected topic types can be read as " + dataType); } } else { selectedTopicTypes = options.topicTypes; } return new FetchRequestImpl( internal, Object.assign(copyOptions(), {topicTypes: selectedTopicTypes, dataType: dataType}) ); }; this.withProperties = function() { return new FetchRequestImpl( internal, Object.assign(copyOptions(), {withProperties: true}) ); }; this.first = function(number) { if (!Number.isInteger(number) || number<1) { throw new Error("Invalid argument "+number); } return new FetchRequestImpl( internal, Object.assign(copyOptions(), {limit: number}) ); }; this.last = function(number) { if (!Number.isInteger(number) || number<1) { throw new Error("Invalid argument "+number); } return new FetchRequestImpl( internal, Object.assign(copyOptions(), {limit: 0-number}) ); }; this.maximumResultSize = function(maximumSize) { if (!Number.isInteger(maximumSize) || maximumSize<0) { throw new Error("Invalid argument "+maximumSize); } return new FetchRequestImpl( internal, Object.assign(copyOptions(), { maximumResultSize: Math.min(maximumSize, internal.getOptions().maxMessageSize) }) ); }; this.fetch = function(topics) { var emitter = new Emitter(); var result = new Result(emitter); var serviceLocator = internal.getServiceLocator(); var FETCH_QUERY = serviceLocator.obtain(Services.FETCH_QUERY); var selector = (arguments.length>1) ? parseSelector(Array.prototype.slice.call(arguments)) : parseSelector(topics); var query = new FetchQuery( selector, options.range, options.topicTypes, options.dataType!==undefined, options.withProperties, options.limit, options.maximumResultSize ); FETCH_QUERY.send(query, function(err, fetchQueryResult) { if (err) { logger.debug('Fetch query failed'); emitter.error(err); } else { var fetchResult = new FetchResult(options.dataType, fetchQueryResult); emitter.emit('complete', fetchResult); } }); return result; }; } ); module.exports = FetchRequestImpl;