@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
233 lines • 31 kB
JavaScript
import { inject, Injectable, signal } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
import { distinctUntilChanged, filter, map, skip, switchMap, tap } from 'rxjs/operators';
import { DEFAULT_INTERVAL_STATE, DEFAULT_INTERVAL_VALUE, GLOBAL_CONTEXT_AUTO_REFRESH } from './widget-auto-refresh-context.model';
import { ActivatedRoute, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
import * as i0 from "@angular/core";
export class WidgetGlobalAutoRefreshService {
constructor() {
/**
* A BehaviorSubject that tracks the number of loading operations in progress.
* Initialized with a count of 0.
*/
this.loadingCount$ = new BehaviorSubject(0);
/**
* An Observable that emits a boolean indicating whether any widgets with global refresh option are currently loading.
* The value is true if the loading count is non-zero, and false if the loading count is zero.
* Uses distinctUntilChanged() to emit only when the boolean value changes.
*/
this.isLoadingWidgets$ = this.loadingCount$.pipe(distinctUntilChanged(), map(count => count !== 0));
/**
* Object containing behavior subjects for managing auto-refresh settings.
*/
this.autoRefreshSettings = {
/**
* BehaviorSubject that emits the current state of auto-refresh button.
* Defaults to DEFAULT_INTERVAL_STATE.
*/
isEnabled$: new BehaviorSubject(DEFAULT_INTERVAL_STATE),
/**
* BehaviorSubject that emits the current auto-refresh interval value.
* Defaults to DEFAULT_INTERVAL_VALUE.
*/
refreshInterval$: new BehaviorSubject(DEFAULT_INTERVAL_VALUE),
/**
* BehaviorSubject that emits whether auto-refresh has been manually disabled by the user.
* Defaults to false.
*/
userDisabledManually$: new BehaviorSubject(false)
};
/**
* Object containing subjects for managing countdown actions.
*/
this.countdownActions = {
/**
* Subject used to stop the countdown.
*/
stop$: new Subject(),
/**
* Subject used to reset the countdown.
*/
reset$: new Subject(),
/**
* Subject that emits when the countdown has ended.
*/
countdownEnded$: new Subject()
};
/**
* Subject that emits when a dashboard save operation is triggered.
*/
this.onDashboardSave$ = new Subject();
/**
* A signal representing the number of widgets with the global auto-refresh option enabled.
*/
this.globalRefreshWidgetsCount = signal(0);
/**
* Tracks the navigation state.
*
* The signal returns a boolean indicating whether a navigation operation is currently in progress.
* It initializes with a default value of `false` and can be toggled to `true` during navigation events from `handleNavigationInProgress$`.
*/
this.navigationInProgress = signal(false);
this.router = inject(Router);
this.activatedRoute = inject(ActivatedRoute);
}
/**
* Increments the loading count by 1.
*/
incrementLoading() {
this.loadingCount$.next(this.loadingCount$.value + 1);
}
/**
* Decrements the loading count by 1.
*/
decrementLoading() {
this.loadingCount$.next(this.loadingCount$.value - 1);
}
/**
* Retrieves an observable that emits the value of a Global Auto Refresh query parameter
* whenever it changes. The query parameter being tracked is determined by
* `GlobalAutoRefreshName.GLOBAL_CONTEXT_AUTO_REFRESH`.
*
* @returns An observable that emits the parsed value of the `GLOBAL_CONTEXT_AUTO_REFRESH` query parameter.
*/
getQueryParamChangeValue$() {
return this.activatedRoute.queryParams.pipe(map(params => params[GLOBAL_CONTEXT_AUTO_REFRESH]), map(this.parseGlobalAutoRefreshParam));
}
/**
* Monitors router navigation events and updates the navigation progress state.
*
* @returns An Observable that emits router events of types NavigationStart, NavigationEnd,
* NavigationCancel, and NavigationError.
*/
handleNavigationInProgress$() {
return this.router.events.pipe(filter(event => event instanceof NavigationStart ||
event instanceof NavigationEnd ||
event instanceof NavigationCancel ||
event instanceof NavigationError), tap(e => this.navigationInProgress.set(e instanceof NavigationStart)));
}
/**
* Sets the global auto-refresh query parameter in the current route.
*
* @param queryParams - An object representing the query parameters to set for the global auto-refresh option.
* The existing query parameters will be merged with these.
*/
async setAutoRefreshQueryParam(queryParams) {
if (this.navigationInProgress()) {
return;
}
this.navigationInProgress.set(true);
await this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams,
queryParamsHandling: 'merge'
});
this.navigationInProgress.set(false);
}
/**
* Handles changes to the edit mode and updates the isEnabled$ variable.
*
* - If auto-refresh was manually disabled by the user (`userDisabledManually$` is `true`), auto-refresh will remain disabled regardless of the edit mode state.
* - If auto-refresh was not manually disabled, it will be disabled when entering edit mode and enabled when exiting edit mode.
*
* @param editMode - A boolean indicating the current state of edit mode (`true` if edit mode is active, `false` otherwise).
*/
onEditModeChange(editMode) {
if (this.autoRefreshSettings.userDisabledManually$.getValue()) {
this.autoRefreshSettings.isEnabled$.next(false);
return;
}
this.autoRefreshSettings.isEnabled$.next(!editMode);
}
/**
* Returns an Observable that triggers the countdown reset action when loading completes.
*
* This method creates an Observable that:
* - Skips a specified number of initial emissions from `isLoadingWidgets$` based on the `skipInitialBehaviorSubjectEmission$` method.
* - Filters out emissions where the loading state is true.
* - On emission where the loading state is false, it triggers a countdown reset action.
*
*/
resetCountdownOnLoadingComplete$() {
return switchMap(() => this.isLoadingWidgets$.pipe(tap(isLoading => isLoading && this.countdownActions.stop$.next()), filter(loading => !loading), tap(() => this.resetCountdown())));
}
/**
* Resets the service's settings and parameters to their default values.
*/
resetServiceToDefaults() {
setTimeout(() => !this.navigationInProgress() && this.clearQueryParam());
this.autoRefreshSettings.refreshInterval$.next(DEFAULT_INTERVAL_VALUE);
this.autoRefreshSettings.userDisabledManually$.next(false);
setTimeout(() => {
this.autoRefreshSettings.isEnabled$.next(DEFAULT_INTERVAL_STATE);
this.resetLoadingToZero();
this.navigationInProgress.set(false);
});
}
/**
* Resets the countdown timer by emitting a reset action after a short delay.
*/
resetCountdown() {
queueMicrotask(() => this.countdownActions.reset$.next());
}
/**
* Initializes the auto-refresh countdown logic based on the widget loading state and edit mode.
*
* This method returns an observable that monitors the widget loading state and triggers specific actions
* related to the countdown process. It performs the following steps:
*
* 1. Skips the initial loading state emitted by `isLoadingWidgets$`.
* 2. Stops the countdown if the widgets are currently loading.
* 3. Filters out cases where widgets are loading or the application is in edit mode.
* 4. Resets the countdown when widgets are not loading and the application is not in edit mode.
*
* @param editMode$ - A `BehaviorSubject` representing whether the application is currently in edit mode.
*
* @returns An `Observable<boolean>` that emits the loading state of the widgets after the initialization steps.
*/
initializeAutoRefreshCountdownLoading$(editMode$) {
return this.isLoadingWidgets$.pipe(skip(1), tap(isLoading => isLoading && this.countdownActions.stop$.next()), filter(isWidgetsLoading => !isWidgetsLoading && !editMode$.getValue()), tap(() => this.resetCountdown()));
}
/**
* Parses a string representation of global auto-refresh parameter into a boolean or null.
*
* Converts the provided `globalAutoRefresh` string into a boolean value or null based on its content:
* - Returns `true` if `globalAutoRefresh` is 'true'.
* - Returns `false` if `globalAutoRefresh` is 'false'.
* - Returns `null` if `globalAutoRefresh` is neither 'true' nor 'false'.
*
* @param globalAutoRefresh - The string representation of the global auto-refresh parameter.
*
* @returns A boolean value corresponding to the parsed global auto-refresh state, or null if the input is not 'true' or 'false'.
*/
parseGlobalAutoRefreshParam(globalAutoRefresh) {
return globalAutoRefresh === 'false' ? false : globalAutoRefresh === 'true' ? true : null;
}
/**
* Resets the loading count to zero.
*/
resetLoadingToZero() {
this.loadingCount$.next(0);
}
/**
* Clears the global auto-refresh query parameter by navigating to the current route with the parameter set to null.
*
*/
clearQueryParam() {
const queryParams = {
globalContextAutoRefresh: null
};
this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams,
queryParamsHandling: 'merge'
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WidgetGlobalAutoRefreshService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WidgetGlobalAutoRefreshService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WidgetGlobalAutoRefreshService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lkZ2V0LWdsb2JhbC1hdXRvLXJlZnJlc2guc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2NvcmUvZGFzaGJvYXJkL3dpZGdldC1hdXRvLXJlZnJlc2gtY29udGV4dC93aWRnZXQtZ2xvYmFsLWF1dG8tcmVmcmVzaC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUF3QyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RixPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHNCQUFzQixFQUN0QiwyQkFBMkIsRUFFNUIsTUFBTSxxQ0FBcUMsQ0FBQztBQUM3QyxPQUFPLEVBQ0wsY0FBYyxFQUVkLGdCQUFnQixFQUNoQixhQUFhLEVBQ2IsZUFBZSxFQUNmLGVBQWUsRUFDZixNQUFNLEVBQ1AsTUFBTSxpQkFBaUIsQ0FBQzs7QUFHekIsTUFBTSxPQUFPLDhCQUE4QjtJQUQzQztRQUVFOzs7V0FHRztRQUNLLGtCQUFhLEdBQUcsSUFBSSxlQUFlLENBQVMsQ0FBQyxDQUFDLENBQUM7UUFFdkQ7Ozs7V0FJRztRQUNLLHNCQUFpQixHQUF3QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FDdEUsb0JBQW9CLEVBQUUsRUFDdEIsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUMxQixDQUFDO1FBRUY7O1dBRUc7UUFDSCx3QkFBbUIsR0FBRztZQUNwQjs7O2VBR0c7WUFDSCxVQUFVLEVBQUUsSUFBSSxlQUFlLENBQVUsc0JBQXNCLENBQUM7WUFD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QUMsQ0FBQztJQUNMLENBQUM7K0dBdlFVLDhCQUE4QjttSEFBOUIsOEJBQThCLGNBRGpCLE1BQU07OzRGQUNuQiw4QkFBOEI7a0JBRDFDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlLCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgTW9ub1R5cGVPcGVyYXRvckZ1bmN0aW9uLCBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgZmlsdGVyLCBtYXAsIHNraXAsIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9JTlRFUlZBTF9TVEFURSxcbiAgREVGQVVMVF9JTlRFUlZBTF9WQUxVRSxcbiAgR0xPQkFMX0NPTlRFWFRfQVVUT19SRUZSRVNILFxuICBHbG9iYWxBdXRvUmVmcmVzaFF1ZXJ5UGFyYW1cbn0gZnJvbSAnLi93aWRnZXQtYXV0by1yZWZyZXNoLWNvbnRleHQubW9kZWwnO1xuaW1wb3J0IHtcbiAgQWN0aXZhdGVkUm91dGUsXG4gIEV2ZW50LFxuICBOYXZpZ2F0aW9uQ2FuY2VsLFxuICBOYXZpZ2F0aW9uRW5kLFxuICBOYXZpZ2F0aW9uRXJyb3IsXG4gIE5hdmlnYXRpb25TdGFydCxcbiAgUm91dGVyXG59IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgV2lkZ2V0R2xvYmFsQXV0b1JlZnJlc2hTZXJ2aWNlIHtcbiAgLyoqXG4gICAqIEEgQmVoYXZpb3JTdWJqZWN0IHRoYXQgdHJhY2tzIHRoZSBudW1iZXIgb2YgbG9hZGluZyBvcGVyYXRpb25zIGluIHByb2dyZXNzLlxuICAgKiBJbml0aWFsaXplZCB3aXRoIGEgY291bnQgb2YgMC5cbiAgICovXG4gIHByaXZhdGUgbG9hZGluZ0NvdW50JCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPigwKTtcblxuICAvKipcbiAgICogQW4gT2JzZXJ2YWJsZSB0aGF0IGVtaXRzIGEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgYW55IHdpZGdldHMgd2l0aCBnbG9iYWwgcmVmcmVzaCBvcHRpb24gYXJlIGN1cnJlbnRseSBsb2FkaW5nLlxuICAgKiBUaGUgdmFsdWUgaXMgdHJ1ZSBpZiB0aGUgbG9hZGluZyBjb3VudCBpcyBub24temVybywgYW5kIGZhbHNlIGlmIHRoZSBsb2FkaW5nIGNvdW50IGlzIHplcm8uXG4gICAqIFVzZXMgZGlzdGluY3RVbnRpbENoYW5nZWQoKSB0byBlbWl0IG9ubHkgd2hlbiB0aGUgYm9vbGVhbiB2YWx1ZSBjaGFuZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBpc0xvYWRpbmdXaWRnZXRzJDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IHRoaXMubG9hZGluZ0NvdW50JC5waXBlKFxuICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgbWFwKGNvdW50ID0+IGNvdW50ICE9PSAwKVxuICApO1xuXG4gIC8qKlxuICAgKiBPYmplY3QgY29udGFpbmluZyBiZWhhdmlvciBzdWJqZWN0cyBmb3IgbWFuYWdpbmcgYXV0by1yZWZyZXNoIHNldHRpbmdzLlxuICAgKi9cbiAgYXV0b1JlZnJlc2hTZXR0aW5ncyA9IHtcbiAgICAvKipcbiAgICAgKiBCZWhhdmlvclN1YmplY3QgdGhhdCBlbWl0cyB0aGUgY3VycmVudCBzdGF0ZSBvZiBhdXRvLXJlZnJlc2ggYnV0dG9uLlxuICAgICAqIERlZmF1bHRzIHRvIERFRkFVTFRfSU5URVJWQUxfU1RBVEUuXG4gICAgICovXG4gICAgaXNFbmFibGVkJDogbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihERUZBVUxUX0lOVEVSVkFMX1NUQVRFKSxcbiAgICAvKipcbiAgICAgKiBCZWhhdmlvclN1YmplY3QgdGhhdCBlbWl0cyB0aGUgY3VycmVudCBhdXRvLXJlZnJlc2ggaW50ZXJ2YWwgdmFsdWUuXG4gICAgICogRGVmYXVsdHMgdG8gREVGQVVMVF9JTlRFUlZBTF9WQUxVRS5cbiAgICAgKi9cbiAgICByZWZyZXNoSW50ZXJ2YWwkOiBuZXcgQmVoYXZpb3JTdWJqZWN0PG51bWJlcj4oREVGQVVMVF9JTlRFUlZBTF9WQUxVRSksXG4gICAgLyoqXG4gICAgICogQmVoYXZpb3JTdWJqZWN0IHRoYXQgZW1pdHMgd2hldGhlciBhdXRvLXJlZnJlc2ggaGFzIGJlZW4gbWFudWFsbHkgZGlzYWJsZWQgYnkgdGhlIHVzZXIuXG4gICAgICogRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAgICovXG4gICAgdXNlckRpc2FibGVkTWFudWFsbHkkOiBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKVxuICB9O1xuXG4gIC8qKlxuICAgKiBPYmplY3QgY29udGFpbmluZyBzdWJqZWN0cyBmb3IgbWFuYWdpbmcgY291bnRkb3duIGFjdGlvbnMuXG4gICAqL1xuICBjb3VudGRvd25BY3Rpb25zID0ge1xuICAgIC8qKlxuICAgICAqIFN1YmplY3QgdXNlZCB0byBzdG9wIHRoZSBjb3VudGRvd24uXG4gICAgICovXG4gICAgc3RvcCQ6IG5ldyBTdWJqZWN0PHZvaWQ+KCksXG4gICAgLyoqXG4gICAgICogU3ViamVjdCB1c2VkIHRvIHJlc2V0IHRoZSBjb3VudGRvd24uXG4gICAgICovXG4gICAgcmVzZXQkOiBuZXcgU3ViamVjdDx2b2lkPigpLFxuICAgIC8qKlxuICAgICAqIFN1YmplY3QgdGhhdCBlbWl0cyB3aGVuIHRoZSBjb3VudGRvd24gaGFzIGVuZGVkLlxuICAgICAqL1xuICAgIGNvdW50ZG93bkVuZGVkJDogbmV3IFN1YmplY3Q8dm9pZD4oKVxuICB9O1xuXG4gIC8qKlxuICAgKiBTdWJqZWN0IHRoYXQgZW1pdHMgd2hlbiBhIGRhc2hib2FyZCBzYXZlIG9wZXJhdGlvbiBpcyB0cmlnZ2VyZWQuXG4gICAqL1xuICBvbkRhc2hib2FyZFNhdmUkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKipcbiAgICogQSBzaWduYWwgcmVwcmVzZW50aW5nIHRoZSBudW1iZXIgb2Ygd2lkZ2V0cyB3aXRoIHRoZSBnbG9iYWwgYXV0by1yZWZyZXNoIG9wdGlvbiBlbmFibGVkLlxuICAgKi9cbiAgZ2xvYmFsUmVmcmVzaFdpZGdldHNDb3VudCA9IHNpZ25hbCgwKTtcblxuICAvKipcbiAgICogVHJhY2tzIHRoZSBuYXZpZ2F0aW9uIHN0YXRlLlxuICAgKlxuICAgKiBUaGUgc2lnbmFsIHJldHVybnMgYSBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciBhIG5hdmlnYXRpb24gb3BlcmF0aW9uIGlzIGN1cnJlbnRseSBpbiBwcm9ncmVzcy5cbiAgICogSXQgaW5pdGlhbGl6ZXMgd2l0aCBhIGRlZmF1bHQgdmFsdWUgb2YgYGZhbHNlYCBhbmQgY2FuIGJlIHRvZ2dsZWQgdG8gYHRydWVgIGR1cmluZyBuYXZpZ2F0aW9uIGV2ZW50cyBmcm9tIGBoYW5kbGVOYXZpZ2F0aW9uSW5Qcm9ncmVzcyRgLlxuICAgKi9cbiAgcHJpdmF0ZSBuYXZpZ2F0aW9uSW5Qcm9ncmVzcyA9IHNpZ25hbChmYWxzZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhY3RpdmF0ZWRSb3V0ZSA9IGluamVjdChBY3RpdmF0ZWRSb3V0ZSk7XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGxvYWRpbmcgY291bnQgYnkgMS5cbiAgICovXG4gIGluY3JlbWVudExvYWRpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5sb2FkaW5nQ291bnQkLm5leHQodGhpcy5sb2FkaW5nQ291bnQkLnZhbHVlICsgMSk7XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgbG9hZGluZyBjb3VudCBieSAxLlxuICAgKi9cbiAgZGVjcmVtZW50TG9hZGluZygpOiB2b2lkIHtcbiAgICB0aGlzLmxvYWRpbmdDb3VudCQubmV4dCh0aGlzLmxvYWRpbmdDb3VudCQudmFsdWUgLSAxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYW4gb2JzZXJ2YWJsZSB0aGF0IGVtaXRzIHRoZSB2YWx1ZSBvZiBhIEdsb2JhbCBBdXRvIFJlZnJlc2ggcXVlcnkgcGFyYW1ldGVyXG4gICAqIHdoZW5ldmVyIGl0IGNoYW5nZXMuIFRoZSBxdWVyeSBwYXJhbWV0ZXIgYmVpbmcgdHJhY2tlZCBpcyBkZXRlcm1pbmVkIGJ5XG4gICAqIGBHbG9iYWxBdXRvUmVmcmVzaE5hbWUuR0xPQkFMX0NPTlRFWFRfQVVUT19SRUZSRVNIYC5cbiAgICpcbiAgICogQHJldHVybnMgQW4gb2JzZXJ2YWJsZSB0aGF0IGVtaXRzIHRoZSBwYXJzZWQgdmFsdWUgb2YgdGhlIGBHTE9CQUxfQ09OVEVYVF9BVVRPX1JFRlJFU0hgIHF1ZXJ5IHBhcmFtZXRlci5cbiAgICovXG4gIGdldFF1ZXJ5UGFyYW1DaGFuZ2VWYWx1ZSQoKTogT2JzZXJ2YWJsZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLmFjdGl2YXRlZFJvdXRlLnF1ZXJ5UGFyYW1zLnBpcGUoXG4gICAgICBtYXAocGFyYW1zID0+IHBhcmFtc1tHTE9CQUxfQ09OVEVYVF9BVVRPX1JFRlJFU0hdKSxcbiAgICAgIG1hcCh0aGlzLnBhcnNlR2xvYmFsQXV0b1JlZnJlc2hQYXJhbSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vbml0b3JzIHJvdXRlciBuYXZpZ2F0aW9uIGV2ZW50cyBhbmQgdXBkYXRlcyB0aGUgbmF2aWdhdGlvbiBwcm9ncmVzcyBzdGF0ZS5cbiAgICpcbiAgICogQHJldHVybnMgQW4gT2JzZXJ2YWJsZSB0aGF0IGVtaXRzIHJvdXRlciBldmVudHMgb2YgdHlwZXMgTmF2aWdhdGlvblN0YXJ0LCBOYXZpZ2F0aW9uRW5kLFxuICAgKiAgICAgICAgICBOYXZpZ2F0aW9uQ2FuY2VsLCBhbmQgTmF2aWdhdGlvbkVycm9yLlxuICAgKi9cbiAgaGFuZGxlTmF2aWdhdGlvbkluUHJvZ3Jlc3MkKCk6IE9ic2VydmFibGU8RXZlbnQ+IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZXIuZXZlbnRzLnBpcGUoXG4gICAgICBmaWx0ZXIoXG4gICAgICAgIGV2ZW50ID0+XG4gICAgICAgICAgZXZlbnQgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uU3RhcnQgfHxcbiAgICAgICAgICBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25FbmQgfHxcbiAgICAgICAgICBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25DYW5jZWwgfHxcbiAgICAgICAgICBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25FcnJvclxuICAgICAgKSxcbiAgICAgIHRhcChlID0+IHRoaXMubmF2aWdhdGlvbkluUHJvZ3Jlc3Muc2V0KGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uU3RhcnQpKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZ2xvYmFsIGF1dG8tcmVmcmVzaCBxdWVyeSBwYXJhbWV0ZXIgaW4gdGhlIGN1cnJlbnQgcm91dGUuXG4gICAqXG4gICAqIEBwYXJhbSBxdWVyeVBhcmFtcyAtIEFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gc2V0IGZvciB0aGUgZ2xvYmFsIGF1dG8tcmVmcmVzaCBvcHRpb24uXG4gICAqICAgICAgICAgICAgICAgICAgICAgIFRoZSBleGlzdGluZyBxdWVyeSBwYXJhbWV0ZXJzIHdpbGwgYmUgbWVyZ2VkIHdpdGggdGhlc2UuXG4gICAqL1xuICBhc3luYyBzZXRBdXRvUmVmcmVzaFF1ZXJ5UGFyYW0ocXVlcnlQYXJhbXM6IEdsb2JhbEF1dG9SZWZyZXNoUXVlcnlQYXJhbSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm5hdmlnYXRpb25JblByb2dyZXNzKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLm5hdmlnYXRpb25JblByb2dyZXNzLnNldCh0cnVlKTtcbiAgICBhd2FpdCB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbXSwge1xuICAgICAgcmVsYXRpdmVUbzogdGhpcy5hY3RpdmF0ZWRSb3V0ZSxcbiAgICAgIHF1ZXJ5UGFyYW1zLFxuICAgICAgcXVlcnlQYXJhbXNIYW5kbGluZzogJ21lcmdlJ1xuICAgIH0pO1xuICAgIHRoaXMubmF2aWdhdGlvbkluUHJvZ3Jlc3Muc2V0KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIGNoYW5nZXMgdG8gdGhlIGVkaXQgbW9kZSBhbmQgdXBkYXRlcyB0aGUgaXNFbmFibGVkJCB2YXJpYWJsZS5cbiAgICpcbiAgICogLSBJZiBhdXRvLXJlZnJlc2ggd2FzIG1hbnVhbGx5IGRpc2FibGVkIGJ5IHRoZSB1c2VyIChgdXNlckRpc2FibGVkTWFudWFsbHkkYCBpcyBgdHJ1ZWApLCBhdXRvLXJlZnJlc2ggd2lsbCByZW1haW4gZGlzYWJsZWQgcmVnYXJkbGVzcyBvZiB0aGUgZWRpdCBtb2RlIHN0YXRlLlxuICAgKiAtIElmIGF1dG8tcmVmcmVzaCB3YXMgbm90IG1hbnVhbGx5IGRpc2FibGVkLCBpdCB3aWxsIGJlIGRpc2FibGVkIHdoZW4gZW50ZXJpbmcgZWRpdCBtb2RlIGFuZCBlbmFibGVkIHdoZW4gZXhpdGluZyBlZGl0IG1vZGUuXG4gICAqXG4gICAqIEBwYXJhbSBlZGl0TW9kZSAtIEEgYm9vbGVhbiBpbmRpY2F0aW5nIHRoZSBjdXJyZW50IHN0YXRlIG9mIGVkaXQgbW9kZSAoYHRydWVgIGlmIGVkaXQgbW9kZSBpcyBhY3RpdmUsIGBmYWxzZWAgb3RoZXJ3aXNlKS5cbiAgICovXG4gIG9uRWRpdE1vZGVDaGFuZ2UoZWRpdE1vZGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLnVzZXJEaXNhYmxlZE1hbnVhbGx5JC5nZXRWYWx1ZSgpKSB7XG4gICAgICB0aGlzLmF1dG9SZWZyZXNoU2V0dGluZ3MuaXNFbmFibGVkJC5uZXh0KGZhbHNlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLmlzRW5hYmxlZCQubmV4dCghZWRpdE1vZGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gT2JzZXJ2YWJsZSB0aGF0IHRyaWdnZXJzIHRoZSBjb3VudGRvd24gcmVzZXQgYWN0aW9uIHdoZW4gbG9hZGluZyBjb21wbGV0ZXMuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNyZWF0ZXMgYW4gT2JzZXJ2YWJsZSB0aGF0OlxuICAgKiAtIFNraXBzIGEgc3BlY2lmaWVkIG51bWJlciBvZiBpbml0aWFsIGVtaXNzaW9ucyBmcm9tIGBpc0xvYWRpbmdXaWRnZXRzJGAgYmFzZWQgb24gdGhlIGBza2lwSW5pdGlhbEJlaGF2aW9yU3ViamVjdEVtaXNzaW9uJGAgbWV0aG9kLlxuICAgKiAtIEZpbHRlcnMgb3V0IGVtaXNzaW9ucyB3aGVyZSB0aGUgbG9hZGluZyBzdGF0ZSBpcyB0cnVlLlxuICAgKiAtIE9uIGVtaXNzaW9uIHdoZXJlIHRoZSBsb2FkaW5nIHN0YXRlIGlzIGZhbHNlLCBpdCB0cmlnZ2VycyBhIGNvdW50ZG93biByZXNldCBhY3Rpb24uXG4gICAqXG4gICAqL1xuICByZXNldENvdW50ZG93bk9uTG9hZGluZ0NvbXBsZXRlJCgpOiBNb25vVHlwZU9wZXJhdG9yRnVuY3Rpb248YW55PiB7XG4gICAgcmV0dXJuIHN3aXRjaE1hcCgoKSA9PlxuICAgICAgdGhpcy5pc0xvYWRpbmdXaWRnZXRzJC5waXBlKFxuICAgICAgICB0YXAoaXNMb2FkaW5nID0+IGlzTG9hZGluZyAmJiB0aGlzLmNvdW50ZG93bkFjdGlvbnMuc3RvcCQubmV4dCgpKSxcbiAgICAgICAgZmlsdGVyKGxvYWRpbmcgPT4gIWxvYWRpbmcpLFxuICAgICAgICB0YXAoKCkgPT4gdGhpcy5yZXNldENvdW50ZG93bigpKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBzZXJ2aWNlJ3Mgc2V0dGluZ3MgYW5kIHBhcmFtZXRlcnMgdG8gdGhlaXIgZGVmYXVsdCB2YWx1ZXMuXG4gICAqL1xuICByZXNldFNlcnZpY2VUb0RlZmF1bHRzKCk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gIXRoaXMubmF2aWdhdGlvbkluUHJvZ3Jlc3MoKSAmJiB0aGlzLmNsZWFyUXVlcnlQYXJhbSgpKTtcblxuICAgIHRoaXMuYXV0b1JlZnJlc2hTZXR0aW5ncy5yZWZyZXNoSW50ZXJ2YWwkLm5leHQoREVGQVVMVF9JTlRFUlZBTF9WQUxVRSk7XG4gICAgdGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLnVzZXJEaXNhYmxlZE1hbnVhbGx5JC5uZXh0KGZhbHNlKTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLmlzRW5hYmxlZCQubmV4dChERUZBVUxUX0lOVEVSVkFMX1NUQVRFKTtcbiAgICAgIHRoaXMucmVzZXRMb2FkaW5nVG9aZXJvKCk7XG4gICAgICB0aGlzLm5hdmlnYXRpb25JblByb2dyZXNzLnNldChmYWxzZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBjb3VudGRvd24gdGltZXIgYnkgZW1pdHRpbmcgYSByZXNldCBhY3Rpb24gYWZ0ZXIgYSBzaG9ydCBkZWxheS5cbiAgICovXG4gIHJlc2V0Q291bnRkb3duKCk6IHZvaWQge1xuICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHRoaXMuY291bnRkb3duQWN0aW9ucy5yZXNldCQubmV4dCgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplcyB0aGUgYXV0by1yZWZyZXNoIGNvdW50ZG93biBsb2dpYyBiYXNlZCBvbiB0aGUgd2lkZ2V0IGxvYWRpbmcgc3RhdGUgYW5kIGVkaXQgbW9kZS5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhbiBvYnNlcnZhYmxlIHRoYXQgbW9uaXRvcnMgdGhlIHdpZGdldCBsb2FkaW5nIHN0YXRlIGFuZCB0cmlnZ2VycyBzcGVjaWZpYyBhY3Rpb25zXG4gICAqIHJlbGF0ZWQgdG8gdGhlIGNvdW50ZG93biBwcm9jZXNzLiBJdCBwZXJmb3JtcyB0aGUgZm9sbG93aW5nIHN0ZXBzOlxuICAgKlxuICAgKiAxLiBTa2lwcyB0aGUgaW5pdGlhbCBsb2FkaW5nIHN0YXRlIGVtaXR0ZWQgYnkgYGlzTG9hZGluZ1dpZGdldHMkYC5cbiAgICogMi4gU3RvcHMgdGhlIGNvdW50ZG93biBpZiB0aGUgd2lkZ2V0cyBhcmUgY3VycmVudGx5IGxvYWRpbmcuXG4gICAqIDMuIEZpbHRlcnMgb3V0IGNhc2VzIHdoZXJlIHdpZGdldHMgYXJlIGxvYWRpbmcgb3IgdGhlIGFwcGxpY2F0aW9uIGlzIGluIGVkaXQgbW9kZS5cbiAgICogNC4gUmVzZXRzIHRoZSBjb3VudGRvd24gd2hlbiB3aWRnZXRzIGFyZSBub3QgbG9hZGluZyBhbmQgdGhlIGFwcGxpY2F0aW9uIGlzIG5vdCBpbiBlZGl0IG1vZGUuXG4gICAqXG4gICAqIEBwYXJhbSBlZGl0TW9kZSQgLSBBIGBCZWhhdmlvclN1YmplY3RgIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoZSBhcHBsaWNhdGlvbiBpcyBjdXJyZW50bHkgaW4gZWRpdCBtb2RlLlxuICAgKlxuICAgKiBAcmV0dXJucyBBbiBgT2JzZXJ2YWJsZTxib29sZWFuPmAgdGhhdCBlbWl0cyB0aGUgbG9hZGluZyBzdGF0ZSBvZiB0aGUgd2lkZ2V0cyBhZnRlciB0aGUgaW5pdGlhbGl6YXRpb24gc3RlcHMuXG4gICAqL1xuICBpbml0aWFsaXplQXV0b1JlZnJlc2hDb3VudGRvd25Mb2FkaW5nJChlZGl0TW9kZSQ6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPik6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmlzTG9hZGluZ1dpZGdldHMkLnBpcGUoXG4gICAgICBza2lwKDEpLFxuICAgICAgdGFwKGlzTG9hZGluZyA9PiBpc0xvYWRpbmcgJiYgdGhpcy5jb3VudGRvd25BY3Rpb25zLnN0b3AkLm5leHQoKSksXG4gICAgICBmaWx0ZXIoaXNXaWRnZXRzTG9hZGluZyA9PiAhaXNXaWRnZXRzTG9hZGluZyAmJiAhZWRpdE1vZGUkLmdldFZhbHVlKCkpLFxuICAgICAgdGFwKCgpID0+IHRoaXMucmVzZXRDb3VudGRvd24oKSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBnbG9iYWwgYXV0by1yZWZyZXNoIHBhcmFtZXRlciBpbnRvIGEgYm9vbGVhbiBvciBudWxsLlxuICAgKlxuICAgKiBDb252ZXJ0cyB0aGUgcHJvdmlkZWQgYGdsb2JhbEF1dG9SZWZyZXNoYCBzdHJpbmcgaW50byBhIGJvb2xlYW4gdmFsdWUgb3IgbnVsbCBiYXNlZCBvbiBpdHMgY29udGVudDpcbiAgICogLSBSZXR1cm5zIGB0cnVlYCBpZiBgZ2xvYmFsQXV0b1JlZnJlc2hgIGlzICd0cnVlJy5cbiAgICogLSBSZXR1cm5zIGBmYWxzZWAgaWYgYGdsb2JhbEF1dG9SZWZyZXNoYCBpcyAnZmFsc2UnLlxuICAgKiAtIFJldHVybnMgYG51bGxgIGlmIGBnbG9iYWxBdXRvUmVmcmVzaGAgaXMgbmVpdGhlciAndHJ1ZScgbm9yICdmYWxzZScuXG4gICAqXG4gICAqIEBwYXJhbSBnbG9iYWxBdXRvUmVmcmVzaCAtIFRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdsb2JhbCBhdXRvLXJlZnJlc2ggcGFyYW1ldGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gdmFsdWUgY29ycmVzcG9uZGluZyB0byB0aGUgcGFyc2VkIGdsb2JhbCBhdXRvLXJlZnJlc2ggc3RhdGUsIG9yIG51bGwgaWYgdGhlIGlucHV0IGlzIG5vdCAndHJ1ZScgb3IgJ2ZhbHNlJy5cbiAgICovXG4gIHByaXZhdGUgcGFyc2VHbG9iYWxBdXRvUmVmcmVzaFBhcmFtKGdsb2JhbEF1dG9SZWZyZXNoOiBzdHJpbmcpOiBib29sZWFuIHwgbnVsbCB7XG4gICAgcmV0dXJuIGdsb2JhbEF1dG9SZWZyZXNoID09PSAnZmFsc2UnID8gZmFsc2UgOiBnbG9iYWxBdXRvUmVmcmVzaCA9PT0gJ3RydWUnID8gdHJ1ZSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBsb2FkaW5nIGNvdW50IHRvIHplcm8uXG4gICAqL1xuICBwcml2YXRlIHJlc2V0TG9hZGluZ1RvWmVybygpOiB2b2lkIHtcbiAgICB0aGlzLmxvYWRpbmdDb3VudCQubmV4dCgwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhcnMgdGhlIGdsb2JhbCBhdXRvLXJlZnJlc2ggcXVlcnkgcGFyYW1ldGVyIGJ5IG5hdmlnYXRpbmcgdG8gdGhlIGN1cnJlbnQgcm91dGUgd2l0aCB0aGUgcGFyYW1ldGVyIHNldCB0byBudWxsLlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBjbGVhclF1ZXJ5UGFyYW0oKTogdm9pZCB7XG4gICAgY29uc3QgcXVlcnlQYXJhbXM6IEdsb2JhbEF1dG9SZWZyZXNoUXVlcnlQYXJhbSA9IHtcbiAgICAgIGdsb2JhbENvbnRleHRBdXRvUmVmcmVzaDogbnVsbFxuICAgIH07XG5cbiAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbXSwge1xuICAgICAgcmVsYXRpdmVUbzogdGhpcy5hY3RpdmF0ZWRSb3V0ZSxcbiAgICAgIHF1ZXJ5UGFyYW1zLFxuICAgICAgcXVlcnlQYXJhbXNIYW5kbGluZzogJ21lcmdlJ1xuICAgIH0pO1xuICB9XG59XG4iXX0=