@genialis/resolwe
Version:
Resolwe frontend libraries
583 lines (582 loc) • 71.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var angular = require("angular");
var _ = require("lodash");
var Rx = require("rx");
var lang_1 = require("../utils/lang");
var error_1 = require("../errors/error");
var DirectiveType;
(function (DirectiveType) {
DirectiveType[DirectiveType["COMPONENT"] = 0] = "COMPONENT";
DirectiveType[DirectiveType["ATTRIBUTE"] = 1] = "ATTRIBUTE";
})(DirectiveType || (DirectiveType = {}));
function safeCallbackApply($scope, callback) {
if ($scope.$$destroyed) {
return;
}
callback();
$scope.$evalAsync();
}
function safeApply(observable, scope, callback) {
callback = angular.isFunction(callback) ? callback : _.noop;
return observable.takeWhile(function () {
return !scope['$$destroyed'];
}).tap(function (data) {
safeCallbackApply(scope, function () { callback(data); });
});
}
/**
* Abstraction of a computation with dependencies to observables.
*/
var Computation = /** @class */ (function () {
/**
* Constructs a new computation.
*
* @param component Owning component
* @param content Computation content
*/
function Computation(component, content) {
this.component = component;
this.content = content;
this._subscriptions = [];
this._pendingSubscriptions = [];
this._dispose = function () { };
this._done = false;
}
/**
* Return true if this computation has finished.
*/
Computation.prototype.isDone = function () {
return this._done;
};
/**
* Sets an alternative dispose callback for this computation. This callback
* is invoked when [[unsubscribe]] is called.
*/
Computation.prototype.setDisposeCallback = function (callback) {
this._dispose = callback;
};
/**
* Subscribes to an observable, registering the subscription as a dependency
* of this component. The subscription is automatically stopped when the
* component is destroyed.
*
* For the target argument, you can either specify a string, in which case
* it represents the name of the component member variable that will be
* populated with the result ite. Or you can specify a function with one
* argument, which will be called when query results change and can do
* anything.
*
* @param target Target component member atribute name or callback
* @param observable Observable or promise to subscribe to
* @return Underlying subscription disposable
*/
Computation.prototype.subscribe = function (target, observable, options) {
var _this = this;
if (options === void 0) { options = {}; }
// Create a guard object that can be removed when a subscription is done. We need
// to use guard objects instead of a simple reference counter because the pending
// subscriptions array may be cleared while callbacks are still outstanding.
var guard = new Object();
if (!options.ignoreReady) {
this._pendingSubscriptions.push(guard);
}
var convertedObservable;
if (lang_1.isPromiseLike(observable)) {
convertedObservable = Rx.Observable.fromPromise(observable);
}
else {
convertedObservable = observable;
}
var releaseGuard = function () {
_this._pendingSubscriptions = _.without(_this._pendingSubscriptions, guard);
};
convertedObservable = convertedObservable.tap(releaseGuard, releaseGuard);
var subscription = safeApply(convertedObservable, this.component.$scope, function (item) {
try {
if (_.isFunction(target)) {
target(item);
}
else {
_this.component[target] = item;
}
}
catch (exception) {
console.warn('Ignored error in ' + _this.component.getConfig().directive, exception);
}
finally {
// Dispose of the subscription immediately if this is a one shot subscription.
if (options.oneShot && subscription) {
subscription.dispose();
}
}
}).subscribe(
// Success handler.
_.noop,
// Error handler.
function (exception) {
if (options.onError) {
console.log('Handled error in ' + _this.component.getConfig().directive, exception);
safeCallbackApply(_this.component.$scope, function () { options.onError(exception); });
}
else {
console.warn('Unhandled error in ' + _this.component.getConfig().directive, exception);
}
});
this._subscriptions.push(subscription);
return subscription;
};
/**
* Returns true if all subscriptions created by calling `subscribe` are ready.
* A subscription is ready when it has received its first batch of data after
* subscribing.
*/
Computation.prototype.subscriptionsReady = function () {
return this._pendingSubscriptions.length === 0;
};
/**
* Runs the computation.
*/
Computation.prototype.compute = function () {
// Stop all subscriptions before running again.
this.stop();
this.content(this);
};
/**
* Disposes of all registered subscriptions.
*/
Computation.prototype.stop = function () {
for (var _i = 0, _a = this._subscriptions; _i < _a.length; _i++) {
var subscription = _a[_i];
subscription.dispose();
}
this._subscriptions = [];
this._pendingSubscriptions = [];
};
/**
* Stops all subscriptions currently registered in this computation and removes
* this computation from the parent component. If a dispose handler has been
* configured, it is invoked.
*/
Computation.prototype.unsubscribe = function () {
this.component.unsubscribe(this);
if (this._dispose)
this._dispose();
this._done = true;
};
return Computation;
}());
exports.Computation = Computation;
/**
* An abstract base class for all components.
*/
var ComponentBase = /** @class */ (function () {
// @ngInject
ComponentBase.$inject = ["$scope"];
function ComponentBase($scope) {
var _this = this;
this.$scope = $scope;
// Computations.
this._computations = [];
// Component state.
this._ready = false;
$scope.$on('$destroy', function () {
_this._ready = false;
// Ensure that all computations get stopped when the component is destroyed.
for (var _i = 0, _a = _this._computations; _i < _a.length; _i++) {
var computation = _a[_i];
computation.stop();
}
_this._computations = [];
// Call destroyed hook.
_this.onComponentDestroyed();
});
// Angular calls $onInit after constructor and bindings initialization.
this['$onInit'] = function () {
_this.onComponentInit();
};
}
/**
* This method will be called after the whole chain of constructors is executed,
* via angular component $onInit. Use it if you have an abstract component that
* manipulates class properties and, as a result, needs to wait for all child
* class properties to be assigned and constructors to finish. (Class properties
* defined in child components are assigned before child's constructor).
*
* Value of `$compileProvider.preAssignBindingsEnabled` (false by default since angular 1.6.0)
* determines if bindings are to be present in `onComponentInit` method (false) or pre-assigned
* in constructor (true).
*
* Order of execution:
* ```ts
* class Child extends Middle {
* public propertyA = 'c' // 5
* constructor() { super() } // 6
* }
* class Middle extends Abstract {
* public propertyB = 'b' // 3
* constructor() { super() } // 4
* }
* class Abstract {
* public propertyA = 'a' // 1
* constructor() {} // 2
* onComponentInit() {} // 7
* }
* ```
*/
ComponentBase.prototype.onComponentInit = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
// Default implementation does nothing.
};
/**
* Destroys the component.
*/
ComponentBase.prototype.destroy = function () {
this.$scope.$destroy();
};
/**
* This method will be called in the compile phase of the directive and may
* be overriden by component implementations.
*/
ComponentBase.onComponentCompile = function (element, attributes) {
// Default implementation does nothing.
};
/**
* @internal
*/
ComponentBase.prototype._onComponentLink = function (scope, element, attributes) {
var args = [];
for (var _i = 3; _i < arguments.length; _i++) {
args[_i - 3] = arguments[_i];
}
try {
// Call the public method that can be overriden by the user.
this.onComponentLink.apply(this, [scope, element, attributes].concat(args));
}
finally {
this._ready = true;
}
};
/**
* This method will be called in the post-link phase of the directive and may
* be overriden by component implementations.
*/
ComponentBase.prototype.onComponentLink = function (scope, element, attributes) {
var args = [];
for (var _i = 3; _i < arguments.length; _i++) {
args[_i - 3] = arguments[_i];
}
// Default implementation does nothing.
};
/**
* This method will be called after the component scope has been destroyed.
*/
ComponentBase.prototype.onComponentDestroyed = function () {
// Default implementation does nothing.
};
/**
* Returns true if the component has been created.
*/
ComponentBase.prototype.isReady = function () {
return this._ready;
};
/**
* Returns true if all subscriptions created by calling `subscribe` are ready.
* A subscription is ready when it has received its first batch of data after
* subscribing.
*/
ComponentBase.prototype.subscriptionsReady = function () {
// Wait until the component has been created.
if (!this.isReady())
return false;
return _.every(this._computations, function (computation) { return computation.subscriptionsReady(); });
};
ComponentBase.prototype._createComputation = function (content) {
if (content === void 0) { content = _.noop; }
var computation = new Computation(this, content);
this._computations.push(computation);
return computation;
};
/**
* Watch component scope and run a computation on changes. The computation is
* executed once immediately prior to watching.
*
* Returned computation instance may be used to stop the watch by calling its
* [[Computation.unsubscribe]] method.
*
* @param context Function which returns the context to watch
* @param content Function to run on changes
* @param objectEquality Should `angular.equals` be used for comparisons
* @returns Computation instance
*/
ComponentBase.prototype.watch = function (context, content, objectEquality) {
var computation = this._createComputation(content);
computation.compute();
// Initial evaluation may stop the computation. In this case, don't
// even create a watch and just return the (done) computation.
if (computation.isDone())
return computation;
var expressions = Array.isArray(context) ? context : [context];
if (!objectEquality) {
var unwatch = this.$scope.$watchGroup(expressions, computation.compute.bind(computation));
computation.setDisposeCallback(unwatch);
return computation;
}
else {
var watchedExpression = function () { return _.map(expressions, function (fn) { return fn(); }); };
if (expressions.length === 1) { // optimize
watchedExpression = expressions[0];
}
var unwatch = this.$scope.$watch(watchedExpression, computation.compute.bind(computation), true);
computation.setDisposeCallback(unwatch);
return computation;
}
};
/**
* Watch component scope and run a computation on changes. This version uses Angular's
* collection watch. The computation is executed once immediately prior to watching.
*
* Returned computation instance may be used to stop the watch by calling its
* [[Computation.unsubscribe]] method.
*
* @param context Function which returns the context to watch
* @param content Function to run on changes
* @returns Computation instance
*/
ComponentBase.prototype.watchCollection = function (context, content) {
var computation = this._createComputation(content);
computation.compute();
// Initial evaluation may stop the computation. In this case, don't
// even create a watch and just return the (done) computation.
if (computation.isDone())
return computation;
var unwatch = this.$scope.$watchCollection(context, computation.compute.bind(computation));
computation.setDisposeCallback(unwatch);
return computation;
};
/**
* Subscribes to an observable, registering the subscription as a dependency
* of this component. The subscription is automatically stopped when the
* component is destroyed.
*
* For the target argument, you can either specify a string, in which case
* it represents the name of the component member variable that will be
* populated with the result ite. Or you can specify a function with one
* argument, which will be called when query results change and can do
* anything.
*
* @param target Target component member atribute name or callback
* @param observable Observable to subscribe to
* @return Underlying subscription
*/
ComponentBase.prototype.subscribe = function (target, observable, options) {
if (options === void 0) { options = {}; }
var computation = this._createComputation();
computation.subscribe(target, observable, options);
return computation;
};
/**
* Unsubscribes the given computation from this component.
*
* @param computation Computation instance
*/
ComponentBase.prototype.unsubscribe = function (computation) {
computation.stop();
_.pull(this._computations, computation);
};
/**
* Helper function to create a wrapper observable around watch.
*
* @param context Function which returns the context to watch
* @param objectEquality Should `angular.equals` be used for comparisons
* @returns Watch observable
*/
ComponentBase.prototype.createWatchObservable = function (context, objectEquality) {
var _this = this;
var notifyObserver = function (observer) {
observer.onNext(context());
};
return Rx.Observable.create(function (observer) {
notifyObserver(observer);
var computation = _this.watch(context, function () { return notifyObserver(observer); }, objectEquality);
return function () { computation.unsubscribe(); };
});
};
/**
* Returns component configuration.
*/
ComponentBase.getConfig = function () {
return this.__componentConfig;
};
/**
* Returns component configuration.
*/
ComponentBase.prototype.getConfig = function () {
return this.constructor.getConfig();
};
/**
* Returns true if the component has a specified attribute configured as
* a binding.
*
* @param name Name of the bound attribute
*/
ComponentBase.hasBinding = function (name) {
return _.some(this.__componentConfig.bindings, function (value, key) {
// In case no attribute name is specified, compare the binding key,
// otherwise compare the attribute name.
var matchedName = value.replace(/^[=@&<]\??/, '');
var boundAttribute = matchedName || key;
return boundAttribute === name;
});
};
/**
* Returns a view configuration that renders this component. This method can be
* used when configuring the Angular UI router as follows:
*
* $stateProvider.state('foo', {
* url: '/foo',
* views: { application: MyComponent.asView() },
* });
*/
ComponentBase.asView = function (options) {
var _this = this;
if (options === void 0) { options = {}; }
var template = '<' + this.__componentConfig.directive;
var attributes = options.attributes || {};
// Setup input bindings.
if (!_.isEmpty(options.inputs)) {
_.forOwn(options.inputs, function (input, key) {
if (!_this.hasBinding(key)) {
throw new error_1.GenError("Input '" + key + "' is not defined on component.");
}
attributes[key] = input;
});
}
// Generate attributes.
if (!_.isEmpty(attributes)) {
_.forOwn(attributes, function (attribute, attributeName) {
if (_.contains(attribute, '"')) {
throw new error_1.GenError("asView attribute '" + attribute + "' is currently not supported.");
}
// TODO: Properly escape attribute values.
template += ' ' + _.kebabCase(attributeName) + '="' + attribute + '"';
});
}
template += '></' + this.__componentConfig.directive + '>';
var result = {
template: template,
};
// Setup parent scope for the intermediate template.
if (options.parent) {
result.scope = options.parent.$scope;
}
return _.extend(result, options.extendWith || {});
};
/**
* Performs any modifications of the component configuration. This method is
* invoked during component class decoration and may arbitrarily modify the
* passed component configuration, before the component is registered with
* Angular.
*
* @param config Component configuration
* @return Modified component configuration
*/
ComponentBase.configureComponent = function (config) {
return config;
};
return ComponentBase;
}());
exports.ComponentBase = ComponentBase;
function directiveFactory(config, type) {
return function (target) {
// Store component configuration on the component, extending configuration obtained from base class.
if (target.__componentConfig) {
target.__componentConfig = _.cloneDeep(target.__componentConfig);
// Don't inherit the abstract flag as otherwise you would be required to explicitly
// set it to false in all subclasses.
delete target.__componentConfig.abstract;
_.merge(target.__componentConfig, config);
}
else {
target.__componentConfig = config;
}
config = target.configureComponent(target.__componentConfig);
if (!config.abstract) {
// If module or directive is not defined for a non-abstract component, this is an error.
if (!config.directive) {
throw new error_1.GenError("Directive not defined for component.");
}
if (!_.startsWith(config.directive, 'gen-')) {
throw new error_1.GenError("Directive not prefixed with \"gen-\": " + config.directive);
}
if (!config.module) {
throw new error_1.GenError("Module not defined for component '" + config.directive + "'.");
}
if (_.any(config.bindings, function (value, key) { return _.startsWith(value.substring(1) || key, 'data'); })) {
throw new Error("Bindings should not start with 'data'");
}
config.module.directive(_.camelCase(config.directive), function () {
var controllerBinding = config.controllerAs || 'ctrl';
var result = {
scope: {},
bindToController: config.bindings || {},
controller: target,
controllerAs: controllerBinding,
compile: function (element, attributes) {
// Call the compile life-cycle static method.
target.onComponentCompile(element, attributes);
return function (scope, element, attributes) {
var _a;
var args = [];
for (var _i = 3; _i < arguments.length; _i++) {
args[_i - 3] = arguments[_i];
}
// Get controller from the scope and call the link life-cycle method.
(_a = scope[controllerBinding])._onComponentLink.apply(_a, [scope, element, attributes].concat(args));
};
},
templateUrl: config.templateUrl,
template: config.template,
transclude: config.transclude,
require: config.require,
};
switch (type) {
case DirectiveType.COMPONENT: {
result.restrict = 'E';
break;
}
case DirectiveType.ATTRIBUTE: {
result.restrict = 'A';
break;
}
default: {
// TODO: use error handler
throw new error_1.GenError("Unknown type " + type);
}
}
return result;
});
}
return target;
};
}
/**
* A decorator that transforms the decorated class into an AngularJS
* component directive with proper dependency injection.
*/
function component(config) {
return directiveFactory(config, DirectiveType.COMPONENT);
}
exports.component = component;
/**
* A decorator that transforms the decorated class into an AngularJS
* attribute directive with proper dependency injection.
*/
function directive(config) {
return directiveFactory(config, DirectiveType.ATTRIBUTE);
}
exports.directive = directive;
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFtQztBQUNuQywwQkFBNEI7QUFDNUIsdUJBQXlCO0FBRXpCLHNDQUE0QztBQUM1Qyx5Q0FBeUM7QUFFekMsSUFBSyxhQUdKO0FBSEQsV0FBSyxhQUFhO0lBQ2QsMkRBQVMsQ0FBQTtJQUNULDJEQUFTLENBQUE7QUFDYixDQUFDLEVBSEksYUFBYSxLQUFiLGFBQWEsUUFHakI7QUEyQ0QsU0FBUyxpQkFBaUIsQ0FBQyxNQUFzQixFQUFFLFFBQW9CO0lBQ25FLElBQVcsTUFBTyxDQUFDLFdBQVcsRUFBRTtRQUM1QixPQUFPO0tBQ1Y7SUFFRCxRQUFRLEVBQUUsQ0FBQztJQUNYLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUN4QixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUksVUFBNEIsRUFBRSxLQUFxQixFQUFFLFFBQTJCO0lBQ2xHLFFBQVEsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFFNUQsT0FBTyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQ3hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDakMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQUMsSUFBSTtRQUNSLGlCQUFpQixDQUFDLEtBQUssRUFBRSxjQUFRLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hELENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVEOztHQUVHO0FBQ0g7SUFNSTs7Ozs7T0FLRztJQUNILHFCQUFtQixTQUF3QixFQUFTLE9BQTRCO1FBQTdELGNBQVMsR0FBVCxTQUFTLENBQWU7UUFBUyxZQUFPLEdBQVAsT0FBTyxDQUFxQjtRQUM1RSxJQUFJLENBQUMsY0FBYyxHQUFH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QVMsQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFGRCw4QkFFQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLFNBQVMsQ0FBQyxNQUE4QjtJQUNwRCxPQUF3QixnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFGRCw4QkFFQyIsImZpbGUiOiJjb3JlL2NvbXBvbmVudHMvYmFzZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFuZ3VsYXIgZnJvbSAnYW5ndWxhcic7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyBSeCBmcm9tICdyeCc7XG5cbmltcG9ydCB7aXNQcm9taXNlTGlrZX0gZnJvbSAnLi4vdXRpbHMvbGFuZyc7XG5pbXBvcnQge0dlbkVycm9yfSBmcm9tICcuLi9lcnJvcnMvZXJyb3InO1xuXG5lbnVtIERpcmVjdGl2ZVR5cGUge1xuICAgIENPTVBPTkVOVCxcbiAgICBBVFRSSUJVVEUsXG59XG5cbi8qKlxuICogQ29tcG9uZW50IGNvbmZpZ3VyYXRpb24uIERpcmVjdGl2ZSBuYW1lIHNob3VsZCBiZSBpbiBkYXNoLWNhc2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcG9uZW50Q29uZmlndXJhdGlvbiB7XG4gICAgYWJzdHJhY3Q/OiBib29sZWFuO1xuICAgIG1vZHVsZT86IGFuZ3VsYXIuSU1vZHVsZTtcbiAgICBkaXJlY3RpdmU/OiBzdHJpbmc7XG4gICAgYmluZGluZ3M/OiBfLkRpY3Rpb25hcnk8c3RyaW5nPjtcbiAgICBjb250cm9sbGVyQXM/OiBzdHJpbmc7XG4gICAgdGVtcGxhdGVVcmw/OiBzdHJpbmc7XG4gICAgdGVtcGxhdGU/OiBzdHJpbmc7XG4gICAgdHJhbnNjbHVkZT86IGJvb2xlYW4gfCB7W3Nsb3Q6IHN0cmluZ106IHN0cmluZ307XG4gICAgcmVxdWlyZT86IHN0cmluZyB8IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudFZpZXdPcHRpb25zIHtcbiAgICBpbnB1dHM/OiBPYmplY3Q7XG4gICAgcGFyZW50PzogQ29tcG9uZW50QmFzZTtcbiAgICBhdHRyaWJ1dGVzPzogT2JqZWN0O1xuICAgIGV4dGVuZFdpdGg/OiBPYmplY3Q7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0YXRpb25GdW5jdGlvbiB7XG4gICAgKGNvbXB1dGF0aW9uOiBDb21wdXRhdGlvbik6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3Vic2NyaXB0aW9uIHtcbiAgICB1bnN1YnNjcmliZSgpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN1YnNjcmliZUNvbXBvbmVudE9wdGlvbnMge1xuICAgIG9uZVNob3Q/OiBib29sZWFuO1xuICAgIG9uRXJyb3I/OiAoZXhjZXB0aW9uOiBhbnkpID0+IHZvaWQ7XG5cbiAgICAvLyBTZXQgdGhpcyB0byB0cnVlIHRvIG1ha2UgdGhlIHN1YnNjcmlwdGlvbiBiZSBpZ25vcmVkIHdoZW4gZGV0ZXJtaW5pbmdcbiAgICAvLyB3aGV0aGVyIHRoZSBjb21wb25lbnQgaXMgZG9uZSB3YWl0aW5nIGZvciBzdWJzY3JpcHRpb25zLlxuICAgIGlnbm9yZVJlYWR5PzogYm9vbGVhbjtcbn1cblxudHlwZSBTdWJzY3JpcHRpb25HdWFyZCA9IHt9O1xuXG5mdW5jdGlvbiBzYWZlQ2FsbGJhY2tBcHBseSgkc2NvcGU6IGFuZ3VsYXIuSVNjb3BlLCBjYWxsYmFjazogKCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIGlmICgoPGFueT4gJHNjb3BlKS4kJGRlc3Ryb3llZCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY2FsbGJhY2soKTtcbiAgICAkc2NvcGUuJGV2YWxBc3luYygpO1xufVxuXG5mdW5jdGlvbiBzYWZlQXBwbHk8VD4ob2JzZXJ2YWJsZTogUnguT2JzZXJ2YWJsZTxUPiwgc2NvcGU6IGFuZ3VsYXIuSVNjb3BlLCBjYWxsYmFjazogKGRhdGE6IFQpID0+IHZvaWQpIHtcbiAgICBjYWxsYmFjayA9IGFuZ3VsYXIuaXNGdW5jdGlvbihjYWxsYmFjaykgPyBjYWxsYmFjayA6IF8ubm9vcDtcblxuICAgIHJldHVybiBvYnNlcnZhYmxlLnRha2VXaGlsZSgoKSA9PiB7XG4gICAgICAgIHJldHVybiAhc2NvcGVbJyQkZGVzdHJveWVkJ107XG4gICAgfSkudGFwKChkYXRhKSA9PiB7XG4gICAgICAgIHNhZmVDYWxsYmFja0FwcGx5KHNjb3BlLCAoKSA9PiB7IGNhbGxiYWNrKGRhdGEpOyB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBBYnN0cmFjdGlvbiBvZiBhIGNvbXB1dGF0aW9uIHdpdGggZGVwZW5kZW5jaWVzIHRvIG9ic2VydmFibGVzLlxuICovXG5leHBvcnQgY2xhc3MgQ29tcHV0YXRpb24ge1xuICAgIHByaXZhdGUgX3N1YnNjcmlwdGlvbnM6IFJ4LkRpc3Bvc2FibGVbXTtcbiAgICBwcml2YXRlIF9wZW5kaW5nU3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uR3VhcmRbXTtcbiAgICBwcml2YXRlIF9kaXNwb3NlOiAoKSA9PiB2b2lkO1xuICAgIHByaXZhdGUgX2RvbmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IGNvbXB1dGF0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIGNvbXBvbmVudCBPd25pbmcgY29tcG9uZW50XG4gICAgICogQHBhcmFtIGNvbnRlbnQgQ29tcHV0YXRpb24gY29udGVudFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBjb21wb25lbnQ6IENvbXBvbmVudEJhc2UsIHB1YmxpYyBjb250ZW50OiBDb21wdXRhdGlvbkZ1bmN0aW9uKSB7IC8vIHRzbGludDpkaXNhYmxlLWxpbmU6bm8tc2hhZG93ZWQtdmFyaWFibGVcbiAgICAgICAgdGhpcy5fc3Vic2NyaXB0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLl9wZW5kaW5nU3Vic2NyaXB0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLl9kaXNwb3NlID0gKCkgPT4geyAvKiBEbyBub3RoaW5nIGJ5IGRlZmF1bHQuICovIH07XG4gICAgICAgIHRoaXMuX2RvbmUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdHJ1ZSBpZiB0aGlzIGNvbXB1dGF0aW9uIGhhcyBmaW5pc2hlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgaXNEb25lKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fZG9uZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGFuIGFsdGVybmF0aXZlIGRpc3Bvc2UgY2FsbGJhY2sgZm9yIHRoaXMgY29tcHV0YXRpb24uIFRoaXMgY2FsbGJhY2tcbiAgICAgKiBpcyBpbnZva2VkIHdoZW4gW1t1bnN1YnNjcmliZV1dIGlzIGNhbGxlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0RGlzcG9zZUNhbGxiYWNrKGNhbGxiYWNrOiAoKSA9PiB2b2lkKSB7XG4gICAgICAgIHRoaXMuX2Rpc3Bvc2UgPSBjYWxsYmFjaztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGFuIG9ic2VydmFibGUsIHJlZ2lzdGVyaW5nIHRoZSBzdWJzY3JpcHRpb24gYXMgYSBkZXBlbmRlbmN5XG4gICAgICogb2YgdGhpcyBjb21wb25lbnQuIFRoZSBzdWJzY3JpcHRpb24gaXMgYXV0b21hdGljYWxseSBzdG9wcGVkIHdoZW4gdGhlXG4gICAgICogY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICAgKlxuICAgICAqIEZvciB0aGUgdGFyZ2V0IGFyZ3VtZW50LCB5b3UgY2FuIGVpdGhlciBzcGVjaWZ5IGEgc3RyaW5nLCBpbiB3aGljaCBjYXNlXG4gICAgICogaXQgcmVwcmVzZW50cyB0aGUgbmFtZSBvZiB0aGUgY29tcG9uZW50IG1lbWJlciB2YXJpYWJsZSB0aGF0IHdpbGwgYmVcbiAgICAgKiBwb3B1bGF0ZWQgd2l0aCB0aGUgcmVzdWx0IGl0ZS4gT3IgeW91IGNhbiBzcGVjaWZ5IGEgZnVuY3Rpb24gd2l0aCBvbmVcbiAgICAgKiBhcmd1bWVudCwgd2hpY2ggd2lsbCBiZSBjYWxsZWQgd2hlbiBxdWVyeSByZXN1bHRzIGNoYW5nZSBhbmQgY2FuIGRvXG4gICAgICogYW55dGhpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0IFRhcmdldCBjb21wb25lbnQgbWVtYmVyIGF0cmlidXRlIG5hbWUgb3IgY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0gb2JzZXJ2YWJsZSBPYnNlcnZhYmxlIG9yIHByb21pc2UgdG8gc3Vic2NyaWJlIHRvXG4gICAgICogQHJldHVybiBVbmRlcmx5aW5nIHN1YnNjcmlwdGlvbiBkaXNwb3NhYmxlXG4gICAgICovXG4gICAgcHVibGljIHN1YnNjcmliZTxUPih0YXJnZXQ6IHN0cmluZyB8ICgoZGF0YTogVCkgPT4gYW55KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmFibGU6IFJ4Lk9ic2VydmFibGU8VD4gfCBQcm9taXNlPGFueT4gfCBhbmd1bGFyLklQcm9taXNlPGFueT4sXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zOiBTdWJzY3JpYmVDb21wb25lbnRPcHRpb25zID0ge30pIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgZ3VhcmQgb2JqZWN0IHRoYXQgY2FuIGJlIHJlbW92ZWQgd2hlbiBhIHN1YnNjcmlwdGlvbiBpcyBkb25lLiBXZSBuZWVkXG4gICAgICAgIC8vIHRvIHVzZSBndWFyZCBvYmplY3RzIGluc3RlYWQgb2YgYSBzaW1wbGUgcmVmZXJlbmNlIGNvdW50ZXIgYmVjYXVzZSB0aGUgcGVuZGluZ1xuICAgICAgICAvLyBzdWJzY3JpcHRpb25zIGFycmF5IG1heSBiZSBjbGVhcmVkIHdoaWxlIGNhbGxiYWNrcyBhcmUgc3RpbGwgb3V0c3RhbmRpbmcuXG4gICAgICAgIGNvbnN0IGd1YXJkID0gbmV3IE9iamVjdCgpO1xuICAgICAgICBpZiAoIW9wdGlvbnMuaWdub3JlUmVhZHkpIHtcbiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdTdWJzY3JpcHRpb25zLnB1c2goZ3VhcmQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbnZlcnRlZE9ic2VydmFibGU6IFJ4Lk9ic2VydmFibGU8VD47XG4gICAgICAgIGlmIChpc1Byb21pc2VMaWtlKG9ic2VydmFibGUpKSB7XG4gICAgICAgICAgICBjb252ZXJ0ZWRPYnNlcnZhYmxlID0gUnguT2JzZXJ2YWJsZS5mcm9tUHJvbWlzZShvYnNlcnZhYmxlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnZlcnRlZE9ic2VydmFibGUgPSBvYnNlcnZhYmxlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVsZWFzZUd1YXJkID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcGVuZGluZ1N1YnNjcmlwdGlvbnMgPSBfLndpdGhvdXQodGhpcy5fcGVuZGluZ1N1YnNjcmlwdGlvbnMsIGd1YXJkKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29udmVydGVkT2JzZXJ2YWJsZSA9IGNvbnZlcnRlZE9ic2VydmFibGUudGFwKHJlbGVhc2VHdWFyZCwgcmVsZWFzZUd1YXJkKTtcblxuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBzYWZlQXBwbHkoXG4gICAgICAgICAgICBjb252ZXJ0ZWRPYnNlcnZhYmxlLFxuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQuJHNjb3BlLFxuICAgICAgICAgICAgKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXy5pc0Z1bmN0aW9uKHRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcG9uZW50W3RhcmdldF0gPSBpdGVtO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSWdub3JlZCBlcnJvciBpbiAnICsgdGhpcy5jb21wb25lbnQuZ2V0Q29uZmlnKCkuZGlyZWN0aXZlLCBleGNlcHRpb24pO1xuICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIERpc3Bvc2Ugb2YgdGhlIHN1YnNjcmlwdGlvbiBpbW1lZGlhdGVseSBpZiB0aGlzIGlzIGEgb25lIHNob3Qgc3Vic2NyaXB0aW9uLlxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5vbmVTaG90ICYmIHN1YnNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgKS5zdWJzY3JpYmUoXG4gICAgICAgICAgICAvLyBTdWNjZXNzIGhhbmRsZXIuXG4gICAgICAgICAgICBfLm5vb3AsXG4gICAgICAgICAgICAvLyBFcnJvciBoYW5kbGVyLlxuICAgICAgICAgICAgKGV4Y2VwdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLm9uRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQGlmbmRlZiBHRU5KU19QUk9EVUNUSU9OXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnSGFuZGxlZCBlcnJvciBpbiAnICsgdGhpcy5jb21wb25lbnQuZ2V0Q29uZmlnKCkuZGlyZWN0aXZlLCBleGNlcHRpb24pO1xuICAgICAgICAgICAgICAgICAgICAvLyBAZW5kaWZcbiAgICAgICAgICAgICAgICAgICAgc2FmZUNhbGxiYWNrQXBwbHkodGhpcy5jb21wb25lbnQuJHNjb3BlLCAoKSA9PiB7IG9wdGlvbnMub25FcnJvcihleGNlcHRpb24pOyB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1VuaGFuZGxlZCBlcnJvciBpbiAnICsgdGhpcy5jb21wb25lbnQuZ2V0Q29uZmlnKCkuZGlyZWN0aXZlLCBleGNlcHRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLl9zdWJzY3JpcHRpb25zLnB1c2goc3Vic2NyaXB0aW9uKTtcbiAgICAgICAgcmV0dXJuIHN1YnNjcmlwdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgYWxsIHN1YnNjcmlwdGlvbnMgY3JlYXRlZCBieSBjYWxsaW5nIGBzdWJzY3JpYmVgIGFyZSByZWFkeS5cbiAgICAgKiBBIHN1YnNjcmlwdGlvbiBpcyByZWFkeSB3aGVuIGl0IGhhcyByZWNlaXZlZCBpdHMgZmlyc3QgYmF0Y2ggb2YgZGF0YSBhZnRlclxuICAgICAqIHN1YnNjcmliaW5nLlxuICAgICAqL1xuICAgIHB1YmxpYyBzdWJzY3JpcHRpb25zUmVhZHkoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wZW5kaW5nU3Vic2NyaXB0aW9ucy5sZW5ndGggPT09IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUnVucyB0aGUgY29tcHV0YXRpb24uXG4gICAgICovXG4gICAgcHVibGljIGNvbXB1dGUoKSB7XG4gICAgICAgIC8vIFN0b3AgYWxsIHN1YnNjcmlwdGlvbnMgYmVmb3JlIHJ1bm5pbmcgYWdhaW4uXG4gICAgICAgIHRoaXMuc3RvcCgpO1xuICAgICAgICB0aGlzLmNvbnRlbnQodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzcG9zZXMgb2YgYWxsIHJlZ2lzdGVyZWQgc3Vic2NyaXB0aW9ucy5cbiAgICAgKi9cbiAgICBwdWJsaWMgc3RvcCgpIHtcbiAgICAgICAgZm9yIChsZXQgc3Vic2NyaXB0aW9uIG9mIHRoaXMuX3N1YnNjcmlwdGlvbnMpIHtcbiAgICAgICAgICAgIHN1YnNjcmlwdGlvbi5kaXNwb3NlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3Vic2NyaXB0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLl9wZW5kaW5nU3Vic2NyaXB0aW9ucyA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0b3BzIGFsbCBzdWJzY3JpcHRpb25zIGN1cnJlbnRseSByZWdpc3RlcmVkIGluIHRoaXMgY29tcHV0YXRpb24gYW5kIHJlbW92ZXNcbiAgICAgKiB0aGlzIGNvbXB1dGF0aW9uIGZyb20gdGhlIHBhcmVudCBjb21wb25lbnQuIElmIGEgZGlzcG9zZSBoYW5kbGVyIGhhcyBiZWVuXG4gICAgICogY29uZmlndXJlZCwgaXQgaXMgaW52b2tlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgdW5zdWJzY3JpYmUoKSB7XG4gICAgICAgIHRoaXMuY29tcG9uZW50LnVuc3Vic2NyaWJlKHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5fZGlzcG9zZSkgdGhpcy5fZGlzcG9zZSgpO1xuICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTtcbiAgICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2F0Y2hFeHByZXNzaW9uT2Y8VD4ge1xuICAgICgpOiBUO1xufVxuZXhwb3J0IHR5cGUgV2F0Y2hFeHByZXNzaW9uID0gV2F0Y2hFeHByZXNzaW9uT2Y8e30+O1xuXG4vKipcbiAqIEFuIGFic3RyYWN0IGJhc2UgY2xhc3MgZm9yIGFsbCBjb21wb25lbnRzLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQ29tcG9uZW50QmFzZSB7XG4gICAgLy8gQ29tcG9uZW50IGNvbmZpZ3VyYXRpb24uXG4gICAgcHVibGljIHN0YXRpYyBfX2NvbXBvbmVudENvbmZpZzogQ29tcG9uZW50Q29uZmlndXJhdGlvbjtcbiAgICAvLyBDb21wdXRhdGlvbnMuXG4gICAgcHJpdmF0ZSBfY29tcHV0YXRpb25zOiBDb21wdXRhdGlvbltdID0gW107XG4gICAgLy8gQ29tcG9uZW50IHN0YXRlLlxuICAgIHByaXZhdGUgX3JlYWR5OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvLyBAbmdJbmplY3RcbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgJHNjb3BlOiBhbmd1bGFyLklTY29wZSkge1xuICAgICAgICAkc2NvcGUuJG9uKCckZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3JlYWR5ID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIEVuc3VyZSB0aGF0IGFsbCBjb21wdXRhdGlvbnMgZ2V0IHN0b3BwZWQgd2hlbiB0aGUgY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICAgICAgICAgIGZvciAobGV0IGNv