@amin-karimi/agm-direction
Version:
Angular Google Maps direction
337 lines • 46.6 kB
JavaScript
import { Directive, Input, Output, EventEmitter } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@amin-karimi/agm-core";
export class AgmDirection {
constructor(gmapsApi) {
this.gmapsApi = gmapsApi;
this.waypoints = [];
this.optimizeWaypoints = true;
this.provideRouteAlternatives = false;
this.avoidHighways = false;
this.avoidTolls = false;
this.avoidFerries = false;
// Remove or draw direction
this.visible = true;
// Direction change event handler
this.onChange = new EventEmitter();
// Direction response for the new request
this.onResponse = new EventEmitter();
// Send a custom infowindow
this.sendInfoWindow = new EventEmitter();
// Status of Directions Query (google.maps.DirectionsStatus.OVER_QUERY_LIMIT)
this.status = new EventEmitter();
// Marker drag event handler
this.originDrag = new EventEmitter();
this.destinationDrag = new EventEmitter();
this.waypointsMarker = [];
// Use for visible flag
this.isFirstChange = true;
}
ngOnInit() {
if (this.visible === true) {
this.directionDraw();
}
}
ngOnChanges(obj) {
/**
* When visible is false then remove the direction layer
*/
if (!this.visible) {
try {
this.removeMarkers();
this.removeDirections();
}
catch (e) { }
}
else {
if (this.isFirstChange) {
/**
* When visible is false at the first time
*/
if (typeof this.directionsRenderer === 'undefined') {
this.directionDraw();
}
this.isFirstChange = false;
return;
}
/**
* When renderOptions are not first change then reset the display
*/
if (typeof obj.renderOptions !== 'undefined') {
if (obj.renderOptions.firstChange === false) {
this.removeMarkers();
this.removeDirections();
}
}
this.directionDraw();
}
}
ngOnDestroy() {
this.destroyMarkers();
this.removeDirections();
}
/**
* This event is fired when the user creating or updating this direction
*/
directionDraw() {
this.gmapsApi.getNativeMap().then(_map => {
// const map = _map as unknown | google.maps.Map;
const map = _map;
if (typeof this.directionsRenderer === 'undefined') {
this.directionsRenderer = new google.maps.DirectionsRenderer(this.renderOptions);
// @ts-ignore
this.directionsRenderer.setMap(map);
this.directionsRenderer.addListener('directions_changed', () => {
this.onChange.emit(this.directionsRenderer.getDirections());
});
}
if (typeof this.directionsService === 'undefined') {
this.directionsService = new google.maps.DirectionsService();
}
if (typeof this.panel === 'undefined') {
// @ts-ignore
this.directionsRenderer.setPanel(null);
}
else {
this.directionsRenderer.setPanel(this.panel);
}
// Render exist direction
if (this.renderRoute) {
this.directionsRenderer.setDirections(this.renderRoute);
this.renderRoute = undefined;
}
else {
// Request new direction
this.directionsService.route({
origin: this.origin,
destination: this.destination,
travelMode: this.travelMode || google.maps.TravelMode.DRIVING,
transitOptions: this.transitOptions,
drivingOptions: this.drivingOptions,
waypoints: this.waypoints,
optimizeWaypoints: this.optimizeWaypoints,
provideRouteAlternatives: this.provideRouteAlternatives,
avoidHighways: this.avoidHighways,
avoidTolls: this.avoidTolls,
avoidFerries: this.avoidFerries,
unitSystem: this.unitSystem,
}, (response, status) => {
this.onResponse.emit(response);
// Emit Query Status
this.status.emit(status);
/**
* DirectionsStatus
* https://developers.google.com/maps/documentation/javascript/directions#DirectionsStatus
*/
switch (status) {
case google.maps.DirectionsStatus.OK:
this.directionsRenderer.setDirections(response);
/**
* Emit The DirectionsResult Object
* https://developers.google.com/maps/documentation/javascript/directions?hl=en#DirectionsResults
*/
// Custom Markers
if (typeof this.markerOptions !== 'undefined') {
this.destroyMarkers();
// Set custom markers
const _route = response.routes[0].legs[0];
try {
// Origin Marker
if (typeof this.markerOptions.origin !== 'undefined') {
this.markerOptions.origin.map = map;
this.markerOptions.origin.position = _route.start_location;
this.originMarker = this.setMarker(map, this.originMarker, this.markerOptions.origin, _route.start_address);
if (this.markerOptions.origin.draggable) {
this.originMarker.addListener('dragend', () => {
this.origin = this.originMarker.position;
this.directionDraw();
this.originDrag.emit(this.origin);
});
}
}
// Destination Marker
if (typeof this.markerOptions.destination !== 'undefined') {
this.markerOptions.destination.map = map;
this.markerOptions.destination.position = _route.end_location;
this.destinationMarker = this.setMarker(map, this.destinationMarker, this.markerOptions.destination, _route.end_address);
if (this.markerOptions.destination.draggable) {
this.destinationMarker.addListener('dragend', () => {
this.destination = this.destinationMarker.position;
this.directionDraw();
this.destinationDrag.emit(this.destination);
});
}
}
// Waypoints Marker
if (typeof this.markerOptions.waypoints !== 'undefined') {
this.waypoints.forEach((waypoint, index) => {
// If waypoints are not array then set all the same
if (!Array.isArray(this.markerOptions.waypoints)) {
this.markerOptions.waypoints.map = map;
this.markerOptions.waypoints.position = _route.via_waypoints[index];
this.waypointsMarker.push(this.setMarker(map, waypoint, this.markerOptions.waypoints, _route.via_waypoints[index]));
}
else {
this.markerOptions.waypoints[index].map = map;
this.markerOptions.waypoints[index].position = _route.via_waypoints[index];
this.waypointsMarker.push(this.setMarker(map, waypoint, this.markerOptions.waypoints[index], _route.via_waypoints[index]));
}
}); // End forEach
}
}
catch (err) {
console.error('MarkerOptions error.', err);
}
}
break;
case google.maps.DirectionsStatus.OVER_QUERY_LIMIT:
console.warn('The webpage has sent too many requests within the allowed time period.');
break;
default:
// console.warn(status);
break;
} // End switch
});
}
});
}
/**
* Custom Origin and Destination Icon
* @param map map
* @param marker marker
* @param markerOpts properties
* @param content marker's infowindow content
* @returns new marker
* @memberof AgmDirection
*/
setMarker(map, marker, markerOpts, content) {
if (typeof this.infoWindow === 'undefined') {
this.infoWindow = new google.maps.InfoWindow();
this.sendInfoWindow.emit(this.infoWindow);
}
marker = new google.maps.Marker(markerOpts);
// https://developers.google.com/maps/documentation/javascript/reference/marker?hl=zh-tw#MarkerOptions.clickable
if (marker.getClickable()) {
marker.addListener('click', () => {
const infowindoContent = typeof markerOpts.infoWindow === 'undefined' ? content : markerOpts.infoWindow;
this.infoWindow.setContent(infowindoContent);
this.infoWindow.open(map, marker);
});
}
return marker;
}
/**
* This event is fired when remove markers
*/
removeMarkers() {
if (typeof this.originMarker !== 'undefined') {
this.originMarker.setMap(null);
}
if (typeof this.destinationMarker !== 'undefined') {
this.destinationMarker.setMap(null);
}
this.waypointsMarker.forEach((w) => {
if (typeof w !== 'undefined') {
w.setMap(null);
}
});
}
/**
* This event is fired when remove directions
*/
removeDirections() {
if (this.directionsRenderer !== undefined) {
// @ts-ignore
this.directionsRenderer.setPanel(null);
this.directionsRenderer.setMap(null);
// @ts-ignore
this.directionsRenderer = undefined;
}
}
/**
* This event is fired when destroy markers
*/
destroyMarkers() {
// Remove origin markers
try {
if (typeof this.originMarker !== 'undefined') {
google.maps.event.clearListeners(this.originMarker, 'click');
if (this.markerOptions.origin.draggable) {
google.maps.event.clearListeners(this.originMarker, 'dragend');
}
}
if (typeof this.destinationMarker !== 'undefined') {
google.maps.event.clearListeners(this.destinationMarker, 'click');
if (this.markerOptions.origin.draggable) {
google.maps.event.clearListeners(this.destinationMarker, 'dragend');
}
}
this.waypointsMarker.forEach((w) => {
if (typeof w !== 'undefined') {
google.maps.event.clearListeners(w, 'click');
}
});
this.removeMarkers();
}
catch (err) {
console.error('Can not reset custom marker.', err);
}
}
}
AgmDirection.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AgmDirection, deps: [{ token: i1.GoogleMapsAPIWrapper }], target: i0.ɵɵFactoryTarget.Directive });
AgmDirection.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: AgmDirection, selector: "agm-direction", inputs: { origin: "origin", destination: "destination", travelMode: "travelMode", transitOptions: "transitOptions", drivingOptions: "drivingOptions", waypoints: "waypoints", optimizeWaypoints: "optimizeWaypoints", provideRouteAlternatives: "provideRouteAlternatives", avoidHighways: "avoidHighways", avoidTolls: "avoidTolls", avoidFerries: "avoidFerries", unitSystem: "unitSystem", renderOptions: "renderOptions", panel: "panel", markerOptions: "markerOptions", infoWindow: "infoWindow", visible: "visible", renderRoute: "renderRoute" }, outputs: { onChange: "onChange", onResponse: "onResponse", sendInfoWindow: "sendInfoWindow", status: "status", originDrag: "originDrag", destinationDrag: "destinationDrag" }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AgmDirection, decorators: [{
type: Directive,
args: [{
selector: 'agm-direction',
}]
}], ctorParameters: function () { return [{ type: i1.GoogleMapsAPIWrapper }]; }, propDecorators: { origin: [{
type: Input
}], destination: [{
type: Input
}], travelMode: [{
type: Input
}], transitOptions: [{
type: Input
}], drivingOptions: [{
type: Input
}], waypoints: [{
type: Input
}], optimizeWaypoints: [{
type: Input
}], provideRouteAlternatives: [{
type: Input
}], avoidHighways: [{
type: Input
}], avoidTolls: [{
type: Input
}], avoidFerries: [{
type: Input
}], unitSystem: [{
type: Input
}], renderOptions: [{
type: Input
}], panel: [{
type: Input
}], markerOptions: [{
type: Input
}], infoWindow: [{
type: Input
}], visible: [{
type: Input
}], renderRoute: [{
type: Input
}], onChange: [{
type: Output
}], onResponse: [{
type: Output
}], sendInfoWindow: [{
type: Output
}], status: [{
type: Output
}], originDrag: [{
type: Output
}], destinationDrag: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdtLWRpcmVjdGlvbi5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hZ20tZGlyZWN0aW9uL3NyYy9saWIvYWdtLWRpcmVjdGlvbi5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFxQixZQUFZLEVBQWEsTUFBTSxlQUFlLENBQUM7OztBQU1yRyxNQUFNLE9BQU8sWUFBWTtJQXVFdkIsWUFDVSxRQUE4QjtRQUE5QixhQUFRLEdBQVIsUUFBUSxDQUFzQjtRQTVEL0IsY0FBUyxHQUFxQyxFQUFFLENBQUM7UUFFakQsc0JBQWlCLEdBQUcsSUFBSSxDQUFDO1FBRXpCLDZCQUF3QixHQUFHLEtBQUssQ0FBQztRQUVqQyxrQkFBYSxHQUFHLEtBQUssQ0FBQztRQUV0QixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBRW5CLGlCQUFZLEdBQUcsS0FBSyxDQUFDO1FBZ0I5QiwyQkFBMkI7UUFDbEIsWUFBTyxHQUFHLElBQUksQ0FBQztRQUt4QixpQ0FBaUM7UUFDdkIsYUFBUSxHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFDO1FBRWhFLHlDQUF5QztRQUMvQixlQUFVLEdBQStDLElBQUksWUFBWSxFQUFnQyxDQUFDO1FBRXBILDJCQUEyQjtRQUNqQixtQkFBYyxHQUF5QyxJQUFJLFlBQVksRUFBMEIsQ0FBQztRQUU1Ryw2RUFBNkU7UUFDbkUsV0FBTSxHQUErQyxJQUFJLFlBQVksRUFBZ0MsQ0FBQztRQUVoSCw0QkFBNEI7UUFDbEIsZUFBVSxHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFDO1FBQ3hELG9CQUFlLEdBQXNCLElBQUksWUFBWSxFQUFPLENBQUM7UUFRL0Qsb0JBQWUsR0FBOEIsRUFBRSxDQUFDO1FBRXhELHVCQUF1QjtRQUNmLGtCQUFhLEdBQUcsSUFBSSxDQUFDO0lBSXpCLENBQUM7SUFFTCxRQUFRO1FBQ04s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LCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUsIElucHV0LCBPdXRwdXQsIE9uQ2hhbmdlcywgT25Jbml0LCBFdmVudEVtaXR0ZXIsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBHb29nbGVNYXBzQVBJV3JhcHBlciB9IGZyb20gJ0BhbWluLWthcmltaS9hZ20tY29yZSc7XHJcblxyXG5ARGlyZWN0aXZlKHtcclxuICBzZWxlY3RvcjogJ2FnbS1kaXJlY3Rpb24nLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgQWdtRGlyZWN0aW9uIGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIE9uRGVzdHJveSB7XHJcblxyXG4gIEBJbnB1dCgpIG9yaWdpbjogc3RyaW5nIHwgZ29vZ2xlLm1hcHMuUGxhY2UgfCBnb29nbGUubWFwcy5MYXRMbmcgfCBnb29nbGUubWFwcy5MYXRMbmdMaXRlcmFsO1xyXG5cclxuICBASW5wdXQoKSBkZXN0aW5hdGlvbjogc3RyaW5nIHwgZ29vZ2xlLm1hcHMuUGxhY2UgfCBnb29nbGUubWFwcy5MYXRMbmcgfCBnb29nbGUubWFwcy5MYXRMbmdMaXRlcmFsO1xyXG5cclxuICBASW5wdXQoKSB0cmF2ZWxNb2RlPzogZ29vZ2xlLm1hcHMuVHJhdmVsTW9kZTtcclxuXHJcbiAgQElucHV0KCkgdHJhbnNpdE9wdGlvbnM/OiBnb29nbGUubWFwcy5UcmFuc2l0T3B0aW9ucztcclxuXHJcbiAgQElucHV0KCkgZHJpdmluZ09wdGlvbnM/OiBnb29nbGUubWFwcy5Ecml2aW5nT3B0aW9ucztcclxuXHJcbiAgQElucHV0KCkgd2F5cG9pbnRzOiBnb29nbGUubWFwcy5EaXJlY3Rpb25zV2F5cG9pbnRbXSA9IFtdO1xyXG5cclxuICBASW5wdXQoKSBvcHRpbWl6ZVdheXBvaW50cyA9IHRydWU7XHJcblxyXG4gIEBJbnB1dCgpIHByb3ZpZGVSb3V0ZUFsdGVybmF0aXZlcyA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKSBhdm9pZEhpZ2h3YXlzID0gZmFsc2U7XHJcblxyXG4gIEBJbnB1dCgpIGF2b2lkVG9sbHMgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KCkgYXZvaWRGZXJyaWVzID0gZmFsc2U7XHJcblxyXG4gIEBJbnB1dCgpIHVuaXRTeXN0ZW0/OiBnb29nbGUubWFwcy5Vbml0U3lzdGVtO1xyXG5cclxuICBASW5wdXQoKSByZW5kZXJPcHRpb25zPzogZ29vZ2xlLm1hcHMuRGlyZWN0aW9uc1JlbmRlcmVyT3B0aW9ucztcclxuXHJcbiAgQElucHV0KCkgcGFuZWw/OiBFbGVtZW50O1xyXG5cclxuICBASW5wdXQoKSBtYXJrZXJPcHRpb25zOiB7XHJcbiAgICBvcmlnaW46IGdvb2dsZS5tYXBzLk1hcmtlck9wdGlvbnMsXHJcbiAgICBkZXN0aW5hdGlvbjogZ29vZ2xlLm1hcHMuTWFya2VyT3B0aW9ucyxcclxuICAgIHdheXBvaW50cz86IGdvb2dsZS5tYXBzLk1hcmtlck9wdGlvbnMsXHJcbiAgfTtcclxuXHJcbiAgQElucHV0KCkgaW5mb1dpbmRvdzogZ29vZ2xlLm1hcHMuSW5mb1dpbmRvdztcclxuXHJcbiAgLy8gUmVtb3ZlIG9yIGRyYXcgZGlyZWN0aW9uXHJcbiAgQElucHV0KCkgdmlzaWJsZSA9IHRydWU7XHJcblxyXG4gIC8vIFJlbmRlciBleGlzdCBkaXJlY3Rpb25cclxuICBASW5wdXQoKSByZW5kZXJSb3V0ZT86IGdvb2dsZS5tYXBzLkRpcmVjdGlvbnNSZXN1bHQgfCBudWxsO1xyXG5cclxuICAvLyBEaXJlY3Rpb24gY2hhbmdlIGV2ZW50IGhhbmRsZXJcclxuICBAT3V0cHV0KCkgb25DaGFuZ2U6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gIC8vIERpcmVjdGlvbiByZXNwb25zZSBmb3IgdGhlIG5ldyByZXF1ZXN0XHJcbiAgQE91dHB1dCgpIG9uUmVzcG9uc2U6IEV2ZW50RW1pdHRlcjxnb29nbGUubWFwcy5EaXJlY3Rpb25zUmVzdWx0PiA9IG5ldyBFdmVudEVtaXR0ZXI8Z29vZ2xlLm1hcHMuRGlyZWN0aW9uc1Jlc3VsdD4oKTtcclxuXHJcbiAgLy8gU2VuZCBhIGN1c3RvbSBpbmZvd2luZG93XHJcbiAgQE91dHB1dCgpIHNlbmRJbmZvV2luZG93OiBFdmVudEVtaXR0ZXI8Z29vZ2xlLm1hcHMuSW5mb1dpbmRvdz4gPSBuZXcgRXZlbnRFbWl0dGVyPGdvb2dsZS5tYXBzLkluZm9XaW5kb3c+KCk7XHJcblxyXG4gIC8vIFN0YXR1cyBvZiBEaXJlY3Rpb25zIFF1ZXJ5IChnb29nbGUubWFwcy5EaXJlY3Rpb25zU3RhdHVzLk9WRVJfUVVFUllfTElNSVQpXHJcbiAgQE91dHB1dCgpIHN0YXR1czogRXZlbnRFbWl0dGVyPGdvb2dsZS5tYXBzLkRpcmVjdGlvbnNTdGF0dXM+ID0gbmV3IEV2ZW50RW1pdHRlcjxnb29nbGUubWFwcy5EaXJlY3Rpb25zU3RhdHVzPigpO1xyXG5cclxuICAvLyBNYXJrZXIgZHJhZyBldmVudCBoYW5kbGVyXHJcbiAgQE91dHB1dCgpIG9yaWdpbkRyYWc6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQE91dHB1dCgpIGRlc3RpbmF0aW9uRHJhZzogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgcHVibGljIGRpcmVjdGlvbnNTZXJ2aWNlOiBnb29nbGUubWFwcy5EaXJlY3Rpb25zU2VydmljZTtcclxuICBwdWJsaWMgZGlyZWN0aW9uc1JlbmRlcmVyOiBnb29nbGUubWFwcy5EaXJlY3Rpb25zUmVuZGVyZXI7XHJcblxyXG4gIC8vIFVzZSBmb3IgY3VzdG9tIG1hcmtlclxyXG4gIHByaXZhdGUgb3JpZ2luTWFya2VyPzogYW55O1xyXG4gIHByaXZhdGUgZGVzdGluYXRpb25NYXJrZXI/OiBhbnk7XHJcbiAgcHJpdmF0ZSB3YXlwb2ludHNNYXJrZXI6IEFycmF5PGdvb2dsZS5tYXBzLk1hcmtlcj4gPSBbXTtcclxuXHJcbiAgLy8gVXNlIGZvciB2aXNpYmxlIGZsYWdcclxuICBwcml2YXRlIGlzRmlyc3RDaGFuZ2UgPSB0cnVlO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgZ21hcHNBcGk6IEdvb2dsZU1hcHNBUElXcmFwcGVyLFxyXG4gICkgeyB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgaWYgKHRoaXMudmlzaWJsZSA9PT0gdHJ1ZSkge1xyXG4gICAgICB0aGlzLmRpcmVjdGlvbkRyYXcoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25DaGFuZ2VzKG9iajogYW55KSB7XHJcbiAgICAvKipcclxuICAgICAqIFdoZW4gdmlzaWJsZSBpcyBmYWxzZSB0aGVuIHJlbW92ZSB0aGUgZGlyZWN0aW9uIGxheWVyXHJcbiAgICAgKi9cclxuICAgIGlmICghdGhpcy52aXNpYmxlKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgdGhpcy5yZW1vdmVNYXJrZXJzKCk7XHJcbiAgICAgICAgdGhpcy5yZW1vdmVEaXJlY3Rpb25zKCk7XHJcbiAgICAgIH0gY2F0Y2ggKGUpIHsgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKHRoaXMuaXNGaXJzdENoYW5nZSkge1xyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFdoZW4gdmlzaWJsZSBpcyBmYWxzZSBhdCB0aGUgZmlyc3QgdGltZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5kaXJlY3Rpb25zUmVuZGVyZXIgPT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICB0aGlzLmRpcmVjdGlvbkRyYXcoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5pc0ZpcnN0Q2hhbmdlID0gZmFsc2U7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvKipcclxuICAgICAgICogV2hlbiByZW5kZXJPcHRpb25zIGFyZSBub3QgZmlyc3QgY2hhbmdlIHRoZW4gcmVzZXQgdGhlIGRpc3BsYXlcclxuICAgICAgICovXHJcbiAgICAgIGlmICh0eXBlb2Ygb2JqLnJlbmRlck9wdGlvbnMgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgaWYgKG9iai5yZW5kZXJPcHRpb25zLmZpcnN0Q2hhbmdlID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgdGhpcy5yZW1vdmVNYXJrZXJzKCk7XHJcbiAgICAgICAgICB0aGlzLnJlbW92ZURpcmVjdGlvbnMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5kaXJlY3Rpb25EcmF3KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpIHtcclxuICAgIHRoaXMuZGVzdHJveU1hcmtlcnMoKTtcclxuICAgIHRoaXMucmVtb3ZlRGlyZWN0aW9ucygpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhpcyBldmVudCBpcyBmaXJlZCB3aGVuIHRoZSB1c2VyIGNyZWF0aW5nIG9yIHVwZGF0aW5nIHRoaXMgZGlyZWN0aW9uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBkaXJlY3Rpb25EcmF3KCkge1xyXG4gICAgdGhpcy5nbWFwc0FwaS5nZXROYXRpdmVNYXAoKS50aGVuKF9tYXAgPT4ge1xyXG5cclxuICAgICAgLy8gY29uc3QgbWFwID0gX21hcCBhcyB1bmtub3duIHwgZ29vZ2xlLm1hcHMuTWFwO1xyXG4gICAgICBjb25zdCBtYXAgPSBfbWFwO1xyXG5cclxuICAgICAgaWYgKHR5cGVvZiB0aGlzLmRpcmVjdGlvbnNSZW5kZXJlciA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICB0aGlzLmRpcmVjdGlvbnNSZW5kZXJlciA9IG5ldyBnb29nbGUubWFwcy5EaXJlY3Rpb25zUmVuZGVyZXIodGhpcy5yZW5kZXJPcHRpb25zKTtcclxuICAgICAgICAvLyBAdHMtaWdub3JlXHJcbiAgICAgICAgdGhpcy5kaXJlY3Rpb25zUmVuZGVyZXIuc2V0TWFwKG1hcCk7XHJcbiAgICAgICAgdGhpcy5kaXJlY3Rpb25zUmVuZGVyZXIuYWRkTGlzdGVuZXIoJ2RpcmVjdGlvbnNfY2hhbmdlZCcsICgpID0+IHtcclxuICAgICAgICAgIHRoaXMub25DaGFuZ2UuZW1pdCh0aGlzLmRpcmVjdGlvbnNSZW5kZXJlci5nZXREaXJlY3Rpb25zKCkpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAodHlwZW9mIHRoaXMuZGlyZWN0aW9uc1NlcnZpY2UgPT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgdGhpcy5kaXJlY3Rpb25zU2VydmljZSA9IG5ldyBnb29nbGUubWFwcy5EaXJlY3Rpb25zU2VydmljZSgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAodHlwZW9mIHRoaXMucGFuZWwgPT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxyXG4gICAgICAgIHRoaXMuZGlyZWN0aW9uc1JlbmRlcmVyLnNldFBhbmVsKG51bGwpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZGlyZWN0aW9uc1JlbmRlcmVyLnNldFBhbmVsKHRoaXMucGFuZWwgYXMgYW55KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gUmVuZGVyIGV4aXN0IGRpcmVjdGlvblxyXG4gICAgICBpZiAodGhpcy5yZW5kZXJSb3V0ZSkge1xyXG4gICAgICAgIHRoaXMuZGlyZWN0aW9uc1JlbmRlcmVyLnNldERpcmVjdGlvbnModGhpcy5yZW5kZXJSb3V0ZSk7XHJcbiAgICAgICAgdGhpcy5yZW5kZXJSb3V0ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgfSBlbHNlIHtcclxuXHJcbiAgICAgICAgLy8gUmVxdWVzdCBuZXcgZGlyZWN0aW9uXHJcbiAgICAgICAgdGhpcy5kaXJlY3Rpb25zU2VydmljZS5yb3V0ZSh7XHJcbiAgICAgICAgICBvcmlnaW46IHRoaXMub3JpZ2luLFxyXG4gICAgICAgICAgZGVzdGluYXRpb246IHRoaXMuZGVzdGluYXRpb24sXHJcbiAgICAgICAgICB0cmF2ZWxNb2RlOiB0aGlzLnRyYXZlbE1vZGUgfHwgZ29vZ2xlLm1hcHMuVHJhdmVsTW9kZS5EUklWSU5HLFxyXG4gICAgICAgICAgdHJhbnNpdE9wdGlvbnM6IHRoaXMudHJhbnNpdE9wdGlvbnMsXHJcbiAgICAgICAgICBkcml2aW5nT3B0aW9uczogdGhpcy5kcml2aW5nT3B0aW9ucyxcclxuICAgICAgICAgIHdheXBvaW50czogdGhpcy53YXlwb2ludHMsXHJcbiAgICAgICAgICBvcHRpbWl6ZVdheXBvaW50czogdGhpcy5vcHRpbWl6ZVdheXBvaW50cyxcclxuICAgICAgICAgIHByb3ZpZGVSb3V0ZUFsdGVybmF0aXZlczogdGhpcy5wcm92aWRlUm91dGVBbHRlcm5hdGl2ZXMsXHJcbiAgICAgICAgICBhdm9pZEhpZ2h3YXlzOiB0aGlzLmF2b2lkSGlnaHdheXMsXHJcbiAgICAgICAgICBhdm9pZFRvbGxzOiB0aGlzLmF2b2lkVG9sbHMsXHJcbiAgICAgICAgICBhdm9pZEZlcnJpZXM6IHRoaXMuYXZvaWRGZXJyaWVzLFxyXG4gICAgICAgICAgdW5pdFN5c3RlbTogdGhpcy51bml0U3lzdGVtLFxyXG4gICAgICAgIH0sIChyZXNwb25zZTogYW55LCBzdGF0dXMpID0+IHtcclxuXHJcbiAgICAgICAgICB0aGlzLm9uUmVzcG9uc2UuZW1pdChyZXNwb25zZSk7XHJcblxyXG4gICAgICAgICAgLy8gRW1pdCBRdWVyeSBTdGF0dXNcclxuICAgICAgICAgIHRoaXMuc3RhdHVzLmVtaXQoc3RhdHVzKTtcclxuXHJcbiAgICAgICAgICAvKipcclxuICAgICAgICAgICAqIERpcmVjdGlvbnNTdGF0dXNcclxuICAgICAgICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVycy5nb29nbGUuY29tL21hcHMvZG9jdW1lbnRhdGlvbi9qYXZhc2NyaXB0L2RpcmVjdGlvbnMjRGlyZWN0aW9uc1N0YXR1c1xyXG4gICAgICAgICAgICovXHJcbiAgICAgICAgICBzd2l0Y2ggKHN0YXR1cykge1xyXG4gICAgICAgICAgICBjYXNlIGdvb2dsZS5tYXBzLkRpcmVjdGlvbnNTdGF0dXMuT0s6XHJcblxyXG4gICAgICAgICAgICAgIHRoaXMuZGlyZWN0aW9uc1JlbmRlcmVyLnNldERpcmVjdGlvbnMocmVzcG9uc2UpO1xyXG5cclxuICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgKiBFbWl0IFRoZSBEaXJlY3Rpb25zUmVzdWx0IE9iamVjdFxyXG4gICAgICAgICAgICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVycy5nb29nbGUuY29tL21hcHMvZG9jdW1lbnRhdGlvbi9qYXZhc2NyaXB0L2RpcmVjdGlvbnM/aGw9ZW4jRGlyZWN0aW9uc1Jlc3VsdHNcclxuICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAvLyBDdXN0b20gTWFya2Vyc1xyXG4gICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5tYXJrZXJPcHRpb25zICE9PSAndW5kZWZpbmVkJykge1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveU1hcmtlcnMoKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBTZXQgY3VzdG9tIG1hcmtlcnNcclxuICAgICAgICAgICAgICAgIGNvbnN0IF9yb3V0ZSA9IHJlc3BvbnNlLnJvdXRlc1swXS5sZWdzWzBdO1xyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgLy8gT3JpZ2luIE1hcmtlclxyXG4gICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMubWFya2VyT3B0aW9ucy5vcmlnaW4gIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZXJPcHRpb25zLm9yaWdpbi5tYXAgPSBtYXA7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZXJPcHRpb25zLm9yaWdpbi5wb3NpdGlvbiA9IF9yb3V0ZS5zdGFydF9sb2NhdGlvbjtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9yaWdpbk1hcmtlciA9IHRoaXMuc2V0TWFya2VyKFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWFwLFxyXG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcmlnaW5NYXJrZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlck9wdGlvbnMub3JpZ2luLFxyXG4gICAgICAgICAgICAgICAgICAgICAgX3JvdXRlLnN0YXJ0X2FkZHJlc3MsXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubWFya2VyT3B0aW9ucy5vcmlnaW4uZHJhZ2dhYmxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9yaWdpbk1hcmtlci5hZGRMaXN0ZW5lcignZHJhZ2VuZCcsICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcmlnaW4gPSB0aGlzLm9yaWdpbk1hcmtlci5wb3NpdGlvbjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXJlY3Rpb25EcmF3KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3JpZ2luRHJhZy5lbWl0KHRoaXMub3JpZ2luKTtcclxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAvLyBEZXN0aW5hdGlvbiBNYXJrZXJcclxuICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm1hcmtlck9wdGlvbnMuZGVzdGluYXRpb24gIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZXJPcHRpb25zLmRlc3RpbmF0aW9uLm1hcCA9IG1hcDtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlck9wdGlvbnMuZGVzdGluYXRpb24ucG9zaXRpb24gPSBfcm91dGUuZW5kX2xvY2F0aW9uO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVzdGluYXRpb25NYXJrZXIgPSB0aGlzLnNldE1hcmtlcihcclxuICAgICAgICAgICAgICAgICAgICAgIG1hcCxcclxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVzdGluYXRpb25NYXJrZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlck9wdGlvbnMuZGVzdGluYXRpb24sXHJcbiAgICAgICAgICAgICAgICAgICAgICBfcm91dGUuZW5kX2FkZHJlc3MsXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5tYXJrZXJPcHRpb25zLmRlc3RpbmF0aW9uLmRyYWdnYWJsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZXN0aW5hdGlvbk1hcmtlci5hZGRMaXN0ZW5lcignZHJhZ2VuZCcsICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZXN0aW5hdGlvbiA9IHRoaXMuZGVzdGluYXRpb25NYXJrZXIucG9zaXRpb247XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGlyZWN0aW9uRHJhdygpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc3RpbmF0aW9uRHJhZy5lbWl0KHRoaXMuZGVzdGluYXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAvLyBXYXlwb2ludHMgTWFya2VyXHJcbiAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5tYXJrZXJPcHRpb25zLndheXBvaW50cyAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53YXlwb2ludHMuZm9yRWFjaCgod2F5cG9pbnQsIGluZGV4KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2F5cG9pbnRzIGFyZSBub3QgYXJyYXkgdGhlbiBzZXQgYWxsIHRoZSBzYW1lXHJcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5tYXJrZXJPcHRpb25zLndheXBvaW50cykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZXJPcHRpb25zLndheXBvaW50cyEubWFwID0gbWFwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlck9wdGlvbnMud2F5cG9pbnRzIS5wb3NpdGlvbiA9IF9yb3V0ZS52aWFfd2F5cG9pbnRzW2luZGV4XTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53YXlwb2ludHNNYXJrZXIucHVzaCh0aGlzLnNldE1hcmtlcihcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd2F5cG9pbnQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZXJPcHRpb25zLndheXBvaW50cyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBfcm91dGUudmlhX3dheXBvaW50c1tpbmRleF0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZXJPcHRpb25zLndheXBvaW50c1tpbmRleF0ubWFwID0gbWFwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlck9wdGlvbnMud2F5cG9pbnRzW2luZGV4XS5wb3NpdGlvbiA9IF9yb3V0ZS52aWFfd2F5cG9pbnRzW2luZGV4XTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53YXlwb2ludHNNYXJrZXIucHVzaCh0aGlzLnNldE1hcmtlcihcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd2F5cG9pbnQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZXJPcHRpb25zLndheXBvaW50c1tpbmRleF0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgX3JvdXRlLnZpYV93YXlwb2ludHNbaW5kZXhdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApKTtcclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7IC8vIEVuZCBmb3JFYWNoXHJcblxyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWFya2VyT3B0aW9ucyBlcnJvci4nLCBlcnIpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICBjYXNlIGdvb2dsZS5tYXBzLkRpcmVjdGlvbnNTdGF0dXMuT1ZFUl9RVUVSWV9MSU1JVDpcclxuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1RoZSB3ZWJwYWdlIGhhcyBzZW50IHRvbyBtYW55IHJlcXVlc3RzIHdpdGhpbiB0aGUgYWxsb3dlZCB0aW1lIHBlcmlvZC4nKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAvLyBjb25zb2xlLndhcm4oc3RhdHVzKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIH0gLy8gRW5kIHN3aXRjaFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEN1c3RvbSBPcmlnaW4gYW5kIERlc3RpbmF0aW9uIEljb25cclxuICAgKiBAcGFyYW0gbWFwIG1hcFxyXG4gICAqIEBwYXJhbSBtYXJrZXIgbWFya2VyXHJcbiAgICogQHBhcmFtIG1hcmtlck9wdHMgcHJvcGVydGllc1xyXG4gICAqIEBwYXJhbSBjb250ZW50IG1hcmtlcidzIGluZm93aW5kb3cgY29udGVudFxyXG4gICAqIEByZXR1cm5zIG5ldyBtYXJrZXJcclxuICAgKiBAbWVtYmVyb2YgQWdtRGlyZWN0aW9uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBzZXRNYXJrZXIoXHJcbiAgICBtYXA6IGdvb2dsZS5tYXBzLk1hcCxcclxuICAgIG1hcmtlcjogZ29vZ2xlLm1hcHMuTWFya2VyIHwgZ29vZ2xlLm1hcHMuRGlyZWN0aW9uc1dheXBvaW50LFxyXG4gICAgbWFya2VyT3B0czogYW55LFxyXG4gICAgY29udGVudDogZ29vZ2xlLm1hcHMuTGF0TG5nIHwgc3RyaW5nXHJcbiAgKTogZ29vZ2xlLm1hcHMuTWFya2VyIHtcclxuICAgIGlmICh0eXBlb2YgdGhpcy5pbmZvV2luZG93ID09PSAndW5kZWZpbmVkJykge1xyXG4gICAgICB0aGlzLmluZm9XaW5kb3cgPSBuZXcgZ29vZ2xlLm1hcHMuSW5mb1dpbmRvdygpO1xyXG4gICAgICB0aGlzLnNlbmRJbmZvV2luZG93LmVtaXQodGhpcy5pbmZvV2luZG93KTtcclxuICAgIH1cclxuXHJcbiAgICBtYXJrZXIgPSBuZXcgZ29vZ2xlLm1hcHMuTWFya2VyKG1hcmtlck9wdHMpO1xyXG4gICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vbWFwcy9kb2N1bWVudGF0aW9uL2phdmFzY3JpcHQvcmVmZXJlbmNlL21hcmtlcj9obD16aC10dyNNYXJrZXJPcHRpb25zLmNsaWNrYWJsZVxyXG4gICAgaWYgKG1hcmtlci5nZXRDbGlja2FibGUoKSkge1xyXG4gICAgICBtYXJrZXIuYWRkTGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGluZm93aW5kb0NvbnRlbnQ6IHN0cmluZyA9IHR5cGVvZiBtYXJrZXJPcHRzLmluZm9XaW5kb3cgPT09ICd1bmRlZmluZWQnID8gY29udGVudCA6IG1hcmtlck9wdHMuaW5mb1dpbmRvdztcclxuICAgICAgICB0aGlzLmluZm9XaW5kb3cuc2V0Q29udGVudChpbmZvd2luZG9Db250ZW50KTtcclxuICAgICAgICB0aGlzLmluZm9XaW5kb3cub3BlbihtYXAsIG1hcmtlciBhcyBnb29nbGUubWFwcy5NVkNPYmplY3QpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIHJldHVybiBtYXJrZXI7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gcmVtb3ZlIG1hcmtlcnNcclxuICAgKi9cclxuICBwcml2YXRlIHJlbW92ZU1hcmtlcnMoKTogdm9pZCB7XHJcbiAgICBpZiAodHlwZW9mIHRoaXMub3JpZ2luTWFya2VyICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICB0aGlzLm9yaWdpbk1hcmtlci5zZXRNYXAobnVsbCk7XHJcbiAgICB9XHJcbiAgICBpZiAodHlwZW9mIHRoaXMuZGVzdGluYXRpb25NYXJrZXIgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgIHRoaXMuZGVzdGluYXRpb25NYXJrZXIuc2V0TWFwKG51bGwpO1xyXG4gICAgfVxyXG4gICAgdGhpcy53YXlwb2ludHNNYXJrZXIuZm9yRWFjaCgodzogYW55KSA9PiB7XHJcbiAgICAgIGlmICh0eXBlb2YgdyAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICB3LnNldE1hcChudWxsKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gcmVtb3ZlIGRpcmVjdGlvbnNcclxuICAgKi9cclxuICBwcml2YXRlIHJlbW92ZURpcmVjdGlvbnMoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5kaXJlY3Rpb25zUmVuZGVyZXIgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAvLyBAdHMtaWdub3JlXHJcbiAgICAgIHRoaXMuZGlyZWN0aW9uc1JlbmRlcmVyLnNldFBhbmVsKG51bGwpO1xyXG4gICAgICB0aGlzLmRpcmVjdGlvbnNSZW5kZXJlci5zZXRNYXAobnVsbCk7XHJcbiAgICAgIC8vIEB0cy1pZ25vcmVcclxuICAgICAgdGhpcy5kaXJlY3Rpb25zUmVuZGVyZXIgPSB1bmRlZmluZWQ7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gZGVzdHJveSBtYXJrZXJzXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBkZXN0cm95TWFya2VycygpOiB2b2lkIHtcclxuICAgIC8vIFJlbW92ZSBvcmlnaW4gbWFya2Vyc1xyXG4gICAgdHJ5IHtcclxuICAgICAgaWYgKHR5cGVvZiB0aGlzLm9yaWdpbk1hcmtlciAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICBnb29nbGUubWFwcy5ldmVudC5jbGVhckxpc3RlbmVycyh0aGlzLm9yaWdpbk1hcmtlciwgJ2NsaWNrJyk7XHJcbiAgICAgICAgaWYgKHRoaXMubWFya2VyT3B0aW9ucy5vcmlnaW4uZHJhZ2dhYmxlKSB7XHJcbiAgICAgICAgICBnb29nbGUubWFwcy5ldmVudC5jbGVhckxpc3RlbmVycyh0aGlzLm9yaWdpbk1hcmtlciwgJ2RyYWdlbmQnKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHR5cGVvZiB0aGlzLmRlc3RpbmF0aW9uTWFya2VyICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICAgIGdvb2dsZS5tYXBzLmV2ZW50LmNsZWFyTGlzdGVuZXJzKHRoaXMuZGVzdGluYXRpb25NYXJrZXIsICdjbGljaycpO1xyXG4gICAgICAgIGlmICh0aGlzLm1hcmtlck9wdGlvbnMub3JpZ2luLmRyYWdnYWJsZSkge1xyXG4gICAgICAgICAgZ29vZ2xlLm1hcHMuZXZlbnQuY2xlYXJMaXN0ZW5lcnModGhpcy5kZXN0aW5hdGlvbk1hcmtlciwgJ2RyYWdlbmQnKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy53YXlwb2ludHNNYXJrZXIuZm9yRWFjaCgodzogYW55KSA9PiB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiB3ICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICAgICAgZ29vZ2xlLm1hcHMuZXZlbnQuY2xlYXJMaXN0ZW5lcnModywgJ2NsaWNrJyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgICAgdGhpcy5yZW1vdmVNYXJrZXJzKCk7XHJcblxyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0NhbiBub3QgcmVzZXQgY3VzdG9tIG1hcmtlci4nLCBlcnIpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0=