UNPKG

@netgrif/components-core

Version:

Netgrif Application engine frontend core Angular library

305 lines 45.1 kB
import { Injectable } from '@angular/core'; import { forkJoin, of, ReplaySubject, Subject } from 'rxjs'; import { Net } from './net'; import { catchError, map, switchMap, tap } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "../resources/engine-endpoint/petri-net-resource.service"; import * as i2 from "../logger/services/logger.service"; /** * Process service is responsible for loading and caching processes needed for any functionality of an app. */ export class ProcessService { _petriNetResource; _log; _nets; _netsSubject; _netUpdate; _requestCache; _referenceRequestCache; LATEST = 'latest'; constructor(_petriNetResource, _log) { this._petriNetResource = _petriNetResource; this._log = _log; this._nets = {}; this._netsSubject = new Subject(); this._netUpdate = new Subject(); this._requestCache = new Map(); this._referenceRequestCache = new Map(); } ngOnDestroy() { this._netsSubject.complete(); this._netUpdate.complete(); Array.from(this._requestCache.values()).forEach(net => net.complete()); Array.from(this._referenceRequestCache.values()).forEach(net => net.complete()); } /** * Get process nets according to provided identifiers. * If any of the requested processes is not cached it will be loaded from the server and saved for later. * @param identifiers Array of identifiers of requested processes. See {@link Net} * @param forceLoad when set to `true` cached processes will be ignored and a backend request will always be made * (unless another is already pending) * @returns Observable of array of loaded processes. Array is emitted only when every process finished loading. * If any of the processes failed to load it is skipped from the result. */ getNets(identifiers, forceLoad = false) { if (identifiers.length === 0) { return of([]); } return forkJoin(identifiers.map(i => { return this.getNet(i, forceLoad); })).pipe(map(nets => nets.filter(n => !!n)), tap(nets => { if (nets.length === 0) { return; } this._netsSubject.next(this._nets); nets.forEach(n => this._netUpdate.next(n)); })); } /** * Get process net by identifier. * @param identifier Identifier of the requested process. See {@link Net} * @param forceLoad when set to `true` cached processes will be ignored and a backend request will always be made * (unless another is already pending) * @returns Observable of [the process]{@link Net}. Process is loaded from a server or picked from the cache. */ getNet(identifier, forceLoad = false) { if (!forceLoad && this._nets[identifier]) { this._log.debug(`returning net '${identifier}' from cache`); return of(this._nets[identifier]); } if (this._requestCache.has(identifier)) { this._log.debug(`returning net '${identifier}' from pending requests`); return this._requestCache.get(identifier).asObservable(); } this._log.debug(`retrieving net '${identifier}' from backend`); this._requestCache.set(identifier, new ReplaySubject(1)); return this.loadNet(identifier).pipe(tap(net => { const s = this._requestCache.get(identifier); if (s) { s.next(net); s.complete(); this._requestCache.delete(identifier); } if (net) { this.publishUpdate(net); } })); } /** * Get process net referencess according to provided identifiers. * * `PetriNetReferences` are not cached. * Each call will result in a new backend request unless a request for the same net is already pending. * @param identifiers Array of identifiers of requested processes. See {@link Net} * @returns Observable of array of loaded processes. Array is emitted only when every process finished loading. * If any of the processes failed to load it is skipped from the result. */ getNetReferences(identifiers) { if (identifiers.length === 0) { return of([]); } return forkJoin(identifiers.map(i => { return this.getNetReference(i); })).pipe(map(references => references.filter(r => !!r))); } /** * Get process net reference by identifier. * * `PetriNetReferences` are not cached. * Each call will result in a new backend request unless a request for the same net is already pending. * @param identifier Identifier of the requested process. See {@link Net} * @returns Observable of [the process]{@link Net}. Process is loaded from a server or picked from the cache. */ getNetReference(identifier) { if (this._referenceRequestCache.has(identifier)) { return this._referenceRequestCache.get(identifier).asObservable(); } this._referenceRequestCache.set(identifier, new ReplaySubject(1)); return this.loadNetReference(identifier).pipe(switchMap(ref => { if (ref !== null) { return forkJoin({ net: of(ref), roles: this.loadRoles(ref.stringId) }); } else { return of({ net: ref, roles: undefined }); } }), map(result => { if (result.net === null) { return null; } return { ...result.net, roles: result.roles.processRoles, permissions: result.roles.permissions }; }), tap(reference => { const s = this._referenceRequestCache.get(identifier); if (s) { s.next(reference); s.complete(); this._referenceRequestCache.delete(identifier); } })); } /** * Remove cached process by identifier. If the process is not found nothing happens. * @param identifier Process identifier */ removeNet(identifier) { if (!this._nets[identifier]) { return; } delete this._nets[identifier]; this.publishUpdate(); } /** * Update cached process object. If the process is not found nothing happens. Process object is replaced. * @param net Updated process object. */ updateNet(net) { if (!this._nets[net.identifier]) { return; } if (!net.transitions.length || !net.transactions.length || !net.roles.length) { forkJoin({ transitions: this.loadTransitions(net.stringId), transactions: this.loadTransactions(net.stringId), roles: this.loadRoles(net.stringId) }).subscribe(values => { net.transitions = values.transitions; net.transactions = values.transactions; net.roles = values.roles.processRoles; net.permissions = values.roles.permissions; this._nets[net.identifier] = net; this.publishUpdate(net); }, error => { this._log.error('Failed to load part of Petri net ' + net.title, error); // throw error; }); } else { this._nets[net.identifier] = net; this.publishUpdate(net); } } /** * Stream of change of the process cache. * New state of cache is emitted every time the cached changed by inserting, updating or deleting a process. * @returns Observable of whole updated cache. */ get nets$() { return this._netsSubject.asObservable(); } /** * Stream of change in the process cache. * New state of cache is emitted every time the cached changed by inserting, updating or deleting a process. * @returns Observable of updated or newly loaded process net. */ get netUpdate$() { return this._netUpdate.asObservable(); } areNetsLoaded(identifiers) { return identifiers.every(identifier => this.isNetLoaded(identifier)); } isNetLoaded(identifier) { return !!this._nets[identifier]; } loadNet(id) { const returnNet = new ReplaySubject(1); this.loadNetReference(id).subscribe(net => { if (net === null) { this._log.debug(`loadNetReference for net '${id}' returned null`); returnNet.next(null); returnNet.complete(); return; } this._log.debug(`loading net '${id}' transitions, transactions and roles`); forkJoin({ transitions: this.loadTransitions(net.stringId), transactions: this.loadTransactions(net.stringId), roles: this.loadRoles(net.stringId) }).subscribe(values => { this._nets[net.identifier] = new Net(net); this._nets[net.identifier].transitions = values.transitions; this._nets[net.identifier].transactions = values.transactions; this._nets[net.identifier].roles = values.roles.processRoles; this._nets[net.identifier].permissions = values.roles.permissions; returnNet.next(this._nets[net.identifier]); returnNet.complete(); }, error => { this._log.error('Failed to load part of Petri net ' + net.title, error); returnNet.next(this._nets[net.identifier]); returnNet.complete(); // throw error; }); }); return returnNet.asObservable(); } loadNetReference(id) { const returnReference = new ReplaySubject(1); this._petriNetResource.getOne(id, this.LATEST).subscribe(reference => { returnReference.next(!reference.stringId ? null : reference); returnReference.complete(); return; }, error => { this._log.error('Failed to load Petri net', error); returnReference.next(null); returnReference.complete(); }); return returnReference.asObservable(); } loadTransitions(id) { return this._petriNetResource.getPetriNetTransitions(id).pipe(map(trans => { if (trans instanceof Array) { return trans; } return []; }), tap(trans => { if (trans.length === 0) { this._log.info('References for transitions of net ' + id + ' were not found!'); } }), catchError(err => { this._log.error('References for transitions of net ' + id + ' failed to load!', err); throw err; })); } loadTransactions(id) { return this._petriNetResource.getPetriNetTransactions(id).pipe(map(trans => { if (trans instanceof Array) { return trans; } return []; }), tap(trans => { if (trans.length === 0) { this._log.info('References for transactions of net ' + id + ' were not found!'); } }), catchError(err => { this._log.error('References for transactions of net ' + id + ' failed to load!', err); throw err; })); } loadRoles(id) { return this._petriNetResource.getPetriNetRoles(id).pipe(tap(rolesAndPerm => { if (rolesAndPerm.processRoles.length === 0) { this._log.info('Roles reference of net ' + id + ' were not found!'); } }), catchError(err => { this._log.error('Roles reference of net ' + id + ' failed to load!', err); throw err; })); } publishUpdate(net) { this._netsSubject.next(this._nets); if (net) { this._netUpdate.next(net); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ProcessService, deps: [{ token: i1.PetriNetResourceService }, { token: i2.LoggerService }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ProcessService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ProcessService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.PetriNetResourceService }, { type: i2.LoggerService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvY2Vzcy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmV0Z3JpZi1jb21wb25lbnRzLWNvcmUvc3JjL2xpYi9wcm9jZXNzL3Byb2Nlc3Muc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsVUFBVSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ3BELE9BQU8sRUFBQyxRQUFRLEVBQWMsRUFBRSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDdEUsT0FBTyxFQUFDLEdBQUcsRUFBQyxNQUFNLE9BQU8sQ0FBQztBQUsxQixPQUFPLEVBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUFTL0Q7O0dBRUc7QUFJSCxNQUFNLE9BQU8sY0FBYztJQVNIO0lBQW9EO0lBUHJELEtBQUssQ0FBVztJQUN6QixZQUFZLENBQW9CO0lBQ2hDLFVBQVUsQ0FBZTtJQUN6QixhQUFhLENBQWtDO0lBQy9DLHNCQUFzQixDQUErRDtJQUMvRSxNQUFNLEdBQUcsUUFBUSxDQUFDO0lBRWxDLFlBQW9CLGlCQUEwQyxFQUFVLElBQW1CO1FBQXZFLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBeUI7UUFBVSxTQUFJLEdBQUosSUFBSSxDQUFlO1FBQ3ZGLElBQUksQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxPQUFPLEVBQVksQ0FBQztRQUM1QyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksT0FBTyxFQUFPLENBQUM7UUFDckMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLEdBQUcsRUFBOEIsQ0FBQztRQUMzRCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxHQUFHLEVBQTJELENBQUM7SUFDckcsQ0FBQztJQUVELFdBQVc7UUFDUCxJQUFJ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QUMsS0FBSyxDQUFDLHFDQUFxQyxHQUFHLEVBQUUsR0FBRyxrQkFBa0IsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUN0RixNQUFNLEdBQUcsQ0FBQztRQUNkLENBQUMsQ0FBQyxDQUNMLENBQUM7SUFDTixDQUFDO0lBRVMsU0FBUyxDQUFDLEVBQVU7UUFDMUIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUNuRCxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFDZixJQUFJLFlBQVksQ0FBQyxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDeEMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMseUJBQXlCLEdBQUcsRUFBRSxHQUFHLGtCQUFrQixDQUFDLENBQUM7YUFDdkU7UUFDTCxDQUFDLENBQUMsRUFDRixVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDYixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxFQUFFLEdBQUcsa0JBQWtCLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDMUUsTUFBTSxHQUFHLENBQUM7UUFDZCxDQUFDLENBQUMsQ0FDTCxDQUFDO0lBQ04sQ0FBQztJQUVTLGFBQWEsQ0FBQyxHQUFTO1FBQzdCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQyxJQUFJLEdBQUcsRUFBRTtZQUNMLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQzdCO0lBQ0wsQ0FBQzt3R0EvVFEsY0FBYzs0R0FBZCxjQUFjLGNBRlgsTUFBTTs7NEZBRVQsY0FBYztrQkFIMUIsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGUsIE9uRGVzdHJveX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge2ZvcmtKb2luLCBPYnNlcnZhYmxlLCBvZiwgUmVwbGF5U3ViamVjdCwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge05ldH0gZnJvbSAnLi9uZXQnO1xuaW1wb3J0IHtQZXRyaU5ldFJlc291cmNlU2VydmljZX0gZnJvbSAnLi4vcmVzb3VyY2VzL2VuZ2luZS1lbmRwb2ludC9wZXRyaS1uZXQtcmVzb3VyY2Uuc2VydmljZSc7XG5pbXBvcnQge0xvZ2dlclNlcnZpY2V9IGZyb20gJy4uL2xvZ2dlci9zZXJ2aWNlcy9sb2dnZXIuc2VydmljZSc7XG5pbXBvcnQgVHJhbnNpdGlvbiBmcm9tICcuL3RyYW5zaXRpb24nO1xuaW1wb3J0IFRyYW5zYWN0aW9uIGZyb20gJy4vdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHtjYXRjaEVycm9yLCBtYXAsIHN3aXRjaE1hcCwgdGFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgUm9sZXNBbmRQZXJtaXNzaW9ucyBmcm9tICcuL3JvbGVzQW5kUGVybWlzc2lvbnMnO1xuaW1wb3J0IHtQZXRyaU5ldFJlZmVyZW5jZX0gZnJvbSAnLi4vcmVzb3VyY2VzL2ludGVyZmFjZS9wZXRyaS1uZXQtcmVmZXJlbmNlJztcbmltcG9ydCB7UGV0cmlOZXRSZWZlcmVuY2VXaXRoUGVybWlzc2lvbnN9IGZyb20gJy4vcGV0cmktbmV0LXJlZmVyZW5jZS13aXRoLXBlcm1pc3Npb25zJztcblxuZXhwb3J0IGludGVyZmFjZSBOZXRDYWNoZSB7XG4gICAgW2s6IHN0cmluZ106IE5ldDtcbn1cblxuLyoqXG4gKiBQcm9jZXNzIHNlcnZpY2UgaXMgcmVzcG9uc2libGUgZm9yIGxvYWRpbmcgYW5kIGNhY2hpbmcgcHJvY2Vzc2VzIG5lZWRlZCBmb3IgYW55IGZ1bmN0aW9uYWxpdHkgb2YgYW4gYXBwLlxuICovXG5ASW5qZWN0YWJsZSh7XG4gICAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIFByb2Nlc3NTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBfbmV0czogTmV0Q2FjaGU7XG4gICAgcHJvdGVjdGVkIF9uZXRzU3ViamVjdDogU3ViamVjdDxOZXRDYWNoZT47XG4gICAgcHJvdGVjdGVkIF9uZXRVcGRhdGU6IFN1YmplY3Q8TmV0PjtcbiAgICBwcm90ZWN0ZWQgX3JlcXVlc3RDYWNoZTogTWFwPHN0cmluZywgUmVwbGF5U3ViamVjdDxOZXQ+PjtcbiAgICBwcm90ZWN0ZWQgX3JlZmVyZW5jZVJlcXVlc3RDYWNoZTogTWFwPHN0cmluZywgUmVwbGF5U3ViamVjdDxQZXRyaU5ldFJlZmVyZW5jZVdpdGhQZXJtaXNzaW9ucz4+O1xuICAgIHB1YmxpYyByZWFkb25seSBMQVRFU1QgPSAnbGF0ZXN0JztcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgX3BldHJpTmV0UmVzb3VyY2U6IFBldHJpTmV0UmVzb3VyY2VTZXJ2aWNlLCBwcml2YXRlIF9sb2c6IExvZ2dlclNlcnZpY2UpIHtcbiAgICAgICAgdGhpcy5fbmV0cyA9IHt9O1xuICAgICAgICB0aGlzLl9uZXRzU3ViamVjdCA9IG5ldyBTdWJqZWN0PE5ldENhY2hlPigpO1xuICAgICAgICB0aGlzLl9uZXRVcGRhdGUgPSBuZXcgU3ViamVjdDxOZXQ+KCk7XG4gICAgICAgIHRoaXMuX3JlcXVlc3RDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBSZXBsYXlTdWJqZWN0PE5ldD4+KCk7XG4gICAgICAgIHRoaXMuX3JlZmVyZW5jZVJlcXVlc3RDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBSZXBsYXlTdWJqZWN0PFBldHJpTmV0UmVmZXJlbmNlV2l0aFBlcm1pc3Npb25zPj4oKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fbmV0c1N1YmplY3QuY29tcGxldGUoKTtcbiAgICAgICAgdGhpcy5fbmV0VXBkYXRlLmNvbXBsZXRlKCk7XG4gICAgICAgIEFycmF5LmZyb20odGhpcy5fcmVxdWVzdENhY2hlLnZhbHVlcygpKS5mb3JFYWNoKG5ldCA9PiBuZXQuY29tcGxldGUoKSk7XG4gICAgICAgIEFycmF5LmZyb20odGhpcy5fcmVmZXJlbmNlUmVxdWVzdENhY2hlLnZhbHVlcygpKS5mb3JFYWNoKG5ldCA9PiBuZXQuY29tcGxldGUoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHByb2Nlc3MgbmV0cyBhY2NvcmRpbmcgdG8gcHJvdmlkZWQgaWRlbnRpZmllcnMuXG4gICAgICogSWYgYW55IG9mIHRoZSByZXF1ZXN0ZWQgcHJvY2Vzc2VzIGlzIG5vdCBjYWNoZWQgaXQgd2lsbCBiZSBsb2FkZWQgZnJvbSB0aGUgc2VydmVyIGFuZCBzYXZlZCBmb3IgbGF0ZXIuXG4gICAgICogQHBhcmFtIGlkZW50aWZpZXJzIEFycmF5IG9mIGlkZW50aWZpZXJzIG9mIHJlcXVlc3RlZCBwcm9jZXNzZXMuIFNlZSB7QGxpbmsgTmV0fVxuICAgICAqIEBwYXJhbSBmb3JjZUxvYWQgd2hlbiBzZXQgdG8gYHRydWVgIGNhY2hlZCBwcm9jZXNzZXMgd2lsbCBiZSBpZ25vcmVkIGFuZCBhIGJhY2tlbmQgcmVxdWVzdCB3aWxsIGFsd2F5cyBiZSBtYWRlXG4gICAgICogKHVubGVzcyBhbm90aGVyIGlzIGFscmVhZHkgcGVuZGluZylcbiAgICAgKiBAcmV0dXJucyBPYnNlcnZhYmxlIG9mIGFycmF5IG9mIGxvYWRlZCBwcm9jZXNzZXMuIEFycmF5IGlzIGVtaXR0ZWQgb25seSB3aGVuIGV2ZXJ5IHByb2Nlc3MgZmluaXNoZWQgbG9hZGluZy5cbiAgICAgKiBJZiBhbnkgb2YgdGhlIHByb2Nlc3NlcyBmYWlsZWQgdG8gbG9hZCBpdCBpcyBza2lwcGVkIGZyb20gdGhlIHJlc3VsdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0TmV0cyhpZGVudGlmaWVyczogQXJyYXk8c3RyaW5nPiwgZm9yY2VMb2FkID0gZmFsc2UpOiBPYnNlcnZhYmxlPEFycmF5PE5ldD4+IHtcbiAgICAgICAgaWYgKGlkZW50aWZpZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIG9mKFtdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm9ya0pvaW4oaWRlbnRpZmllcnMubWFwKGkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TmV0KGksIGZvcmNlTG9hZCk7XG4gICAgICAgIH0pKS5waXBlKFxuICAgICAgICAgICAgbWFwKG5ldHMgPT4gbmV0cy5maWx0ZXIobiA9PiAhIW4pKSxcbiAgICAgICAgICAgIHRhcChuZXRzID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobmV0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9uZXRzU3ViamVjdC5uZXh0KHRoaXMuX25ldHMpO1xuICAgICAgICAgICAgICAgIG5ldHMuZm9yRWFjaChuID0+IHRoaXMuX25ldFVwZGF0ZS5uZXh0KG4pKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHByb2Nlc3MgbmV0IGJ5IGlkZW50aWZpZXIuXG4gICAgICogQHBhcmFtIGlkZW50aWZpZXIgSWRlbnRpZmllciBvZiB0aGUgcmVxdWVzdGVkIHByb2Nlc3MuIFNlZSB7QGxpbmsgTmV0fVxuICAgICAqIEBwYXJhbSBmb3JjZUxvYWQgd2hlbiBzZXQgdG8gYHRydWVgIGNhY2hlZCBwcm9jZXNzZXMgd2lsbCBiZSBpZ25vcmVkIGFuZCBhIGJhY2tlbmQgcmVxdWVzdCB3aWxsIGFsd2F5cyBiZSBtYWRlXG4gICAgICogKHVubGVzcyBhbm90aGVyIGlzIGFscmVhZHkgcGVuZGluZylcbiAgICAgKiBAcmV0dXJucyBPYnNlcnZhYmxlIG9mIFt0aGUgcHJvY2Vzc117QGxpbmsgTmV0fS4gUHJvY2VzcyBpcyBsb2FkZWQgZnJvbSBhIHNlcnZlciBvciBwaWNrZWQgZnJvbSB0aGUgY2FjaGUuXG4gICAgICovXG4gICAgcHVibGljIGdldE5ldChpZGVudGlmaWVyOiBzdHJpbmcsIGZvcmNlTG9hZCA9IGZhbHNlKTogT2JzZXJ2YWJsZTxOZXQ+IHtcbiAgICAgICAgaWYgKCFmb3JjZUxvYWQgJiYgdGhpcy5fbmV0c1tpZGVudGlmaWVyXSkge1xuICAgICAgICAgICAgdGhpcy5fbG9nLmRlYnVnKGByZXR1cm5pbmcgbmV0ICcke2lkZW50aWZpZXJ9JyBmcm9tIGNhY2hlYCk7XG4gICAgICAgICAgICByZXR1cm4gb2YodGhpcy5fbmV0c1tpZGVudGlmaWVyXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3JlcXVlc3RDYWNoZS5oYXMoaWRlbnRpZmllcikpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvZy5kZWJ1ZyhgcmV0dXJuaW5nIG5ldCAnJHtpZGVudGlmaWVyfScgZnJvbSBwZW5kaW5nIHJlcXVlc3RzYCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcmVxdWVzdENhY2hlLmdldChpZGVudGlmaWVyKS5hc09ic2VydmFibGUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9sb2cuZGVidWcoYHJldHJpZXZpbmcgbmV0ICcke2lkZW50aWZpZXJ9JyBmcm9tIGJhY2tlbmRgKTtcbiAgICAgICAgdGhpcy5fcmVxdWVzdENhY2hlLnNldChpZGVudGlmaWVyLCBuZXcgUmVwbGF5U3ViamVjdDxOZXQ+KDEpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9hZE5ldChpZGVudGlmaWVyKS5waXBlKFxuICAgICAgICAgICAgdGFwKG5ldCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcyA9IHRoaXMuX3JlcXVlc3RDYWNoZS5nZXQoaWRlbnRpZmllcik7XG4gICAgICAgICAgICAgICAgaWYgKHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcy5uZXh0KG5ldCk7XG4gICAgICAgICAgICAgICAgICAgIHMuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdENhY2hlLmRlbGV0ZShpZGVudGlmaWVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG5ldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hVcGRhdGUobmV0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBwcm9jZXNzIG5ldCByZWZlcmVuY2VzcyBhY2NvcmRpbmcgdG8gcHJvdmlkZWQgaWRlbnRpZmllcnMuXG4gICAgICpcbiAgICAgKiBgUGV0cmlOZXRSZWZlcmVuY2VzYCBhcmUgbm90IGNhY2hlZC5cbiAgICAgKiBFYWNoIGNhbGwgd2lsbCByZXN1bHQgaW4gYSBuZXcgYmFja2VuZCByZXF1ZXN0IHVubGVzcyBhIHJlcXVlc3QgZm9yIHRoZSBzYW1lIG5ldCBpcyBhbHJlYWR5IHBlbmRpbmcuXG4gICAgICogQHBhcmFtIGlkZW50aWZpZXJzIEFycmF5IG9mIGlkZW50aWZpZXJzIG9mIHJlcXVlc3RlZCBwcm9jZXNzZXMuIFNlZSB7QGxpbmsgTmV0fVxuICAgICAqIEByZXR1cm5zIE9ic2VydmFibGUgb2YgYXJyYXkgb2YgbG9hZGVkIHByb2Nlc3Nlcy4gQXJyYXkgaXMgZW1pdHRlZCBvbmx5IHdoZW4gZXZlcnkgcHJvY2VzcyBmaW5pc2hlZCBsb2FkaW5nLlxuICAgICAqIElmIGFueSBvZiB0aGUgcHJvY2Vzc2VzIGZhaWxlZCB0byBsb2FkIGl0IGlzIHNraXBwZWQgZnJvbSB0aGUgcmVzdWx0LlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXROZXRSZWZlcmVuY2VzKGlkZW50aWZpZXJzOiBBcnJheTxzdHJpbmc+KTogT2JzZXJ2YWJsZTxBcnJheTxQZXRyaU5ldFJlZmVyZW5jZVdpdGhQZXJtaXNzaW9ucz4+IHtcbiAgICAgICAgaWYgKGlkZW50aWZpZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIG9mKFtdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm9ya0pvaW4oaWRlbnRpZmllcnMubWFwKGkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TmV0UmVmZXJlbmNlKGkpO1xuICAgICAgICB9KSkucGlwZShcbiAgICAgICAgICAgIG1hcChyZWZlcmVuY2VzID0+IHJlZmVyZW5jZXMuZmlsdGVyKHIgPT4gISFyKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgcHJvY2VzcyBuZXQgcmVmZXJlbmNlIGJ5IGlkZW50aWZpZXIuXG4gICAgICpcbiAgICAgKiBgUGV0cmlOZXRSZWZlcmVuY2VzYCBhcmUgbm90IGNhY2hlZC5cbiAgICAgKiBFYWNoIGNhbGwgd2lsbCByZXN1bHQgaW4gYSBuZXcgYmFja2VuZCByZXF1ZXN0IHVubGVzcyBhIHJlcXVlc3QgZm9yIHRoZSBzYW1lIG5ldCBpcyBhbHJlYWR5IHBlbmRpbmcuXG4gICAgICogQHBhcmFtIGlkZW50aWZpZXIgSWRlbnRpZmllciBvZiB0aGUgcmVxdWVzdGVkIHByb2Nlc3MuIFNlZSB7QGxpbmsgTmV0fVxuICAgICAqIEByZXR1cm5zIE9ic2VydmFibGUgb2YgW3RoZSBwcm9jZXNzXXtAbGluayBOZXR9LiBQcm9jZXNzIGlzIGxvYWRlZCBmcm9tIGEgc2VydmVyIG9yIHBpY2tlZCBmcm9tIHRoZSBjYWNoZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0TmV0UmVmZXJlbmNlKGlkZW50aWZpZXI6IHN0cmluZyk6IE9ic2VydmFibGU8UGV0cmlOZXRSZWZlcmVuY2VXaXRoUGVybWlzc2lvbnM+IHtcbiAgICAgICAgaWYgKHRoaXMuX3JlZmVyZW5jZVJlcXVlc3RDYWNoZS5oYXMoaWRlbnRpZmllcikpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9yZWZlcmVuY2VSZXF1ZXN0Q2FjaGUuZ2V0KGlkZW50aWZpZXIpLmFzT2JzZXJ2YWJsZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3JlZmVyZW5jZVJlcXVlc3RDYWNoZS5zZXQoaWRlbnRpZmllciwgbmV3IFJlcGxheVN1YmplY3Q8UGV0cmlOZXRSZWZlcmVuY2VXaXRoUGVybWlzc2lvbnM+KDEpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9hZE5ldFJlZmVyZW5jZShpZGVudGlmaWVyKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKHJlZiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHJlZiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm9ya0pvaW4oe25ldDogb2YocmVmKSwgcm9sZXM6IHRoaXMubG9hZFJvbGVzKHJlZi5zdHJpbmdJZCl9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2Yoe25ldDogcmVmLCByb2xlczogdW5kZWZpbmVkfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBtYXAocmVzdWx0ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lm5ldCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgLi4ucmVzdWx0Lm5ldCxcbiAgICAgICAgICAgICAgICAgICAgcm9sZXM6IHJlc3VsdC5yb2xlcy5wcm9jZXNzUm9sZXMsXG4gICAgICAgICAgICAgICAgICAgIHBlcm1pc3Npb25zOiByZXN1bHQucm9sZXMucGVybWlzc2lvbnNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0YXAocmVmZXJlbmNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzID0gdGhpcy5fcmVmZXJlbmNlUmVxdWVzdENhY2hlLmdldChpZGVudGlmaWVyKTtcbiAgICAgICAgICAgICAgICBpZiAocykge1xuICAgICAgICAgICAgICAgICAgICBzLm5leHQocmVmZXJlbmNlKTtcbiAgICAgICAgICAgICAgICAgICAgcy5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWZlcmVuY2VSZXF1ZXN0Q2FjaGUuZGVsZXRlKGlkZW50aWZpZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGNhY2hlZCBwcm9jZXNzIGJ5IGlkZW50aWZpZXIuIElmIHRoZSBwcm9jZXNzIGlzIG5vdCBmb3VuZCBub3RoaW5nIGhhcHBlbnMuXG4gICAgICogQHBhcmFtIGlkZW50aWZpZXIgUHJvY2VzcyBpZGVudGlmaWVyXG4gICAgICovXG4gICAgcHVibGljIHJlbW92ZU5ldChpZGVudGlmaWVyOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLl9uZXRzW2lkZW50aWZpZXJdKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlIHRoaXMuX25ldHNbaWRlbnRpZmllcl07XG4gICAgICAgIHRoaXMucHVibGlzaFVwZGF0ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSBjYWNoZWQgcHJvY2VzcyBvYmplY3QuIElmIHRoZSBwcm9jZXNzIGlzIG5vdCBmb3VuZCBub3RoaW5nIGhhcHBlbnMuIFByb2Nlc3Mgb2JqZWN0IGlzIHJlcGxhY2VkLlxuICAgICAqIEBwYXJhbSBuZXQgVXBkYXRlZCBwcm9jZXNzIG9iamVjdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgdXBkYXRlTmV0KG5ldDogTmV0KTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5fbmV0c1tuZXQuaWRlbnRpZmllcl0pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIW5ldC50cmFuc2l0aW9ucy5sZW5ndGggfHwgIW5ldC50cmFuc2FjdGlvbnMubGVuZ3RoIHx8ICFuZXQucm9sZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBmb3JrSm9pbih7XG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvbnM6IHRoaXMubG9hZFRyYW5zaXRpb25zKG5ldC5zdHJpbmdJZCksXG4gICAgICAgICAgICAgICAgdHJhbnNhY3Rpb25zOiB0aGlzLmxvYWRUcmFuc2FjdGlvbnMobmV0LnN0cmluZ0lkKSxcbiAgICAgICAgICAgICAgICByb2xlczogdGhpcy5sb2FkUm9sZXMobmV0LnN0cmluZ0lkKVxuICAgICAgICAgICAgfSkuc3Vic2NyaWJlKHZhbHVlcyA9PiB7XG4gICAgICAgICAgICAgICAgbmV0LnRyYW5zaXRpb25zID0gdmFsdWVzLnRyYW5zaXRpb25zO1xuICAgICAgICAgICAgICAgIG5ldC50cmFuc2FjdGlvbnMgPSB2YWx1ZXMudHJhbnNhY3Rpb25zO1xuICAgICAgICAgICAgICAgIG5ldC5yb2xlcyA9IHZhbHVlcy5yb2xlcy5wcm9jZXNzUm9sZXM7XG4gICAgICAgICAgICAgICAgbmV0LnBlcm1pc3Npb25zID0gdmFsdWVzLnJvbGVzLnBlcm1pc3Npb25zO1xuICAgICAgICAgICAgICAgIHRoaXMuX25ldHNbbmV0LmlkZW50aWZpZXJdID0gbmV0O1xuICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaFVwZGF0ZShuZXQpO1xuICAgICAgICAgICAgfSwgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX2xvZy5lcnJvcignRmFpbGVkIHRvIGxvYWQgcGFydCBvZiBQZXRyaSBuZXQgJyArIG5ldC50aXRsZSwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIC8vIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9uZXRzW25ldC5pZGVudGlmaWVyXSA9IG5ldDtcbiAgICAgICAgICAgIHRoaXMucHVibGlzaFVwZGF0ZShuZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9mIGNoYW5nZSBvZiB0aGUgcHJvY2VzcyBjYWNoZS5cbiAgICAgKiBOZXcgc3RhdGUgb2YgY2FjaGUgaXMgZW1pdHRlZCBldmVyeSB0aW1lIHRoZSBjYWNoZWQgY2hhbmdlZCBieSBpbnNlcnRpbmcsIHVwZGF0aW5nIG9yIGRlbGV0aW5nIGEgcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyBPYnNlcnZhYmxlIG9mIHdob2xlIHVwZGF0ZWQgY2FjaGUuXG4gICAgICovXG4gICAgcHVibGljIGdldCBuZXRzJCgpOiBPYnNlcnZhYmxlPE5ldENhY2hlPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9uZXRzU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW0gb2YgY2hhbmdlIGluIHRoZSBwcm9jZXNzIGNhY2hlLlxuICAgICAqIE5ldyBzdGF0ZSBvZiBjYWNoZSBpcyBlbWl0dGVkIGV2ZXJ5IHRpbWUgdGhlIGNhY2hlZCBjaGFuZ2VkIGJ5IGluc2VydGluZywgdXBkYXRpbmcgb3IgZGVsZXRpbmcgYSBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIE9ic2VydmFibGUgb2YgdXBkYXRlZCBvciBuZXdseSBsb2FkZWQgcHJvY2VzcyBuZXQuXG4gICAgICovXG4gICAgcHVibGljIGdldCBuZXRVcGRhdGUkKCk6IE9ic2VydmFibGU8TmV0PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9uZXRVcGRhdGUuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFyZU5ldHNMb2FkZWQoaWRlbnRpZmllcnM6IEFycmF5PHN0cmluZz4pOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGlkZW50aWZpZXJzLmV2ZXJ5KGlkZW50aWZpZXIgPT4gdGhpcy5pc05ldExvYWRlZChpZGVudGlmaWVyKSk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzTmV0TG9hZGVkKGlkZW50aWZpZXI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gISF0aGlzLl9uZXRzW2lkZW50aWZpZXJdO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBsb2FkTmV0KGlkOiBzdHJpbmcpOiBPYnNlcnZhYmxlPE5ldD4ge1xuICAgICAgICBjb25zdCByZXR1cm5OZXQgPSBuZXcgUmVwbGF5U3ViamVjdDxOZXQ+KDEpO1xuICAgICAgICB0aGlzLmxvYWROZXRSZWZlcmVuY2UoaWQpLnN1YnNjcmliZShuZXQgPT4ge1xuICAgICAgICAgICAgaWYgKG5ldCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2xvZy5kZWJ1ZyhgbG9hZE5ldFJlZmVyZW5jZSBmb3IgbmV0ICcke2lkfScgcmV0dXJuZWQgbnVsbGApO1xuICAgICAgICAgICAgICAgIHJldHVybk5ldC5uZXh0KG51bGwpO1xuICAgICAgICAgICAgICAgIHJldHVybk5ldC5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2xvZy5kZWJ1ZyhgbG9hZGluZyBuZXQgJyR7aWR9JyB0cmFuc2l0aW9ucywgdHJhbnNhY3Rpb25zIGFuZCByb2xlc2ApO1xuICAgICAgICAgICAgZm9ya0pvaW4oe1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25zOiB0aGlzLmxvYWRUcmFuc2l0aW9ucyhuZXQuc3RyaW5nSWQpLFxuICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uczogdGhpcy5sb2FkVHJhbnNhY3Rpb25zKG5ldC5zdHJpbmdJZCksXG4gICAgICAgICAgICAgICAgcm9sZXM6IHRoaXMubG9hZFJvbGVzKG5ldC5zdHJpbmdJZClcbiAgICAgICAgICAgIH0pLnN1YnNjcmliZSh2YWx1ZXMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX25ldHNbbmV0LmlkZW50aWZpZXJdID0gbmV3IE5ldChuZXQpO1xuICAgICAgICAgICAgICAgIHRoaXMuX25ldHNbbmV0LmlkZW50aWZpZXJdLnRyYW5zaXRpb25zID0gdmFsdWVzLnRyYW5zaXRpb25zO1xuICAgICAgICAgICAgICAgIHRoaXMuX25ldHNbbmV0LmlkZW50aWZpZXJdLnRyYW5zYWN0aW9ucyA9IHZhbHVlcy50cmFuc2FjdGlvbnM7XG4gICAgICAgICAgICAgICAgdGhpcy5fbmV0c1tuZXQuaWRlbnRpZmllcl0ucm9sZXMgPSB2YWx1ZXMucm9sZXMucHJvY2Vzc1JvbGVzO1xuICAgICAgICAgICAgICAgIHRoaXMuX25ldHNbbmV0LmlkZW50aWZpZXJdLnBlcm1pc3Npb25zID0gdmFsdWVzLnJvbGVzLnBlcm1pc3Npb25zO1xuICAgICAgICAgICAgICAgIHJldHVybk5ldC5uZXh0KHRoaXMuX25ldHNbbmV0LmlkZW50aWZpZXJdKTtcbiAgICAgICAgICAgICAgICByZXR1cm5OZXQuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0sIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2cuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIHBhcnQgb2YgUGV0cmkgbmV0ICcgKyBuZXQudGl0bGUsIGVycm9yKTtcbiAgICAgICAgICAgICAgICByZXR1cm5OZXQubmV4dCh0aGlzLl9uZXRzW25ldC5pZGVudGlmaWVyXSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuTmV0LmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgLy8gdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXR1cm5OZXQuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGxvYWROZXRSZWZlcmVuY2UoaWQ6IHN0cmluZyk6IE9ic2VydmFibGU8UGV0cmlOZXRSZWZlcmVuY2U+IHtcbiAgICAgICAgY29uc3QgcmV0dXJuUmVmZXJlbmNlID0gbmV3IFJlcGxheVN1YmplY3Q8UGV0cmlOZXRSZWZlcmVuY2U+KDEpO1xuICAgICAgICB0aGlzLl9wZXRyaU5ldFJlc291cmNlLmdldE9uZShpZCwgdGhpcy5MQVRFU1QpLnN1YnNjcmliZShyZWZlcmVuY2UgPT4ge1xuICAgICAgICAgICAgcmV0dXJuUmVmZXJlbmNlLm5leHQoIXJlZmVyZW5jZS5zdHJpbmdJZCA/IG51bGwgOiByZWZlcmVuY2UpO1xuICAgICAgICAgICAgcmV0dXJuUmVmZXJlbmNlLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0sIGVycm9yID0+IHtcbiAgICAgICAgICAgIHRoaXMuX2xvZy5lcnJvcignRmFpbGVkIHRvIGxvYWQgUGV0cmkgbmV0JywgZXJyb3IpO1xuICAgICAgICAgICAgcmV0dXJuUmVmZXJlbmNlLm5leHQobnVsbCk7XG4gICAgICAgICAgICByZXR1cm5SZWZlcmVuY2UuY29tcGxldGUoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXR1cm5SZWZlcmVuY2UuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGxvYWRUcmFuc2l0aW9ucyhpZDogc3RyaW5nKTogT2JzZXJ2YWJsZTxBcnJheTxUcmFuc2l0aW9uPj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcGV0cmlOZXRSZXNvdXJjZS5nZXRQZXRyaU5ldFRyYW5zaXRpb25zKGlkKS5waXBlKFxuICAgICAgICAgICAgbWFwKHRyYW5zID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodHJhbnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgdGFwKHRyYW5zID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodHJhbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvZy5pbmZvKCdSZWZlcmVuY2VzIGZvciB0cmFuc2l0aW9ucyBvZiBuZXQgJyArIGlkICsgJyB3ZXJlIG5vdCBmb3VuZCEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNhdGNoRXJyb3IoZXJyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2cuZXJyb3IoJ1JlZmVyZW5jZXMgZm9yIHRyYW5zaXRpb25zIG9mIG5ldCAnICsgaWQgKyAnIGZhaWxlZCB0byBsb2FkIScsIGVycik7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbG9hZFRyYW5zYWN0aW9ucyhpZDogc3RyaW5nKTogT2JzZXJ2YWJsZTxBcnJheTxUcmFuc2FjdGlvbj4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BldHJpTmV0UmVzb3VyY2UuZ2V0UGV0cmlOZXRUcmFuc2FjdGlvbnMoaWQpLnBpcGUoXG4gICAgICAgICAgICBtYXAodHJhbnMgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0cmFucyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cmFucztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0YXAodHJhbnMgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0cmFucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9nLmluZm8oJ1JlZmVyZW5jZXMgZm9yIHRyYW5zYWN0aW9ucyBvZiBuZXQgJyArIGlkICsgJyB3ZXJlIG5vdCBmb3VuZCEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNhdGNoRXJyb3IoZXJyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2cuZXJyb3IoJ1JlZmVyZW5jZXMgZm9yIHRyYW5zYWN0aW9ucyBvZiBuZXQgJyArIGlkICsgJyBmYWlsZWQgdG8gbG9hZCEnLCBlcnIpO1xuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGxvYWRSb2xlcyhpZDogc3RyaW5nKTogT2JzZXJ2YWJsZTxSb2xlc0FuZFBlcm1pc3Npb25zPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wZXRyaU5ldFJlc291cmNlLmdldFBldHJpTmV0Um9sZXMoaWQpLnBpcGUoXG4gICAgICAgICAgICB0YXAocm9sZXNBbmRQZXJtID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocm9sZXNBbmRQZXJtLnByb2Nlc3NSb2xlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9nLmluZm8oJ1JvbGVzIHJlZmVyZW5jZSBvZiBuZXQgJyArIGlkICsgJyB3ZXJlIG5vdCBmb3VuZCEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNhdGNoRXJyb3IoZXJyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2cuZXJyb3IoJ1JvbGVzIHJlZmVyZW5jZSBvZiBuZXQgJyArIGlkICsgJyBmYWlsZWQgdG8gbG9hZCEnLCBlcnIpO1xuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHB1Ymxpc2hVcGRhdGUobmV0PzogTmV0KTogdm9pZCB7XG4gICAgICAgIHRoaXMuX25ldHNTdWJqZWN0Lm5leHQodGhpcy5fbmV0cyk7XG4gICAgICAgIGlmIChuZXQpIHtcbiAgICAgICAgICAgIHRoaXMuX25ldFVwZGF0ZS5uZXh0KG5ldCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=