io.parrots
Version:
Parrots.io App
537 lines (536 loc) • 58.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import { Injectable, Inject } from '@angular/core';
import { Http, RequestOptions } from '@angular/http';
import { CONNECTION_DATA } from 'com.phloxui';
import { BackgroundProcessManager } from 'com.phloxui';
import { ConnectionManager } from 'com.phloxui';
import { ParrotsDefaultConnectionManager } from '../share/ParrotsDefaultConnectionManager';
import { TEST_MODE, TEST_DATA } from '../test';
const /** @type {?} */ RUNNING = 'RUNNING';
const /** @type {?} */ BASE_URL = 'http://10.1.0.22/api';
const /** @type {?} */ TEST_INSTANCE_ID = 'TEST';
/**
* <p style="text-indent: 2em;">
* A <code>ng</code> service class implementing [[InstanceConnectionManager]] service interface. Please see [[InstanceConnectionManager]] for more details.
* </p>
*
* @author shiorin, tee4cute
*/
export class InstanceConnectionManager {
/**
* @param {?} connectionManager
* @param {?} http
* @param {?} bgProcessMgr
* @param {?} testMode
* @param {?} testData
*/
constructor(connectionManager, http, bgProcessMgr, testMode, testData) {
this.seletedInstanceId = "";
this.http = http;
this.bgProcessMgr = bgProcessMgr;
this.connectionManager = connectionManager;
this.instanceConnectionManagerMap = {};
this.testMode = testMode;
this.testData = testData;
// if (testMode) {
this.seletedInstanceId = TEST_INSTANCE_ID;
this.instanceConnectionManagerMap[this.seletedInstanceId] = new ParrotsDefaultConnectionManager(null, this.http, this.bgProcessMgr, testMode, testData);
// }
}
/**
* @param {?} instanceUUID
* @return {?}
*/
getNodes(instanceUUID) {
if (this.connectionManager !== null && typeof this.connectionManager !== 'undefined') {
let /** @type {?} */ url = BASE_URL + "/instance/" + instanceUUID + "/node";
let /** @type {?} */ requestOptionsArgs = new RequestOptions();
return this.connectionManager.getWithHttpInfo(url, requestOptionsArgs);
}
else {
return Promise.reject(null);
}
}
/**
* ## setup instance: generate connectionManager by instanceUUID and cache in map
* @param {?} instanceUUID
* @param {?=} loginData
* @return {?}
*/
setUpInstance(instanceUUID, loginData) {
return new Promise((resolve, reject) => {
this.getNodes(instanceUUID).then((res) => {
let /** @type {?} */ itemNodes = JSON.parse(res._body).items;
let /** @type {?} */ runnintMode = false;
for (let /** @type {?} */ itemNode of itemNodes) {
if (itemNode.status === RUNNING) {
runnintMode = true;
let /** @type {?} */ conMgr = new ParrotsDefaultConnectionManager(null, this.http, this.bgProcessMgr, this.testMode, this.testData);
conMgr.setName(itemNode._uuid);
//Set for test.
let /** @type {?} */ url = itemNode.serverNode.hostName == "localhost" ? "http://10.1.0.22" : itemNode.serverNode.hostName;
url += ":" + itemNode.servicePort + "/api";
conMgr.addBaseURLs(url);
if (loginData !== undefined) {
url += "/user/login";
this.connectionManager.postWithHttpInfo(url, loginData, new RequestOptions()).then((res) => {
let /** @type {?} */ sessionId = JSON.parse((/** @type {?} */ (res))._body).sessionId;
conMgr.setDefaultHeader('Session-Id', sessionId);
this.instanceConnectionManagerMap[instanceUUID] = conMgr;
resolve(itemNodes);
}).catch((error) => {
this.instanceConnectionManagerMap[instanceUUID] = conMgr;
reject(error);
});
}
else {
this.instanceConnectionManagerMap[instanceUUID] = conMgr;
}
}
}
if (loginData === undefined) {
if (runnintMode) {
resolve(itemNodes);
}
reject(itemNodes);
}
}).catch((error) => {
reject(error);
});
});
}
/**
* ## setup instances: generate connectionManager by instanceUUIDs and cache in map
* @param {?} instances
* @return {?}
*/
setUpInstances(instances) {
if (instances === undefined || instances === null) {
return Promise.resolve([]);
}
let /** @type {?} */ proms = [];
for (let /** @type {?} */ instanceUUID in instances) {
if (instanceUUID === null || instanceUUID === undefined) {
continue;
}
proms.push(this.setUpInstance(instanceUUID, instances[instanceUUID]));
}
return Promise.all(proms);
}
/**
* ## remove instance by instanceUUID from map
* @param {?} instanceUUID
* @return {?}
*/
tearDownInstance(instanceUUID) {
delete this.instanceConnectionManagerMap[instanceUUID];
}
/**
* ## remove instance instanceUUID from map
* @param {?=} instanceUUID
* @return {?}
*/
getInstanceConnectionManager(instanceUUID) {
if (instanceUUID !== undefined && instanceUUID !== null && instanceUUID !== '') {
return this.instanceConnectionManagerMap[instanceUUID];
}
if (this.seletedInstanceId === undefined || this.seletedInstanceId === null) {
return null;
}
return this.instanceConnectionManagerMap[this.seletedInstanceId];
}
/**
* @param {?} instanceUUID
* @return {?}
*/
selectInstance(instanceUUID) {
this.seletedInstanceId = instanceUUID;
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
get(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().get(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
getWithHttpInfo(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().getWithHttpInfo(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} body
* @param {?} requestOptionsArgs
* @return {?}
*/
post(url, body, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().post(url, body, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} body
* @param {?} requestOptionsArgs
* @return {?}
*/
postWithHttpInfo(url, body, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().postWithHttpInfo(url, body, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} body
* @param {?} requestOptionsArgs
* @return {?}
*/
put(url, body, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().put(url, body, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} body
* @param {?} requestOptionsArgs
* @return {?}
*/
putWithHttpInfo(url, body, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().putWithHttpInfo(url, body, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
delete(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().delete(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
deleteWithHttpInfo(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().deleteWithHttpInfo(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} body
* @param {?} requestOptionsArgs
* @return {?}
*/
patch(url, body, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().patch(url, body, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} body
* @param {?} requestOptionsArgs
* @return {?}
*/
patchWithHttpInfo(url, body, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().patchWithHttpInfo(url, body, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
head(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().head(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
headWithHttpInfo(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().headWithHttpInfo(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
options(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().options(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
optionsWithHttpInfo(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().optionsWithHttpInfo(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
request(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().request(url, requestOptionsArgs);
}
/**
* @param {?} url
* @param {?} requestOptionsArgs
* @return {?}
*/
requestWithHttpInfo(url, requestOptionsArgs) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
return Promise.reject('Connection Manager is not setup yet.');
}
return this.getInstanceConnectionManager().requestWithHttpInfo(url, requestOptionsArgs);
}
/**
* @return {?}
*/
getRunningProcessesCount() {
if (this.seletedInstanceId === null || this.seletedInstanceId === undefined) {
return null;
}
if (this.bgProcessMgr != null && typeof this.bgProcessMgr !== 'undefined') {
this.bgProcessMgr.getRunningProcessesCount(CONNECTION_DATA, this.seletedInstanceId);
}
return 0;
}
/**
* @return {?}
*/
getRunningProcesses() {
if (this.seletedInstanceId === null || this.seletedInstanceId === undefined) {
return null;
}
if (this.bgProcessMgr != null && typeof this.bgProcessMgr !== 'undefined') {
this.bgProcessMgr.getRunningProcesses(CONNECTION_DATA, this.seletedInstanceId);
}
return [];
}
/**
* @return {?}
*/
getConnectionQuality() {
// TODO
return this.connectionManager.getConnectionQuality();
}
/**
* @param {?} urls
* @return {?}
*/
setBaseURLs(urls) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().setBaseURLs(urls);
}
/**
* @return {?}
*/
resetBaseURLs() {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().resetBaseURLs();
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
setDefaultHeader(key, value) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().setDefaultHeader(key, value);
}
/**
* @param {?} key
* @return {?}
*/
removeDefaultHeader(key) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().removeDefaultHeader(key);
}
/**
* @return {?}
*/
resetDefaultHeaders() {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().resetDefaultHeaders();
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
setSearch(key, value) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().setSearch(key, value);
}
/**
* @param {?} key
* @return {?}
*/
removeSearch(key) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().removeSearch(key);
}
/**
* @return {?}
*/
resetSearch() {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().resetSearch();
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
setParam(key, value) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().setParam(key, value);
}
/**
* @param {?} key
* @return {?}
*/
removeParam(key) {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().removeParam(key);
}
/**
* @return {?}
*/
resetParams() {
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().resetParams();
}
/**
* @return {?}
*/
getName() {
return this.name;
}
/**
* @param {?} name
* @return {?}
*/
setName(name) {
this.name = name;
if (this.getInstanceConnectionManager() === null || this.getInstanceConnectionManager() === undefined) {
throw ('Connection Manager is not setup yet.');
}
this.getInstanceConnectionManager().setName(name);
}
/**
* @template R
* @param {?} type
* @return {?}
*/
createResource(type) {
return this.getInstanceConnectionManager().createResource(type);
}
}
InstanceConnectionManager.decorators = [
{ type: Injectable },
];
/** @nocollapse */
InstanceConnectionManager.ctorParameters = () => [
{ type: ConnectionManager, },
{ type: Http, },
{ type: BackgroundProcessManager, },
{ type: undefined, decorators: [{ type: Inject, args: [TEST_MODE,] },] },
{ type: undefined, decorators: [{ type: Inject, args: [TEST_DATA,] },] },
];
function InstanceConnectionManager_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
InstanceConnectionManager.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
InstanceConnectionManager.ctorParameters;
/** @type {?} */
InstanceConnectionManager.prototype.instanceConnectionManagerMap;
/** @type {?} */
InstanceConnectionManager.prototype.connectionManager;
/** @type {?} */
InstanceConnectionManager.prototype.http;
/** @type {?} */
InstanceConnectionManager.prototype.bgProcessMgr;
/** @type {?} */
InstanceConnectionManager.prototype.seletedInstanceId;
/** @type {?} */
InstanceConnectionManager.prototype.name;
/** @type {?} */
InstanceConnectionManager.prototype.testMode;
/** @type {?} */
InstanceConnectionManager.prototype.testData;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vaW8ucGFycm90cy8iLCJzb3VyY2VzIjpbImxpYi9zZXJ2aWNlL0luc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLElBQUksRUFBWSxjQUFjLEVBQStCLE1BQU0sZUFBZSxDQUFDO0FBQzVGLE9BQU8sRUFBc0IsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFaEQsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDM0YsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFFL0MsdUJBQU0sT0FBTyxHQUFXLFNBQVMsQ0FBQztBQUNsQyx1QkFBTSxRQUFRLEdBQVcsc0JBQXNCLENBQUM7QUFDaEQsdUJBQU0sZ0JBQWdCLEdBQVcsTUFBTSxDQUFDOzs7Ozs7OztBQVd4QyxNQUFNOzs7Ozs7OztJQVdKLFlBQVksaUJBQW9DLEVBQUUsSUFBVSxFQUFFLFlBQXNDLEVBQXFCLFVBQXNDO1FBRTdKLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGlCQUFpQixDQUFDO1FBQzNDLElBQUksQ0FBQyw0QkFBNEIsR0FBRyxFQUFFLENBQUM7UUFFdkMsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFR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QyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7Ozs7WUE1WG5FLFVBQVU7Ozs7WUFqQkYsaUJBQWlCO1lBSGpCLElBQUk7WUFFSix3QkFBd0I7NENBOEJ3RSxNQUFNLFNBQUMsU0FBUzs0Q0FBc0IsTUFBTSxTQUFDLFNBQVMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBJbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh0dHAsIFJlc3BvbnNlLCBSZXF1ZXN0T3B0aW9ucywgUmVxdWVzdE9wdGlvbnNBcmdzLCBIZWFkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvaHR0cCc7XG5pbXBvcnQgeyBJQ29ubmVjdGlvbk1hbmFnZXIsIENPTk5FQ1RJT05fREFUQSB9IGZyb20gJ2NvbS5waGxveHVpJztcbmltcG9ydCB7IEJhY2tncm91bmRQcm9jZXNzTWFuYWdlciB9IGZyb20gJ2NvbS5waGxveHVpJztcbmltcG9ydCB7IENvbm5lY3Rpb25NYW5hZ2VyIH0gZnJvbSAnY29tLnBobG94dWknO1xuaW1wb3J0IHsgQWJzdHJhY3RTZXJ2ZXJSZXNvdXJjZSB9IGZyb20gJ2NvbS5waGxveHVpJztcbmltcG9ydCB7IFBhcnJvdHNEZWZhdWx0Q29ubmVjdGlvbk1hbmFnZXIgfSBmcm9tICcuLi9zaGFyZS9QYXJyb3RzRGVmYXVsdENvbm5lY3Rpb25NYW5hZ2VyJztcbmltcG9ydCB7IFRFU1RfTU9ERSwgVEVTVF9EQVRBIH0gZnJvbSAnLi4vdGVzdCc7XG5cbmNvbnN0IFJVTk5JTkc6IHN0cmluZyA9ICdSVU5OSU5HJztcbmNvbnN0IEJBU0VfVVJMOiBzdHJpbmcgPSAnaHR0cDovLzEwLjEuMC4yMi9hcGknO1xuY29uc3QgVEVTVF9JTlNUQU5DRV9JRDogc3RyaW5nID0gJ1RFU1QnO1xuXG5cbi8qKlxuICogPHAgc3R5bGU9XCJ0ZXh0LWluZGVudDogMmVtO1wiPlxuICogQSA8Y29kZT5uZzwvY29kZT4gc2VydmljZSBjbGFzcyBpbXBsZW1lbnRpbmcgW1tJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyXV0gc2VydmljZSBpbnRlcmZhY2UuIFBsZWFzZSBzZWUgW1tJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyXV0gZm9yIG1vcmUgZGV0YWlscy5cbiAqIDwvcD5cbiAqXG4gKiBAYXV0aG9yIHNoaW9yaW4sIHRlZTRjdXRlXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyIGltcGxlbWVudHMgSUNvbm5lY3Rpb25NYW5hZ2VyIHtcblxuICBwcml2YXRlIGluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXJNYXA6IGFueTtcbiAgcHJpdmF0ZSBjb25uZWN0aW9uTWFuYWdlcjogQ29ubmVjdGlvbk1hbmFnZXI7XG4gIHByaXZhdGUgaHR0cDogSHR0cDtcbiAgcHJpdmF0ZSBiZ1Byb2Nlc3NNZ3I6IEJhY2tncm91bmRQcm9jZXNzTWFuYWdlcjtcbiAgcHJpdmF0ZSBzZWxldGVkSW5zdGFuY2VJZDogc3RyaW5nO1xuICBwcml2YXRlIG5hbWU6IHN0cmluZztcbiAgcHJpdmF0ZSB0ZXN0TW9kZTogYm9vbGVhbjtcbiAgcHJpdmF0ZSB0ZXN0RGF0YTogYW55O1xuXG4gIGNvbnN0cnVjdG9yKGNvbm5lY3Rpb25NYW5hZ2VyOiBDb25uZWN0aW9uTWFuYWdlciwgaHR0cDogSHR0cCwgYmdQcm9jZXNzTWdyOiBCYWNrZ3JvdW5kUHJvY2Vzc01hbmFnZXIsIEBJbmplY3QoVEVTVF9NT0RFKSB0ZXN0TW9kZTogYm9vbGVhbiwgQEluamVjdChURVNUX0RBVEEpIHRlc3REYXRhOiBhbnkpIHtcblxuICAgIHRoaXMuc2VsZXRlZEluc3RhbmNlSWQgPSBcIlwiO1xuICAgIHRoaXMuaHR0cCA9IGh0dHA7XG4gICAgdGhpcy5iZ1Byb2Nlc3NNZ3IgPSBiZ1Byb2Nlc3NNZ3I7XG4gICAgdGhpcy5jb25uZWN0aW9uTWFuYWdlciA9IGNvbm5lY3Rpb25NYW5hZ2VyO1xuICAgIHRoaXMuaW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlck1hcCA9IHt9O1xuXG4gICAgdGhpcy50ZXN0TW9kZSA9IHRlc3RNb2RlO1xuICAgIHRoaXMudGVzdERhdGEgPSB0ZXN0RGF0YTtcblxuICAgIC8vIGlmICh0ZXN0TW9kZSkge1xuICAgICAgdGhpcy5zZWxldGVkSW5zdGFuY2VJZCA9IFRFU1RfSU5TVEFOQ0VfSUQ7XG4gICAgICB0aGlzLmluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXJNYXBbdGhpcy5zZWxldGVkSW5zdGFuY2VJZF0gPSBuZXcgUGFycm90c0RlZmF1bHRDb25uZWN0aW9uTWFuYWdlcihudWxsLCB0aGlzLmh0dHAsIHRoaXMuYmdQcm9jZXNzTWdyLCB0ZXN0TW9kZSwgdGVzdERhdGEpO1xuICAgIC8vIH1cblxuICB9XG5cbiAgcHJpdmF0ZSBnZXROb2RlcyhpbnN0YW5jZVVVSUQ6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKHRoaXMuY29ubmVjdGlvbk1hbmFnZXIgIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuY29ubmVjdGlvbk1hbmFnZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsZXQgdXJsOiBhbnkgPSBCQVNFX1VSTCArIFwiL2luc3RhbmNlL1wiICsgaW5zdGFuY2VVVUlEICsgXCIvbm9kZVwiO1xuXG4gICAgICBsZXQgcmVxdWVzdE9wdGlvbnNBcmdzID0gbmV3IFJlcXVlc3RPcHRpb25zKCk7XG5cbiAgICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb25NYW5hZ2VyLmdldFdpdGhIdHRwSW5mbyh1cmwsIHJlcXVlc3RPcHRpb25zQXJncyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChudWxsKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogIyMgc2V0dXAgaW5zdGFuY2U6IGdlbmVyYXRlIGNvbm5lY3Rpb25NYW5hZ2VyIGJ5IGluc3RhbmNlVVVJRCBhbmQgY2FjaGUgaW4gbWFwXG4gICAqL1xuICBwdWJsaWMgc2V0VXBJbnN0YW5jZShpbnN0YW5jZVVVSUQ6IHN0cmluZywgbG9naW5EYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmdldE5vZGVzKGluc3RhbmNlVVVJRCkudGhlbigocmVzKSA9PiB7XG4gICAgICAgIGxldCBpdGVtTm9kZXMgPSBKU09OLnBhcnNlKHJlcy5fYm9keSkuaXRlbXM7XG5cbiAgICAgICAgbGV0IHJ1bm5pbnRNb2RlID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGl0ZW1Ob2RlIG9mIGl0ZW1Ob2Rlcykge1xuICAgICAgICAgIGlmIChpdGVtTm9kZS5zdGF0dXMgPT09IFJVTk5JTkcpIHtcblxuICAgICAgICAgICAgcnVubmludE1vZGUgPSB0cnVlO1xuICAgICAgICAgICAgbGV0IGNvbk1nciA9IG5ldyBQYXJyb3RzRGVmYXVsdENvbm5lY3Rpb25NYW5hZ2VyKG51bGwsIHRoaXMuaHR0cCwgdGhpcy5iZ1Byb2Nlc3NNZ3IsIHRoaXMudGVzdE1vZGUsIHRoaXMudGVzdERhdGEpO1xuICAgICAgICAgICAgY29uTWdyLnNldE5hbWUoaXRlbU5vZGUuX3V1aWQpO1xuXG4gICAgICAgICAgICAvL1NldCBmb3IgdGVzdC5cbiAgICAgICAgICAgIGxldCB1cmw6IHN0cmluZyA9IGl0ZW1Ob2RlLnNlcnZlck5vZGUuaG9zdE5hbWUgPT0gXCJsb2NhbGhvc3RcIiA/IFwiaHR0cDovLzEwLjEuMC4yMlwiIDogaXRlbU5vZGUuc2VydmVyTm9kZS5ob3N0TmFtZTtcbiAgICAgICAgICAgIHVybCArPSBcIjpcIiArIGl0ZW1Ob2RlLnNlcnZpY2VQb3J0ICsgXCIvYXBpXCI7XG4gICAgICAgICAgICBjb25NZ3IuYWRkQmFzZVVSTHModXJsKTtcblxuICAgICAgICAgICAgaWYgKGxvZ2luRGF0YSAhPT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgICAgdXJsICs9IFwiL3VzZXIvbG9naW5cIjtcbiAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uTWFuYWdlci5wb3N0V2l0aEh0dHBJbmZvKHVybCwgbG9naW5EYXRhLCBuZXcgUmVxdWVzdE9wdGlvbnMoKSkudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IHNlc3Npb25JZCA9IEpTT04ucGFyc2UoKHJlcyBhcyBhbnkpLl9ib2R5KS5zZXNzaW9uSWQ7XG4gICAgICAgICAgICAgICAgY29uTWdyLnNldERlZmF1bHRIZWFkZXIoJ1Nlc3Npb24tSWQnLCBzZXNzaW9uSWQpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlck1hcFtpbnN0YW5jZVVVSURdID0gY29uTWdyO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoaXRlbU5vZGVzKTtcbiAgICAgICAgICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyTWFwW2luc3RhbmNlVVVJRF0gPSBjb25NZ3I7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLmluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXJNYXBbaW5zdGFuY2VVVUlEXSA9IGNvbk1ncjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobG9naW5EYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAocnVubmludE1vZGUpIHtcbiAgICAgICAgICAgIHJlc29sdmUoaXRlbU5vZGVzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZWplY3QoaXRlbU5vZGVzKTtcbiAgICAgICAgfVxuXG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gIH1cblxuICAvKipcbiAgICogIyMgc2V0dXAgaW5zdGFuY2VzOiBnZW5lcmF0ZSBjb25uZWN0aW9uTWFuYWdlciBieSBpbnN0YW5jZVVVSURzIGFuZCBjYWNoZSBpbiBtYXBcbiAgICovXG4gIHB1YmxpYyBzZXRVcEluc3RhbmNlcyhpbnN0YW5jZXM6IHN0cmluZ1tdKTogUHJvbWlzZTxhbnlbXT4ge1xuXG4gICAgaWYgKGluc3RhbmNlcyA9PT0gdW5kZWZpbmVkIHx8IGluc3RhbmNlcyA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShbXSk7XG4gICAgfVxuXG4gICAgbGV0IHByb21zOiBQcm9taXNlPGFueT5bXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaW5zdGFuY2VVVUlEIGluIGluc3RhbmNlcykge1xuICAgICAgaWYgKGluc3RhbmNlVVVJRCA9PT0gbnVsbCB8fCBpbnN0YW5jZVVVSUQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgcHJvbXMucHVzaCh0aGlzLnNldFVwSW5zdGFuY2UoaW5zdGFuY2VVVUlELCBpbnN0YW5jZXNbaW5zdGFuY2VVVUlEXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9tcyk7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiAjIyByZW1vdmUgaW5zdGFuY2UgYnkgaW5zdGFuY2VVVUlEIGZyb20gbWFwXG4gICAqL1xuICBwdWJsaWMgdGVhckRvd25JbnN0YW5jZShpbnN0YW5jZVVVSUQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGRlbGV0ZSB0aGlzLmluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXJNYXBbaW5zdGFuY2VVVUlEXTtcbiAgfVxuXG4gIC8qKlxuICAgKiAjIyByZW1vdmUgaW5zdGFuY2UgaW5zdGFuY2VVVUlEIGZyb20gbWFwXG4gICAqL1xuICBwdWJsaWMgZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcihpbnN0YW5jZVVVSUQ/OiBzdHJpbmcpOiBJQ29ubmVjdGlvbk1hbmFnZXIge1xuICAgIGlmIChpbnN0YW5jZVVVSUQgIT09IHVuZGVmaW5lZCAmJiBpbnN0YW5jZVVVSUQgIT09IG51bGwgJiYgaW5zdGFuY2VVVUlEICE9PSAnJykge1xuICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlck1hcFtpbnN0YW5jZVVVSURdO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNlbGV0ZWRJbnN0YW5jZUlkID09PSB1bmRlZmluZWQgfHwgdGhpcy5zZWxldGVkSW5zdGFuY2VJZCA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuaW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlck1hcFt0aGlzLnNlbGV0ZWRJbnN0YW5jZUlkXTtcbiAgfVxuXG4gIHB1YmxpYyBzZWxlY3RJbnN0YW5jZShpbnN0YW5jZVVVSUQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuc2VsZXRlZEluc3RhbmNlSWQgPSBpbnN0YW5jZVVVSUQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0KHVybDogc3RyaW5nLCByZXF1ZXN0T3B0aW9uc0FyZ3M6IFJlcXVlc3RPcHRpb25zQXJncyk6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSBudWxsIHx8IHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29ubmVjdGlvbiBNYW5hZ2VyIGlzIG5vdCBzZXR1cCB5ZXQuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldEluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIoKS5nZXQodXJsLCByZXF1ZXN0T3B0aW9uc0FyZ3MpO1xuICB9XG5cbiAgcHVibGljIGdldFdpdGhIdHRwSW5mbyh1cmw6IHN0cmluZywgcmVxdWVzdE9wdGlvbnNBcmdzOiBSZXF1ZXN0T3B0aW9uc0FyZ3MpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgaWYgKHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSBudWxsIHx8IHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29ubmVjdGlvbiBNYW5hZ2VyIGlzIG5vdCBzZXR1cCB5ZXQuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldEluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIoKS5nZXRXaXRoSHR0cEluZm8odXJsLCByZXF1ZXN0T3B0aW9uc0FyZ3MpO1xuICB9XG5cbiAgcHVibGljIHBvc3QodXJsOiBzdHJpbmcsIGJvZHk6IGFueSwgcmVxdWVzdE9wdGlvbnNBcmdzOiBSZXF1ZXN0T3B0aW9uc0FyZ3MpOiBQcm9taXNlPGFueT4ge1xuICAgIGlmICh0aGlzLmdldEluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIoKSA9PT0gbnVsbCB8fCB0aGlzLmdldEluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIoKSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0Nvbm5lY3Rpb24gTWFuYWdlciBpcyBub3Qgc2V0dXAgeWV0LicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkucG9zdCh1cmwsIGJvZHksIHJlcXVlc3RPcHRpb25zQXJncyk7XG4gIH1cblxuICBwdWJsaWMgcG9zdFdpdGhIdHRwSW5mbyh1cmw6IHN0cmluZywgYm9keTogYW55LCByZXF1ZXN0T3B0aW9uc0FyZ3M6IFJlcXVlc3RPcHRpb25zQXJncyk6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgICBpZiAodGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IG51bGwgfHwgdGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25uZWN0aW9uIE1hbmFnZXIgaXMgbm90IHNldHVwIHlldC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpLnBvc3RXaXRoSHR0cEluZm8odXJsLCBib2R5LCByZXF1ZXN0T3B0aW9uc0FyZ3MpO1xuICB9XG5cbiAgcHVibGljIHB1dCh1cmw6IHN0cmluZywgYm9keTogYW55LCByZXF1ZXN0T3B0aW9uc0FyZ3M6IFJlcXVlc3RPcHRpb25zQXJncyk6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSBudWxsIHx8IHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29ubmVjdGlvbiBNYW5hZ2VyIGlzIG5vdCBzZXR1cCB5ZXQuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldEluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIoKS5wdXQodXJsLCBib2R5LCByZXF1ZXN0T3B0aW9uc0FyZ3MpO1xuICB9XG5cbiAgcHVibGljIHB1dFdpdGhIdHRwSW5mbyh1cmw6IHN0cmluZywgYm9keTogYW55LCByZXF1ZXN0T3B0aW9uc0FyZ3M6IFJlcXVlc3RPcHRpb25zQXJncyk6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgICBpZiAodGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IG51bGwgfHwgdGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25uZWN0aW9uIE1hbmFnZXIgaXMgbm90IHNldHVwIHlldC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpLnB1dFdpdGhIdHRwSW5mbyh1cmwsIGJvZHksIHJlcXVlc3RPcHRpb25zQXJncyk7XG4gIH1cblxuICBwdWJsaWMgZGVsZXRlKHVybDogc3RyaW5nLCByZXF1ZXN0T3B0aW9uc0FyZ3M6IFJlcXVlc3RPcHRpb25zQXJncyk6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSBudWxsIHx8IHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29ubmVjdGlvbiBNYW5hZ2VyIGlzIG5vdCBzZXR1cCB5ZXQuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldEluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIoKS5kZWxldGUodXJsLCByZXF1ZXN0T3B0aW9uc0FyZ3MpO1xuICB9XG5cbiAgcHVibGljIGRlbGV0ZVdpdGhIdHRwSW5mbyh1cmw6IHN0cmluZywgcmVxdWVzdE9wdGlvbnNBcmdzOiBSZXF1ZXN0T3B0aW9uc0FyZ3MpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgaWYgKHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSBudWxsIHx8IHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29ubmVjdGlvbiBNYW5hZ2VyIGlzIG5vdCBzZXR1cCB5ZXQuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldEluc3RhbmNlQ29ubmVjdGlvbk1hbmFnZXIoKS5kZWxldGVXaXRoSHR0cEluZm8odXJsLCByZXF1ZXN0T3B0aW9uc0FyZ3MpO1xuICB9XG5cbiAgcHVibGljIHBhdGNoKHVybDogc3RyaW5nLCBib2R5OiBhbnksIHJlcXVlc3RPcHRpb25zQXJnczogUmVxdWVzdE9wdGlvbnNBcmdzKTogUHJvbWlzZTxhbnk+IHtcbiAgICBpZiAodGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IG51bGwgfHwgdGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25uZWN0aW9uIE1hbmFnZXIgaXMgbm90IHNldHVwIHlldC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpLnBhdGNoKHVybCwgYm9keSwgcmVxdWVzdE9wdGlvbnNBcmdzKTtcbiAgfVxuXG4gIHB1YmxpYyBwYXRjaFdpdGhIdHRwSW5mbyh1cmw6IHN0cmluZywgYm9keTogYW55LCByZXF1ZXN0T3B0aW9uc0FyZ3M6IFJlcXVlc3RPcHRpb25zQXJncyk6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgICBpZiAodGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IG51bGwgfHwgdGhpcy5nZXRJbnN0YW5jZUNvbm5lY3Rpb25NYW5hZ2VyKCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDb25uZWN0aW9uIE1hbmFnZXIgaXMgbm90IHNldHVwIHlldC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpLnBhdGNoV2l0aEh0dHBJbmZvKHVybCwgYm9keSwgcmVxdWVzdE9wdGlvbnNBcmdzKTtcbiAgfVxuXG4gIHB1YmxpYyBoZWFkKHVybDogc3RyaW5nLCByZXF1ZXN0T3B0aW9uc0FyZ3M6IFJlcXVlc3RPcHRpb25zQXJncyk6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSBudWxsIHx8IHRoaXMuZ2V0SW5zdGFuY2VDb25uZWN0aW9uTWFuYWdlcigpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQ29ubmVjdGlvbiBNYW5hZ2VyIGlzIG5vdC