diffusion
Version:
Diffusion JavaScript client
240 lines (201 loc) • 8.09 kB
JavaScript
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;