@codebakery/origami
Version:
Angular + Polymer
404 lines • 48.4 kB
JavaScript
import { __decorate, __extends, __param } from "tslib";
import { AfterViewInit, Directive, ElementRef, HostListener, Inject, Injector, Input, OnDestroy, Optional, Provider, Renderer2, forwardRef } from '@angular/core';
import { COMPOSITION_BUFFER_MODE, DefaultValueAccessor, NG_VALUE_ACCESSOR, NgControl, Validators } from '@angular/forms';
/**
* OrigamiControlValueAccessor provider.
*/
export var ORIGAMI_CONTROL_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return OrigamiControlValueAccessor; }),
multi: true
};
/**
* A value accessor for `ngModel`, `formControl`, and `formControlName`, on
* custom elements. In addition to one of the above directives, `origami`
* should be added to the element to denote that this value accessor should
* control it.
*
* Example: `<paper-input [(ngModel)]="value" origami></paper-input>`
*
* The connected element should implement one of the below
* properties:
*
* - `checked` as a boolean for checkbox-like elements.
* - `selected` for single selectable elements. It must be an index or string
* name attribute.
* - `selectedItem` for single selectable elements. It may be any type.
* - `selectedValues` for multi selectable elements. It must be an array of
* indices or string name attributes.
* - `selectedItems` for multi selectable elements. It must be an array of any
* type.
* - `value` for any basic form element. It may be any type.
*
* For selectable and multi selectable elements, the attribute `useKey` should
* be specified if the control bindings an index or name value to the element
* instead of an object.
*
* Additionally, an element may implement one or more of the following
* properties:
*
* - `disabled` as a boolean
* - `invalid` as a boolean to indicate validity
* - `validate()` as a function to run custom validation
*
* To listen for changes to these events, an element should implement one or
* more of the following events to notify Angular of any updates.
*
* - `input` - will update any of the above properties
* - `blur`
* - `checked-changed`
* - `selected-changed`
* - `selected-item-changed`
* - `selected-values-changed`
* - `selected-items-changed`
* - `value-changed`
* - `invalid-changed`
*/
var OrigamiControlValueAccessor = /** @class */ (function (_super) {
__extends(OrigamiControlValueAccessor, _super);
function OrigamiControlValueAccessor(elementRef, injector, renderer, compositionMode) {
var _this = _super.call(this, renderer, elementRef, compositionMode) || this;
_this.elementRef = elementRef;
_this.injector = injector;
_this.renderer = renderer;
/**
* The key to use when reporting that an element's `validate()` function
* returns false. When this happens, the control's `errors` object will be
* set with this key and a value of true.
*
* The default key is "validate".
*/
_this.validationErrorsKey = 'validate';
/**
* Most custom elements property will emit a `property-changed` event when
* their value is set. This flag informs the value accessor to ignore the
* next event while it is in the middle of writing a value.
*/
_this.isWritingValue = false;
/**
* Flag that informs the value accessor that it is currently updating an
* element and should ignore additional `invalid` property changes until it is
* complete.
*/
_this.ignoreInvalidChanges = false;
return _this;
}
Object.defineProperty(OrigamiControlValueAccessor.prototype, "control", {
/**
* The `AbstractControl` attached to this element.
*/
get: function () {
if (!this._control) {
this._control = this.injector.get(NgControl).control;
}
return this._control;
},
enumerable: true,
configurable: true
});
/**
* Lifecycle callback that will connect an element's validatable properties
* (if they are implemented) to the Angular control.
*/
OrigamiControlValueAccessor.prototype.ngAfterViewInit = function () {
var _this = this;
var element = this.elementRef.nativeElement;
if (this.isValidatable(element)) {
// The control will always be set by ngAfterViewInit due to the nature of
// the directive's selectors
var control_1 = this.control;
// Allows Angular validators to update the custom element's validity
this.statusSub = control_1.statusChanges.subscribe(function () {
if (typeof _this.isInvalid === 'function') {
element.invalid = _this.isInvalid(control_1);
}
else {
element.invalid = !!control_1.invalid && !!control_1.dirty;
}
});
// Allows custom element validate function to update Angular control's
// validity
if (this.shouldUseValidate(element)) {
control_1.setValidators(Validators.compose([
control_1.validator,
function () {
var _a;
if (element.validate()) {
return null;
}
else {
return _a = {}, _a[_this.validationErrorsKey] = true, _a;
}
}
]));
}
}
};
/**
* Lifecycle callback to clean up subscriptions.
*/
OrigamiControlValueAccessor.prototype.ngOnDestroy = function () {
if (this.statusSub) {
this.statusSub.unsubscribe();
}
};
/**
* Writes a value to a custom element's correct value property, based on what
* kind of element the directive controls.
*
* @param value the value to write
*/
OrigamiControlValueAccessor.prototype.writeValue = function (value) {
this.isWritingValue = true;
var element = this.elementRef.nativeElement;
if (this.isMultiSelectable(element) || this.isSelectable(element)) {
var property = this.getSelectableProperty(element, value);
if (property) {
element[property] = value;
}
}
else if (this.isCheckedElement(element)) {
element.checked = Boolean(value);
}
else {
_super.prototype.writeValue.call(this, value);
}
this.isWritingValue = false;
};
/**
* Listen for custom element events and notify Angular of any changes.
*
* @param event the change event
*/
OrigamiControlValueAccessor.prototype.onChangedEvent = function (event) {
if (!this.isWritingValue) {
var element = this.elementRef.nativeElement;
var changed = false;
switch (event.type) {
case 'selected-items-changed':
case 'selected-item-changed': {
var property = this.getSelectableProperty(element);
changed = property === 'selectedItems' || property === 'selectedItem';
break;
}
case 'selected-values-changed':
case 'selected-changed': {
var property = this.getSelectableProperty(element);
changed = property === 'selectedValues' || property === 'selected';
break;
}
default:
changed = true;
}
if (changed) {
var property = void 0;
if (this.isMultiSelectable(element) || this.isSelectable(element)) {
// property will be defined if we reach this since changed can only
// be true if the property is defined for selectable elements
property = this.getSelectableProperty(element);
}
else if (this.isCheckedElement(element)) {
property = 'checked';
}
else {
property = 'value';
}
// Don't use `event.detail.value`, since we cannot assume that all
// change events will provide that. Additionally, some event details
// may be splices of an array or object instead of the current value.
this.onChange(element[property]);
}
}
};
/**
* Listen for `invalid` property changes. Some elements, such as
* `<vaadin-date-picker>` have multiple "values". Setting the primary value
* (ex. the date string) may result in a temporarily invalid element until
* subsequent values (ex. the selected date) have been updated.
*
* Since this value accessor only listens for value changes, it may not be
* notified of the change in validity. This listener will listen for any
* explicity validity changes from the element and re-evaluate a control's
* validity if it and the element's validity are out of sync.
*/
OrigamiControlValueAccessor.prototype.onInvalidChanged = function () {
if (!this.ignoreInvalidChanges) {
var element = this.elementRef.nativeElement;
if (this.isValidatable(element) &&
this.control &&
this.control.invalid !== element.invalid) {
this.ignoreInvalidChanges = true;
this.control.updateValueAndValidity();
this.ignoreInvalidChanges = false;
}
}
};
/**
* Determines whether or not an element is checkbox-like.
*
* @param element the element to check
*/
OrigamiControlValueAccessor.prototype.isCheckedElement = function (element) {
return this.isPropertyDefined(element, 'checked');
};
/**
* Determines whether or not an element is selectable-like.
*
* @param element the element to check
*/
OrigamiControlValueAccessor.prototype.isSelectable = function (element) {
return (this.isPropertyDefined(element, 'selected') ||
this.isPropertyDefined(element, 'selectedItem'));
};
/**
* Determines whether or not an element is multi selectable-like.
*
* @param element the element to check
*/
OrigamiControlValueAccessor.prototype.isMultiSelectable = function (element) {
if (element &&
(this.isPropertyDefined(element, 'selectedValues') ||
this.isPropertyDefined(element, 'selectedItems'))) {
return this.isSelectable(element) ? element.multi === true : true;
}
else {
return false;
}
};
/**
* Determines whether or not an element is validatable-like.
*
* @param element the element to check
*/
OrigamiControlValueAccessor.prototype.isValidatable = function (element) {
return this.isPropertyDefined(element, 'invalid');
};
OrigamiControlValueAccessor.prototype.shouldUseValidate = function (element) {
if (typeof element.validate === 'function') {
// Some element's (such as `<vaadin-text-field>`) may not actually mutate
// the `invalid` property when `validate()` is called. In these
// situations, it's possible for Angular to set an element as invalid and
// never be able to recover since the element's `validate()` will always
// report it is invalid.
//
// In these situations, Origami should ignore the element's validate()
// function.
this.ignoreInvalidChanges = true;
var wasInvalid = element.invalid;
// If the element does mutate `invalid`, ask it to do so first to get a
// baseline.
element.validate();
// When `validate()` is called next, we will know if the element mutates
// `invalid` if the expected value matches `invalid` after changing
// `invalid` to something else.
var expected = element.invalid;
element.invalid = !element.invalid;
element.validate();
var validateMutatesInvalid = element.invalid === expected;
element.invalid = wasInvalid;
this.ignoreInvalidChanges = false;
return validateMutatesInvalid;
}
else {
return false;
}
};
/**
* Determines whether or not a property is defined anywhere in the provided
* element's prototype chain.
*
* @param element the element to check
* @param property the property to check for
*/
OrigamiControlValueAccessor.prototype.isPropertyDefined = function (element, property) {
return !!element && property in element;
};
/**
* Retrieves the property name of the selectable or multi-selectable element
* that should be updated. This method will use defined properties and the
* value type to determine which property should be used. If it cannot
* determine which property to use, it will return undefined.
*
* @param element the element to get the property for
* @param value a value for the element's property
* @returns the property name, or undefined if it cannot be determined
*/
OrigamiControlValueAccessor.prototype.getSelectableProperty = function (element, value) {
var isMulti = this.isMultiSelectable(element);
var valueProp = isMulti ? 'selectedItems' : 'selectedItem';
var indexProp = isMulti ? 'selectedValues' : 'selected';
if (typeof this.useSelectableValueProp !== 'boolean') {
// Determine whether we should be setting the index or value property for
// a selectable element
var hasValueProp = valueProp in element;
var hasIndexProp = indexProp in element;
if (hasValueProp && !hasIndexProp) {
this.useSelectableValueProp = true;
}
else if (!hasValueProp && hasIndexProp) {
this.useSelectableValueProp = false;
}
else if (typeof value !== 'undefined' && value !== null) {
var previousValue = element[valueProp];
// When the element has both properties, try to set it to the value
// property first. If it fails, then use the index property
try {
element[valueProp] = value;
}
catch (error) {
// Could throw if the value is an unexpected type
}
// Check to see if the value we set it to is still accurate. If it's
// not then the element silently rejected the new value.
this.useSelectableValueProp = element[valueProp] === value;
element[valueProp] = previousValue;
}
else {
return undefined;
}
}
if (element.itemValuePath) {
// <vaadin-combo-box> will want to use selectedItem for object values.
// However, if `itemValuePath` is set then the control value is not the
// item itself, but the `value` property.
return 'value';
}
else {
return this.useSelectableValueProp ? valueProp : indexProp;
}
};
OrigamiControlValueAccessor.ctorParameters = function () { return [
{ type: ElementRef },
{ type: Injector },
{ type: Renderer2 },
{ type: Boolean, decorators: [{ type: Optional }, { type: Inject, args: [COMPOSITION_BUFFER_MODE,] }] }
]; };
__decorate([
Input()
], OrigamiControlValueAccessor.prototype, "isInvalid", void 0);
__decorate([
Input()
], OrigamiControlValueAccessor.prototype, "validationErrorsKey", void 0);
__decorate([
HostListener('selected-items-changed', ['$event']),
HostListener('selected-item-changed', ['$event']),
HostListener('selected-values-changed', ['$event']),
HostListener('selected-changed', ['$event']),
HostListener('checked-changed', ['$event']),
HostListener('value-changed', ['$event'])
], OrigamiControlValueAccessor.prototype, "onChangedEvent", null);
__decorate([
HostListener('invalid-changed')
], OrigamiControlValueAccessor.prototype, "onInvalidChanged", null);
OrigamiControlValueAccessor = __decorate([
Directive({
selector: '[ngModel][origami],[formControlName][origami],[formControl][origami]',
providers: [ORIGAMI_CONTROL_VALUE_ACCESSOR]
}),
__param(3, Optional()),
__param(3, Inject(COMPOSITION_BUFFER_MODE))
], OrigamiControlValueAccessor);
return OrigamiControlValueAccessor;
}(DefaultValueAccessor));
export { OrigamiControlValueAccessor };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsdWUtYWNjZXNzb3IuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AY29kZWJha2VyeS9vcmlnYW1pL2Zvcm1zLyIsInNvdXJjZXMiOlsic3JjL3ZhbHVlLWFjY2Vzc29yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsYUFBYSxFQUNiLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixRQUFRLEVBQ1IsS0FBSyxFQUNMLFNBQVMsRUFDVCxRQUFRLEVBQ1IsUUFBUSxFQUNSLFNBQVMsRUFDVCxVQUFVLEVBQ1gsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixvQkFBb0IsRUFDcEIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxVQUFVLEVBRVgsTUFBTSxnQkFBZ0IsQ0FBQztBQW1DeEI7O0dBRUc7QUFDSCxNQUFNLENBQUMsSUFBTSw4QkFBOEIsR0FBYTtJQUN0RCxPQUFPLEVBQUUsaUJBQWlCO0lBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsY0FBTSxPQUFBLDJCQUEyQixFQUEzQixDQUEyQixDQUFDO0lBQzFELEtBQUssRUFBRSxJQUFJO0NBQ1osQ0FBQztBQUVGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRDRztBQU1IO0lBQWlELCtDQUFvQjtJQXlEbkUscUNBQ1MsVUFBc0IsRUFDbkIsUUFBa0IsRUFDbEIsUUFBbUIsRUFHN0IsZUFBd0I7UUFOMUIsWUFRRSxrQkFBTSxRQUFRLEVBQUUsVUFBVSxFQUFFLGVBQWUsQ0FBQyxTQUM3QztRQVJRLGdCQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ25CLGNBQVEsR0FBUixRQUFRLENBQVU7UUFDbEIsY0FBUSxHQUFSLFFBQVEsQ0FBVztRQW5EL0I7Ozs7OztXQU1HO1FBRUgseUJBQW1CLEdBQUcsVUFBVSxDQUFDO1FBaUJqQzs7OztXQUlHO1FBQ0ssb0JBQWMsR0FBRyxLQUFLLENBQUM7UUFDL0I7Ozs7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LENBQUMsaUJBQWlCLENBQUM7dUVBYy9CO0lBdk5VLDJCQUEyQjtRQUx2QyxTQUFTLENBQUM7WUFDVCxRQUFRLEVBQ04sc0VBQXNFO1lBQ3hFLFNBQVMsRUFBRSxDQUFDLDhCQUE4QixDQUFDO1NBQzVDLENBQUM7UUE4REcsV0FBQSxRQUFRLEVBQUUsQ0FBQTtRQUNWLFdBQUEsTUFBTSxDQUFDLHVCQUF1QixDQUFDLENBQUE7T0E5RHZCLDJCQUEyQixDQW9XdkM7SUFBRCxrQ0FBQztDQUFBLEFBcFdELENBQWlELG9CQUFvQixHQW9XcEU7U0FwV1ksMkJBQTJCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBIb3N0TGlzdGVuZXIsXG4gIEluamVjdCxcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9wdGlvbmFsLFxuICBQcm92aWRlcixcbiAgUmVuZGVyZXIyLFxuICBmb3J3YXJkUmVmXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQ09NUE9TSVRJT05fQlVGRkVSX01PREUsXG4gIERlZmF1bHRWYWx1ZUFjY2Vzc29yLFxuICBOR19WQUxVRV9BQ0NFU1NPUixcbiAgTmdDb250cm9sLFxuICBWYWxpZGF0b3JzLFxuICBBYnN0cmFjdENvbnRyb2xcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG4vKipcbiAqIEFuIGludGVyZmFjZSBmb3IgZGV0ZXJtaW5pbmcgaWYgYW4gZWxlbWVudCBpcyBhIGNoZWNrYm94LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENoZWNrZWRFbGVtZW50TGlrZSB7XG4gIGNoZWNrZWQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEFuIGludGVyZmFjZSBmb3IgZGV0ZXJtaW5pbmcgaWYgYW4gZWxlbWVudCBpcyBzZWxlY3RhYmxlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlbGVjdGFibGVMaWtlIHtcbiAgbXVsdGk/OiBib29sZWFuO1xuICBzZWxlY3RlZD86IHN0cmluZyB8IG51bWJlcjtcbiAgc2VsZWN0ZWRJdGVtPzogYW55O1xufVxuXG4vKipcbiAqIEFuIGludGVyZmFjZSBmb3IgZGV0ZXJtaW5pbmcgaWYgYW4gZWxlbWVudCBpcyBtdWx0aSBzZWxlY3RhYmxlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE11bHRpU2VsZWN0YWJsZUxpa2Uge1xuICBtdWx0aT86IGJvb2xlYW47XG4gIHNlbGVjdGVkVmFsdWVzPzogQXJyYXk8c3RyaW5nIHwgbnVtYmVyPjtcbiAgc2VsZWN0ZWRJdGVtcz86IGFueVtdO1xufVxuXG4vKipcbiAqIEFuIGludGVyZmFjZSBmb3IgZGV0ZXJtaW5pbmcgaWYgYW4gZWxlbWVudCBpcyB2YWxpZGF0YWJsZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0YWJsZUxpa2Uge1xuICBpbnZhbGlkPzogYm9vbGVhbjtcbiAgdmFsaWRhdGU/KCk6IHZvaWQ7XG59XG5cbi8qKlxuICogT3JpZ2FtaUNvbnRyb2xWYWx1ZUFjY2Vzc29yIHByb3ZpZGVyLlxuICovXG5leHBvcnQgY29uc3QgT1JJR0FNSV9DT05UUk9MX1ZBTFVFX0FDQ0VTU09SOiBQcm92aWRlciA9IHtcbiAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE9yaWdhbWlDb250cm9sVmFsdWVBY2Nlc3NvciksXG4gIG11bHRpOiB0cnVlXG59O1xuXG4vKipcbiAqIEEgdmFsdWUgYWNjZXNzb3IgZm9yIGBuZ01vZGVsYCwgYGZvcm1Db250cm9sYCwgYW5kIGBmb3JtQ29udHJvbE5hbWVgLCBvblxuICogY3VzdG9tIGVsZW1lbnRzLiBJbiBhZGRpdGlvbiB0byBvbmUgb2YgdGhlIGFib3ZlIGRpcmVjdGl2ZXMsIGBvcmlnYW1pYFxuICogc2hvdWxkIGJlIGFkZGVkIHRvIHRoZSBlbGVtZW50IHRvIGRlbm90ZSB0aGF0IHRoaXMgdmFsdWUgYWNjZXNzb3Igc2hvdWxkXG4gKiBjb250cm9sIGl0LlxuICpcbiAqIEV4YW1wbGU6IGA8cGFwZXItaW5wdXQgWyhuZ01vZGVsKV09XCJ2YWx1ZVwiIG9yaWdhbWk+PC9wYXBlci1pbnB1dD5gXG4gKlxuICogVGhlIGNvbm5lY3RlZCBlbGVtZW50IHNob3VsZCBpbXBsZW1lbnQgb25lIG9mIHRoZSBiZWxvd1xuICogcHJvcGVydGllczpcbiAqXG4gKiAtIGBjaGVja2VkYCBhcyBhIGJvb2xlYW4gZm9yIGNoZWNrYm94LWxpa2UgZWxlbWVudHMuXG4gKiAtIGBzZWxlY3RlZGAgZm9yIHNpbmdsZSBzZWxlY3RhYmxlIGVsZW1lbnRzLiBJdCBtdXN0IGJlIGFuIGluZGV4IG9yIHN0cmluZ1xuICogICBuYW1lIGF0dHJpYnV0ZS5cbiAqIC0gYHNlbGVjdGVkSXRlbWAgZm9yIHNpbmdsZSBzZWxlY3RhYmxlIGVsZW1lbnRzLiBJdCBtYXkgYmUgYW55IHR5cGUuXG4gKiAtIGBzZWxlY3RlZFZhbHVlc2AgZm9yIG11bHRpIHNlbGVjdGFibGUgZWxlbWVudHMuIEl0IG11c3QgYmUgYW4gYXJyYXkgb2ZcbiAqICAgaW5kaWNlcyBvciBzdHJpbmcgbmFtZSBhdHRyaWJ1dGVzLlxuICogLSBgc2VsZWN0ZWRJdGVtc2AgZm9yIG11bHRpIHNlbGVjdGFibGUgZWxlbWVudHMuIEl0IG11c3QgYmUgYW4gYXJyYXkgb2YgYW55XG4gKiAgIHR5cGUuXG4gKiAtIGB2YWx1ZWAgZm9yIGFueSBiYXNpYyBmb3JtIGVsZW1lbnQuIEl0IG1heSBiZSBhbnkgdHlwZS5cbiAqXG4gKiBGb3Igc2VsZWN0YWJsZSBhbmQgbXVsdGkgc2VsZWN0YWJsZSBlbGVtZW50cywgdGhlIGF0dHJpYnV0ZSBgdXNlS2V5YCBzaG91bGRcbiAqIGJlIHNwZWNpZmllZCBpZiB0aGUgY29udHJvbCBiaW5kaW5ncyBhbiBpbmRleCBvciBuYW1lIHZhbHVlIHRvIHRoZSBlbGVtZW50XG4gKiBpbnN0ZWFkIG9mIGFuIG9iamVjdC5cbiAqXG4gKiBBZGRpdGlvbmFsbHksIGFuIGVsZW1lbnQgbWF5IGltcGxlbWVudCBvbmUgb3IgbW9yZSBvZiB0aGUgZm9sbG93aW5nXG4gKiBwcm9wZXJ0aWVzOlxuICpcbiAqIC0gYGRpc2FibGVkYCBhcyBhIGJvb2xlYW5cbiAqIC0gYGludmFsaWRgIGFzIGEgYm9vbGVhbiB0byBpbmRpY2F0ZSB2YWxpZGl0eVxuICogLSBgdmFsaWRhdGUoKWAgYXMgYSBmdW5jdGlvbiB0byBydW4gY3VzdG9tIHZhbGlkYXRpb25cbiAqXG4gKiBUbyBsaXN0ZW4gZm9yIGNoYW5nZXMgdG8gdGhlc2UgZXZlbnRzLCBhbiBlbGVtZW50IHNob3VsZCBpbXBsZW1lbnQgb25lIG9yXG4gKiBtb3JlIG9mIHRoZSBmb2xsb3dpbmcgZXZlbnRzIHRvIG5vdGlmeSBBbmd1bGFyIG9mIGFueSB1cGRhdGVzLlxuICpcbiAqIC0gYGlucHV0YCAtIHdpbGwgdXBkYXRlIGFueSBvZiB0aGUgYWJvdmUgcHJvcGVydGllc1xuICogLSBgYmx1cmBcbiAqIC0gYGNoZWNrZWQtY2hhbmdlZGBcbiAqIC0gYHNlbGVjdGVkLWNoYW5nZWRgXG4gKiAtIGBzZWxlY3RlZC1pdGVtLWNoYW5nZWRgXG4gKiAtIGBzZWxlY3RlZC12YWx1ZXMtY2hhbmdlZGBcbiAqIC0gYHNlbGVjdGVkLWl0ZW1zLWNoYW5nZWRgXG4gKiAtIGB2YWx1ZS1jaGFuZ2VkYFxuICogLSBgaW52YWxpZC1jaGFuZ2VkYFxuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6XG4gICAgJ1tuZ01vZGVsXVtvcmlnYW1pXSxbZm9ybUNvbnRyb2xOYW1lXVtvcmlnYW1pXSxbZm9ybUNvbnRyb2xdW29yaWdhbWldJyxcbiAgcHJvdmlkZXJzOiBbT1JJR0FNSV9DT05UUk9MX1ZBTFVFX0FDQ0VTU09SXVxufSlcbmV4cG9ydCBjbGFzcyBPcmlnYW1pQ29udHJvbFZhbHVlQWNjZXNzb3IgZXh0ZW5kcyBEZWZhdWx0VmFsdWVBY2Nlc3NvclxuICBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBPdmVycmlkZXMgdGhlIGxvZ2ljIHRvIGRldGVybWluZSB3aGF0IHRvIHNldCBhbiBlbGVtZW50J3MgYGludmFsaWRgXG4gICAqIHByb3BlcnR5IHRvIGdpdmVuIHRoZSBwcm92aWRlZCBgQWJzdHJhY3RDb250cm9sYC4gVGhlIGRlZmF1bHQgaXMgdG8gc2V0IHRoZVxuICAgKiBlbGVtZW50IGFzIGBpbnZhbGlkYCB3aGVuZXZlciB0aGUgY29udHJvbCBpcyBib3RoIGludmFsaWQgYW5kIGRpcnR5LlxuICAgKi9cbiAgQElucHV0KClcbiAgaXNJbnZhbGlkPzogKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkgPT4gYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBrZXkgdG8gdXNlIHdoZW4gcmVwb3J0aW5nIHRoYXQgYW4gZWxlbWVudCdzIGB2YWxpZGF0ZSgpYCBmdW5jdGlvblxuICAgKiByZXR1cm5zIGZhbHNlLiBXaGVuIHRoaXMgaGFwcGVucywgdGhlIGNvbnRyb2wncyBgZXJyb3JzYCBvYmplY3Qgd2lsbCBiZVxuICAgKiBzZXQgd2l0aCB0aGlzIGtleSBhbmQgYSB2YWx1ZSBvZiB0cnVlLlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCBrZXkgaXMgXCJ2YWxpZGF0ZVwiLlxuICAgKi9cbiAgQElucHV0KClcbiAgdmFsaWRhdGlvbkVycm9yc0tleSA9ICd2YWxpZGF0ZSc7XG5cbiAgLyoqXG4gICAqIFRoZSBgQWJzdHJhY3RDb250cm9sYCBhdHRhY2hlZCB0byB0aGlzIGVsZW1lbnQuXG4gICAqL1xuICBnZXQgY29udHJvbCgpOiBBYnN0cmFjdENvbnRyb2wgfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5fY29udHJvbCkge1xuICAgICAgdGhpcy5fY29udHJvbCA9ICg8TmdDb250cm9sPnRoaXMuaW5qZWN0b3IuZ2V0KE5nQ29udHJvbCkpLmNvbnRyb2whO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9jb250cm9sO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1YnNjcmlwdGlvbiB0byB0aGUgTmdDb250cm9sJ3Mgc3RhdHVzQ2hhbmdlcy5cbiAgICovXG4gIHByb3RlY3RlZCBzdGF0dXNTdWI/OiB7IHVuc3Vic2NyaWJlKCk6IHZvaWQgfTtcbiAgLyoqXG4gICAqIE1vc3QgY3VzdG9tIGVsZW1lbnRzIHByb3BlcnR5IHdpbGwgZW1pdCBhIGBwcm9wZXJ0eS1jaGFuZ2VkYCBldmVudCB3aGVuXG4gICAqIHRoZWlyIHZhbHVlIGlzIHNldC4gVGhpcyBmbGFnIGluZm9ybXMgdGhlIHZhbHVlIGFjY2Vzc29yIHRvIGlnbm9yZSB0aGVcbiAgICogbmV4dCBldmVudCB3aGlsZSBpdCBpcyBpbiB0aGUgbWlkZGxlIG9mIHdyaXRpbmcgYSB2YWx1ZS5cbiAgICovXG4gIHByaXZhdGUgaXNXcml0aW5nVmFsdWUgPSBmYWxzZTtcbiAgLyoqXG4gICAqIEZsYWcgdGhhdCBpbmZvcm1zIHRoZSB2YWx1ZSBhY2Nlc3NvciB0aGF0IGl0IGlzIGN1cnJlbnRseSB1cGRhdGluZyBhblxuICAgKiBlbGVtZW50IGFuZCBzaG91bGQgaWdub3JlIGFkZGl0aW9uYWwgYGludmFsaWRgIHByb3BlcnR5IGNoYW5nZXMgdW50aWwgaXQgaXNcbiAgICogY29tcGxldGUuXG4gICAqL1xuICBwcml2YXRlIGlnbm9yZUludmFsaWRDaGFuZ2VzID0gZmFsc2U7XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciBvciBub3QgdG8gdXNlIHRoZSB2YWx1ZSBwcm9wZXJ0eSBvciBpbmRleCBwcm9wZXJ0eSBmb3IgYVxuICAgKiBzZWxlY3Qgb3IgbXVsaXQtc2VsZWN0IGVsZW1lbnQuIFdoZW4gdW5kZWZpbmVkLCBpdCBpbmRpY2F0ZXMgdGhhdCB0aGVcbiAgICogZGV0ZXJtaW5hdGlvbiBvZiB3aGljaCBwcm9wZXJ0eSB0byB1c2UgaGFzIG5vdCBvY2N1cnJlZCB5ZXQuXG4gICAqL1xuICBwcml2YXRlIHVzZVNlbGVjdGFibGVWYWx1ZVByb3A/OiBib29sZWFuO1xuICAvKipcbiAgICogQ2FjaGVkIGBjb250cm9sYCB2YWx1ZS5cbiAgICovXG4gIHByaXZhdGUgX2NvbnRyb2w6IEFic3RyYWN0Q29udHJvbCB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBwcm90ZWN0ZWQgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByb3RlY3RlZCByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIEBPcHRpb25hbCgpXG4gICAgQEluamVjdChDT01QT1NJVElPTl9CVUZGRVJfTU9ERSlcbiAgICBjb21wb3NpdGlvbk1vZGU6IGJvb2xlYW5cbiAgKSB7XG4gICAgc3VwZXIocmVuZGVyZXIsIGVsZW1lbnRSZWYsIGNvbXBvc2l0aW9uTW9kZSk7XG4gIH1cblxuICAvKipcbiAgICogTGlmZWN5Y2xlIGNhbGxiYWNrIHRoYXQgd2lsbCBjb25uZWN0IGFuIGVsZW1lbnQncyB2YWxpZGF0YWJsZSBwcm9wZXJ0aWVzXG4gICAqIChpZiB0aGV5IGFyZSBpbXBsZW1lbnRlZCkgdG8gdGhlIEFuZ3VsYXIgY29udHJvbC5cbiAgICovXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKHRoaXMuaXNWYWxpZGF0YWJsZShlbGVtZW50KSkge1xuICAgICAgLy8gVGhlIGNvbnRyb2wgd2lsbCBhbHdheXMgYmUgc2V0IGJ5IG5nQWZ0ZXJWaWV3SW5pdCBkdWUgdG8gdGhlIG5hdHVyZSBvZlxuICAgICAgLy8gdGhlIGRpcmVjdGl2ZSdzIHNlbGVjdG9yc1xuICAgICAgY29uc3QgY29udHJvbCA9IHRoaXMuY29udHJvbCE7XG4gICAgICAvLyBBbGxvd3MgQW5ndWxhciB2YWxpZGF0b3JzIHRvIHVwZGF0ZSB0aGUgY3VzdG9tIGVsZW1lbnQncyB2YWxpZGl0eVxuICAgICAgdGhpcy5zdGF0dXNTdWIgPSBjb250cm9sLnN0YXR1c0NoYW5nZXMhLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5pc0ludmFsaWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICBlbGVtZW50LmludmFsaWQgPSB0aGlzLmlzSW52YWxpZChjb250cm9sKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbGVtZW50LmludmFsaWQgPSAhIWNvbnRyb2wuaW52YWxpZCAmJiAhIWNvbnRyb2wuZGlydHk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBBbGxvd3MgY3VzdG9tIGVsZW1lbnQgdmFsaWRhdGUgZnVuY3Rpb24gdG8gdXBkYXRlIEFuZ3VsYXIgY29udHJvbCdzXG4gICAgICAvLyB2YWxpZGl0eVxuICAgICAgaWYgKHRoaXMuc2hvdWxkVXNlVmFsaWRhdGUoZWxlbWVudCkpIHtcbiAgICAgICAgY29udHJvbC5zZXRWYWxpZGF0b3JzKFxuICAgICAgICAgIFZhbGlkYXRvcnMuY29tcG9zZShbXG4gICAgICAgICAgICBjb250cm9sLnZhbGlkYXRvcixcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGVsZW1lbnQudmFsaWRhdGUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IFt0aGlzLnZhbGlkYXRpb25FcnJvcnNLZXldOiB0cnVlIH07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICBdKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMaWZlY3ljbGUgY2FsbGJhY2sgdG8gY2xlYW4gdXAgc3Vic2NyaXB0aW9ucy5cbiAgICovXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGlmICh0aGlzLnN0YXR1c1N1Yikge1xuICAgICAgdGhpcy5zdGF0dXNTdWIudW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogV3JpdGVzIGEgdmFsdWUgdG8gYSBjdXN0b20gZWxlbWVudCdzIGNvcnJlY3QgdmFsdWUgcHJvcGVydHksIGJhc2VkIG9uIHdoYXRcbiAgICoga2luZCBvZiBlbGVtZW50IHRoZSBkaXJlY3RpdmUgY29udHJvbHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSB0aGUgdmFsdWUgdG8gd3JpdGVcbiAgICovXG4gIHdyaXRlVmFsdWUodmFsdWU6IGFueSkge1xuICAgIHRoaXMuaXNXcml0aW5nVmFsdWUgPSB0cnVlO1xuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICBpZiAodGhpcy5pc011bHRpU2VsZWN0YWJsZShlbGVtZW50KSB8fCB0aGlzLmlzU2VsZWN0YWJsZShlbGVtZW50KSkge1xuICAgICAgY29uc3QgcHJvcGVydHkgPSB0aGlzLmdldFNlbGVjdGFibGVQcm9wZXJ0eShlbGVtZW50LCB2YWx1ZSk7XG4gICAgICBpZiAocHJvcGVydHkpIHtcbiAgICAgICAgKDxhbnk+ZWxlbWVudClbcHJvcGVydHldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aGlzLmlzQ2hlY2tlZEVsZW1lbnQoZWxlbWVudCkpIHtcbiAgICAgIGVsZW1lbnQuY2hlY2tlZCA9IEJvb2xlYW4odmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdXBlci53cml0ZVZhbHVlKHZhbHVlKTtcbiAgICB9XG5cbiAgICB0aGlzLmlzV3JpdGluZ1ZhbHVlID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogTGlzdGVuIGZvciBjdXN0b20gZWxlbWVudCBldmVudHMgYW5kIG5vdGlmeSBBbmd1bGFyIG9mIGFueSBjaGFuZ2VzLlxuICAgKlxuICAgKiBAcGFyYW0gZXZlbnQgdGhlIGNoYW5nZSBldmVudFxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignc2VsZWN0ZWQtaXRlbXMtY2hhbmdlZCcsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ3NlbGVjdGVkLWl0ZW0tY2hhbmdlZCcsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ3NlbGVjdGVkLXZhbHVlcy1jaGFuZ2VkJywgWyckZXZlbnQnXSlcbiAgQEhvc3RMaXN0ZW5lcignc2VsZWN0ZWQtY2hhbmdlZCcsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ2NoZWNrZWQtY2hhbmdlZCcsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ3ZhbHVlLWNoYW5nZWQnLCBbJyRldmVudCddKVxuICBvbkNoYW5nZWRFdmVudChldmVudDogRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuaXNXcml0aW5nVmFsdWUpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICAgIGxldCBjaGFuZ2VkID0gZmFsc2U7XG4gICAgICBzd2l0Y2ggKGV2ZW50LnR5cGUpIHtcbiAgICAgICAgY2FzZSAnc2VsZWN0ZWQtaXRlbXMtY2hhbmdlZCc6XG4gICAgICAgIGNhc2UgJ3NlbGVjdGVkLWl0ZW0tY2hhbmdlZCc6IHtcbiAgICAgICAgICBjb25zdCBwcm9wZXJ0eSA9IHRoaXMuZ2V0U2VsZWN0YWJsZVByb3BlcnR5KGVsZW1lbnQpO1xuICAgICAgICAgIGNoYW5nZWQgPSBwcm9wZXJ0eSA9PT0gJ3NlbGVjdGVkSXRlbXMnIHx8IHByb3BlcnR5ID09PSAnc2VsZWN0ZWRJdGVtJztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdzZWxlY3RlZC12YWx1ZXMtY2hhbmdlZCc6XG4gICAgICAgIGNhc2UgJ3NlbGVjdGVkLWNoYW5nZWQnOiB7XG4gICAgICAgICAgY29uc3QgcHJvcGVydHkgPSB0aGlzLmdldFNlbGVjdGFibGVQcm9wZXJ0eShlbGVtZW50KTtcbiAgICAgICAgICBjaGFuZ2VkID0gcHJvcGVydHkgPT09ICdzZWxlY3RlZFZhbHVlcycgfHwgcHJvcGVydHkgPT09ICdzZWxlY3RlZCc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYW5nZWQpIHtcbiAgICAgICAgbGV0IHByb3BlcnR5OiBzdHJpbmc7XG4gICAgICAgIGlmICh0aGlzLmlzTXVsdGlTZWxlY3RhYmxlKGVsZW1lbnQpIHx8IHRoaXMuaXNTZWxlY3RhYmxlKGVsZW1lbnQpKSB7XG4gICAgICAgICAgLy8gcHJvcGVydHkgd2lsbCBiZSBkZWZpbmVkIGlmIHdlIHJlYWNoIHRoaXMgc2luY2UgY2hhbmdlZCBjYW4gb25seVxuICAgICAgICAgIC8vIGJlIHRydWUgaWYgdGhlIHByb3BlcnR5IGlzIGRlZmluZWQgZm9yIHNlbGVjdGFibGUgZWxlbWVudHNcbiAgICAgICAgICBwcm9wZXJ0eSA9IHRoaXMuZ2V0U2VsZWN0YWJsZVByb3BlcnR5KGVsZW1lbnQpITtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmlzQ2hlY2tlZEVsZW1lbnQoZWxlbWVudCkpIHtcbiAgICAgICAgICBwcm9wZXJ0eSA9ICdjaGVja2VkJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwcm9wZXJ0eSA9ICd2YWx1ZSc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEb24ndCB1c2UgYGV2ZW50LmRldGFpbC52YWx1ZWAsIHNpbmNlIHdlIGNhbm5vdCBhc3N1bWUgdGhhdCBhbGxcbiAgICAgICAgLy8gY2hhbmdlIGV2ZW50cyB3aWxsIHByb3ZpZGUgdGhhdC4gQWRkaXRpb25hbGx5LCBzb21lIGV2ZW50IGRldGFpbHNcbiAgICAgICAgLy8gbWF5IGJlIHNwbGljZXMgb2YgYW4gYXJyYXkgb3Igb2JqZWN0IGluc3RlYWQgb2YgdGhlIGN1cnJlbnQgdmFsdWUuXG4gICAgICAgIHRoaXMub25DaGFuZ2UoZWxlbWVudFtwcm9wZXJ0eV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0ZW4gZm9yIGBpbnZhbGlkYCBwcm9wZXJ0eSBjaGFuZ2VzLiBTb21lIGVsZW1lbnRzLCBzdWNoIGFzXG4gICAqIGA8dmFhZGluLWRhdGUtcGlja2VyPmAgaGF2ZSBtdWx0aXBsZSBcInZhbHVlc1wiLiBTZXR0aW5nIHRoZSBwcmltYXJ5IHZhbHVlXG4gICAqIChleC4gdGhlIGRhdGUgc3RyaW5nKSBtYXkgcmVzdWx0IGluIGEgdGVtcG9yYXJpbHkgaW52YWxpZCBlbGVtZW50IHVudGlsXG4gICAqIHN1YnNlcXVlbnQgdmFsdWVzIChleC4gdGhlIHNlbGVjdGVkIGRhdGUpIGhhdmUgYmVlbiB1cGRhdGVkLlxuICAgKlxuICAgKiBTaW5jZSB0aGlzIHZhbHVlIGFjY2Vzc29yIG9ubHkgbGlzdGVucyBmb3IgdmFsdWUgY2hhbmdlcywgaXQgbWF5IG5vdCBiZVxuICAgKiBub3RpZmllZCBvZiB0aGUgY2hhbmdlIGluIHZhbGlkaXR5LiBUaGlzIGxpc3RlbmVyIHdpbGwgbGlzdGVuIGZvciBhbnlcbiAgICogZXhwbGljaXR5IHZhbGlkaXR5IGNoYW5nZXMgZnJvbSB0aGUgZWxlbWVudCBhbmQgcmUtZXZhbHVhdGUgYSBjb250cm9sJ3NcbiAgICogdmFsaWRpdHkgaWYgaXQgYW5kIHRoZSBlbGVtZW50J3MgdmFsaWRpdHkgYXJlIG91dCBvZiBzeW5jLlxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignaW52YWxpZC1jaGFuZ2VkJylcbiAgb25JbnZhbGlkQ2hhbmdlZCgpIHtcbiAgICBpZiAoIXRoaXMuaWdub3JlSW52YWxpZENoYW5nZXMpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5pc1ZhbGlkYXRhYmxlKGVsZW1lbnQpICYmXG4gICAgICAgIHRoaXMuY29udHJvbCAmJlxuICAgICAgICB0aGlzLmNvbnRyb2wuaW52YWxpZCAhPT0gZWxlbWVudC5pbnZhbGlkXG4gICAgICApIHtcbiAgICAgICAgdGhpcy5pZ25vcmVJbnZhbGlkQ2hhbmdlcyA9IHRydWU7XG4gICAgICAgIHRoaXMuY29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XG4gICAgICAgIHRoaXMuaWdub3JlSW52YWxpZENoYW5nZXMgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIG9yIG5vdCBhbiBlbGVtZW50IGlzIGNoZWNrYm94LWxpa2UuXG4gICAqXG4gICAqIEBwYXJhbSBlbGVtZW50IHRoZSBlbGVtZW50IHRvIGNoZWNrXG4gICAqL1xuICBpc0NoZWNrZWRFbGVtZW50KGVsZW1lbnQ6IGFueSk6IGVsZW1lbnQgaXMgQ2hlY2tlZEVsZW1lbnRMaWtlIHtcbiAgICByZXR1cm4gdGhpcy5pc1Byb3BlcnR5RGVmaW5lZChlbGVtZW50LCAnY2hlY2tlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciBvciBub3QgYW4gZWxlbWVudCBpcyBzZWxlY3RhYmxlLWxpa2UuXG4gICAqXG4gICAqIEBwYXJhbSBlbGVtZW50IHRoZSBlbGVtZW50IHRvIGNoZWNrXG4gICAqL1xuICBpc1NlbGVjdGFibGUoZWxlbWVudDogYW55KTogZWxlbWVudCBpcyBTZWxlY3RhYmxlTGlrZSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuaXNQcm9wZXJ0eURlZmluZWQoZWxlbWVudCwgJ3NlbGVjdGVkJykgfHxcbiAgICAgIHRoaXMuaXNQcm9wZXJ0eURlZmluZWQoZWxlbWVudCwgJ3NlbGVjdGVkSXRlbScpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgb3Igbm90IGFuIGVsZW1lbnQgaXMgbXVsdGkgc2VsZWN0YWJsZS1saWtlLlxuICAgKlxuICAgKiBAcGFyYW0gZWxlbWVudCB0aGUgZWxlbWVudCB0byBjaGVja1xuICAgKi9cbiAgaXNNdWx0aVNlbGVjdGFibGUoZWxlbWVudDogYW55KTogZWxlbWVudCBpcyBNdWx0aVNlbGVjdGFibGVMaWtlIHtcbiAgICBpZiAoXG4gICAgICBlbGVtZW50ICYmXG4gICAgICAodGhpcy5pc1Byb3BlcnR5RGVmaW5lZChlbGVtZW50LCAnc2VsZWN0ZWRWYWx1ZXMnKSB8fFxuICAgICAgICB0aGlzLmlzUHJvcGVydHlEZWZpbmVkKGVsZW1lbnQsICdzZWxlY3RlZEl0ZW1zJykpXG4gICAgKSB7XG4gICAgICByZXR1cm4gdGhpcy5pc1NlbGVjdGFibGUoZWxlbWVudCkgPyBlbGVtZW50Lm11bHRpID09PSB0cnVlIDogdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgb3Igbm90IGFuIGVsZW1lbnQgaXMgdmFsaWRhdGFibGUtbGlrZS5cbiAgICpcbiAgICogQHBhcmFtIGVsZW1lbnQgdGhlIGVsZW1lbnQgdG8gY2hlY2tcbiAgICovXG4gIGlzVmFsaWRhdGFibGUoZWxlbWVudDogYW55KTogZWxlbWVudCBpcyBWYWxpZGF0YWJsZUxpa2Uge1xuICAgIHJldHVybiB0aGlzLmlzUHJvcGVydHlEZWZpbmVkKGVsZW1lbnQsICdpbnZhbGlkJyk7XG4gIH1cblxuICBzaG91bGRVc2VWYWxpZGF0ZShlbGVtZW50OiBhbnkpOiBlbGVtZW50IGlzIHsgdmFsaWRhdGUoKTogYm9vbGVhbiB9IHtcbiAgICBpZiAodHlwZW9mIGVsZW1lbnQudmFsaWRhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIC8vIFNvbWUgZWxlbWVudCdzIChzdWNoIGFzIGA8dmFhZGluLXRleHQtZmllbGQ+YCkgbWF5IG5vdCBhY3R1YWxseSBtdXRhdGVcbiAgICAgIC8vIHRoZSBgaW52YWxpZGAgcHJvcGVydHkgd2hlbiBgdmFsaWRhdGUoKWAgaXMgY2FsbGVkLiBJbiB0aGVzZVxuICAgICAgLy8gc2l0dWF0aW9ucywgaXQncyBwb3NzaWJsZSBmb3IgQW5ndWxhciB0byBzZXQgYW4gZWxlbWVudCBhcyBpbnZhbGlkIGFuZFxuICAgICAgLy8gbmV2ZXIgYmUgYWJsZSB0byByZWNvdmVyIHNpbmNlIHRoZSBlbGVtZW50J3MgYHZhbGlkYXRlKClgIHdpbGwgYWx3YXlzXG4gICAgICAvLyByZXBvcnQgaXQgaXMgaW52YWxpZC5cbiAgICAgIC8vXG4gICAgICAvLyBJbiB0aGVzZSBzaXR1YXRpb25zLCBPcmlnYW1pIHNob3VsZCBpZ25vcmUgdGhlIGVsZW1lbnQncyB2YWxpZGF0ZSgpXG4gICAgICAvLyBmdW5jdGlvbi5cbiAgICAgIHRoaXMuaWdub3JlSW52YWxpZENoYW5nZXMgPSB0cnVlO1xuICAgICAgY29uc3Qgd2FzSW52YWxpZCA9IGVsZW1lbnQuaW52YWxpZDtcbiAgICAgIC8vIElmIHRoZSBlbGVtZW50IGRvZXMgbXV0YXRlIGBpbnZhbGlkYCwgYXNrIGl0IHRvIGRvIHNvIGZpcnN0IHRvIGdldCBhXG4gICAgICAvLyBiYXNlbGluZS5cbiAgICAgIGVsZW1lbnQudmFsaWRhdGUoKTtcbiAgICAgIC8vIFdoZW4gYHZhbGlkYXRlKClgIGlzIGNhbGxlZCBuZXh0LCB3ZSB3aWxsIGtub3cgaWYgdGhlIGVsZW1lbnQgbXV0YXRlc1xuICAgICAgLy8gYGludmFsaWRgIGlmIHRoZSBleHBlY3RlZCB2YWx1ZSBtYXRjaGVzIGBpbnZhbGlkYCBhZnRlciBjaGFuZ2luZ1xuICAgICAgLy8gYGludmFsaWRgIHRvIHNvbWV0aGluZyBlbHNlLlxuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBlbGVtZW50LmludmFsaWQ7XG4gICAgICBlbGVtZW50LmludmFsaWQgPSAhZWxlbWVudC5pbnZhbGlkO1xuICAgICAgZWxlbWVudC52YWxpZGF0ZSgpO1xuICAgICAgY29uc3QgdmFsaWRhdGVNdXRhdGVzSW52YWxpZCA9IGVsZW1lbnQuaW52YWxpZCA9PT0gZXhwZWN0ZWQ7XG4gICAgICBlbGVtZW50LmludmFsaWQgPSB3YXNJbnZhbGlkO1xuICAgICAgdGhpcy5pZ25vcmVJbnZhbGlkQ2hhbmdlcyA9IGZhbHNlO1xuICAgICAgcmV0dXJuIHZhbGlkYXRlTXV0YXRlc0ludmFsaWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIG9yIG5vdCBhIHByb3BlcnR5IGlzIGRlZmluZWQgYW55d2hlcmUgaW4gdGhlIHByb3ZpZGVkXG4gICAqIGVsZW1lbnQncyBwcm90b3R5cGUgY2hhaW4uXG4gICAqXG4gICAqIEBwYXJhbSBlbGVtZW50IHRoZSBlbGVtZW50IHRvIGNoZWNrXG4gICAqIEBwYXJhbSBwcm9wZXJ0eSB0aGUgcHJvcGVydHkgdG8gY2hlY2sgZm9yXG4gICAqL1xuICBwcml2YXRlIGlzUHJvcGVydHlEZWZpbmVkKGVsZW1lbnQ6IGFueSwgcHJvcGVydHk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIWVsZW1lbnQgJiYgcHJvcGVydHkgaW4gZWxlbWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHByb3BlcnR5IG5hbWUgb2YgdGhlIHNlbGVjdGFibGUgb3IgbXVsdGktc2VsZWN0YWJsZSBlbGVtZW50XG4gICAqIHRoYXQgc2hvdWxkIGJlIHVwZGF0ZWQuIFRoaXMgbWV0aG9kIHdpbGwgdXNlIGRlZmluZWQgcHJvcGVydGllcyBhbmQgdGhlXG4gICAqIHZhbHVlIHR5cGUgdG8gZGV0ZXJtaW5lIHdoaWNoIHByb3BlcnR5IHNob3VsZCBiZSB1c2VkLiBJZiBpdCBjYW5ub3RcbiAgICogZGV0ZXJtaW5lIHdoaWNoIHByb3BlcnR5IHRvIHVzZSwgaXQgd2lsbCByZXR1cm4gdW5kZWZpbmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZWxlbWVudCB0aGUgZWxlbWVudCB0byBnZXQgdGhlIHByb3BlcnR5IGZvclxuICAgKiBAcGFyYW0gdmFsdWUgYSB2YWx1ZSBmb3IgdGhlIGVsZW1lbnQncyBwcm9wZXJ0eVxuICAgKiBAcmV0dXJucyB0aGUgcHJvcGVydHkgbmFtZSwgb3IgdW5kZWZpbmVkIGlmIGl0IGNhbm5vdCBiZSBkZXRlcm1pbmVkXG4gICAqL1xuICBwcml2YXRlIGdldFNlbGVjdGFibGVQcm9wZXJ0eShlbGVtZW50OiBhbnksIHZhbHVlPzogYW55KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBpc011bHRpID0gdGhpcy5pc011bHRpU2VsZWN0YWJsZShlbGVtZW50KTtcbiAgICBjb25zdCB2YWx1ZVByb3AgPSBpc011bHRpID8gJ3NlbGVjdGVkSXRlbXMnIDogJ3NlbGVjdGVkSXRlbSc7XG4gICAgY29uc3QgaW5kZXhQcm9wID0gaXNNdWx0aSA/ICdzZWxlY3RlZFZhbHVlcycgOiAnc2VsZWN0ZWQnO1xuICAgIGlmICh0eXBlb2YgdGhpcy51c2VTZWxlY3RhYmxlVmFsdWVQcm9wICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIC8vIERldGVybWluZSB3aGV0aGVyIHdlIHNob3VsZCBiZSBzZXR0aW5nIHRoZSBpbmRleCBvciB2YWx1ZSBwcm9wZXJ0eSBmb3JcbiAgICAgIC8vIGEgc2VsZWN0YWJsZSBlbGVtZW50XG4gICAgICBjb25zdCBoYXNWYWx1ZVByb3AgPSB2YWx1ZVByb3AgaW4gZWxlbWVudDtcbiAgICAgIGNvbnN0IGhhc0luZGV4UHJvcCA9IGluZGV4UHJvcCBpbiBlbGVtZW50O1xuICAgICAgaWYgKGhhc1ZhbHVlUHJvcCAmJiAhaGFzSW5kZXhQcm9wKSB7XG4gICAgICAgIHRoaXMudXNlU2VsZWN0YWJsZVZhbHVlUHJvcCA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKCFoYXNWYWx1ZVByb3AgJiYgaGFzSW5kZXhQcm9wKSB7XG4gICAgICAgIHRoaXMudXNlU2VsZWN0YWJsZVZhbHVlUHJvcCA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnICYmIHZhbHVlICE9PSBudWxsKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzVmFsdWUgPSBlbGVtZW50W3ZhbHVlUHJvcF07XG4gICAgICAgIC8vIFdoZW4gdGhlIGVsZW1lbnQgaGFzIGJvdGggcHJvcGVydGllcywgdHJ5IHRvIHNldCBpdCB0byB0aGUgdmFsdWVcbiAgICAgICAgLy8gcHJvcGVydHkgZmlyc3QuIElmIGl0IGZhaWxzLCB0aGVuIHVzZSB0aGUgaW5kZXggcHJvcGVydHlcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBlbGVtZW50W3ZhbHVlUHJvcF0gPSB2YWx1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAvLyBDb3VsZCB0aHJvdyBpZiB0aGUgdmFsdWUgaXMgYW4gdW5leHBlY3RlZCB0eXBlXG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0byBzZWUgaWYgdGhlIHZhbHVlIHdlIHNldCBpdCB0byBpcyBzdGlsbCBhY2N1cmF0ZS4gSWYgaXQnc1xuICAgICAgICAvLyBub3QgdGhlbiB0aGUgZWxlbWVudCBzaWxlbnRseSByZWplY3RlZCB0aGUgbmV3IHZhbHVlLlxuICAgICAgICB0aGlzLnVzZVNlbGVjdGFibGVWYWx1ZVByb3AgPSBlbGVtZW50W3ZhbHVlUHJvcF0gPT09IHZhbHVlO1xuICAgICAgICBlbGVtZW50W3ZhbHVlUHJvcF0gPSBwcmV2aW91c1ZhbHVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudC5pdGVtVmFsdWVQYXRoKSB7XG4gICAgICAvLyA8dmFhZGluLWNvbWJvLWJveD4gd2lsbCB3YW50IHRvIHVzZSBzZWxlY3RlZEl0ZW0gZm9yIG9iamVjdCB2YWx1ZXMuXG4gICAgICAvLyBIb3dldmVyLCBpZiBgaXRlbVZhbHVlUGF0aGAgaXMgc2V0IHRoZW4gdGhlIGNvbnRyb2wgdmFsdWUgaXMgbm90IHRoZVxuICAgICAgLy8gaXRlbSBpdHNlbGYsIGJ1dCB0aGUgYHZhbHVlYCBwcm9wZXJ0eS5cbiAgICAgIHJldHVybiAndmFsdWUnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy51c2VTZWxlY3RhYmxlVmFsdWVQcm9wID8gdmFsdWVQcm9wIDogaW5kZXhQcm9wO1xuICAgIH1cbiAgfVxufVxuIl19