UNPKG

@versatiledatakit/data-pipelines

Version:

Data Pipelines help Data Engineers develop, deploy, run, and manage data processing workloads (called 'Data Job')

185 lines 48.1 kB
/* * Copyright 2023-2025 Broadcom * SPDX-License-Identifier: Apache-2.0 */ import { Injectable } from '@angular/core'; import { merge, of, throwError } from 'rxjs'; import { catchError, map, switchMap, take, tap } from 'rxjs/operators'; import { createEffect, ofType } from '@ngrx/effects'; import { CollectionsUtil, ComponentFailed, ComponentLoaded, ComponentUpdate, extractTaskFromIdentifier, generateErrorCode, getModel, getModelAndTask, LOADED, processServiceRequestError, TaurusBaseEffects } from '@versatiledatakit/shared'; import { ErrorUtil } from '../../shared/utils'; import { FILTER_REQ_PARAM, JOB_DEPLOYMENT_ID_REQ_PARAM, JOB_DETAILS_DATA_KEY, JOB_DETAILS_REQ_PARAM, JOB_EXECUTIONS_DATA_KEY, JOB_NAME_REQ_PARAM, JOB_STATE_DATA_KEY, JOB_STATE_REQ_PARAM, JOB_STATUS_REQ_PARAM, JOBS_DATA_KEY, ORDER_REQ_PARAM, TEAM_NAME_REQ_PARAM } from '../../model'; import { TASK_LOAD_JOB_DETAILS, TASK_LOAD_JOB_EXECUTIONS, TASK_LOAD_JOB_STATE, TASK_LOAD_JOBS_STATE, TASK_UPDATE_JOB_DESCRIPTION, TASK_UPDATE_JOB_STATUS } from '../tasks'; import { LOAD_JOB_ERROR_CODES, LOAD_JOBS_ERROR_CODES, UPDATE_JOB_DETAILS_ERROR_CODES } from '../error-codes'; import { FETCH_DATA_JOB, FETCH_DATA_JOB_EXECUTIONS, FETCH_DATA_JOBS, UPDATE_DATA_JOB } from '../actions'; import * as i0 from "@angular/core"; import * as i1 from "@ngrx/effects"; import * as i2 from "@versatiledatakit/shared"; import * as i3 from "../../services"; /** * ** Effect for DataJobs. */ export class DataJobsEffects extends TaurusBaseEffects { /** * ** Constructor. */ constructor(actions$, componentService, dataJobsApiService) { super(actions$, componentService, DataJobsEffects.CLASS_NAME); this.dataJobsApiService = dataJobsApiService; /** * ** Load DataJobs data. */ this.loadDataJobs$ = createEffect(() => this.actions$.pipe(ofType(FETCH_DATA_JOBS), getModel(this.componentService), switchMap((model) => this._loadDataJobs(model)))); this.loadDataJob$ = createEffect(() => this.actions$.pipe(ofType(FETCH_DATA_JOB), getModel(this.componentService), switchMap((model) => merge(this._executeJobTask(model, TASK_LOAD_JOB_STATE), this._executeJobTask(model, TASK_LOAD_JOB_DETAILS), this._executeJobTask(model, TASK_LOAD_JOB_EXECUTIONS))))); this.loadDataJobExecutions$ = createEffect(() => this.actions$.pipe(ofType(FETCH_DATA_JOB_EXECUTIONS), getModel(this.componentService), switchMap((model) => this._executeJobTask(model, TASK_LOAD_JOB_EXECUTIONS)))); this.updateDataJob$ = createEffect(() => this.actions$.pipe(ofType(UPDATE_DATA_JOB), getModelAndTask(this.componentService), switchMap(([model, task]) => this._updateJob(model, task)) // eslint-disable-line rxjs/no-unsafe-switchmap )); this.registerEffectsErrorCodes(); } /** * @inheritDoc * @protected */ registerEffectsErrorCodes() { LOAD_JOB_ERROR_CODES[TASK_LOAD_JOB_STATE] = this.dataJobsApiService.errorCodes.getJob; LOAD_JOB_ERROR_CODES[TASK_LOAD_JOB_DETAILS] = this.dataJobsApiService.errorCodes.getJobDetails; LOAD_JOB_ERROR_CODES[TASK_LOAD_JOB_EXECUTIONS] = this.dataJobsApiService.errorCodes.getJobExecutions; LOAD_JOBS_ERROR_CODES[TASK_LOAD_JOBS_STATE] = this.dataJobsApiService.errorCodes.getJobs; UPDATE_JOB_DETAILS_ERROR_CODES[TASK_UPDATE_JOB_STATUS] = this.dataJobsApiService.errorCodes.updateDataJobStatus; UPDATE_JOB_DETAILS_ERROR_CODES[TASK_UPDATE_JOB_DESCRIPTION] = this.dataJobsApiService.errorCodes.updateDataJob; } _loadDataJobs(componentModel) { const componentState = componentModel.getComponentState(); const task = TASK_LOAD_JOBS_STATE; return of(componentModel).pipe(switchMap((model) => this.dataJobsApiService .getJobs(componentState.filter.criteria, componentState.search, componentState.page.page, componentState.page.size) .pipe(map((response) => model .clearTask() .removeErrorCodePatterns(LOAD_JOBS_ERROR_CODES[TASK_LOAD_JOBS_STATE].All) .withData(JOBS_DATA_KEY, response.data) .withTask(task) .withStatusLoaded() .getComponentState()), map((state) => ComponentLoaded.of(state)), catchError((error) => this._getLatestModel(model).pipe(map((newModel) => ComponentFailed.of(newModel .withData(JOBS_DATA_KEY, { content: [], totalItems: 0, totalPages: 0 }) .withError(processServiceRequestError(this.objectUUID, LOAD_JOBS_ERROR_CODES[TASK_LOAD_JOBS_STATE], ErrorUtil.extractError(error))) .withTask(task) .withStatusFailed() .getComponentState()))))))); } _executeJobTask(model, task) { switch (task) { case TASK_LOAD_JOB_STATE: return this._fetchJobData( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.dataJobsApiService.getJob.bind(this.dataJobsApiService), LOAD_JOB_ERROR_CODES[TASK_LOAD_JOB_STATE], model, TASK_LOAD_JOB_STATE, JOB_STATE_DATA_KEY); case TASK_LOAD_JOB_DETAILS: return this._fetchJobData( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.dataJobsApiService.getJobDetails.bind(this.dataJobsApiService), LOAD_JOB_ERROR_CODES[TASK_LOAD_JOB_DETAILS], model, TASK_LOAD_JOB_DETAILS, JOB_DETAILS_DATA_KEY); case TASK_LOAD_JOB_EXECUTIONS: return this._loadDataJobExecutionsGraphQL(model); default: return throwError(() => new Error('Unknown action task for Data Pipelines.')).pipe(this._handleError(model, null, task)); } } _fetchJobData(executor, executorErrorCodes, componentModel, task, dataKey) { return of(componentModel).pipe(switchMap((model) => executor(componentModel.getComponentState().requestParams.get(TEAM_NAME_REQ_PARAM), componentModel.getComponentState().requestParams.get(JOB_NAME_REQ_PARAM)).pipe(switchMap((data) => { let obsoleteStatus; return this._getLatestModel(model).pipe(tap((newModel) => (obsoleteStatus = newModel.status)), map((newModel) => newModel .removeErrorCodePatterns(executorErrorCodes.All) .withTask(task) .withData(dataKey, data) .withStatusLoaded() .getComponentState()), map((state) => (obsoleteStatus === LOADED ? ComponentUpdate.of(state) : ComponentLoaded.of(state)))); }), this._handleError(model, executorErrorCodes, task)))); } _updateJob(model, taskIdentifier) { const task = extractTaskFromIdentifier(taskIdentifier); const requestParams = model.getComponentState().requestParams; if (task === TASK_UPDATE_JOB_DESCRIPTION) { const jobDetails = requestParams.get(JOB_DETAILS_REQ_PARAM); return this.dataJobsApiService .updateDataJob(requestParams.get(TEAM_NAME_REQ_PARAM), requestParams.get(JOB_NAME_REQ_PARAM), jobDetails) .pipe(map(() => ComponentLoaded.of(model .removeErrorCodePatterns(UPDATE_JOB_DETAILS_ERROR_CODES[TASK_UPDATE_JOB_DESCRIPTION].All) .withTask(taskIdentifier) .withData(JOB_DETAILS_DATA_KEY, jobDetails) .withStatusLoaded() .getComponentState())), this._handleError(model, UPDATE_JOB_DETAILS_ERROR_CODES[TASK_UPDATE_JOB_DESCRIPTION], taskIdentifier)); } if (task === TASK_UPDATE_JOB_STATUS) { const jobState = model.getComponentState().requestParams.get(JOB_STATE_REQ_PARAM); return this.dataJobsApiService .updateDataJobStatus(requestParams.get(TEAM_NAME_REQ_PARAM), requestParams.get(JOB_NAME_REQ_PARAM), requestParams.get(JOB_DEPLOYMENT_ID_REQ_PARAM), requestParams.get(JOB_STATUS_REQ_PARAM)) .pipe(map(() => ComponentLoaded.of(model .removeErrorCodePatterns(UPDATE_JOB_DETAILS_ERROR_CODES[TASK_UPDATE_JOB_STATUS].All) .withTask(taskIdentifier) .withData(JOB_STATE_DATA_KEY, jobState) .withStatusLoaded() .getComponentState())), this._handleError(model, UPDATE_JOB_DETAILS_ERROR_CODES[TASK_UPDATE_JOB_STATUS], taskIdentifier)); } const error = new Error('Unsupported action task for Data Pipelines, update Data Job.'); console.error(error); return of(ComponentFailed.of(model .withTask(taskIdentifier) .withError({ objectUUID: this.objectUUID, code: generateErrorCode(DataJobsEffects.CLASS_NAME, DataJobsEffects.PUBLIC_NAME, '_updateJob', 'UnsupportedActionTask'), error }) .withStatusFailed() .getComponentState())); } _loadDataJobExecutionsGraphQL(componentModel) { const componentState = componentModel.getComponentState(); const requestParams = componentState.requestParams; return of(componentModel).pipe(switchMap((model) => this.dataJobsApiService .getJobExecutions(requestParams.get(TEAM_NAME_REQ_PARAM), requestParams.get(JOB_NAME_REQ_PARAM), true, requestParams.get(FILTER_REQ_PARAM), requestParams.get(ORDER_REQ_PARAM)) .pipe(switchMap((response) => { let obsoleteStatus; return this._getLatestModel(model).pipe(tap((newModel) => (obsoleteStatus = newModel.status)), map((newModel) => newModel .removeErrorCodePatterns(LOAD_JOB_ERROR_CODES[TASK_LOAD_JOB_EXECUTIONS].All) .withTask(TASK_LOAD_JOB_EXECUTIONS) .withData(JOB_EXECUTIONS_DATA_KEY, response.content) .withStatusLoaded() .getComponentState()), map((state) => (obsoleteStatus === LOADED ? ComponentUpdate.of(state) : ComponentLoaded.of(state)))); }), this._handleError(model, LOAD_JOB_ERROR_CODES[TASK_LOAD_JOB_EXECUTIONS], TASK_LOAD_JOB_EXECUTIONS)))); } _getLatestModel(componentModel) { const componentState = componentModel.getComponentState(); return this.componentService.getModel(componentState.id, componentState.routePathSegments, ['*']).pipe(take(1)); } _handleError(obsoleteModel, executorErrorCodes, task) { return catchError((error) => { return this._getLatestModel(obsoleteModel).pipe(map((newModel) => newModel .withTask(task) .withError(CollectionsUtil.isLiteralObject(executorErrorCodes) ? processServiceRequestError(this.objectUUID, executorErrorCodes, ErrorUtil.extractError(error)) : { objectUUID: this.objectUUID, code: generateErrorCode(DataJobsEffects.CLASS_NAME, DataJobsEffects.PUBLIC_NAME, '_handleError', 'GenericError'), error: error }) .withStatusFailed() .getComponentState()), map((state) => ComponentFailed.of(state))); }); } } /** * @inheritDoc */ DataJobsEffects.CLASS_NAME = 'DataJobsEffects'; /** * @inheritDoc */ DataJobsEffects.PUBLIC_NAME = 'Data-Jobs-Effects'; DataJobsEffects.ɵfac = function DataJobsEffects_Factory(t) { return new (t || DataJobsEffects)(i0.ɵɵinject(i1.Actions), i0.ɵɵinject(i2.ComponentService), i0.ɵɵinject(i3.DataJobsApiService)); }; DataJobsEffects.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DataJobsEffects, factory: DataJobsEffects.ɵfac }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DataJobsEffects, [{ type: Injectable }], function () { return [{ type: i1.Actions }, { type: i2.ComponentService }, { type: i3.DataJobsApiService }]; }, null); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS1qb2JzLmVmZmVjdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXRhLXBpcGVsaW5lcy9zcmMvbGliL3N0YXRlL2VmZmVjdHMvZGF0YS1qb2JzLmVmZmVjdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQUUsS0FBSyxFQUFjLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDekQsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV2RSxPQUFPLEVBQVcsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU5RCxPQUFPLEVBQ0gsZUFBZSxFQUNmLGVBQWUsRUFDZixlQUFlLEVBSWYsZUFBZSxFQUNmLHlCQUF5QixFQUN6QixpQkFBaUIsRUFDakIsUUFBUSxFQUNSLGVBQWUsRUFDZixNQUFNLEVBQ04sMEJBQTBCLEVBRzFCLGlCQUFpQixFQUNwQixNQUFNLDBCQUEwQixDQUFDO0FBRWxDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUvQyxPQUFPLEVBTUgsZ0JBQWdCLEVBQ2hCLDJCQUEyQixFQUMzQixvQkFBb0IsRUFDcEIscUJBQXFCLEVBQ3JCLHVCQUF1QixFQUN2QixrQkFBa0IsRUFDbEIsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQixvQkFBb0IsRUFDcEIsYUFBYSxFQUNiLGVBQWUsRUFDZixtQkFBbUIsRUFDdEIsTUFBTSxhQUFhLENBQUM7QUFFckIsT0FBTyxFQUlILHFCQUFxQixFQUNyQix3QkFBd0IsRUFDeEIsbUJBQW1CLEVBQ25CLG9CQUFvQixFQUNwQiwyQkFBMkIsRUFDM0Isc0JBQXNCLEVBQ3pC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LENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxrQkFBa0IsRUFBRSxTQUFTLENBQUMsWUFBWSxDQUFDLEtBQWMsQ0FBQyxDQUFDO2dCQUN6RyxDQUFDLENBQUM7b0JBQ0ksVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO29CQUMzQixJQUFJLEVBQUUsaUJBQWlCLENBQ25CLGVBQWUsQ0FBQyxVQUFVLEVBQzFCLGVBQWUsQ0FBQyxXQUFXLEVBQzNCLGNBQWMsRUFDZCxjQUFjLENBQ2pCO29CQUNELEtBQUssRUFBRSxLQUFjO2lCQUN4QixDQUNWO2lCQUNBLGdCQUFnQixFQUFFO2lCQUNsQixpQkFBaUIsRUFBRSxDQUMzQixFQUNELEdBQUcsQ0FBa0MsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDN0UsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQzs7QUFuVkQ7O0dBRUc7QUFDc0IsMEJBQVUsR0FBRyxpQkFBa0IsQ0FBQTtBQUV4RDs7R0FFRztBQUNzQiwyQkFBVyxHQUFHLG1CQUFvQixDQUFBOzhFQVRsRCxlQUFlO3FFQUFmLGVBQWUsV0FBZixlQUFlO3VGQUFmLGVBQWU7Y0FEM0IsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgMjAyMy0yMDI1IEJyb2FkY29tXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5cbmltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgbWVyZ2UsIE9ic2VydmFibGUsIG9mLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBtYXAsIHN3aXRjaE1hcCwgdGFrZSwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBBY3Rpb25zLCBjcmVhdGVFZmZlY3QsIG9mVHlwZSB9IGZyb20gJ0BuZ3J4L2VmZmVjdHMnO1xuXG5pbXBvcnQge1xuICAgIENvbGxlY3Rpb25zVXRpbCxcbiAgICBDb21wb25lbnRGYWlsZWQsXG4gICAgQ29tcG9uZW50TG9hZGVkLFxuICAgIENvbXBvbmVudE1vZGVsLFxuICAgIENvbXBvbmVudFNlcnZpY2UsXG4gICAgQ29tcG9uZW50U3RhdGUsXG4gICAgQ29tcG9uZW50VXBkYXRlLFxuICAgIGV4dHJhY3RUYXNrRnJvbUlkZW50aWZpZXIsXG4gICAgZ2VuZXJhdGVFcnJvckNvZGUsXG4gICAgZ2V0TW9kZWwsXG4gICAgZ2V0TW9kZWxBbmRUYXNrLFxuICAgIExPQURFRCxcbiAgICBwcm9jZXNzU2VydmljZVJlcXVlc3RFcnJvcixcbiAgICBTZXJ2aWNlSHR0cEVycm9yQ29kZXMsXG4gICAgU3RhdHVzVHlwZSxcbiAgICBUYXVydXNCYXNlRWZmZWN0c1xufSBmcm9tICdAdmVyc2F0aWxlZGF0YWtpdC9zaGFyZWQnO1xuXG5pbXBvcnQgeyBFcnJvclV0aWwgfSBmcm9tICcuLi8uLi9zaGFyZWQvdXRpbHMnO1xuXG5pbXBvcnQge1xuICAgIERhdGFKb2IsXG4gICAgRGF0YUpvYkRldGFpbHMsXG4gICAgRGF0YUpvYkV4ZWN1dGlvbkZpbHRlcixcbiAgICBEYXRhSm9iRXhlY3V0aW9uT3JkZXIsXG4gICAgRGF0YUpvYlBhZ2UsXG4gICAgRklMVEVSX1JFUV9QQVJBTSxcbiAgICBKT0JfREVQTE9ZTUVOVF9JRF9SRVFfUEFSQU0sXG4gICAgSk9CX0RFVEFJTFNfREFUQV9LRVksXG4gICAgSk9CX0RFVEFJTFNfUkVRX1BBUkFNLFxuICAgIEpPQl9FWEVDVVRJT05TX0RBVEFfS0VZLFxuICAgIEpPQl9OQU1FX1JFUV9QQVJBTSxcbiAgICBKT0JfU1RBVEVfREFUQV9LRVksXG4gICAgSk9CX1NUQVRFX1JFUV9QQVJBTSxcbiAgICBKT0JfU1RBVFVTX1JFUV9QQVJBTSxcbiAgICBKT0JTX0RBVEFfS0VZLFxuICAgIE9SREVSX1JFUV9QQVJBTSxcbiAgICBURUFNX05BTUVfUkVRX1BBUkFNXG59IGZyb20gJy4uLy4uL21vZGVsJztcblxuaW1wb3J0IHtcbiAgICBEYXRhSm9iTG9hZFRhc2tzLFxuICAgIERhdGFKb2JzTG9hZFRhc2tzLFxuICAgIERhdGFKb2JVcGRhdGVUYXNrcyxcbiAgICBUQVNLX0xPQURfSk9CX0RFVEFJTFMsXG4gICAgVEFTS19MT0FEX0pPQl9FWEVDVVRJT05TLFxuICAgIFRBU0tfTE9BRF9KT0JfU1RBVEUsXG4gICAgVEFTS19MT0FEX0pPQlNfU1RBVEUsXG4gICAgVEFTS19VUERBVEVfSk9CX0RFU0NSSVBUSU9OLFxuICAgIFRBU0tfVVBEQVRFX0pPQl9TVEFUVVNcbn0gZnJvbSAnLi4vdGFza3MnO1xuXG5pbXBvcnQgeyBMT0FEX0pPQl9FUlJPUl9DT0RFUywgTE9BRF9KT0JTX0VSUk9SX0NPREVTLCBVUERBVEVfSk9CX0RFVEFJTFNfRVJST1JfQ09ERVMgfSBmcm9tICcuLi9lcnJvci1jb2Rlcyc7XG5cbmltcG9ydCB7IEZFVENIX0RBVEFfSk9CLCBGRVRDSF9EQVRBX0pPQl9FWEVDVVRJT05TLCBGRVRDSF9EQVRBX0pPQlMsIFVQREFURV9EQVRBX0pPQiB9IGZyb20gJy4uL2FjdGlvbnMnO1xuXG5pbXBvcnQgeyBEYXRhSm9ic0FwaVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcyc7XG5cbi8qKlxuICogKiogRWZmZWN0IGZvciBEYXRhSm9icy5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIERhdGFKb2JzRWZmZWN0cyBleHRlbmRzIFRhdXJ1c0Jhc2VFZmZlY3RzIHtcbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdERvY1xuICAgICAqL1xuICAgIHN0YXRpYyBvdmVycmlkZSByZWFkb25seSBDTEFTU19OQU1FID0gJ0RhdGFKb2JzRWZmZWN0cyc7XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdERvY1xuICAgICAqL1xuICAgIHN0YXRpYyBvdmVycmlkZSByZWFkb25seSBQVUJMSUNfTkFNRSA9ICdEYXRhLUpvYnMtRWZmZWN0cyc7XG5cbiAgICAvKipcbiAgICAgKiAqKiBMb2FkIERhdGFKb2JzIGRhdGEuXG4gICAgICovXG4gICAgbG9hZERhdGFKb2JzJCA9IGNyZWF0ZUVmZmVjdCgoKSA9PlxuICAgICAgICB0aGlzLmFjdGlvbnMkLnBpcGUoXG4gICAgICAgICAgICBvZlR5cGUoRkVUQ0hfREFUQV9KT0JTKSxcbiAgICAgICAgICAgIGdldE1vZGVsKHRoaXMuY29tcG9uZW50U2VydmljZSksXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKG1vZGVsOiBDb21wb25lbnRNb2RlbCkgPT4gdGhpcy5fbG9hZERhdGFKb2JzKG1vZGVsKSlcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICBsb2FkRGF0YUpvYiQgPSBjcmVhdGVFZmZlY3QoKCkgPT5cbiAgICAgICAgdGhpcy5hY3Rpb25zJC5waXBlKFxuICAgICAgICAgICAgb2ZUeXBlKEZFVENIX0RBVEFfSk9CKSxcbiAgICAgICAgICAgIGdldE1vZGVsKHRoaXMuY29tcG9uZW50U2VydmljZSksXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKG1vZGVsKSA9PlxuICAgICAgICAgICAgICAgIG1lcmdlKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9leGVjdXRlSm9iVGFzayhtb2RlbCwgVEFTS19MT0FEX0pPQl9TVEFURSksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWN1dGVKb2JUYXNrKG1vZGVsLCBUQVNLX0xPQURfSk9CX0RFVEFJTFMpLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9leGVjdXRlSm9iVGFzayhtb2RlbCwgVEFTS19MT0FEX0pPQl9FWEVDVVRJT05TKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICBsb2FkRGF0YUpvYkV4ZWN1dGlvbnMkID0gY3JlYXRlRWZmZWN0KCgpID0+XG4gICAgICAgIHRoaXMuYWN0aW9ucyQucGlwZShcbiAgICAgICAgICAgIG9mVHlwZShGRVRDSF9EQVRBX0pPQl9FWEVDVVRJT05TKSxcbiAgICAgICAgICAgIGdldE1vZGVsKHRoaXMuY29tcG9uZW50U2VydmljZSksXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKG1vZGVsKSA9PiB0aGlzLl9leGVjdXRlSm9iVGFzayhtb2RlbCwgVEFTS19MT0FEX0pPQl9FWEVDVVRJT05TKSlcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICB1cGRhdGVEYXRhSm9iJCA9IGNyZWF0ZUVmZmVjdCgoKSA9PlxuICAgICAgICB0aGlzLmFjdGlvbnMkLnBpcGUoXG4gICAgICAgICAgICBvZlR5cGUoVVBEQVRFX0RBVEFfSk9CKSxcbiAgICAgICAgICAgIGdldE1vZGVsQW5kVGFzayh0aGlzLmNvbXBvbmVudFNlcnZpY2UpLFxuICAgICAgICAgICAgc3dpdGNoTWFwKChbbW9kZWwsIHRhc2tdKSA9PiB0aGlzLl91cGRhdGVKb2IobW9kZWwsIHRhc2spKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJ4anMvbm8tdW5zYWZlLXN3aXRjaG1hcFxuICAgICAgICApXG4gICAgKTtcblxuICAgIC8qKlxuICAgICAqICoqIENvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBhY3Rpb25zJDogQWN0aW9ucyxcbiAgICAgICAgY29tcG9uZW50U2VydmljZTogQ29tcG9uZW50U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBkYXRhSm9ic0FwaVNlcnZpY2U6IERhdGFKb2JzQXBpU2VydmljZVxuICAgICkge1xuICAgICAgICBzdXBlcihhY3Rpb25zJCwgY29tcG9uZW50U2VydmljZSwgRGF0YUpvYnNFZmZlY3RzLkNMQVNTX05BTUUpO1xuXG4gICAgICAgIHRoaXMucmVnaXN0ZXJFZmZlY3RzRXJyb3JDb2RlcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0RG9jXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWdpc3RlckVmZmVjdHNFcnJvckNvZGVzKCk6IHZvaWQge1xuICAgICAgICBMT0FEX0pPQl9FUlJPUl9DT0RFU1tUQVNLX0xPQURfSk9CX1NUQVRFXSA9IHRoaXMuZGF0YUpvYnNBcGlTZXJ2aWNlLmVycm9yQ29kZXMuZ2V0Sm9iO1xuICAgICAgICBMT0FEX0pPQl9FUlJPUl9DT0RFU1tUQVNLX0xPQURfSk9CX0RFVEFJTFNdID0gdGhpcy5kYXRhSm9ic0FwaVNlcnZpY2UuZXJyb3JDb2Rlcy5nZXRKb2JEZXRhaWxzO1xuICAgICAgICBMT0FEX0pPQl9FUlJPUl9DT0RFU1tUQVNLX0xPQURfSk9CX0VYRUNVVElPTlNdID0gdGhpcy5kYXRhSm9ic0FwaVNlcnZpY2UuZXJyb3JDb2Rlcy5nZXRKb2JFeGVjdXRpb25zO1xuXG4gICAgICAgIExPQURfSk9CU19FUlJPUl9DT0RFU1tUQVNLX0xPQURfSk9CU19TVEFURV0gPSB0aGlzLmRhdGFKb2JzQXBpU2VydmljZS5lcnJvckNvZGVzLmdldEpvYnM7XG5cbiAgICAgICAgVVBEQVRFX0pPQl9ERVRBSUxTX0VSUk9SX0NPREVTW1RBU0tfVVBEQVRFX0pPQl9TVEFUVVNdID0gdGhpcy5kYXRhSm9ic0FwaVNlcnZpY2UuZXJyb3JDb2Rlcy51cGRhdGVEYXRhSm9iU3RhdHVzO1xuICAgICAgICBVUERBVEVfSk9CX0RFVEFJTFNfRVJST1JfQ09ERVNbVEFTS19VUERBVEVfSk9CX0RFU0NSSVBUSU9OXSA9IHRoaXMuZGF0YUpvYnNBcGlTZXJ2aWNlLmVycm9yQ29kZXMudXBkYXRlRGF0YUpvYjtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9sb2FkRGF0YUpvYnMoY29tcG9uZW50TW9kZWw6IENvbXBvbmVudE1vZGVsKTogT2JzZXJ2YWJsZTxDb21wb25lbnRMb2FkZWQgfCBDb21wb25lbnRGYWlsZWQ+IHtcbiAgICAgICAgY29uc3QgY29tcG9uZW50U3RhdGUgPSBjb21wb25lbnRNb2RlbC5nZXRDb21wb25lbnRTdGF0ZSgpO1xuICAgICAgICBjb25zdCB0YXNrOiBEYXRhSm9ic0xvYWRUYXNrcyA9IFRBU0tfTE9BRF9KT0JTX1NUQVRFO1xuXG4gICAgICAgIHJldHVybiBvZihjb21wb25lbnRNb2RlbCkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgobW9kZWwpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhSm9ic0FwaVNlcnZpY2VcbiAgICAgICAgICAgICAgICAgICAgLmdldEpvYnMoY29tcG9uZW50U3RhdGUuZmlsdGVyLmNyaXRlcmlhLCBjb21wb25lbnRTdGF0ZS5zZWFyY2gsIGNvbXBvbmVudFN0YXRlLnBhZ2UucGFnZSwgY29tcG9uZW50U3RhdGUucGFnZS5zaXplKVxuICAgICAgICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgocmVzcG9uc2UpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNsZWFyVGFzaygpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVFcnJvckNvZGVQYXR0ZXJucyhMT0FEX0pPQlNfRVJST1JfQ09ERVNbVEFTS19MT0FEX0pPQlNfU1RBVEVdLkFsbClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhEYXRhKEpPQlNfREFUQV9LRVksIHJlc3BvbnNlLmRhdGEpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC53aXRoVGFzayh0YXNrKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAud2l0aFN0YXR1c0xvYWRlZCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5nZXRDb21wb25lbnRTdGF0ZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWFwPENvbXBvbmVudFN0YXRlLCBDb21wb25lbnRMb2FkZWQ+KChzdGF0ZSkgPT4gQ29tcG9uZW50TG9hZGVkLm9mKHN0YXRlKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaEVycm9yPENvbXBvbmVudEZhaWxlZCwgT2JzZXJ2YWJsZTxDb21wb25lbnRGYWlsZWQ+PigoZXJyb3I6IHVua25vd24pID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZ2V0TGF0ZXN0TW9kZWwobW9kZWwpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgobmV3TW9kZWwpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb21wb25lbnRGYWlsZWQub2YoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3TW9kZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhEYXRhKEpPQlNfREFUQV9LRVksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxJdGVtczogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsUGFnZXM6IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBhcyBEYXRhSm9iUGFnZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NTZXJ2aWNlUmVxdWVzdEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub2JqZWN0VVVJRCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMT0FEX0pPQlNfRVJST1JfQ09ERVNbVEFTS19MT0FEX0pPQlNfU1RBVEVdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVycm9yVXRpbC5leHRyYWN0RXJyb3IoZXJyb3IgYXMgRXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhUYXNrKHRhc2spXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC53aXRoU3RhdHVzRmFpbGVkKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmdldENvbXBvbmVudFN0YXRlKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2V4ZWN1dGVKb2JUYXNrKG1vZGVsOiBDb21wb25lbnRNb2RlbCwgdGFzazogRGF0YUpvYkxvYWRUYXNrcyk6IE9ic2VydmFibGU8Q29tcG9uZW50TG9hZGVkIHwgQ29tcG9uZW50RmFpbGVkPiB7XG4gICAgICAgIHN3aXRjaCAodGFzaykge1xuICAgICAgICAgICAgY2FzZSBUQVNLX0xPQURfSk9CX1NUQVRFOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9mZXRjaEpvYkRhdGE8RGF0YUpvYj4oXG4gICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFyZ3VtZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YUpvYnNBcGlTZXJ2aWNlLmdldEpvYi5iaW5kKHRoaXMuZGF0YUpvYnNBcGlTZXJ2aWNlKSxcbiAgICAgICAgICAgICAgICAgICAgTE9BRF9KT0JfRVJST1JfQ09ERVNbVEFTS19MT0FEX0pPQl9TVEFURV0sXG4gICAgICAgICAgICAgICAgICAgIG1vZGVsLFxuICAgICAgICAgICAgICAgICAgICBUQVNLX0xPQURfSk9CX1NUQVRFLFxuICAgICAgICAgICAgICAgICAgICBKT0JfU1RBVEVfREFUQV9LRVlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY2FzZSBUQVNLX0xPQURfSk9CX0RFVEFJTFM6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2ZldGNoSm9iRGF0YShcbiAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXJndW1lbnRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhSm9ic0FwaVNlcnZpY2UuZ2V0Sm9iRGV0YWlscy5iaW5kKHRoaXMuZGF0YUpvYnNBcGlTZXJ2aWNlKSxcbiAgICAgICAgICAgICAgICAgICAgTE9BRF9KT0JfRVJST1JfQ09ERVNbVEFTS19MT0FEX0pPQl9ERVRBSUxTXSxcbiAgICAgICAgICAgICAgICAgICAgbW9kZWwsXG4gICAgICAgICAgICAgICAgICAgIFRBU0tfTE9BRF9KT0JfREVUQUlMUyxcbiAgICAgICAgICAgICAgICAgICAgSk9CX0RFVEFJTFNfREFUQV9LRVlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY2FzZSBUQVNLX0xPQURfSk9CX0VYRUNVVElPTlM6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWREYXRhSm9iRXhlY3V0aW9uc0dyYXBoUUwobW9kZWwpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBuZXcgRXJyb3IoJ1Vua25vd24gYWN0aW9uIHRhc2sgZm9yIERhdGEgUGlwZWxpbmVzLicpKS5waXBlKHRoaXMuX2hhbmRsZUVycm9yKG1vZGVsLCBudWxsLCB0YXNrKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIF9mZXRjaEpvYkRhdGE8VD4oXG4gICAgICAgIGV4ZWN1dG9yOiAocGFyYW0xOiBzdHJpbmcsIHBhcmFtMjogc3RyaW5nKSA9PiBPYnNlcnZhYmxlPFQ+LFxuICAgICAgICBleGVjdXRvckVycm9yQ29kZXM6IFJlYWRvbmx5PFJlY29yZDxrZXlvZiBTZXJ2aWNlSHR0cEVycm9yQ29kZXMsIHN0cmluZz4+LFxuICAgICAgICBjb21wb25lbnRNb2RlbDogQ29tcG9uZW50TW9kZWwsXG4gICAgICAgIHRhc2s6IERhdGFKb2JMb2FkVGFza3MgfCBzdHJpbmcsXG4gICAgICAgIGRhdGFLZXk6IHN0cmluZ1xuICAgICk6IE9ic2VydmFibGU8Q29tcG9uZW50TG9hZGVkIHwgQ29tcG9uZW50VXBkYXRlIHwgQ29tcG9uZW50RmFpbGVkPiB7XG4gICAgICAgIHJldHVybiBvZihjb21wb25lbnRNb2RlbCkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgobW9kZWwpID0+XG4gICAgICAgICAgICAgICAgZXhlY3V0b3IoXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE1vZGVsLmdldENvbXBvbmVudFN0YXRlKCkucmVxdWVzdFBhcmFtcy5nZXQoVEVBTV9OQU1FX1JFUV9QQVJBTSkgYXMgc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRNb2RlbC5nZXRDb21wb25lbnRTdGF0ZSgpLnJlcXVlc3RQYXJhbXMuZ2V0KEpPQl9OQU1FX1JFUV9QQVJBTSkgYXMgc3RyaW5nXG4gICAgICAgICAgICAgICAgKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKGRhdGEpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvYnNvbGV0ZVN0YXR1czogU3RhdHVzVHlwZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2dldExhdGVzdE1vZGVsKG1vZGVsKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcCgobmV3TW9kZWwpID0+IChvYnNvbGV0ZVN0YXR1cyA9IG5ld01vZGVsLnN0YXR1cykpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgobmV3TW9kZWwpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld01vZGVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlRXJyb3JDb2RlUGF0dGVybnMoZXhlY3V0b3JFcnJvckNvZGVzLkFsbClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC53aXRoVGFzayh0YXNrKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhEYXRhKGRhdGFLZXksIGRhdGEpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAud2l0aFN0YXR1c0xvYWRlZCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZ2V0Q29tcG9uZW50U3RhdGUoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChzdGF0ZSkgPT4gKG9ic29sZXRlU3RhdHVzID09PSBMT0FERUQgPyBDb21wb25lbnRVcGRhdGUub2Yoc3RhdGUpIDogQ29tcG9uZW50TG9hZGVkLm9mKHN0YXRlKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faGFuZGxlRXJyb3IobW9kZWwsIGV4ZWN1dG9yRXJyb3JDb2RlcywgdGFzaylcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfdXBkYXRlSm9iKG1vZGVsOiBDb21wb25lbnRNb2RlbCwgdGFza0lkZW50aWZpZXI6IHN0cmluZyk6IE9ic2VydmFibGU8Q29tcG9uZW50VXBkYXRlIHwgQ29tcG9uZW50RmFpbGVkPiB7XG4gICAgICAgIGNvbnN0IHRhc2sgPSBleHRyYWN0VGFza0Zyb21JZGVudGlmaWVyPERhdGFKb2JVcGRhdGVUYXNrcz4odGFza0lkZW50aWZpZXIpO1xuICAgICAgICBjb25zdCByZXF1ZXN0UGFyYW1zID0gbW9kZWwuZ2V0Q29tcG9uZW50U3RhdGUoKS5yZXF1ZXN0UGFyYW1zO1xuXG4gICAgICAgIGlmICh0YXNrID09PSBUQVNLX1VQREFURV9KT0JfREVTQ1JJUFRJT04pIHtcbiAgICAgICAgICAgIGNvbnN0IGpvYkRldGFpbHM6IERhdGFKb2JEZXRhaWxzID0gcmVxdWVzdFBhcmFtcy5nZXQoSk9CX0RFVEFJTFNfUkVRX1BBUkFNKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YUpvYnNBcGlTZXJ2aWNlXG4gICAgICAgICAgICAgICAgLnVwZGF0ZURhdGFKb2IoXG4gICAgICAgICAgICAgICAgICAgIHJlcXVlc3RQYXJhbXMuZ2V0KFRFQU1fTkFNRV9SRVFfUEFSQU0pIGFzIHN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdFBhcmFtcy5nZXQoSk9CX05BTUVfUkVRX1BBUkFNKSBhcyBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgIGpvYkRldGFpbHNcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgIG1hcCgoKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgQ29tcG9uZW50TG9hZGVkLm9mKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVFcnJvckNvZGVQYXR0ZXJucyhVUERBVEVfSk9CX0RFVEFJTFNfRVJST1JfQ09ERVNbVEFTS19VUERBVEVfSk9CX0RFU0NSSVBUSU9OXS5BbGwpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC53aXRoVGFzayh0YXNrSWRlbnRpZmllcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhEYXRhKEpPQl9ERVRBSUxTX0RBVEFfS0VZLCBqb2JEZXRhaWxzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAud2l0aFN0YXR1c0xvYWRlZCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5nZXRDb21wb25lbnRTdGF0ZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2hhbmRsZUVycm9yKG1vZGVsLCBVUERBVEVfSk9CX0RFVEFJTFNfRVJST1JfQ09ERVNbVEFTS19VUERBVEVfSk9CX0RFU0NSSVBUSU9OXSwgdGFza0lkZW50aWZpZXIpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0YXNrID09PSBUQVNLX1VQREFURV9KT0JfU1RBVFVTKSB7XG4gICAgICAgICAgICBjb25zdCBqb2JTdGF0ZTogRGF0YUpvYiA9IG1vZGVsLmdldENvbXBvbmVudFN0YXRlKCkucmVxdWVzdFBhcmFtcy5nZXQoSk9CX1NUQVRFX1JFUV9QQVJBTSk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFKb2JzQXBpU2VydmljZVxuICAgICAgICAgICAgICAgIC51cGRhdGVEYXRhSm9iU3RhdHVzKFxuICAgICAgICAgICAgICAgICAgICByZXF1ZXN0UGFyYW1zLmdldChURUFNX05BTUVfUkVRX1BBUkFNKSBhcyBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgIHJlcXVlc3RQYXJhbXMuZ2V0KEpPQl9OQU1FX1JFUV9QQVJBTSkgYXMgc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICByZXF1ZXN0UGFyYW1zLmdldChKT0JfREVQTE9ZTUVOVF9JRF9SRVFfUEFSQU0pIGFzIHN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdFBhcmFtcy5nZXQoSk9CX1NUQVRVU19SRVFfUEFSQU0pIGFzIGJvb2xlYW5cbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgIG1hcCgoKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgQ29tcG9uZW50TG9hZGVkLm9mKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVFcnJvckNvZGVQYXR0ZXJucyhVUERBVEVfSk9CX0RFVEFJTFNfRVJST1JfQ09ERVNbVEFTS19VUERBVEVfSk9CX1NUQVRVU10uQWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAud2l0aFRhc2sodGFza0lkZW50aWZpZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC53aXRoRGF0YShKT0JfU1RBVEVfREFUQV9LRVksIGpvYlN0YXRlKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAud2l0aFN0YXR1c0xvYWRlZCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5nZXRDb21wb25lbnRTdGF0ZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2hhbmRsZUVycm9yKG1vZGVsLCBVUERBVEVfSk9CX0RFVEFJTFNfRVJST1JfQ09ERVNbVEFTS19VUERBVEVfSk9CX1NUQVRVU10sIHRhc2tJZGVudGlmaWVyKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgYWN0aW9uIHRhc2sgZm9yIERhdGEgUGlwZWxpbmVzLCB1cGRhdGUgRGF0YSBKb2IuJyk7XG5cbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG5cbiAgICAgICAgcmV0dXJuIG9mKFxuICAgICAgICAgICAgQ29tcG9uZW50RmFpbGVkLm9mKFxuICAgICAgICAgICAgICAgIG1vZGVsXG4gICAgICAgICAgICAgICAgICAgIC53aXRoVGFzayh0YXNrSWRlbnRpZmllcilcbiAgICAgICAgICAgICAgICAgICAgLndpdGhFcnJvcih7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RVVUlEOiB0aGlzLm9iamVjdFVVSUQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBnZW5lcmF0ZUVycm9yQ29kZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRhSm9ic0VmZmVjdHMuQ0xBU1NfTkFNRSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRhSm9ic0VmZmVjdHMuUFVCTElDX05BTUUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ191cGRhdGVKb2InLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdVbnN1cHBvcnRlZEFjdGlvblRhc2snXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLndpdGhTdGF0dXNGYWlsZWQoKVxuICAgICAgICAgICAgICAgICAgICAuZ2V0Q29tcG9uZW50U3RhdGUoKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2xvYWREYXRhSm9iRXhlY3V0aW9uc0dyYXBoUUwoY29tcG9uZW50TW9kZWw6IENvbXBvbmVudE1vZGVsKTogT2JzZXJ2YWJsZTxDb21wb25lbnRMb2FkZWQ+IHtcbiAgICAgICAgY29uc3QgY29tcG9uZW50U3RhdGUgPSBjb21wb25lbnRNb2RlbC5nZXRDb21wb25lbnRTdGF0ZSgpO1xuICAgICAgICBjb25zdCByZXF1ZXN0UGFyYW1zID0gY29tcG9uZW50U3RhdGUucmVxdWVzdFBhcmFtcztcblxuICAgICAgICByZXR1cm4gb2YoY29tcG9uZW50TW9kZWwpLnBpcGUoXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKG1vZGVsKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuZGF0YUpvYnNBcGlTZXJ2aWNlXG4gICAgICAgICAgICAgICAgICAgIC5nZXRKb2JFeGVjdXRpb25zKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdFBhcmFtcy5nZXQoVEVBTV9OQU1FX1JFUV9QQVJBTSkgYXMgc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdFBhcmFtcy5nZXQoSk9CX05BTUVfUkVRX1BBUkFNKSBhcyBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdFBhcmFtcy5nZXQoRklMVEVSX1JFUV9QQVJBTSkgYXMgRGF0YUpvYkV4ZWN1dGlvbkZpbHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RQYXJhbXMuZ2V0KE9SREVSX1JFUV9QQVJBTSkgYXMgRGF0YUpvYkV4ZWN1dGlvbk9yZGVyXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9ic29sZXRlU3RhdHVzOiBTdGF0dXNUeXBlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2dldExhdGVzdE1vZGVsKG1vZGVsKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXAoKG5ld01vZGVsKSA9PiAob2Jzb2xldGVTdGF0dXMgPSBuZXdNb2RlbC5zdGF0dXMpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChuZXdNb2RlbCkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld01vZGVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUVycm9yQ29kZVBhdHRlcm5zKExPQURfSk9CX0VSUk9SX0NPREVTW1RBU0tfTE9BRF9KT0JfRVhFQ1VUSU9OU10uQWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC53aXRoVGFzayhUQVNLX0xPQURfSk9CX0VYRUNVVElPTlMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhEYXRhKEpPQl9FWEVDVVRJT05TX0RBVEFfS0VZLCByZXNwb25zZS5jb250ZW50KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC53aXRoU3RhdHVzTG9hZGVkKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZ2V0Q29tcG9uZW50U3RhdGUoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAoKHN0YXRlKSA9PiAob2Jzb2xldGVTdGF0dXMgPT09IExPQURFRCA/IENvbXBvbmVudFVwZGF0ZS5vZihzdGF0ZSkgOiBDb21wb25lbnRMb2FkZWQub2Yoc3RhdGUpKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9oYW5kbGVFcnJvcihtb2RlbCwgTE9BRF9KT0JfRVJST1JfQ09ERVNbVEFTS19MT0FEX0pPQl9FWEVDVVRJT05TXSwgVEFTS19MT0FEX0pPQl9FWEVDVVRJT05TKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ2V0TGF0ZXN0TW9kZWwoY29tcG9uZW50TW9kZWw6IENvbXBvbmVudE1vZGVsKTogT2JzZXJ2YWJsZTxDb21wb25lbnRNb2RlbD4ge1xuICAgICAgICBjb25zdCBjb21wb25lbnRTdGF0ZSA9IGNvbXBvbmVudE1vZGVsLmdldENvbXBvbmVudFN0YXRlKCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50U2VydmljZS5nZXRNb2RlbChjb21wb25lbnRTdGF0ZS5pZCwgY29tcG9uZW50U3RhdGUucm91dGVQYXRoU2VnbWVudHMsIFsnKiddKS5waXBlKHRha2UoMSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2hhbmRsZUVycm9yKFxuICAgICAgICBvYnNvbGV0ZU1vZGVsOiBDb21wb25lbnRNb2RlbCxcbiAgICAgICAgZXhlY3V0b3JFcnJvckNvZGVzOiBSZWFkb25seTxSZWNvcmQ8a2V5b2YgU2VydmljZUh0dHBFcnJvckNvZGVzLCBzdHJpbmc+PixcbiAgICAgICAgdGFzazogRGF0YUpvYkxvYWRUYXNrcyB8IHN0cmluZ1xuICAgICkge1xuICAgICAgICByZXR1cm4gY2F0Y2hFcnJvcjxDb21wb25lbnRMb2FkZWQgfCBDb21wb25lbnRVcGRhdGUsIE9ic2VydmFibGU8Q29tcG9uZW50RmFpbGVkPj4oKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TGF0ZXN0TW9kZWwob2Jzb2xldGVNb2RlbCkucGlwZShcbiAgICAgICAgICAgICAgICBtYXAoKG5ld01vZGVsKSA9PlxuICAgICAgICAgICAgICAgICAgICBuZXdNb2RlbFxuICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhUYXNrKHRhc2spXG4gICAgICAgICAgICAgICAgICAgICAgICAud2l0aEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvbGxlY3Rpb25zVXRpbC5pc0xpdGVyYWxPYmplY3QoZXhlY3V0b3JFcnJvckNvZGVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHByb2Nlc3NTZXJ2aWNlUmVxdWVzdEVycm9yKHRoaXMub2JqZWN0VVVJRCwgZXhlY3V0b3JFcnJvckNvZGVzLCBFcnJvclV0aWwuZXh0cmFjdEVycm9yKGVycm9yIGFzIEVycm9yKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFVVSUQ6IHRoaXMub2JqZWN0VVVJRCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogZ2VuZXJhdGVFcnJvckNvZGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRhSm9ic0VmZmVjdHMuQ0xBU1NfTkFNRSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERhdGFKb2JzRWZmZWN0cy5QVUJMSUNfTkFNRSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdfaGFuZGxlRXJyb3InLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0dlbmVyaWNFcnJvcidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yIGFzIEVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgLndpdGhTdGF0dXNGYWlsZWQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmdldENvbXBvbmVudFN0YXRlKClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIG1hcDxDb21wb25lbnRTdGF0ZSwgQ29tcG9uZW50RmFpbGVkPigoc3RhdGUpID0+IENvbXBvbmVudEZhaWxlZC5vZihzdGF0ZSkpXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG59XG4iXX0=