UNPKG

@alfresco/adf-content-services

Version:
391 lines 55 kB
/*! * @license * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { inject, Injectable } from '@angular/core'; import { Minimatch } from 'minimatch'; import { Subject } from 'rxjs'; import { FileUploadCompleteEvent, FileUploadDeleteEvent, FileUploadErrorEvent, FileUploadEvent } from '../events/file.event'; import { FileUploadStatus } from '../models/file.model'; import { AppConfigService } from '@alfresco/adf-core'; import { filter } from 'rxjs/operators'; import { DiscoveryApiService } from '../../common/services/discovery-api.service'; import { NodesApi, UploadApi, VersionsApi } from '@alfresco/js-api'; import { AlfrescoApiService } from '../../services/alfresco-api.service'; import * as i0 from "@angular/core"; const MIN_CANCELLABLE_FILE_SIZE = 1000000; const MAX_CANCELLABLE_FILE_PERCENTAGE = 50; export class UploadService { get uploadApi() { this._uploadApi = this._uploadApi ?? new UploadApi(this.apiService.getInstance()); return this._uploadApi; } get nodesApi() { this._nodesApi = this._nodesApi ?? new NodesApi(this.apiService.getInstance()); return this._nodesApi; } get versionsApi() { this._versionsApi = this._versionsApi ?? new VersionsApi(this.apiService.getInstance()); return this._versionsApi; } constructor() { this.queue = []; this.queueChanged = new Subject(); this.fileUpload = new Subject(); this.fileUploadStarting = new Subject(); this.fileUploadCancelled = new Subject(); this.fileUploadProgress = new Subject(); this.fileUploadAborted = new Subject(); this.fileUploadError = new Subject(); this.fileUploadComplete = new Subject(); this.fileUploadDeleted = new Subject(); this.fileDeleted = new Subject(); this.cache = {}; this.totalComplete = 0; this.totalAborted = 0; this.totalError = 0; this.excludedFileList = []; this.excludedFoldersList = []; this.matchingOptions = null; this.folderMatchingOptions = null; this.apiService = inject(AlfrescoApiService); this.appConfigService = inject(AppConfigService); this.discoveryApiService = inject(DiscoveryApiService); this.discoveryApiService.ecmProductInfo$.pipe(filter((info) => !!info)).subscribe(({ status }) => { this.isThumbnailGenerationEnabled = status.isThumbnailGenerationEnabled; }); } clearCache() { this.cache = {}; } /** * Returns the number of concurrent threads for uploading. * * @returns Number of concurrent threads (default 1) */ getThreadsCount() { return this.appConfigService.get('upload.threads', 1); } /** * Checks whether the service still has files uploading or awaiting upload. * * @returns True if files in the queue are still uploading, false otherwise */ isUploading() { const finishedFileStates = [ FileUploadStatus.Complete, FileUploadStatus.Cancelled, FileUploadStatus.Aborted, FileUploadStatus.Error, FileUploadStatus.Deleted ]; return this.queue.reduce((stillUploading, currentFile) => stillUploading || finishedFileStates.indexOf(currentFile.status) === -1, false); } /** * Gets the file Queue * * @returns Array of files that form the queue */ getQueue() { return this.queue; } /** * Adds files to the uploading queue to be uploaded * * @param files One or more separate parameters or an array of files to queue * @returns Array of files that were not blocked from upload by the ignore list */ addToQueue(...files) { const allowedFiles = files.filter((currentFile) => this.filterElement(currentFile)); this.queue = this.queue.concat(allowedFiles); this.queueChanged.next(this.queue); return allowedFiles; } /** * Finds all the files in the queue that are not yet uploaded and uploads them into the directory folder. * * @param successEmitter Emitter to invoke on file success status change * @param errorEmitter Emitter to invoke on file error status change */ uploadFilesInTheQueue(successEmitter, errorEmitter) { const files = this.getFilesToUpload(); if (files && files.length > 0) { for (const file of files) { this.onUploadStarting(file); const promise = this.beginUpload(file, successEmitter, errorEmitter); this.cache[file.name] = promise; const next = () => { setTimeout(() => this.uploadFilesInTheQueue(successEmitter, errorEmitter), 100); }; promise.next = next; promise.then(() => next(), () => next()); } } } /** * Cancels uploading of files. * If the file is smaller than 1 MB the file will be uploaded and then the node deleted * to prevent having files that were aborted but still uploaded. * * @param files One or more separate parameters or an array of files specifying uploads to cancel */ cancelUpload(...files) { files.forEach((file) => { const promise = this.cache[file.name]; if (promise) { if (this.isSaveToAbortFile(file)) { promise.abort(); } else { this.abortedFile = file.name; } delete this.cache[file.name]; promise.next(); } else { const performAction = this.getAction(file); if (performAction) { performAction(); } } }); } /** Clears the upload queue */ clearQueue() { this.queue = []; this.totalComplete = 0; this.totalAborted = 0; this.totalError = 0; } /** * Gets an upload promise for a file. * * @param file The target file * @returns Promise that is resolved if the upload is successful or error otherwise */ getUploadPromise(file) { const opts = { include: ['allowableOperations'] }; if (this.isThumbnailGenerationEnabled) { opts.renditions = 'doclib'; } if (file.options?.versioningEnabled !== undefined) { opts.versioningEnabled = file.options.versioningEnabled; } if (file.options.newVersion === true) { opts.overwrite = true; opts.majorVersion = file.options.majorVersion; opts.comment = file.options.comment; opts.name = file.name; } else { opts.autoRename = true; } if (file.options.nodeType) { opts.nodeType = file.options.nodeType; } if (file.id) { return this.nodesApi.updateNodeContent(file.id, file.file, opts); } else { const nodeBody = { ...file.options, name: file.name, nodeType: file.options.nodeType }; delete nodeBody['versioningEnabled']; return this.uploadApi.uploadFile(file.file, file.options.path, file.options.parentId, nodeBody, opts); } } getFilesToUpload() { const cached = Object.keys(this.cache); const threadsCount = this.getThreadsCount(); if (cached.length >= threadsCount) { return []; } const files = this.queue .filter((toUpload) => !cached.includes(toUpload.name) && toUpload.status === FileUploadStatus.Pending) .slice(0, threadsCount); return files; } beginUpload(file, successEmitter, errorEmitter) { const promise = this.getUploadPromise(file); promise .on('progress', (progress) => { this.onUploadProgress(file, progress); }) .on('abort', () => { this.onUploadAborted(file); if (successEmitter) { successEmitter.emit({ value: 'File aborted' }); } }) .on('error', (err) => { this.onUploadError(file, err); if (errorEmitter) { errorEmitter.emit({ value: 'Error file uploaded' }); } }) .on('success', (data) => { if (this.abortedFile === file.name) { this.onUploadAborted(file); if (file.id === undefined) { this.deleteAbortedNode(data.entry.id); } else { this.deleteAbortedNodeVersion(data.entry.id, data.entry.properties['cm:versionLabel']); } if (successEmitter) { successEmitter.emit({ value: 'File deleted' }); } } else { this.onUploadComplete(file, data); if (successEmitter) { successEmitter.emit({ value: data }); } } }) .catch(() => { }); return promise; } onUploadStarting(file) { if (file) { file.status = FileUploadStatus.Starting; const event = new FileUploadEvent(file, FileUploadStatus.Starting); this.fileUpload.next(event); this.fileUploadStarting.next(event); } } onUploadProgress(file, progress) { if (file) { file.progress = progress; file.status = FileUploadStatus.Progress; const event = new FileUploadEvent(file, FileUploadStatus.Progress); this.fileUpload.next(event); this.fileUploadProgress.next(event); } } onUploadError(file, error) { if (file) { file.errorCode = error?.status; file.status = FileUploadStatus.Error; this.totalError++; const promise = this.cache[file.name]; if (promise) { delete this.cache[file.name]; } const event = new FileUploadErrorEvent(file, error, this.totalError); this.fileUpload.next(event); this.fileUploadError.next(event); } } onUploadComplete(file, data) { if (file) { file.status = FileUploadStatus.Complete; file.data = data; this.totalComplete++; const promise = this.cache[file.name]; if (promise) { delete this.cache[file.name]; } const event = new FileUploadCompleteEvent(file, this.totalComplete, data, this.totalAborted); this.fileUpload.next(event); this.fileUploadComplete.next(event); } } onUploadAborted(file) { if (file) { file.status = FileUploadStatus.Aborted; this.totalAborted++; const event = new FileUploadEvent(file, FileUploadStatus.Aborted); this.fileUpload.next(event); this.fileUploadAborted.next(event); } } onUploadCancelled(file) { if (file) { file.status = FileUploadStatus.Cancelled; const event = new FileUploadEvent(file, FileUploadStatus.Cancelled); this.fileUpload.next(event); this.fileUploadCancelled.next(event); } } onUploadDeleted(file) { if (file) { file.status = FileUploadStatus.Deleted; this.totalComplete--; const event = new FileUploadDeleteEvent(file, this.totalComplete); this.fileUpload.next(event); this.fileUploadDeleted.next(event); } } getAction(file) { const actions = { [FileUploadStatus.Pending]: () => this.onUploadCancelled(file), [FileUploadStatus.Deleted]: () => this.onUploadDeleted(file), [FileUploadStatus.Error]: () => this.onUploadError(file, null) }; return actions[file.status]; } deleteAbortedNode(nodeId) { this.nodesApi.deleteNode(nodeId, { permanent: true }).then(() => (this.abortedFile = undefined)); } deleteAbortedNodeVersion(nodeId, versionId) { this.versionsApi.deleteVersion(nodeId, versionId).then(() => (this.abortedFile = undefined)); } isSaveToAbortFile(file) { return file.size > MIN_CANCELLABLE_FILE_SIZE && file.progress.percent < MAX_CANCELLABLE_FILE_PERCENTAGE; } filterElement(file) { this.excludedFileList = this.appConfigService.get('files.excluded'); this.excludedFoldersList = this.appConfigService.get('folders.excluded'); let isAllowed = true; if (this.excludedFileList) { this.matchingOptions = this.appConfigService.get('files.match-options'); isAllowed = this.isFileNameAllowed(file); } if (isAllowed && this.excludedFoldersList) { this.folderMatchingOptions = this.appConfigService.get('folders.match-options'); isAllowed = this.isParentFolderAllowed(file); } return isAllowed; } isParentFolderAllowed(file) { let isAllowed = true; const currentFile = file.file; const fileRelativePath = currentFile.webkitRelativePath ? currentFile.webkitRelativePath : file.options.path; if (currentFile && fileRelativePath) { isAllowed = this.excludedFoldersList.filter((folderToExclude) => fileRelativePath.split('/').some((pathElement) => { const minimatch = new Minimatch(folderToExclude, this.folderMatchingOptions); return minimatch.match(pathElement); })).length === 0; } return isAllowed; } isFileNameAllowed(file) { return (this.excludedFileList.filter((pattern) => { const minimatch = new Minimatch(pattern, this.matchingOptions); return minimatch.match(file.name); }).length === 0); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: UploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: UploadService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: UploadService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL2NvbW1vbi9zZXJ2aWNlcy91cGxvYWQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQWdCLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN0QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxxQkFBcUIsRUFBRSxvQkFBb0IsRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM3SCxPQUFPLEVBQWlDLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdkYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ2xGLE9BQU8sRUFBa0IsUUFBUSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNwRixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQzs7QUFFekUsTUFBTSx5QkFBeUIsR0FBRyxPQUFPLENBQUM7QUFDMUMsTUFBTSwrQkFBK0IsR0FBRyxFQUFFLENBQUM7QUFLM0MsTUFBTSxPQUFPLGFBQWE7SUF5QnRCLElBQUksU0FBUztRQUNULElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDbEYsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQzNCLENBQUM7SUFHRCxJQUFJLFFBQVE7UUFDUixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBR0QsSUFBSSxXQUFXO1FBQ1gsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUN4RixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQU1EO1FBN0NBLFVBQUssR0FBZ0IsRUFBRSxDQUFDO1FBQ3hCLGlCQUFZLEdBQXlCLElBQUksT0FBTyxFQUFlLENBQUM7UUFDaEUsZUFBVSxHQUE2QixJQUFJLE9BQU8sRUFBbUIsQ0FBQztRQUN0RSx1QkFBa0IsR0FBNkIsSUFBSSxPQUFPLEVBQW1CLENBQUM7UUFDOUUsd0JBQW1CLEdBQTZCLElBQUksT0FBTyxFQUFtQixDQUFDO1FBQy9FLHVCQUFrQixHQUE2QixJQUFJLE9BQU8sRUFBbUIsQ0FBQztRQUM5RSxzQkFBaUIsR0FBNkIsSUFBSSxPQUFPLEVBQW1CLENBQUM7UUFDN0Usb0JBQWUsR0FBa0MsSUFBSSxPQUFPLEVBQXdCLENBQUM7UUFDckYsdUJBQWtCLEdBQXFDLElBQUksT0FBTyxFQUEyQixDQUFDO1FBQzlGLHNCQUFpQixHQUFtQyxJQUFJLE9BQU8sRUFBeUIsQ0FBQztRQUN6RixnQkFBVyxHQUFvQixJQUFJLE9BQU8sRUFBVSxDQUFDO1FBRTdDLFVBQUssR0FBMkIsRUFBRSxDQUFDO1FBQ25DLGtCQUFhLEdBQVcsQ0FBQyxDQUFDO1FBQzFCLGlCQUFZLEdBQVcsQ0FBQyxDQUFDO1FBQ3pCLGVBQVUsR0FBVyxDQUFDLENBQUM7UUFDdkIscUJBQWdCLEdBQWEsRUFBRSxDQUFDO1FBQ2hDLHdCQUFtQixHQUFhLEVBQUUsQ0FBQztRQUNuQyxvQkFBZSxHQUFRLElBQUksQ0FBQztRQUM1QiwwQkFBcUIsR0FBUSxJQUFJLENBQUM7UUFzQmhDLGVBQVUsR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUN4QyxxQkFBZ0IsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM1Qyx3QkFBbUIsR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUd4RCxJQUFJLENBQUMsbUJBQW1CLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRTtZQUM3RixJQUFJLENBQUMsNEJBQTRCLEdBQUcsTUFBTSxDQUFDLDRCQUE0QixDQUFDO1FBQzVFLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELFVBQVU7UUFDTixJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGVBQWU7UUFDWCxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQVMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxXQUFXO1FBQ1AsTUFBTSxrQkFBa0IsR0FBRztZQUN2QixnQkFBZ0IsQ0FBQyxRQUFRO1lBQ3pCLGdCQUFnQixDQUFDLFNBQVM7WUFDMUIsZ0JBQWdCLENBQUMsT0FBTztZQUN4QixnQkFBZ0IsQ0FBQyxLQUFLO1lBQ3RCLGdCQUFnQixDQUFDLE9BQU87U0FDM0IsQ0FBQztRQUNGLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQ3BCLENBQUMsY0FBdUIsRUFBRSxXQUFzQixFQUFFLEVBQUUsQ0FBQyxjQUFjLElBQUksa0JBQWtCLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFDNUgsS0FBSyxDQUNSLENBQUM7SUFDTixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFFBQVE7UUFDSixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsVUFBVSxDQUFDLEdBQUcsS0FBa0I7UUFDNUIsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ3BGLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25DLE9BQU8sWUFBWSxDQUFDO0lBQ3hCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILHFCQUFxQixDQUFDLGNBQWtDLEVBQUUsWUFBZ0M7UUFDdEYsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFFdEMsSUFBSSxLQUFLLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM1QixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUN2QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRTVCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDckUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDO2dCQUVoQyxNQUFNLElBQUksR0FBRyxHQUFHLEVBQUU7b0JBQ2QsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQ3BGLENBQUMsQ0FBQztnQkFFRixPQUFPLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztnQkFFcEIsT0FBTyxDQUFDLElBQUksQ0FDUixHQUFHLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFDWixHQUFHLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FDZixDQUFDO1lBQ04sQ0FBQztRQUNMLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsWUFBWSxDQUFDLEdBQUcsS0FBa0I7UUFDOUIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ25CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RDLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ1YsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDL0IsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNwQixDQUFDO3FCQUFNLENBQUM7b0JBQ0osSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUNqQyxDQUFDO2dCQUNELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzdCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNuQixDQUFDO2lCQUFNLENBQUM7Z0JBQ0osTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFM0MsSUFBSSxhQUFhLEVBQUUsQ0FBQztvQkFDaEIsYUFBYSxFQUFFLENBQUM7Z0JBQ3BCLENBQUM7WUFDTCxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsOEJBQThCO0lBQzlCLFVBQVU7UUFDTixJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNoQixJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxJQUFlO1FBQzVCLE1BQU0sSUFBSSxHQUFRO1lBQ2QsT0FBTyxFQUFFLENBQUMscUJBQXFCLENBQUM7U0FDbkMsQ0FBQztRQUVGLElBQUksSUFBSSxDQUFDLDRCQUE0QixFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxRQUFRLENBQUM7UUFDL0IsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztRQUM1RCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztZQUN0QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDO1lBQzlDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7WUFDcEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQzFCLENBQUM7YUFBTSxDQUFDO1lBQ0osSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDM0IsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDO1FBQzFDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNWLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxJQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDNUUsQ0FBQzthQUFNLENBQUM7WUFDSixNQUFNLFFBQVEsR0FBbUIsRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDdkcsT0FBTyxRQUFRLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUVyQyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzFHLENBQUM7SUFDTCxDQUFDO0lBRU8sZ0JBQWdCO1FBQ3BCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUU1QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLElBQUksWUFBWSxFQUFFLENBQUM7WUFDaEMsT0FBTyxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUs7YUFDbkIsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssZ0JBQWdCLENBQUMsT0FBTyxDQUFDO2FBQ3JHLEtBQUssQ0FBQyxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFNUIsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVPLFdBQVcsQ0FBQyxJQUFlLEVBQUUsY0FBa0MsRUFBRSxZQUFnQztRQUNyRyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUMsT0FBTzthQUNGLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxRQUE0QixFQUFFLEVBQUU7WUFDN0MsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMxQyxDQUFDLENBQUM7YUFDRCxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0IsSUFBSSxjQUFjLEVBQUUsQ0FBQztnQkFDakIsY0FBYyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxjQUFjLEVBQUUsQ0FBQyxDQUFDO1lBQ25ELENBQUM7UUFDTCxDQUFDLENBQUM7YUFDRCxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDakIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDOUIsSUFBSSxZQUFZLEVBQUUsQ0FBQztnQkFDZixZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLHFCQUFxQixFQUFFLENBQUMsQ0FBQztZQUN4RCxDQUFDO1FBQ0wsQ0FBQyxDQUFDO2FBQ0QsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3BCLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzNCLElBQUksSUFBSSxDQUFDLEVBQUUsS0FBSyxTQUFTLEVBQUUsQ0FBQztvQkFDeEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzFDLENBQUM7cUJBQU0sQ0FBQztvQkFDSixJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO2dCQUMzRixDQUFDO2dCQUNELElBQUksY0FBYyxFQUFFLENBQUM7b0JBQ2pCLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztnQkFDbkQsQ0FBQztZQUNMLENBQUM7aUJBQU0sQ0FBQztnQkFDSixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNsQyxJQUFJLGNBQWMsRUFBRSxDQUFDO29CQUNqQixjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ3pDLENBQUM7WUFDTCxDQUFDO1FBQ0wsQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO1FBRXJCLE9BQU8sT0FBTyxDQUFDO0lBQ25CLENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxJQUFlO1FBQ3BDLElBQUksSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDLFFBQVEsQ0FBQztZQUN4QyxNQUFNLEtBQUssR0FBRyxJQUFJLGVBQWUsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbkUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGdCQUFnQixDQUFDLElBQWUsRUFBRSxRQUE0QjtRQUNsRSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1AsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7WUFDekIsSUFBSSxDQUFDLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUM7WUFFeEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxlQUFlLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ25FLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEMsQ0FBQztJQUNMLENBQUM7SUFFTyxhQUFhLENBQUMsSUFBZSxFQUFFLEtBQTBCO1FBQzdELElBQUksSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssRUFBRSxNQUFNLENBQUM7WUFDL0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUM7WUFDckMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBRWxCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RDLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ1YsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNqQyxDQUFDO1lBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNyRSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGdCQUFnQixDQUFDLElBQWUsRUFBRSxJQUFTO1FBQy9DLElBQUksSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDLFFBQVEsQ0FBQztZQUN4QyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztZQUNqQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDckIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEMsSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDVixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pDLENBQUM7WUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLHVCQUF1QixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDN0YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGVBQWUsQ0FBQyxJQUFlO1FBQ25DLElBQUksSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQztZQUN2QyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFFcEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxlQUFlLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2xFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNMLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxJQUFlO1FBQ3JDLElBQUksSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDLFNBQVMsQ0FBQztZQUV6QyxNQUFNLEtBQUssR0FBRyxJQUFJLGVBQWUsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDcEUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGVBQWUsQ0FBQyxJQUFlO1FBQ25DLElBQUksSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQztZQUN2QyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFFckIsTUFBTSxLQUFLLEdBQUcsSUFBSSxxQkFBcUIsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ2xFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNMLENBQUM7SUFFTyxTQUFTLENBQUMsSUFBZTtRQUM3QixNQUFNLE9BQU8sR0FBRztZQUNaLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQztZQUM5RCxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDO1lBQzVELENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDO1NBQ2pFLENBQUM7UUFFRixPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVPLGlCQUFpQixDQUFDLE1BQWM7UUFDcEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3JHLENBQUM7SUFFTyx3QkFBd0IsQ0FBQyxNQUFjLEVBQUUsU0FBaUI7UUFDOUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUNqRyxDQUFDO0lBRU8saUJBQWlCLENBQUMsSUFBZTtRQUNyQyxPQUFPLElBQUksQ0FBQyxJQUFJLEdBQUcseUJBQXlCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEdBQUcsK0JBQStCLENBQUM7SUFDNUcsQ0FBQztJQUVPLGFBQWEsQ0FBQyxJQUFlO1FBQ2pDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFXLGdCQUFnQixDQUFDLENBQUM7UUFDOUUsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQVcsa0JBQWtCLENBQUMsQ0FBQztRQUNuRixJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFFckIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQztZQUN4RSxTQUFTLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFFRCxJQUFJLFNBQVMsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUN4QyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1lBQ2hGLFNBQVMsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakQsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7SUFFTyxxQkFBcUIsQ0FBQyxJQUFlO1FBQ3pDLElBQUksU0FBUyxHQUFZLElBQUksQ0FBQztRQUM5QixNQUFNLFdBQVcsR0FBUSxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ25DLE1BQU0sZ0JBQWdCLEdBQUcsV0FBVyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQzdHLElBQUksV0FBVyxJQUFJLGdCQUFnQixFQUFFLENBQUM7WUFDbEMsU0FBUztnQkFDTCxJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FDaEQsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFO29CQUM3QyxNQUFNLFNBQVMsR0FBRyxJQUFJLFNBQVMsQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7b0JBQzdFLE9BQU8sU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDeEMsQ0FBQyxDQUFDLENBQ0wsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNyQixDQUFDO0lBRU8saUJBQWlCLENBQUMsSUFBZTtRQUNyQyxPQUFPLENBQ0gsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ3JDLE1BQU0sU0FBUyxHQUFHLElBQUksU0FBUyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDL0QsT0FBTyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QyxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUNsQixDQUFDO0lBQ04sQ0FBQzs4R0FqYVEsYUFBYTtrSEFBYixhQUFhLGNBRlYsTUFBTTs7MkZBRVQsYUFBYTtrQkFIekIsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgwqkgMjAwNS0yMDI1IEh5bGFuZCBTb2Z0d2FyZSwgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEV2ZW50RW1pdHRlciwgaW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBNaW5pbWF0Y2ggfSBmcm9tICdtaW5pbWF0Y2gnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgRmlsZVVwbG9hZENvbXBsZXRlRXZlbnQsIEZpbGVVcGxvYWREZWxldGVFdmVudCwgRmlsZVVwbG9hZEVycm9yRXZlbnQsIEZpbGVVcGxvYWRFdmVudCB9IGZyb20gJy4uL2V2ZW50cy9maWxlLmV2ZW50JztcbmltcG9ydCB7IEZpbGVNb2RlbCwgRmlsZVVwbG9hZFByb2dyZXNzLCBGaWxlVXBsb2FkU3RhdHVzIH0gZnJvbSAnLi4vbW9kZWxzL2ZpbGUubW9kZWwnO1xuaW1wb3J0IHsgQXBwQ29uZmlnU2VydmljZSB9IGZyb20gJ0BhbGZyZXNjby9hZGYtY29yZSc7XG5pbXBvcnQgeyBmaWx0ZXIgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBEaXNjb3ZlcnlBcGlTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL3NlcnZpY2VzL2Rpc2NvdmVyeS1hcGkuc2VydmljZSc7XG5pbXBvcnQgeyBOb2RlQm9keUNyZWF0ZSwgTm9kZXNBcGksIFVwbG9hZEFwaSwgVmVyc2lvbnNBcGkgfSBmcm9tICdAYWxmcmVzY28vanMtYXBpJztcbmltcG9ydCB7IEFsZnJlc2NvQXBpU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FsZnJlc2NvLWFwaS5zZXJ2aWNlJztcblxuY29uc3QgTUlOX0NBTkNFTExBQkxFX0ZJTEVfU0laRSA9IDEwMDAwMDA7XG5jb25zdCBNQVhfQ0FOQ0VMTEFCTEVfRklMRV9QRVJDRU5UQUdFID0gNTA7XG5cbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgVXBsb2FkU2VydmljZSB7XG4gICAgcXVldWU6IEZpbGVNb2RlbFtdID0gW107XG4gICAgcXVldWVDaGFuZ2VkOiBTdWJqZWN0PEZpbGVNb2RlbFtdPiA9IG5ldyBTdWJqZWN0PEZpbGVNb2RlbFtdPigpO1xuICAgIGZpbGVVcGxvYWQ6IFN1YmplY3Q8RmlsZVVwbG9hZEV2ZW50PiA9IG5ldyBTdWJqZWN0PEZpbGVVcGxvYWRFdmVudD4oKTtcbiAgICBmaWxlVXBsb2FkU3RhcnRpbmc6IFN1YmplY3Q8RmlsZVVwbG9hZEV2ZW50PiA9IG5ldyBTdWJqZWN0PEZpbGVVcGxvYWRFdmVudD4oKTtcbiAgICBmaWxlVXBsb2FkQ2FuY2VsbGVkOiBTdWJqZWN0PEZpbGVVcGxvYWRFdmVudD4gPSBuZXcgU3ViamVjdDxGaWxlVXBsb2FkRXZlbnQ+KCk7XG4gICAgZmlsZVVwbG9hZFByb2dyZXNzOiBTdWJqZWN0PEZpbGVVcGxvYWRFdmVudD4gPSBuZXcgU3ViamVjdDxGaWxlVXBsb2FkRXZlbnQ+KCk7XG4gICAgZmlsZVVwbG9hZEFib3J0ZWQ6IFN1YmplY3Q8RmlsZVVwbG9hZEV2ZW50PiA9IG5ldyBTdWJqZWN0PEZpbGVVcGxvYWRFdmVudD4oKTtcbiAgICBmaWxlVXBsb2FkRXJyb3I6IFN1YmplY3Q8RmlsZVVwbG9hZEVycm9yRXZlbnQ+ID0gbmV3IFN1YmplY3Q8RmlsZVVwbG9hZEVycm9yRXZlbnQ+KCk7XG4gICAgZmlsZVVwbG9hZENvbXBsZXRlOiBTdWJqZWN0PEZpbGVVcGxvYWRDb21wbGV0ZUV2ZW50PiA9IG5ldyBTdWJqZWN0PEZpbGVVcGxvYWRDb21wbGV0ZUV2ZW50PigpO1xuICAgIGZpbGVVcGxvYWREZWxldGVkOiBTdWJqZWN0PEZpbGVVcGxvYWREZWxldGVFdmVudD4gPSBuZXcgU3ViamVjdDxGaWxlVXBsb2FkRGVsZXRlRXZlbnQ+KCk7XG4gICAgZmlsZURlbGV0ZWQ6IFN1YmplY3Q8c3RyaW5nPiA9IG5ldyBTdWJqZWN0PHN0cmluZz4oKTtcblxuICAgIHByaXZhdGUgY2FjaGU6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSB7fTtcbiAgICBwcml2YXRlIHRvdGFsQ29tcGxldGU6IG51bWJlciA9IDA7XG4gICAgcHJpdmF0ZSB0b3RhbEFib3J0ZWQ6IG51bWJlciA9IDA7XG4gICAgcHJpdmF0ZSB0b3RhbEVycm9yOiBudW1iZXIgPSAwO1xuICAgIHByaXZhdGUgZXhjbHVkZWRGaWxlTGlzdDogc3RyaW5nW10gPSBbXTtcbiAgICBwcml2YXRlIGV4Y2x1ZGVkRm9sZGVyc0xpc3Q6IHN0cmluZ1tdID0gW107XG4gICAgcHJpdmF0ZSBtYXRjaGluZ09wdGlvbnM6IGFueSA9IG51bGw7XG4gICAgcHJpdmF0ZSBmb2xkZXJNYXRjaGluZ09wdGlvbnM6IGFueSA9IG51bGw7XG4gICAgcHJpdmF0ZSBhYm9ydGVkRmlsZTogc3RyaW5nO1xuICAgIHByaXZhdGUgaXNUaHVtYm5haWxHZW5lcmF0aW9uRW5hYmxlZDogYm9vbGVhbjtcblxuICAgIHByaXZhdGUgX3VwbG9hZEFwaTogVXBsb2FkQXBpO1xuICAgIGdldCB1cGxvYWRBcGkoKTogVXBsb2FkQXBpIHtcbiAgICAgICAgdGhpcy5fdXBsb2FkQXBpID0gdGhpcy5fdXBsb2FkQXBpID8/IG5ldyBVcGxvYWRBcGkodGhpcy5hcGlTZXJ2aWNlLmdldEluc3RhbmNlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdXBsb2FkQXBpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX25vZGVzQXBpOiBOb2Rlc0FwaTtcbiAgICBnZXQgbm9kZXNBcGkoKTogTm9kZXNBcGkge1xuICAgICAgICB0aGlzLl9ub2Rlc0FwaSA9IHRoaXMuX25vZGVzQXBpID8/IG5ldyBOb2Rlc0FwaSh0aGlzLmFwaVNlcnZpY2UuZ2V0SW5zdGFuY2UoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9ub2Rlc0FwaTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF92ZXJzaW9uc0FwaTogVmVyc2lvbnNBcGk7XG4gICAgZ2V0IHZlcnNpb25zQXBpKCk6IFZlcnNpb25zQXBpIHtcbiAgICAgICAgdGhpcy5fdmVyc2lvbnNBcGkgPSB0aGlzLl92ZXJzaW9uc0FwaSA/PyBuZXcgVmVyc2lvbnNBcGkodGhpcy5hcGlTZXJ2aWNlLmdldEluc3RhbmNlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbnNBcGk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFwaVNlcnZpY2UgPSBpbmplY3QoQWxmcmVzY29BcGlTZXJ2aWNlKTtcbiAgICBwcm90ZWN0ZWQgYXBwQ29uZmlnU2VydmljZSA9IGluamVjdChBcHBDb25maWdTZXJ2aWNlKTtcbiAgICBwcm90ZWN0ZWQgZGlzY292ZXJ5QXBpU2VydmljZSA9IGluamVjdChEaXNjb3ZlcnlBcGlTZXJ2aWNlKTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmRpc2NvdmVyeUFwaVNlcnZpY2UuZWNtUHJvZHVjdEluZm8kLnBpcGUoZmlsdGVyKChpbmZvKSA9PiAhIWluZm8pKS5zdWJzY3JpYmUoKHsgc3RhdHVzIH0pID0+IHtcbiAgICAgICAgICAgIHRoaXMuaXNUaHVtYm5haWxHZW5lcmF0aW9uRW5hYmxlZCA9IHN0YXR1cy5pc1RodW1ibmFpbEdlbmVyYXRpb25FbmFibGVkO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjbGVhckNhY2hlKCkge1xuICAgICAgICB0aGlzLmNhY2hlID0ge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGNvbmN1cnJlbnQgdGhyZWFkcyBmb3IgdXBsb2FkaW5nLlxuICAgICAqXG4gICAgICogQHJldHVybnMgTnVtYmVyIG9mIGNvbmN1cnJlbnQgdGhyZWFkcyAoZGVmYXVsdCAxKVxuICAgICAqL1xuICAgIGdldFRocmVhZHNDb3VudCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5hcHBDb25maWdTZXJ2aWNlLmdldDxudW1iZXI+KCd1cGxvYWQudGhyZWFkcycsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIHRoZSBzZXJ2aWNlIHN0aWxsIGhhcyBmaWxlcyB1cGxvYWRpbmcgb3IgYXdhaXRpbmcgdXBsb2FkLlxuICAgICAqXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiBmaWxlcyBpbiB0aGUgcXVldWUgYXJlIHN0aWxsIHVwbG9hZGluZywgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgaXNVcGxvYWRpbmcoKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGZpbmlzaGVkRmlsZVN0YXRlcyA9IFtcbiAgICAgICAgICAgIEZpbGVVcGxvYWRTdGF0dXMuQ29tcGxldGUsXG4gICAgICAgICAgICBGaWxlVXBsb2FkU3RhdHVzLkNhbmNlbGxlZCxcbiAgICAgICAgICAgIEZpbGVVcGxvYWRTdGF0dXMuQWJvcnRlZCxcbiAgICAgICAgICAgIEZpbGVVcGxvYWRTdGF0dXMuRXJyb3IsXG4gICAgICAgICAgICBGaWxlVXBsb2FkU3RhdHVzLkRlbGV0ZWRcbiAgICAgICAgXTtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVldWUucmVkdWNlKFxuICAgICAgICAgICAgKHN0aWxsVXBsb2FkaW5nOiBib29sZWFuLCBjdXJyZW50RmlsZTogRmlsZU1vZGVsKSA9PiBzdGlsbFVwbG9hZGluZyB8fCBmaW5pc2hlZEZpbGVTdGF0ZXMuaW5kZXhPZihjdXJyZW50RmlsZS5zdGF0dXMpID09PSAtMSxcbiAgICAgICAgICAgIGZhbHNlXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZmlsZSBRdWV1ZVxuICAgICAqXG4gICAgICogQHJldHVybnMgQXJyYXkgb2YgZmlsZXMgdGhhdCBmb3JtIHRoZSBxdWV1ZVxuICAgICAqL1xuICAgIGdldFF1ZXVlKCk6IEZpbGVNb2RlbFtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVldWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBmaWxlcyB0byB0aGUgdXBsb2FkaW5nIHF1ZXVlIHRvIGJlIHVwbG9hZGVkXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmlsZXMgT25lIG9yIG1vcmUgc2VwYXJhdGUgcGFyYW1ldGVycyBvciBhbiBhcnJheSBvZiBmaWxlcyB0byBxdWV1ZVxuICAgICAqIEByZXR1cm5zIEFycmF5IG9mIGZpbGVzIHRoYXQgd2VyZSBub3QgYmxvY2tlZCBmcm9tIHVwbG9hZCBieSB0aGUgaWdub3JlIGxpc3RcbiAgICAgKi9cbiAgICBhZGRUb1F1ZXVlKC4uLmZpbGVzOiBGaWxlTW9kZWxbXSk6IEZpbGVNb2RlbFtdIHtcbiAgICAgICAgY29uc3QgYWxsb3dlZEZpbGVzID0gZmlsZXMuZmlsdGVyKChjdXJyZW50RmlsZSkgPT4gdGhpcy5maWx0ZXJFbGVtZW50KGN1cnJlbnRGaWxlKSk7XG4gICAgICAgIHRoaXMucXVldWUgPSB0aGlzLnF1ZXVlLmNvbmNhdChhbGxvd2VkRmlsZXMpO1xuICAgICAgICB0aGlzLnF1ZXVlQ2hhbmdlZC5uZXh0KHRoaXMucXVldWUpO1xuICAgICAgICByZXR1cm4gYWxsb3dlZEZpbGVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmRzIGFsbCB0aGUgZmlsZXMgaW4gdGhlIHF1ZXVlIHRoYXQgYXJlIG5vdCB5ZXQgdXBsb2FkZWQgYW5kIHVwbG9hZHMgdGhlbSBpbnRvIHRoZSBkaXJlY3RvcnkgZm9sZGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN1Y2Nlc3NFbWl0dGVyIEVtaXR0ZXIgdG8gaW52b2tlIG9uIGZpbGUgc3VjY2VzcyBzdGF0dXMgY2hhbmdlXG4gICAgICogQHBhcmFtIGVycm9yRW1pdHRlciBFbWl0dGVyIHRvIGludm9rZSBvbiBmaWxlIGVycm9yIHN0YXR1cyBjaGFuZ2VcbiAgICAgKi9cbiAgICB1cGxvYWRGaWxlc0luVGhlUXVldWUoc3VjY2Vzc0VtaXR0ZXI/OiBFdmVudEVtaXR0ZXI8YW55PiwgZXJyb3JFbWl0dGVyPzogRXZlbnRFbWl0dGVyPGFueT4pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZmlsZXMgPSB0aGlzLmdldEZpbGVzVG9VcGxvYWQoKTtcblxuICAgICAgICBpZiAoZmlsZXMgJiYgZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblVwbG9hZFN0YXJ0aW5nKGZpbGUpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuYmVnaW5VcGxvYWQoZmlsZSwgc3VjY2Vzc0VtaXR0ZXIsIGVycm9yRW1pdHRlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWNoZVtmaWxlLm5hbWVdID0gcHJvbWlzZTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IG5leHQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy51cGxvYWRGaWxlc0luVGhlUXVldWUoc3VjY2Vzc0VtaXR0ZXIsIGVycm9yRW1pdHRlciksIDEwMCk7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHByb21pc2UubmV4dCA9IG5leHQ7XG5cbiAgICAgICAgICAgICAgICBwcm9taXNlLnRoZW4oXG4gICAgICAgICAgICAgICAgICAgICgpID0+IG5leHQoKSxcbiAgICAgICAgICAgICAgICAgICAgKCkgPT4gbmV4dCgpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbmNlbHMgdXBsb2FkaW5nIG9mIGZpbGVzLlxuICAgICAqIElmIHRoZSBmaWxlIGlzIHNtYWxsZXIgdGhhbiAxIE1CIHRoZSBmaWxlIHdpbGwgYmUgdXBsb2FkZWQgYW5kIHRoZW4gdGhlIG5vZGUgZGVsZXRlZFxuICAgICAqIHRvIHByZXZlbnQgaGF2aW5nIGZpbGVzIHRoYXQgd2VyZSBhYm9ydGVkIGJ1dCBzdGlsbCB1cGxvYWRlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmaWxlcyBPbmUgb3IgbW9yZSBzZXBhcmF0ZSBwYXJhbWV0ZXJzIG9yIGFuIGFycmF5IG9mIGZpbGVzIHNwZWNpZnlpbmcgdXBsb2FkcyB0byBjYW5jZWxcbiAgICAgKi9cbiAgICBjYW5jZWxVcGxvYWQoLi4uZmlsZXM6IEZpbGVNb2RlbFtdKSB7XG4gICAgICAgIGZpbGVzLmZvckVhY2goKGZpbGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLmNhY2hlW2ZpbGUubmFtZV07XG4gICAgICAgICAgICBpZiAocHJvbWlzZSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzU2F2ZVRvQWJvcnRGaWxlKGZpbGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb21pc2UuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFib3J0ZWRGaWxlID0gZmlsZS5uYW1lO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5jYWNoZVtmaWxlLm5hbWVdO1xuICAgICAgICAgICAgICAgIHByb21pc2UubmV4dCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwZXJmb3JtQWN0aW9uID0gdGhpcy5nZXRBY3Rpb24oZmlsZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGVyZm9ybUFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBwZXJmb3JtQWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogQ2xlYXJzIHRoZSB1cGxvYWQgcXVldWUgKi9cbiAgICBjbGVhclF1ZXVlKCkge1xuICAgICAgICB0aGlzLnF1ZXVlID0gW107XG4gICAgICAgIHRoaXMudG90YWxDb21wbGV0ZSA9IDA7XG4gICAgICAgIHRoaXMudG90YWxBYm9ydGVkID0gMDtcbiAgICAgICAgdGhpcy50b3RhbEVycm9yID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFuIHVwbG9hZCBwcm9taXNlIGZvciBhIGZpbGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmlsZSBUaGUgdGFyZ2V0IGZpbGVcbiAgICAgKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHVwbG9hZCBpcyBzdWNjZXNzZnVsIG9yIGVycm9yIG90aGVyd2lzZVxuICAgICAqL1xuICAgIGdldFVwbG9hZFByb21pc2UoZmlsZTogRmlsZU1vZGVsKTogYW55IHtcbiAgICAgICAgY29uc3Qgb3B0czogYW55ID0ge1xuICAgICAgICAgICAgaW5jbHVkZTogWydhbGxvd2FibGVPcGVyYXRpb25zJ11cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5pc1RodW1ibmFpbEdlbmVyYXRpb25FbmFibGVkKSB7XG4gICAgICAgICAgICBvcHRzLnJlbmRpdGlvbnMgPSAnZG9jbGliJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWxlLm9wdGlvbnM/LnZlcnNpb25pbmdFbmFibGVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG9wdHMudmVyc2lvbmluZ0VuYWJsZWQgPSBmaWxlLm9wdGlvbnMudmVyc2lvbmluZ0VuYWJsZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsZS5vcHRpb25zLm5ld1ZlcnNpb24gPT09IHRydWUpIHtcbiAgICAgICAgICAgIG9wdHMub3ZlcndyaXRlID0gdHJ1ZTtcbiAgICAgICAgICAgIG9wdHMubWFqb3JWZXJzaW9uID0gZmlsZS5vcHRpb25zLm1ham9yVmVyc2lvbjtcbiAgICAgICAgICAgIG9wdHMuY29tbWVudCA9IGZpbGUub3B0aW9ucy5jb21tZW50O1xuICAgICAgICAgICAgb3B0cy5uYW1lID0gZmlsZS5uYW1lO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3B0cy5hdXRvUmVuYW1lID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWxlLm9wdGlvbnMubm9kZVR5cGUpIHtcbiAgICAgICAgICAgIG9wdHMubm9kZVR5cGUgPSBmaWxlLm9wdGlvbnMubm9kZVR5cGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsZS5pZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubm9kZXNBcGkudXBkYXRlTm9kZUNvbnRlbnQoZmlsZS5pZCwgZmlsZS5maWxlIGFzIGFueSwgb3B0cyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBub2RlQm9keTogTm9kZUJvZHlDcmVhdGUgPSB7IC4uLmZpbGUub3B0aW9ucywgbmFtZTogZmlsZS5uYW1lLCBub2RlVHlwZTogZmlsZS5vcHRpb25zLm5vZGVUeXBlIH07XG4gICAgICAgICAgICBkZWxldGUgbm9kZUJvZHlbJ3ZlcnNpb25pbmdFbmFibGVkJ107XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnVwbG9hZEFwaS51cGxvYWRGaWxlKGZpbGUuZmlsZSwgZmlsZS5vcHRpb25zLnBhdGgsIGZpbGUub3B0aW9ucy5wYXJlbnRJZCwgbm9kZUJvZHksIG9wdHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRGaWxlc1RvVXBsb2FkKCk6IEZpbGVNb2RlbFtdIHtcbiAgICAgICAgY29uc3QgY2FjaGVkID0gT2JqZWN0LmtleXModGhpcy5jYWNoZSk7XG4gICAgICAgIGNvbnN0IHRocmVhZHNDb3VudCA9IHRoaXMuZ2V0VGhyZWFkc0NvdW50KCk7XG5cbiAgICAgICAgaWYgKGNhY2hlZC5sZW5ndGggPj0gdGhyZWFkc0NvdW50KSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmaWxlcyA9IHRoaXMucXVldWVcbiAgICAgICAgICAgIC5maWx0ZXIoKHRvVXBsb2FkKSA9PiAhY2FjaGVkLmluY2x1ZGVzKHRvVXBsb2FkLm5hbWUpICYmIHRvVXBsb2FkLnN0YXR1cyA9PT0gRmlsZVVwbG9hZFN0YXR1cy5QZW5kaW5nKVxuICAgICAgICAgICAgLnNsaWNlKDAsIHRocmVhZHNDb3VudCk7XG5cbiAgICAgICAgcmV0dXJuIGZpbGVzO1xuICAgIH1cblxuICAgIHByaXZhdGUgYmVnaW5VcGxvYWQoZmlsZTogRmlsZU1vZGVsLCBzdWNjZXNzRW1pdHRlcj86IEV2ZW50RW1pdHRlcjxhbnk+LCBlcnJvckVtaXR0ZXI/OiBFdmVudEVtaXR0ZXI8YW55Pik6IGFueSB7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLmdldFVwbG9hZFByb21pc2UoZmlsZSk7XG4gICAgICAgIHByb21pc2VcbiAgICAgICAgICAgIC5vbigncHJvZ3Jlc3MnLCAocHJvZ3Jlc3M6IEZpbGVVcGxvYWRQcm9ncmVzcykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25VcGxvYWRQcm9ncmVzcyhmaWxlLCBwcm9ncmVzcyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdhYm9ydCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uVXBsb2FkQWJvcnRlZChmaWxlKTtcbiAgICAgICAgICAgICAgICBpZiAoc3VjY2Vzc0VtaXR0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0VtaXR0ZXIuZW1pdCh7IHZhbHVlOiAnRmlsZSBhYm9ydGVkJyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdlcnJvcicsIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uVXBsb2FkRXJyb3IoZmlsZSwgZXJyKTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3JFbWl0dGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yRW1pdHRlci5lbWl0KHsgdmFsdWU6ICdFcnJvciBmaWxlIHVwbG9hZGVkJyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdzdWNjZXNzJywgKGRhdGEpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5hYm9ydGVkRmlsZSA9PT0gZmlsZS5uYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25VcGxvYWRBYm9ydGVkKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsZS5pZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlbGV0ZUFib3J0ZWROb2RlKGRhdGEuZW50cnkuaWQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWxldGVBYm9ydGVkTm9kZVZlcnNpb24oZGF0YS5lbnRyeS5pZCwgZGF0YS5lbnRyeS5wcm9wZXJ0aWVzWydjbTp2ZXJzaW9uTGFiZWwnXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHN1Y2Nlc3NFbWl0dGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzRW1pdHRlci5lbWl0KHsgdmFsdWU6ICdGaWxlIGRlbGV0ZWQnIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblVwbG9hZENvbXBsZXRlKGZpbGUsIGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3VjY2Vzc0VtaXR0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NFbWl0dGVyLmVtaXQoeyB2YWx1ZTogZGF0YSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKCkgPT4ge30pO1xuXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25VcGxvYWRTdGFydGluZyhmaWxlOiBGaWxlTW9kZWwpOiB2b2lkIHtcbiAgICAgICAgaWYgKGZpbGUpIHtcbiAgICAgICAgICAgIGZpbGUuc3RhdHVzID0gRmlsZVVwbG9hZFN0YXR1cy5TdGFydGluZztcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gbmV3IEZpbGVVcGxvYWRFdmVudChmaWxlLCBGaWxlVXBsb2FkU3RhdHVzLlN0YXJ0aW5nKTtcbiAgICAgICAgICAgIHRoaXMuZmlsZVVwbG9hZC5uZXh0KGV2ZW50KTtcbiAgICAgICAgICAgIHRoaXMuZmlsZVVwbG9hZFN0YXJ0aW5nLm5leHQoZXZlbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblVwbG9hZFByb2dyZXNzKGZpbGU6IEZpbGVNb2RlbCwgcHJvZ3Jlc3M6IEZpbGVVcGxvYWRQcm9ncmVzcyk6IHZvaWQge1xuICAgICAgICBpZiAoZmlsZSkge1xuICAgICAgICAgICAgZmlsZS5wcm9ncmVzcyA9IHByb2dyZXNzO1xuICAgICAgICAgICAgZmlsZS5zdGF0dXMgPSBGaWxlVXBsb2FkU3RhdHVzLlByb2dyZXNzO1xuXG4gICAgICAgICAgICBjb25zdCBldmVudCA9IG5ldyBGaWxlVXBsb2FkRXZlbnQoZmlsZSwgRmlsZVVwbG9hZFN0YXR1cy5Qcm9ncmVzcyk7XG4gICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWQubmV4dChldmVudCk7XG4gICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRQcm9ncmVzcy5uZXh0KGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25VcGxvYWRFcnJvcihmaWxlOiBGaWxlTW9kZWwsIGVycm9yOiB7IHN0YXR1cz86IG51bWJlciB9KTogdm9pZCB7XG4gICAgICAgIGlmIChmaWxlKSB7XG4gICAgICAgICAgICBmaWxlLmVycm9yQ29kZSA9IGVycm9yPy5zdGF0dXM7XG4gICAgICAgICAgICBmaWxlLnN0YXR1cyA9IEZpbGVVcGxvYWRTdGF0dXMuRXJyb3I7XG4gICAgICAgICAgICB0aGlzLnRvdGFsRXJyb3IrKztcblxuICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuY2FjaGVbZmlsZS5uYW1lXTtcbiAgICAgICAgICAgIGlmIChwcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FjaGVbZmlsZS5uYW1lXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBuZXcgRmlsZVVwbG9hZEVycm9yRXZlbnQoZmlsZSwgZXJyb3IsIHRoaXMudG90YWxFcnJvcik7XG4gICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWQubmV4dChldmVudCk7XG4gICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRFcnJvci5uZXh0KGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25VcGxvYWRDb21wbGV0ZShmaWxlOiBGaWxlTW9kZWwsIGRhdGE6IGFueSk6IHZvaWQge1xuICAgICAgICBpZiAoZmlsZSkge1xuICAgICAgICAgICAgZmlsZS5zdGF0dXMgPSBGaWxlVXBsb2FkU3RhdHVzLkNvbXBsZXRlO1xuICAgICAgICAgICAgZmlsZS5kYXRhID0gZGF0YTtcbiAgICAgICAgICAgIHRoaXMudG90YWxDb21wbGV0ZSsrO1xuICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuY2FjaGVbZmlsZS5uYW1lXTtcbiAgICAgICAgICAgIGlmIChwcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FjaGVbZmlsZS5uYW1lXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBuZXcgRmlsZVVwbG9hZENvbXBsZXRlRXZlbnQoZmlsZSwgdGhpcy50b3RhbENvbXBsZXRlLCBkYXRhLCB0aGlzLnRvdGFsQWJvcnRlZCk7XG4gICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWQubmV4dChldmVudCk7XG4gICAgICAgICAgICB0aGlzLm