UNPKG

angular-odata

Version:

Client side OData typescript library for Angular

1,227 lines 177 kB
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
import { CID_FIELD_NAME, COMPUTED, DEFAULT_VERSION, OPTIMISTIC_CONCURRENCY, EVENT_SPLITTER, } from '../constants';
import { ODataHelper } from '../helper';
import { ODataEntityResource, ODataEntitySetResource, ODataNavigationPropertyResource, ODataPropertyResource, } from '../resources';
import { EdmType } from '../types';
import { Objects, Types } from '../utils';
import { ODataCollection } from './collection';
import { ODataModel } from './model';
import { EventEmitter } from '@angular/core';
import { ODataEntityAnnotations, } from '../annotations';
export var ODataModelEventType;
(function (ODataModelEventType) {
    ODataModelEventType["Change"] = "change";
    ODataModelEventType["Reset"] = "reset";
    ODataModelEventType["Update"] = "update";
    ODataModelEventType["Sort"] = "sort";
    ODataModelEventType["Destroy"] = "destroy";
    ODataModelEventType["Add"] = "add";
    ODataModelEventType["Remove"] = "remove";
    ODataModelEventType["Invalid"] = "invalid";
    ODataModelEventType["Request"] = "request";
    ODataModelEventType["Sync"] = "sync";
    ODataModelEventType["Attach"] = "attach";
})(ODataModelEventType || (ODataModelEventType = {}));
export class ODataModelEvent {
    type;
    value;
    previous;
    options;
    constructor(type, { model, collection, previous, value, attr, options, bubbles, chain, } = {}) {
        this.type = type;
        this.model = model;
        this.collection = collection;
        this.previous = previous;
        this.value = value;
        this.options = options;
        this.chain = chain ?? [
            [
                (this.model || this.collection),
                attr || null,
            ],
        ];
        this.bubbles = bubbles ?? BUBBLES.indexOf(this.type) !== -1;
    }
    chain;
    push(model, attr) {
        return new ODataModelEvent(this.type, {
            model: this.model ?? (model instanceof ODataModel ? model : undefined),
            collection: this.collection ??
                (model instanceof ODataCollection
                    ? model
                    : undefined),
            previous: this.previous,
            value: this.value,
            options: {
                ...this.options,
                index: attr instanceof ODataModelAttribute ? attr.name : attr,
            },
            bubbles: this.bubbles,
            chain: [[model, attr], ...this.chain],
        });
    }
    bubbles;
    stopPropagation() {
        this.bubbles = false;
    }
    visited(model) {
        return (this.chain.some((c) => c[0] === model) &&
            this.chain[this.chain.length - 1][0] !== model);
    }
    canContinueWith(self) {
        return this.bubbles && !this.visited(self);
    }
    get path() {
        return this.chain
            .map(([, attr], index) => typeof attr === 'number'
            ? `[${attr}]`
            : attr instanceof ODataModelAttribute
                ? index === 0
                    ? attr.name
                    : `.${attr.name}`
                : '')
            .join('');
    }
    //Reference to the model which the event was dispatched
    model;
    //Identifies the current model for the event
    get currentModel() {
        const link = this.chain.find((c) => ODataModelOptions.isModel(c[0]));
        return link !== undefined ? link[0] : undefined;
    }
    //Reference to the collection which the event was dispatched
    collection;
    //Identifies the current collection for the event
    get currentCollection() {
        const link = this.chain.find((c) => ODataModelOptions.isCollection(c[0]));
        return link !== undefined
            ? link[0]
            : undefined;
    }
}
export class ODataModelEventEmitter extends EventEmitter {
    model;
    collection;
    constructor({ model, collection, } = {}) {
        super();
        this.model = model;
        this.collection = collection;
    }
    trigger(type, { collection, previous, value, attr, options, bubbles, } = {}) {
        const _trigger = (name) => this.emit(new ODataModelEvent(name, {
            model: this.model,
            collection: collection ?? this.collection,
            previous,
            value,
            attr,
            options,
            bubbles,
        }));
        if (type && EVENT_SPLITTER.test(type)) {
            for (const name of type.split(EVENT_SPLITTER)) {
                _trigger(name);
            }
        }
        else {
            _trigger(type);
        }
    }
}
export const BUBBLES = [
    ODataModelEventType.Change,
    ODataModelEventType.Reset,
    ODataModelEventType.Update,
    ODataModelEventType.Destroy,
    ODataModelEventType.Add,
    ODataModelEventType.Remove,
];
export const INCLUDE_SHALLOW = {
    include_concurrency: true,
    include_computed: true,
    include_key: true,
    include_id: false,
};
export const INCLUDE_DEEP = {
    include_navigation: true,
    include_non_field: true,
    ...INCLUDE_SHALLOW,
};
export var ODataModelState;
(function (ODataModelState) {
    ODataModelState[ODataModelState["Added"] = 0] = "Added";
    ODataModelState[ODataModelState["Removed"] = 1] = "Removed";
    ODataModelState[ODataModelState["Changed"] = 2] = "Changed";
    ODataModelState[ODataModelState["Unchanged"] = 3] = "Unchanged";
})(ODataModelState || (ODataModelState = {}));
export function Model({ cid = CID_FIELD_NAME } = {}) {
    return (constructor) => {
        const Klass = constructor;
        if (!Klass.hasOwnProperty('options'))
            Klass.options = {
                fields: new Map(),
            };
        Klass.options.cid = cid;
        return constructor;
    };
}
export function ModelField({ name, ...options } = {}) {
    return (target, key) => {
        const Klass = target.constructor;
        if (!Klass.hasOwnProperty('options'))
            Klass.options = {
                fields: new Map(),
            };
        options.field = name ?? key;
        Klass.options.fields.set(key, options);
    };
}
export class ODataModelField {
    name;
    field;
    parser;
    options;
    optionsForType;
    modelForType;
    collectionForType;
    enumForType;
    structuredForType;
    default;
    required;
    concurrency;
    maxLength;
    minLength;
    min;
    max;
    pattern;
    parserOptions;
    constructor(options, { name, field, parser, ...opts }) {
        this.options = options;
        this.name = name;
        this.field = field;
        this.parser = parser;
        this.default = opts.default || parser.default;
        this.required = Boolean(opts.required || !parser.nullable);
        this.concurrency = Boolean(opts.concurrency);
        this.maxLength = opts.maxLength || parser.maxLength;
        this.minLength = opts.minLength;
        this.min = opts.min;
        this.max = opts.max;
        this.pattern = opts.pattern;
    }
    get type() {
        return this.parser.type;
    }
    get navigation() {
        return this.parser.navigation;
    }
    get collection() {
        return this.parser.collection;
    }
    annotatedValue(term) {
        return this.parser.annotatedValue(term);
    }
    configure({ optionsForType, modelForType, collectionForType, enumForType, structuredForType, concurrency, options, }) {
        this.optionsForType = optionsForType;
        this.modelForType = modelForType;
        this.collectionForType = collectionForType;
        this.enumForType = enumForType;
        this.structuredForType = structuredForType;
        this.parserOptions = options;
        if (concurrency)
            this.concurrency = concurrency;
        if (this.default !== undefined)
            this.default = this.deserialize(this.default, options);
    }
    isKey() {
        return this.parser.isKey();
    }
    hasReferentials() {
        return this.parser.hasReferentials();
    }
    get referentials() {
        return this.parser.referentials;
    }
    isStructuredType() {
        return this.parser.isStructuredType();
    }
    structuredType() {
        const structuredType = this.structuredForType
            ? this.structuredForType(this.type)
            : undefined;
        //Throw error if not found
        if (!structuredType)
            throw new Error(`Could not find structured type for ${this.parser.type}`);
        return structuredType;
    }
    isEnumType() {
        return this.parser.isEnumType();
    }
    enumType() {
        const enumType = this.enumForType ? this.enumForType(this.type) : undefined;
        //Throw error if not found
        if (!enumType)
            throw new Error(`Could not find enum type for ${this.parser.type}`);
        return enumType;
    }
    validate(value, { method, navigation = false, } = {}) {
        if (ODataModelOptions.isModel(value)) {
            return !value.isValid({ method, navigation }) ? value._errors : undefined;
        }
        else if (ODataModelOptions.isCollection(value)) {
            return value
                .models()
                .some((m) => !m.isValid({ method, navigation }))
                ? value.models().map((m) => m._errors)
                : undefined;
        }
        else {
            const computed = this.annotatedValue(COMPUTED);
            const errors = this.parser?.validate(value, { method, navigation }) || [];
            if (this.required &&
                (value === null || (value === undefined && method !== 'modify')) && // Is null or undefined without patch?
                !(computed && method === 'create') // Not (Is Computed field and create) ?
            ) {
                errors['push'](`required`);
            }
            if (this.maxLength !== undefined &&
                typeof value === 'string' &&
                value.length > this.maxLength) {
                errors['push'](`maxlength`);
            }
            if (this.minLength !== undefined &&
                typeof value === 'string' &&
                value.length < this.minLength) {
                errors['push'](`minlength`);
            }
            if (this.min !== undefined &&
                typeof value === 'number' &&
                value < this.min) {
                errors['push'](`min`);
            }
            if (this.max !== undefined &&
                typeof value === 'number' &&
                value > this.max) {
                errors['push'](`max`);
            }
            if (this.pattern !== undefined &&
                typeof value === 'string' &&
                !this.pattern.test(value)) {
                errors['push'](`pattern`);
            }
            return !Types.isEmpty(errors) ? errors : undefined;
        }
    }
    defaults() {
        const meta = this.optionsForType
            ? this.optionsForType(this.type)
            : undefined;
        return this.isStructuredType() && meta !== undefined
            ? meta.defaults()
            : this.default;
    }
    deserialize(value, options) {
        const parserOptions = options ?? this.parserOptions;
        return this.parser.deserialize(value, parserOptions);
    }
    serialize(value, options) {
        const parserOptions = options ?? this.parserOptions;
        return this.parser.serialize(value, parserOptions);
    }
    encode(value, options) {
        const parserOptions = options ?? this.parserOptions;
        return this.parser.encode(value, parserOptions);
    }
    resourceFactory(base) {
        if (!(base instanceof ODataEntityResource ||
            base instanceof ODataNavigationPropertyResource ||
            base instanceof ODataPropertyResource))
            throw new Error("Can't build resource for non compatible base type");
        return this.navigation
            ? base.navigationProperty(this.parser.name)
            : base.property(this.parser.name);
    }
    annotationsFactory(base) {
        return this.parser.collection
            ? base.property(this.parser.name, 'collection')
            : base.property(this.parser.name, 'single');
    }
    modelFactory({ parent, value, reset, }) {
        // Model
        const annots = this.annotationsFactory(parent.annots());
        let Model = this.modelForType ? this.modelForType(this.type) : undefined;
        if (Model === undefined)
            throw Error(`No Model type for ${this.name}`);
        if (value !== undefined) {
            annots.update(value);
        }
        if (annots?.type !== undefined && Model.meta !== null) {
            const meta = Model.meta.findChildOptions((o) => o.isTypeOf(annots.type))?.structuredType;
            if (meta !== undefined && meta.model !== undefined)
                // Change to child model
                Model = meta.model;
        }
        return new Model((value || {}), {
            annots,
            reset,
            parent: [parent, this],
        });
    }
    collectionFactory({ parent, value, reset, }) {
        // Collection Factory
        const annots = this.annotationsFactory(parent.annots());
        const Collection = this.collectionForType
            ? this.collectionForType(this.type)
            : undefined;
        if (Collection === undefined)
            throw Error(`No Collection type for ${this.name}`);
        return new Collection((value || []), {
            annots: annots,
            reset,
            parent: [parent, this],
        });
    }
}
export class ODataModelAttribute {
    _model;
    _field;
    state = ODataModelState.Unchanged;
    value;
    change;
    subscription;
    events$ = new ODataModelEventEmitter();
    constructor(_model, _field) {
        this._model = _model;
        this._field = _field;
    }
    get type() {
        return this._field.type;
    }
    get navigation() {
        return this._field.navigation;
    }
    get computed() {
        return this._field.annotatedValue(COMPUTED);
    }
    get concurrency() {
        return Boolean(this._field.concurrency);
    }
    get referentials() {
        return this._field.referentials;
    }
    get options() {
        return this._field.options;
    }
    get name() {
        return this._field.name;
    }
    get fieldName() {
        return this._field.field;
    }
    get() {
        return this.state === ODataModelState.Changed ? this.change : this.value;
    }
    set(value, reset = false, reparent = false) {
        const current = this.get();
        if (ODataModelOptions.isModel(current) ||
            ODataModelOptions.isCollection(current))
            this.unlink(current);
        const changed = ODataModelOptions.isModel(current) && ODataModelOptions.isModel(value)
            ? !current.equals(value)
            : ODataModelOptions.isCollection(current) &&
                ODataModelOptions.isCollection(value)
                ? !current.equals(value)
                : !Types.isEqual(current, value);
        if (reset) {
            this.value = value;
            this.state = ODataModelState.Unchanged;
        }
        else if (Types.isEqual(value, this.value)) {
            this.state = ODataModelState.Unchanged;
        }
        else if (changed) {
            this.change = value;
            this.state = ODataModelState.Changed;
        }
        if (ODataModelOptions.isModel(value) ||
            ODataModelOptions.isCollection(value)) {
            this.link(value, reparent);
        }
        return changed;
    }
    isChanged({ include_navigation = false, } = {}) {
        const current = this.get();
        return (this.state === ODataModelState.Changed ||
            ((ODataModelOptions.isModel(current) ||
                ODataModelOptions.isCollection(current)) &&
                current.hasChanged({ include_navigation })));
    }
    reset() {
        if (ODataModelOptions.isModel(this.change) ||
            ODataModelOptions.isCollection(this.change))
            this.unlink(this.change);
        this.state = ODataModelState.Unchanged;
        if (ODataModelOptions.isModel(this.value) ||
            ODataModelOptions.isCollection(this.value))
            this.link(this.value);
    }
    link(value, reparent = false) {
        this.subscription = value.events$.subscribe((e) => this.events$.emit(e));
        if (reparent) {
            value._parent = [this._model, this._field];
        }
    }
    unlink(value, reparent = false) {
        this.subscription?.unsubscribe();
        this.subscription = undefined;
        if (reparent) {
            value._parent = null;
        }
    }
}
export class ODataModelOptions {
    name;
    cid;
    base;
    _fields = [];
    structuredType;
    entitySet;
    // Hierarchy
    parent;
    children = [];
    events$ = new ODataModelEventEmitter();
    constructor({ config, structuredType, }) {
        this.name = structuredType.name;
        this.base = structuredType.base;
        this.structuredType = structuredType;
        this.cid = config?.cid ?? CID_FIELD_NAME;
        config.fields.forEach((value, key) => this.addField(key, value));
    }
    get api() {
        return this.structuredType.api;
    }
    type({ alias = false } = {}) {
        return this.structuredType.type({ alias });
    }
    isOpenType() {
        return this.structuredType.isOpenType();
    }
    isEntityType() {
        return this.structuredType.isEntityType();
    }
    isComplexType() {
        return this.structuredType.isComplexType();
    }
    isTypeOf(type) {
        return this.structuredType.type() === type;
    }
    isModelFor(entity) {
        // Resolve By Type
        const type = this.api.options.helper.type(entity);
        if (type && this.isTypeOf(type))
            return true;
        // Resolve By fields
        const keys = Object.keys(entity);
        const names = this.fields({
            include_navigation: true,
            include_parents: true,
        }).map((f) => f.name);
        return keys.every((key) => names.includes(key));
    }
    findChildOptions(predicate) {
        if (predicate(this))
            return this;
        let match;
        for (const ch of this.children) {
            match = ch.findChildOptions(predicate);
            if (match !== undefined)
                break;
        }
        return match;
    }
    configure({ options }) {
        if (this.base) {
            const parent = this.api.optionsForType(this.base);
            parent.children.push(this);
            this.parent = parent;
        }
        this.entitySet = this.api.findEntitySetForEntityType(this.type());
        let concurrencyFields = [];
        if (this.entitySet !== undefined) {
            concurrencyFields =
                this.entitySet.annotatedValue(OPTIMISTIC_CONCURRENCY) || [];
        }
        this._fields.forEach((field) => {
            const concurrency = concurrencyFields.indexOf(field.field) !== -1;
            field.configure({
                optionsForType: (t) => this.api.optionsForType(t),
                modelForType: (t) => this.api.modelForType(t),
                collectionForType: (t) => this.api.collectionForType(t),
                enumForType: (t) => this.api.findEnumType(t),
                structuredForType: (t) => this.api.findStructuredType(t),
                concurrency,
                options,
            });
        });
    }
    fields({ include_navigation, include_parents, }) {
        return [
            ...(include_parents && this.parent !== undefined
                ? this.parent.fields({ include_navigation, include_parents })
                : []),
            ...this._fields.filter((field) => include_navigation || !field.navigation),
        ];
    }
    field(name) {
        const field = this.findField(name);
        //Throw error if not found
        if (!field)
            throw new Error(`No field with name ${name}`);
        return field;
    }
    findField(name, { reset } = {}) {
        return this.fields({
            include_parents: true,
            include_navigation: true,
        }).find((modelField) => (reset && modelField.field === name) || modelField.name === name);
    }
    addField(name, options) {
        const { field, parser, ...opts } = options;
        if (field === undefined || name === undefined)
            throw new Error('Model Properties need name and field');
        const fieldParser = parser ?? this.structuredType.field(field);
        if (fieldParser === undefined)
            throw new Error(`No parser for ${field} with name = ${name}`);
        const modelField = new ODataModelField(this, {
            name,
            field,
            parser: fieldParser,
            ...opts,
        });
        this._fields.push(modelField);
        return modelField;
    }
    tsToEdm = {
        string: EdmType.String,
        number: EdmType.Int32,
        bigint: EdmType.Int64,
        boolean: EdmType.Boolean,
    };
    modelFieldFactory(self, name, type) {
        const structuredFieldParser = this.structuredType.addField(name, {
            type,
        });
        structuredFieldParser.configure({
            parserForType: (type) => this.api.parserForType(type),
            options: this.api.options,
        });
        const modelField = this.addField(name, {
            field: name,
            parser: structuredFieldParser,
        });
        modelField.configure({
            optionsForType: (t) => this.api.optionsForType(t),
            modelForType: (t) => this.api.modelForType(t),
            collectionForType: (t) => this.api.collectionForType(t),
            enumForType: (t) => this.api.findEnumType(t),
            structuredForType: (t) => this.api.findStructuredType(t),
            options: this.api.options,
            concurrency: false,
        });
        Object.defineProperty(self, modelField.name, {
            configurable: true,
            get: () => this.get(self, modelField),
            set: (value) => this.set(self, modelField, value),
        });
        return modelField;
    }
    attach(self, resource) {
        if (self._resource !== null &&
            resource.outgoingType() !== self._resource.outgoingType() &&
            !self._resource.isSubtypeOf(resource))
            throw new Error(`Can't attach ${resource.outgoingType()} to ${self._resource.outgoingType()}`);
        const current = self._resource;
        if (current === null || !current.isEqualTo(resource)) {
            self._resource = resource;
            self.events$.trigger(ODataModelEventType.Attach, {
                previous: current,
                value: resource,
            });
        }
    }
    //# region Resource
    static chain(child) {
        const chain = [];
        let tuple = [child, null];
        while (tuple !== null) {
            const parent = tuple;
            if (chain.some((p) => p[0] === parent[0]))
                break;
            chain.splice(0, 0, parent);
            tuple = tuple[0]._parent;
        }
        return chain;
    }
    static resource(child) {
        let resource = null;
        let prevField = null;
        for (const [model, field] of ODataModelOptions.chain(child)) {
            resource = resource || model._resource;
            if (resource === null)
                break;
            if (ODataModelOptions.isModel(model) &&
                (prevField === null || prevField.collection)) {
                const m = model;
                // Resolve subtype if collection not is from field
                // FIXME
                /*
                if (field === null) {
                  const r = m._meta.modelResourceFactory(resource.cloneQuery<T>());
                  if (r !== null && !r.isTypeOf(resource) && r.isSubtypeOf(resource)) {
                    resource = r;
                  }
                }
                */
                // Resolve key
                const mKey = m.key({ field_mapping: true });
                if (mKey !== undefined) {
                    resource =
                        resource instanceof ODataEntitySetResource
                            ? resource.entity(mKey)
                            : resource.key(mKey);
                }
            }
            prevField = field;
            if (field === null && model._resource !== null) {
                // Apply the query from model to new resource
                model._resource.query((qs) => resource?.query((qd) => qd.restore(qs.store())));
            }
            else if (field !== null) {
                resource = field.resourceFactory(resource);
            }
        }
        return resource;
    }
    collectionResourceFactory(query) {
        if (this.entitySet === undefined)
            return null;
        return ODataEntitySetResource.factory(this.api, {
            path: this.entitySet.name,
            type: this.entitySet.entityType,
            query,
        });
    }
    modelResourceFactory(query) {
        const resource = this.collectionResourceFactory(query);
        if (resource instanceof ODataEntitySetResource)
            return resource.entity();
        return resource;
    }
    //#endregion
    bind(self, { parent, resource, annots, } = {}) {
        // Events
        self.events$.subscribe((e) => this.events$.emit(e));
        // Parent
        if (parent !== undefined) {
            self._parent = parent;
        }
        // Resource
        if (self._parent === null && resource === undefined)
            resource = this.modelResourceFactory();
        if (resource) {
            this.attach(self, resource);
        }
        // Annotations
        self._annotations =
            annots ?? new ODataEntityAnnotations(ODataHelper[DEFAULT_VERSION]);
        // Fields
        this.fields({
            include_navigation: true,
            include_parents: true,
        }).forEach((field) => {
            Object.defineProperty(self, field.name, {
                configurable: true,
                get: () => this.get(self, field),
                set: (value) => this.set(self, field, value),
            });
        });
    }
    query(self, resource, func) {
        resource.query(func);
        this.attach(self, resource);
        return self;
    }
    resolveKey(value, { field_mapping = false, resolve = true, single = true, } = {}) {
        const keyTypes = this.structuredType.keys({ include_parents: true });
        const key = new Map();
        for (const kt of keyTypes) {
            let v = value;
            let options = this;
            let field;
            for (const name of kt.name.split('/')) {
                if (options === undefined)
                    break;
                field = options
                    .fields({ include_navigation: false, include_parents: true })
                    .find((field) => field.field === name);
                if (field !== undefined) {
                    v =
                        Types.isPlainObject(v) || ODataModelOptions.isModel(v)
                            ? v[field.name]
                            : v;
                    options = this.api.optionsForType(field.type);
                }
            }
            if (field === undefined)
                return undefined;
            let name = field_mapping ? field.field : field.name;
            if (kt.alias !== undefined)
                name = kt.alias;
            key.set(name, v);
        }
        if (key.size === 0)
            return undefined;
        return resolve
            ? Objects.resolveKey(key, { single })
            : Object.fromEntries(key);
    }
    resolveReferential(value, attr, { field_mapping = false, resolve = true, single = false, } = {}) {
        const referential = new Map();
        for (const ref of attr.referentials) {
            const from = this.fields({
                include_navigation: false,
                include_parents: true,
            }).find((p) => p.field === ref.referencedProperty);
            const to = attr.options
                .fields({ include_navigation: false, include_parents: true })
                .find((field) => field.field === ref.property);
            if (from !== undefined && to !== undefined) {
                const name = field_mapping ? to.field : to.name;
                referential.set(name, value && value[from.name]);
            }
        }
        if (referential.size === 0)
            return undefined;
        if (referential.size === 1 && Array.from(referential.values())[0] === null)
            return null;
        return resolve
            ? Objects.resolveKey(referential, { single })
            : Object.fromEntries(referential);
    }
    resolveReferenced(value, attr, { field_mapping = false, resolve = true, single = false, } = {}) {
        const referenced = new Map();
        for (const ref of attr.referentials) {
            const from = this.fields({
                include_navigation: false,
                include_parents: true,
            }).find((field) => field.field === ref.property);
            const meta = this.api.optionsForType(attr.type);
            const to = meta
                ?.fields({ include_navigation: false, include_parents: true })
                .find((field) => field.field === ref.referencedProperty);
            if (from !== undefined && to !== undefined) {
                const name = field_mapping ? to.field : to.name;
                referenced.set(name, value && value[from.name]);
            }
        }
        if (referenced.size === 0)
            return undefined;
        if (referenced.size === 1 && Array.from(referenced.values())[0] === null)
            return null;
        return resolve
            ? Objects.resolveKey(referenced, { single })
            : Object.fromEntries(referenced);
    }
    validate(self, { method, navigation = false, } = {}) {
        const errors = this.fields({
            include_parents: true,
            include_navigation: navigation,
        }).reduce((acc, field) => {
            const value = self[field.name];
            const errs = field.validate(value, { method });
            return errs !== undefined
                ? Object.assign(acc, { [field.name]: errs })
                : acc;
        }, {});
        return !Types.isEmpty(errors) ? errors : undefined;
    }
    defaults() {
        const defs = this.fields({
            include_navigation: false,
            include_parents: true,
        }).reduce((acc, field) => {
            const value = field.defaults();
            return value !== undefined
                ? Object.assign(acc, { [field.name]: value })
                : acc;
        }, {});
        return !Types.isEmpty(defs) ? defs : undefined;
    }
    hasChanged(self, { include_navigation = false } = {}) {
        return [...self._attributes.values()]
            .filter((attr) => !attr.navigation || include_navigation)
            .some((attr) => attr.isChanged({ include_navigation }));
    }
    hasKey(self) {
        return this.resolveKey(self) !== undefined;
    }
    withResource(self, resource, ctx) {
        // Push
        self.pushResource(resource);
        // Execute function
        const result = ctx(self);
        if (result instanceof Observable) {
            return result.pipe(finalize(() => {
                // Pop
                self.popResource();
            }));
        }
        else {
            // Pop
            self.popResource();
            return result;
        }
    }
    asEntity(self, ctx) {
        // Clone query from him or parent
        let query = self._resource?.cloneQuery();
        if (query === undefined &&
            self._parent &&
            self._parent[0] instanceof ODataCollection)
            query = self._parent[0]._resource?.cloneQuery();
        // Build new resource
        const resource = this.modelResourceFactory(query);
        return this.withResource(self, resource, ctx);
    }
    toEntity(self, { client_id = false, include_navigation = false, include_concurrency = false, include_computed = false, include_key = true, include_id = false, include_non_field = false, changes_only = false, field_mapping = false, chain = [], } = {}) {
        let entity = [...self._attributes.values()]
            .filter(
        // Chain
        (attr) => chain.every((c) => c !== attr.get()))
            .filter(
        // Changes only
        (attr) => !changes_only ||
            (changes_only && attr.isChanged({ include_navigation })))
            .filter((attr) => 
        // Navigation
        (include_navigation && attr.navigation && attr.get() !== null) ||
            !attr.navigation)
            .reduce((acc, attr) => {
            const name = field_mapping ? attr.fieldName : attr.name;
            let value = attr.get();
            const computed = attr.computed;
            const navigation = attr.navigation;
            const concurrency = attr.concurrency;
            if (ODataModelOptions.isModel(value)) {
                value = value.toEntity({
                    client_id,
                    include_navigation,
                    include_concurrency,
                    include_computed,
                    include_non_field,
                    field_mapping,
                    changes_only: changes_only && !!navigation,
                    include_key: include_key && !!navigation,
                    include_id: include_id && !!navigation,
                    chain: [self, ...chain],
                });
            }
            else if (ODataModelOptions.isCollection(value)) {
                value = value.toEntities({
                    client_id,
                    include_navigation,
                    include_concurrency,
                    include_computed,
                    include_non_field,
                    field_mapping,
                    changes_only: changes_only && !!navigation,
                    include_key: include_key && !!navigation,
                    include_id: include_id && !!navigation,
                    chain: [self, ...chain],
                });
            }
            if (include_concurrency && concurrency) {
                return Object.assign(acc, { [name]: value });
            }
            else if (include_computed && computed) {
                return Object.assign(acc, { [name]: value });
            }
            else if (changes_only && attr.isChanged()) {
                return Object.assign(acc, { [name]: value });
            }
            else if (!changes_only && !concurrency && !computed) {
                return Object.assign(acc, { [name]: value });
            }
            return acc;
        }, {});
        if (include_non_field) {
            const names = Object.keys(entity);
            // Attributes from object (attributes for object)
            const nonFieldAttrs = Object.entries(self)
                .filter(([k]) => names.indexOf(k) === -1 && !k.startsWith('_') && !k.endsWith('$'))
                .reduce((acc, [k, v]) => Object.assign(acc, { [k]: v }), {});
            entity = { ...entity, ...nonFieldAttrs };
        }
        // Add client_id
        if (client_id) {
            entity[this.cid] = self[this.cid];
        }
        // Add key
        if (include_key) {
            entity = {
                ...entity,
                ...this.resolveKey(self, { field_mapping, resolve: false }),
            };
        }
        // Add id
        if (include_id) {
            self.asEntity((e) => {
                const resource = e.resource();
                if (resource)
                    entity[this.api.options.helper.ODATA_ID] = `${resource.clearQuery()}`;
            });
        }
        // Add type
        if (self._parent !== null &&
            ((ODataModelOptions.isModel(self._parent[0]) &&
                self._parent[1] !== null &&
                this.api.optionsForType(self._parent[1].type) !== self._meta) ||
                (ODataModelOptions.isCollection(self._parent[0]) &&
                    self._parent[0]._model
                        .meta !== self._meta))) {
            entity[this.api.options.helper.ODATA_TYPE] =
                `#${this.structuredType.type()}`;
        }
        return entity;
    }
    reset(self, { name, silent = false } = {}) {
        let changes = [];
        if (name !== undefined) {
            // Reset value
            const attribute = self._attributes.get(name);
            if (attribute !== undefined &&
                attribute.isChanged({ include_navigation: true })) {
                attribute.reset();
                changes = [name];
            }
            else if (attribute?.isChanged()) {
                attribute.reset();
                changes = [name];
            }
        }
        else {
            // reset all
            changes = [...self._attributes.keys()];
            //self._changes.clear();
            self._attributes.forEach((attr, key) => {
                if (attr.isChanged({ include_navigation: true })) {
                    attr.reset();
                    changes.push(key);
                }
            });
        }
        if (!silent && changes.length > 0) {
            self.events$.trigger(ODataModelEventType.Reset, { options: { changes } });
        }
    }
    assign(self, entity, { add = true, merge = true, remove = true, reset = false, reparent = false, silent = false, } = {}) {
        const changes = [];
        // Update annotations
        self.annots().update(entity);
        // Update attributes
        const attrs = self.annots().attributes(entity, 'full');
        Object.entries(attrs)
            .filter(([, value]) => value !== undefined) // Filter undefined
            .forEach(([key, value]) => {
            const field = this.findField(key, { reset });
            if (field !== undefined || this.isOpenType()) {
                // Delegated to private setter
                if (this.set(self, field ?? key, value, {
                    add,
                    merge,
                    remove,
                    reset,
                    reparent,
                    silent,
                })) {
                    changes.push(field?.name ?? key);
                }
            }
            else {
                // Basic assignment
                const current = self[key];
                self[key] = value;
                if (current !== value)
                    changes.push(key);
            }
        });
        if (!silent && changes.length > 0) {
            self.events$.trigger(reset ? ODataModelEventType.Reset : ODataModelEventType.Update, { options: { changes } });
        }
        return self;
    }
    static isModel(obj) {
        return Types.rawType(obj) === 'Model';
    }
    static isCollection(obj) {
        return Types.rawType(obj) === 'Collection';
    }
    get(self, field) {
        const attr = self._attributes.get(field instanceof ODataModelField ? field.name : field);
        if (attr !== undefined) {
            const value = attr.get();
            if ((attr.navigation && value === null) ||
                ODataModelOptions.isModel(value)) {
                // Check for reference
                const referenced = this.resolveReferenced(self, attr, {
                    resolve: false,
                });
                if (value !== null && referenced !== null && referenced !== undefined) {
                    value.assign(referenced, {
                        silent: true,
                    });
                }
                else if (value !== null && referenced === null) {
                    // New value is null
                    attr.set(null);
                }
                else if (value === null && referenced !== null) {
                    // New value is undefined
                    attr.set(undefined);
                }
            }
            return value;
        }
        else if (typeof field === 'string' &&
            !field.startsWith('_') &&
            !field.endsWith('$')) {
            return self[field];
        }
        return undefined;
    }
    set(self, field, value, { add, merge, remove, reset, reparent, silent, type, } = {}) {
        let modelField = field instanceof ODataModelField ? field : this.findField(field);
        if (modelField === undefined &&
            this.isOpenType() &&
            typeof field === 'string') {
            type = type ?? this.tsToEdm[typeof value] ?? EdmType.String;
            modelField = this.modelFieldFactory(self, field, type);
        }
        if (modelField === undefined)
            throw new Error(`No field with name ${field}`);
        let changed = false;
        let attr = self._attributes.get(modelField.name);
        // Ensures that the attribute exists
        if (attr === undefined) {
            attr = new ODataModelAttribute(self, modelField);
            this._link(self, attr);
            self._attributes.set(modelField.name, attr);
        }
        const current = attr.get();
        if (modelField.isStructuredType()) {
            if (value === null) {
                // New value is null
                changed = attr.set(value, reset, reparent);
            }
            else if (ODataModelOptions.isCollection(current)) {
                // Current is collection
                const currentCollection = current;
                if (ODataModelOptions.isCollection(value)) {
                    // New value is collection
                    changed = attr.set(value, reset, reparent);
                }
                else if (Types.isArray(value)) {
                    // New value is array
                    currentCollection._annotations = modelField.annotationsFactory(self.annots());
                    currentCollection.assign(value, {
                        add,
                        merge,
                        remove,
                        reset,
                        reparent,
                        silent,
                    });
                    changed = currentCollection.hasChanged();
                }
            }
            else if (ODataModelOptions.isModel(current)) {
                // Current is model
                const currentModel = current;
                if (ODataModelOptions.isModel(value)) {
                    // New value is model
                    changed = attr.set(value, reset, reparent);
                }
                else if (Types.isPlainObject(value)) {
                    currentModel._annotations = modelField.annotationsFactory(self.annots());
                    currentModel.assign(value, {
                        add,
                        merge,
                        remove,
                        reset,
                        reparent,
                        silent,
                    });
                    changed = currentModel.hasChanged();
                }
            }
            else {
                // Current is null or undefined
                // create new model/collection for given value
                changed = attr.set(ODataModelOptions.isCollection(value) ||
                    ODataModelOptions.isModel(value)
                    ? value
                    : modelField.collection
                        ? modelField.collectionFactory({
                            parent: self,
                            value: value,
                            reset: reset,
                        })
                        : modelField.modelFactory({
                            parent: self,
                            value: value,
                            reset: reset,
                        }), reset, reparent);
            }
            // Resolve referentials
            if (!ODataModelOptions.isCollection(attr.get())) {
                const meta = this.api.optionsForType(modelField.type);
                const ref = meta?.resolveReferential(attr.get(), attr, {
                    resolve: false,
                });
                if (ref !== null && ref !== undefined) {
                    Object.assign(self, ref);
                }
            }
        }
        else {
            changed = attr.set(value, reset, reparent);
        }
        if (!silent && changed) {
            self.events$.trigger(ODataModelEventType.Change, {
                attr,
                value,
                previous: current,
                options: { key: modelField.isKey() },
            });
        }
        return changed;
    }
    _link(self, attr) {
        attr.events$.subscribe((event) => {
            if (event.canContinueWith(self)) {
                if (event.model === attr.get()) {
                    if (event.type === ODataModelEventType.Change &&
                        attr.navigation &&
                        event.options?.key) {
                        const ref = attr.get().referential(attr);
                        if (ref !== null && ref !== undefined) {
                            Object.assign(self, ref);
                        }
                    }
                }
                self.events$.emit(event.push(self, attr));
            }
        });
    }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItb2RhdGEvc3JjL2xpYi9tb2RlbHMvb3B0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUNoRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUMsT0FBTyxFQUNMLGNBQWMsRUFDZCxRQUFRLEVBQ1IsZUFBZSxFQUNmLHNCQUFzQixFQUN0QixjQUFjLEdBQ2YsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVF4QyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLHNCQUFzQixFQUN0QiwrQkFBK0IsRUFDL0IscUJBQXFCLEdBQ3RCLE1BQU0sY0FBYyxDQUFDO0FBT3RCLE9BQU8sRUFBRSxPQUFPLEVBQWlCLE1BQU0sVUFBVSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQzFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDL0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNyQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sRUFFTCxzQkFBc0IsR0FDdkIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixNQUFNLENBQU4sSUFBWSxtQkFZWDtBQVpELFdBQVksbUJBQW1CO0lBQzdCLHdDQUFpQixDQUFBO0lBQ2pCLHNDQUFlLENBQUE7SUFDZix3Q0FBaUIsQ0FBQTtJQUNqQixvQ0FBYSxDQUFBO0lBQ2IsMENBQW1CLENBQUE7SUFDbkIsa0NBQVcsQ0FBQTtJQUNYLHdDQUFpQixDQUFBO0lBQ2pCLDBDQUFtQixDQUFBO0lBQ25CLDBDQUFtQixD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RSxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFFO2FBQ3JDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRU8sS0FBSyxDQUFJLElBQW1CLEVBQUUsSUFBNEI7UUFDaEUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUEyQixFQUFFLEVBQUU7WUFDckQsSUFBSSxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ2hDLElBQUksS0FBSyxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQztvQkFDL0IsSUFDRSxLQUFLLENBQUMsSUFBSSxLQUFLLG1CQUFtQixDQUFDLE1BQU07d0JBQ3pDLElBQUksQ0FBQyxVQUFVO3dCQUNmLEtBQUssQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUNsQixDQUFDO3dCQUNELE1BQU0sR0FBRyxHQUFJLElBQUksQ0FBQyxHQUFHLEVBQXNCLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO3dCQUM5RCxJQUFJLEdBQUcsS0FBSyxJQUFJLElBQUksR0FBRyxLQUFLLFNBQVMsRUFBRSxDQUFDOzRCQUN0QyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQzt3QkFDM0IsQ0FBQztvQkFDSCxDQUFDO2dCQUNILENBQUM7Z0JBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUM1QyxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGZpbmFsaXplIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgQ0lEX0ZJRUxEX05BTUUsXG4gIENPTVBVVEVELFxuICBERUZBVUxUX1ZFUlNJT04sXG4gIE9QVElNSVNUSUNfQ09OQ1VSUkVOQ1ksXG4gIEVWRU5UX1NQTElUVEVSLFxufSBmcm9tICcuLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgT0RhdGFIZWxwZXIgfSBmcm9tICcuLi9oZWxwZXInO1xuaW1wb3J0IHtcbiAgRW50aXR5S2V5LFxuICBPRGF0YVF1ZXJ5T3B0aW9ucyxcbiAgT0RhdGFRdWVyeU9wdGlvbnNIYW5kbGVyLFxuICBPRGF0YVJlc291cmNlLFxuICBPRGF0YVNpbmdsZXRvblJlc291cmNlLFxufSBmcm9tICcuLi9yZXNvdXJjZXMnO1xuaW1wb3J0IHtcbiAgT0RhdGFFbnRpdHlSZXNvdXJjZSxcbiAgT0RhdGFFbnRpdHlTZXRSZXNvdXJjZSxcbiAgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZSxcbiAgT0RhdGFQcm9wZXJ0eVJlc291cmNlLFxufSBmcm9tICcuLi9yZXNvdXJjZXMnO1xuaW1wb3J0IHtcbiAgT0RhdGFFbnRpdHlTZXQsXG4gIE9EYXRhRW51bVR5cGUsXG4gIE9EYXRhU3RydWN0dXJlZFR5cGUsXG4gIE9EYXRhU3RydWN0dXJlZFR5cGVGaWVsZFBhcnNlcixcbn0gZnJvbSAnLi4vc2NoZW1hJztcbmltcG9ydCB7IEVkbVR5cGUsIFBhcnNlck9wdGlvbnMgfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBPYmplY3RzLCBUeXBlcyB9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCB7IE9EYXRhQ29sbGVjdGlvbiB9IGZyb20gJy4vY29sbGVjdGlvbic7XG5pbXBvcnQgeyBPRGF0YU1vZGVsIH0gZnJvbSAnLi9tb2RlbCc7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIE9EYXRhRW50aXRpZXNBbm5vdGF0aW9ucyxcbiAgT0RhdGFFbnRpdHlBbm5vdGF0aW9ucyxcbn0gZnJvbSAnLi4vYW5ub3RhdGlvbnMnO1xuXG5leHBvcnQgZW51bSBPRGF0YU1vZGVsRXZlbnRUeXBlIHtcbiAgQ2hhbmdlID0gJ2NoYW5nZScsXG4gIFJlc2V0ID0gJ3Jlc2V0JyxcbiAgVXBkYXRlID0gJ3VwZGF0ZScsXG4gIFNvcnQgPSAnc29ydCcsXG4gIERlc3Ryb3kgPSAnZGVzdHJveScsXG4gIEFkZCA9ICdhZGQnLFxuICBSZW1vdmUgPSAncmVtb3ZlJyxcbiAgSW52YWxpZCA9ICdpbnZhbGlkJyxcbiAgUmVxdWVzdCA9ICdyZXF1ZXN0JyxcbiAgU3luYyA9ICdzeW5jJyxcbiAgQXR0YWNoID0gJ2F0dGFjaCcsXG59XG5cbmV4cG9ydCBjbGFzcyBPRGF0YU1vZGVsRXZlbnQ8VD4ge1xuICB0eXBlOiBPRGF0YU1vZGVsRXZlbnRUeXBlIHwgc3RyaW5nO1xuICB2YWx1ZT86IGFueTtcbiAgcHJldmlvdXM/OiBhbnk7XG4gIG9wdGlvbnM/OiBhbnk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgdHlwZTogT0RhdGFNb2RlbEV2ZW50VHlwZSB8IHN0cmluZyxcbiAgICB7XG4gICAgICBtb2RlbCxcbiAgICAgIGNvbGxlY3Rpb24sXG4gICAgICBwcmV2aW91cyxcbiAgICAgIHZhbHVlLFxuICAgICAgYXR0cixcbiAgICAgIG9wdGlvbnMsXG4gICAgICBidWJibGVzLFxuICAgICAgY2hhaW4sXG4gICAgfToge1xuICAgICAgbW9kZWw/OiBPRGF0YU1vZGVsPFQ+O1xuICAgICAgY29sbGVjdGlvbj86IE9EYXRhQ29sbGVjdGlvbjxULCBPRGF0YU1vZGVsPFQ+PjtcbiAgICAgIGF0dHI/OiBPRGF0YU1vZGVsQXR0cmlidXRlPGFueT4gfCBudW1iZXI7XG4gICAgICBwcmV2aW91cz86IGFueTtcbiAgICAgIHZhbHVlPzogYW55O1xuICAgICAgb3B0aW9ucz86IGFueTtcbiAgICAgIGJ1YmJsZXM/OiBib29sZWFuO1xuICAgICAgY2hhaW4/OiBbXG4gICAgICAgIE9EYXRhTW9kZWw8YW55PiB8IE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4sXG4gICAgICAgIE9EYXRhTW9kZWxBdHRyaWJ1dGU8YW55PiB8IG51bWJlciB8IG51bGwsXG4gICAgICBdW107XG4gICAgfSA9IHt9LFxuICApIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMubW9kZWwgPSBtb2RlbDtcbiAgICB0aGlzLmNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uO1xuICAgIHRoaXMucHJldmlvdXMgPSBwcmV2aW91cztcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLmNoYWluID0gY2hhaW4gPz8gW1xuICAgICAgW1xuICAgICAgICAodGhpcy5tb2RlbCB8fCB0aGlzLmNvbGxlY3Rpb24pIGFzXG4gICAgICAgICAgfCBPRGF0YU1vZGVsPGFueT5cbiAgICAgICAgICB8IE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4sXG4gICAgICAgIGF0dHIgfHwgbnVsbCxcbiAgICAgIF0sXG4gICAgXTtcbiAgICB0aGlzLmJ1YmJsZXMgPSBidWJibGVzID8/IEJVQkJMRVMuaW5kZXhPZih0aGlzLnR5cGUpICE9PSAtMTtcbiAgfVxuXG4gIGNoYWluOiBbXG4gICAgT0RhdGFNb2RlbDxhbnk+IHwgT0RhdGFDb2xsZWN0aW9uPGFueSwgT0RhdGFNb2RlbDxhbnk+PixcbiAgICBPRGF0YU1vZGVsQXR0cmlidXRlPGFueT4gfCBudW1iZXIgfCBudWxsLFxuICBdW107XG5cbiAgcHVzaChcbiAgICBtb2RlbDogT0RhdGFNb2RlbDxhbnk+IHwgT0RhdGFDb2xsZWN0aW9uPGFueSwgT0RhdGFNb2RlbDxhbnk+PixcbiAgICBhdHRyOiBPRGF0YU1vZGVsQXR0cmlidXRlPGFueT4gfCBudW1iZXIsXG4gICkge1xuICAgIHJldHVybiBuZXcgT0RhdGFNb2RlbEV2ZW50PGFueT4odGhpcy50eXBlLCB7XG4gICAgICBtb2RlbDogdGhpcy5tb2RlbCA/PyAobW9kZWwgaW5zdGFuY2VvZiBPRGF0YU1vZGVsID8gbW9kZWwgOiB1bmRlZmluZWQpLFxuICAgICAgY29sbGVjdGlvbjpcbiAgICAgICAgdGhpcy5jb2xsZWN0aW9uID8/XG4gICAgICAgIChtb2RlbCBpbnN0YW5jZW9mIE9EYXRhQ29sbGVjdGlvblxuICAgICAgICAgID8gKG1vZGVsIGFzIE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4pXG4gICAgICAgICAgOiB1bmRlZmluZWQpLFxuICAgICAgcHJldmlvdXM6IHRoaXMucHJldmlvdXMsXG4gICAgICB2YWx1ZTogdGhpcy52YWx1ZSxcbiAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgLi4udGhpcy5vcHRpb25zLFxuICAgICAgICBpbmRleDogYXR0ciBpbnN0YW5jZW9mIE9EYXRhTW9kZWxBdHRyaWJ1dGUgPyBhdHRyLm5hbWUgOiBhdHRyLFxuICAgICAgfSxcbiAgICAgIGJ1YmJsZXM6IHRoaXMuYnViYmxlcyxcbiAgICAgIGNoYWluOiBbW21vZGVsLCBhdHRyXSwgLi4udGhpcy5jaGFpbl0sXG4gICAgfSk7XG4gIH1cblxuICBidWJibGVzOiBib29sZWFuO1xuICBzdG9wUHJvcGFnYXRpb24oKSB7XG4gICAgdGhpcy5idWJibGVzID0gZmFsc2U7XG4gIH1cblxuICB2aXNpdGVkKG1vZGVsOiBPRGF0YU1vZGVsPGFueT4gfCBPRGF0YUNvbGxlY3Rpb248YW55LCBPRGF0YU1vZGVsPGFueT4+KSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY2hhaW4uc29tZSgoYykgPT4gY1swXSA9PT0gbW9kZWwpICYmXG4gICAgICB0aGlzLmNoYWluW3RoaXMuY2hhaW4ubGVuZ3RoIC0gMV1bMF0gIT09IG1vZGVsXG4gICAgKTtcbiAgfVxuXG4gIGNhbkNvbnRpbnVlV2l0aChzZWxmOiBPRGF0YU1vZGVsPFQ+IHwgT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+KSB7XG4gICAgcmV0dXJuIHRoaXMuYnViYmxlcyAmJiAhdGhpcy52aXNpdGVkKHNlbGYpO1xuICB9XG5cbiAgZ2V0IHBhdGgoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hhaW5cbiAgICAgIC5tYXAoKFssIGF0dHJdLCBpbmRleCkgPT5cbiAgICAgICAgdHlwZW9mIGF0dHIgPT09ICdudW1iZXInXG4gICAgICAgICAgPyBgWyR7YXR0cn1dYFxuICAgICAgICAgIDogYXR0ciBpbnN0YW5jZW9mIE9EYXRhTW9kZWxBdHRyaWJ1dGVcbiAgICAgICAgICAgID8gaW5kZXggPT09IDBcbiAgICAgICAgICAgICAgPyBhdHRyLm5hbWVcbiAgICAgICAgICAgICAgOiBgLiR7YXR0ci5uYW1lfWBcbiAgICAgICAgICAgIDogJycsXG4gICAgICApXG4gICAgICAuam9pbignJyk7XG4gIH1cblxuICAvL1JlZmVyZW5jZSB0byB0aGUgbW9kZWwgd2hpY2ggdGhlIGV2ZW50IHdhcyBkaXNwYXRjaGVkXG4gIG1vZGVsPzogT0RhdGFNb2RlbDxUPjtcbiAgLy9JZGVudGlmaWVzIHRoZSBjdXJyZW50IG1vZGVsIGZvciB0aGUgZXZlbnRcbiAgZ2V0IGN1cnJlbnRNb2RlbCgpOiBPRGF0YU1vZGVsPGFueT4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGxpbmsgPSB0aGlzLmNoYWluLmZpbmQoKGMpID0+IE9EYXRhTW9kZWxPcHRpb25zLmlzTW9kZWwoY1swXSkpO1xuICAgIHJldHVybiBsaW5rICE9PSB1bmRlZmluZWQgPyAobGlua1swXSBhcyBPRGF0YU1vZGVsPGFueT4pIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgLy9SZWZlcmVuY2UgdG8gdGhlIGNvbGxlY3Rpb24gd2hpY2ggdGhlIGV2ZW50IHdhcyBkaXNwYXRjaGVkXG4gIGNvbGxlY3Rpb24/OiBPRGF0YUNvbGxlY3Rpb248VCwgT0RhdGFNb2RlbDxUPj47XG4gIC8vSWRlbnRpZmllcyB0aGUgY3VycmVudCBjb2xsZWN0aW9uIGZvciB0aGUgZXZlbnRcbiAgZ2V0IGN1cnJlbnRDb2xsZWN0aW9uKCk6IE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGxpbmsgPSB0aGlzLmNoYWluLmZpbmQoKGMpID0+IE9EYXRhTW9kZWxPcHRpb25zLmlzQ29sbGVjdGlvbihjWzBdKSk7XG4gICAgcmV0dXJuIGxpbmsgIT09IHVuZGVmaW5lZFxuICAgICAgPyAobGlua1swXSBhcyBPRGF0YUNvbGxlY3Rpb248YW55LCBPRGF0YU1vZGVsPGFueT4+KVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE9EYXRhTW9kZWxFdmVudEVtaXR0ZXI8VD4gZXh0ZW5kcyBFdmVudEVtaXR0ZXI8XG4gIE9EYXRhTW9kZWxFdmVudDxUPlxuPiB7XG4gIG1vZGVsPzogT0RhdGFNb2RlbDxUPjtcbiAgY29sbGVjdGlvbj86IE9EYXRhQ29sbGVjdGlvbjxULCBPRGF0YU1vZGVsPFQ+PjtcblxuICBjb25zdHJ1Y3Rvcih7XG4gICAgbW9kZWwsXG4gICAgY29sbGVjdGlvbixcbiAgfToge1xuICAgIG1vZGVsPzogT0RhdGFNb2RlbDxUPjtcbiAgICBjb2xsZWN0aW9uPzogT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+O1xuICB9ID0ge30pIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMubW9kZWwgPSBtb2RlbDtcbiAgICB0aGlzLmNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uO1xuICB9XG5cbiAgdHJpZ2dlcihcbiAgICB0eXBlOiBPRGF0YU1vZGVsRXZlbnRUeXBlIHwgc3RyaW5nLFxuICAgIHtcbiAgICAgIGNvbGxlY3Rpb24sXG4gICAgICBwcmV2aW91cyxcbiAgICAgIHZhbHVlLFxuICAgICAgYXR0cixcbiAgICAgIG9wdGlvbnMsXG4gICAgICBidWJibGVzLFxuICAgIH06IHtcbiAgICAgIGNvbGxlY3Rpb24/OiBPRGF0YUNvbGxlY3Rpb248VCwgT0RhdGFNb2RlbDxUPj47XG4gICAgICBhdHRyPzogT0RhdGFNb2RlbEF0dHJpYnV0ZTxhbnk+IHwgbnVtYmVyO1xuICAgICAgcHJldmlvdXM/OiBhbnk7XG4gICAgICB2YWx1ZT86IGFueTtcbiAgICAgIG9wdGlvbnM/OiBhbnk7XG4gICAgICBidWJibGVzPzogYm9vbGVhbjtcbiAgICB9ID0ge30sXG4gICkge1xuICAgIGNvbnN0IF90cmlnZ2VyID0gKG5hbWU6IHN0cmluZykgPT5cbiAgICAgIHRoaXMuZW1pdChcbiAgICAgICAgbmV3IE9EYXRhTW9kZWxFdmVudChuYW1lLCB7XG4gICAgICAgICAgbW9kZWw6IHRoaXMubW9kZWwsXG4gICAgICAgICAgY29sbGVjdGlvbjogY29sbGVjdGlvbiA/PyB0aGlzLmNvbGxlY3Rpb24sXG4gICAgICAgICAgcHJldmlvdXMsXG4gICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgYXR0cixcbiAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgIGJ1YmJsZXMsXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICBpZiAodHlwZSAmJiBFVkVOVF9TUExJVFRFUi50ZXN0KHR5cGUpKSB7XG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgdHlwZS5zcGxpdChFVkVOVF9TUExJVFRFUikpIHtcbiAgICAgICAgX3RyaWdnZXIobmFtZSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIF90cmlnZ2VyKHR5cGUpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY29uc3QgQlVCQkxFUzogKE9EYXRhTW9kZWxFdmVudFR5cGUgfCBzdHJpbmcpW10gPSBbXG4gIE9EYXRhTW9kZWxFdmVudFR5cGUuQ2hhbmdlLFxuICBPRGF0YU1vZGVsRXZlbnRUeXBlLlJlc2V0LFxuICBPRGF0YU1vZGVsRXZlbnRUeXBlLlVwZGF0ZSxcbiAgT0RhdGFNb2RlbEV2ZW50VHlwZS5EZXN0cm95LFxuICBPRGF0YU1vZGVsRXZlbnRUeXBlLkFkZCxcbiAgT0RhdGFNb2RlbEV2ZW50VHlwZS5SZW1vdmUsXG5dO1xuXG5leHBvcnQgY29uc3QgSU5DTFVERV9TSEFMTE9XID0ge1xuICBpbmNsdWRlX2NvbmN1cnJlbmN5OiB0cnVlLFxuICBpbmNsdWRlX2NvbXB1dGVkOiB0cnVlLFxuICBpbmNsdWRlX2tleTogdHJ1ZSxcbiAgaW5jbHVkZV9pZDogZmFsc2UsXG59O1xuXG5leHBvcnQgY29uc3QgSU5DTFVERV9ERUVQID0ge1xuICBpbmNsdWRlX25hdmlnYXRpb246IHRydWUsXG4gIGluY2x1ZGVfbm9uX2ZpZWxkOiB0cnVlLFxuICAuLi5JTkNMVURFX1NIQUxMT1csXG59O1xuXG5leHBvcnQgZW51bSBPRGF0YU1vZGVsU3RhdGUge1xuICBBZGRlZCxcbiAgUmVtb3ZlZCxcbiAgQ2hhbmdlZCxcbiAgVW5jaGFuZ2VkLFxufVxuXG5leHBvcnQgdHlwZSBNb2RlbEludGVyZmFjZTxUPiA9IHtcbiAgW1AgaW4ga2V5b2YgVF06IFRbUF0gZXh0ZW5kcyAoaW5mZXIgVSlbXVxuICAgID8gT0RhdGFDb2xsZWN0aW9uPFUsIE9EYXRhTW9kZWw8VT4gJiBNb2RlbEludGVyZmFjZTxVPj5cbiAgICA6IFRbUF0gZXh0ZW5kcyBvYmplY3RcbiAgICAgID8gT0RhdGFNb2RlbDxUW1BdPiAmIE1vZGVsSW50ZXJmYWNlPFRbUF0+XG4gICAgICA6IFRbUF07XG59O1xuXG5leHBvcnQgdHlwZSBNb2RlbE9wdGlvbnMgPSB7XG4gIGNpZD86IHN0cmluZztcbiAgZmllbGRzOiBNYXA8c3RyaW5nLCBNb2RlbEZpZWxkT3B0aW9ucz47XG59O1xuXG5leHBvcnQgdHlwZSBNb2RlbEZpZWxkT3B0aW9ucyA9IHtcbiAgZmllbGQ/OiBzdHJpbmc7XG4gIHBhcnNlcj86IE9EYXRhU3RydWN0dXJlZFR5cGVGaWVsZFBhcnNlcjxhbnk+O1xuICBkZWZhdWx0PzogYW55O1xuICByZXF1aXJlZD86IGJvb2xlYW47XG4gIGNvbmN1cnJlbmN5PzogYm9vbGVhbjtcbiAgbWF4TGVuZ3RoPzogbnVtYmVyO1xuICBtaW5MZW5ndGg/OiBudW1iZXI7XG4gIG1pbj86IG51bWJlcjtcbiAgbWF4PzogbnVtYmVyO1xuICBwYXR0ZXJuPzogUmVnRXhwO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIE1vZGVsKHsgY2lkID0gQ0lEX0ZJRUxEX05BTUUgfTogeyBjaWQ/OiBzdHJpbmcgfSA9IHt9KSB7XG4gIHJldHVybiA8VCBleHRlbmRzIHsgbmV3ICguLi5hcmdzOiBhbnlbXSk6IHt9IH0+KGNvbnN0cnVjdG9yOiBUKSA9PiB7XG4gICAgY29uc3QgS2xhc3MgPSA8YW55PmNvbnN0cnVjdG9yO1xuICAgIGlmICghS2xhc3MuaGFzT3duUHJvcGVydHkoJ29wdGlvbnMnKSlcbiAgICAgIEtsYXNzLm9wdGlvbnMgPSB7XG4gICAgICAgIGZpZWxkczogbmV3IE1hcDxzdHJpbmcsIE1vZGVsRmllbGRPcHRpb25zPigpLFxuICAgICAgfSBhcyBNb2RlbE9wdGlvbnM7XG4gICAgS2xhc3Mub3B0aW9ucy5jaWQgPSBjaWQ7XG4gICAgcmV0dXJuIGNvbnN0cnVjdG9yO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gTW9kZWxGaWVsZCh7XG4gIG5hbWUsXG4gIC4uLm9wdGlvbnNcbn06IHsgbmFtZT86IHN0cmluZyB9ICYgTW9kZWxGaWVsZE9wdGlvbnMgPSB7fSkge1xuICByZXR1cm4gKHRhcmdldDogYW55LCBrZXk6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgIGNvbnN0IEtsYXNzID0gdGFyZ2V0LmNvbnN0cnVjdG9yO1xuICAgIGlmICghS2xhc3MuaGFzT3duUHJvcGVydHkoJ29wdGlvbnMnKSlcbiAgICAgIEtsYXNzLm9wdGlvbnMgPSB7XG4gICAgICAgIGZpZWxkczogbmV3IE1hcDxzdHJpbmcsIE1vZGVsRmllbGRPcHRpb25zPigpLFxuICAgICAgfSBhcyBNb2RlbE9wdGlvbnM7XG4gICAgb3B0aW9ucy5maWVsZCA9IG5hbWUgPz8ga2V5O1xuICAgIEtsYXNzLm9wdGlvbnMuZmllbGRzLnNldChrZXksIG9wdGlvbnMpO1xuICB9O1xufVxuXG5leHBvcnQgdHlwZSBPRGF0YU1vZGVsRmllbGRPcHRpb25zPEY+ID0gTW9kZWxGaWVsZE9wdGlvbnMgJiB7XG4gIG5hbWU6IHN0cmluZztcbiAgZmllbGQ6IHN0cmluZztcbiAgcGFyc2VyOiBPRGF0YVN0cnVjdHVyZWRUeXBlRmllbGRQYXJzZXI8Rj47XG59O1xuXG5leHBvcnQgY2xhc3MgT0RhdGFNb2RlbEZpZWxkPEY+IHtcbiAgbmFtZTogc3RyaW5nO1xuICBmaWVsZDogc3RyaW5nO1xuICBwYXJzZXI6IE9EYXRhU3RydWN0dXJlZFR5cGVGaWVsZFBhcnNlcjxGPjtcbiAgb3B0aW9uczogT0RhdGFNb2RlbE9wdGlvbnM8YW55PjtcbiAgb3B0aW9uc0ZvclR5cGU/OiAodHlwZTogc3RyaW5nKSA9PiBPRGF0YU1vZGVsT3B0aW9uczxhbnk+IHwgdW5kZWZpbmVkO1xuICBtb2RlbEZvclR5cGU/OiAodDogc3RyaW5nKSA9PiB0eXBlb2YgT0RhdGFNb2RlbDxhbnk+IHwgdW5kZWZpbmVkO1xuICBjb2xsZWN0aW9uRm9yVHlwZT86IChcbiAgICB0OiBzdHJpbmcsXG4gICkgPT4gdHlwZW9mIE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4gfCB1bmRlZmluZWQ7XG4gIGVudW1Gb3JUeXBlPzogKHQ6IHN0cmluZykgPT4gT0RhdGFFbnVtVHlwZTxGPiB8IHVuZGVmaW5lZDtcbiAgc3RydWN0dXJlZEZvclR5cGU/OiAodDogc3RyaW5nKSA9PiBPRGF0YVN0cnVjdHVyZWRUeXBlPEY+IHwgdW5kZWZpbmVkO1xuICBkZWZhdWx0PzogYW55O1xuICByZXF1aXJlZDogYm9vbGVhbjtcbiAgY29uY3VycmVuY3k6IGJvb2xlYW47XG4gIG1heExlbmd0aD86IG51bWJlcjtcbiAgbWluTGVuZ3RoPzogbnVtYmVyO1xuICBtaW4/OiBudW1iZXI7XG4gIG1heD86IG51bWJlcjtcbiAgcGF0dGVybj86IFJlZ0V4cDtcbiAgcGFyc2VyT3B0aW9ucz86IFBhcnNlck9wdGlvbnM7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb3B0aW9uczogT0RhdGFNb2RlbE9wdGlvbnM8YW55PixcbiAgICB7IG5hbWUsIGZpZWxkLCBwYXJzZXIsIC4uLm9wdHMgfTogT0RhdGFNb2RlbEZpZWxkT3B0aW9uczxGPixcbiAgKSB7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgIHRoaXMuZmllbGQgPSBmaWVsZDtcbiAgICB0aGlzLnBhcnNlciA9IHBhcnNlcjtcbiAgICB0aGlzLmRlZmF1bHQgPSBvcHRzLmRlZmF1bHQgfHwgcGFyc2VyLmRlZmF1bHQ7XG4gICAgdGhpcy5yZXF1aXJlZCA9IEJvb2xlYW4ob3B0cy5yZXF1aXJlZCB8fCAhcGFyc2VyLm51bGxhYmxlKTtcbiAgICB0aGlzLmNvbmN1cnJlbmN5ID0gQm9vbGVhbihvcHRzLmNvbmN1cnJlbmN5KTtcbiAgICB0aGlzLm1heExlbmd0aCA9IG9wdHMubWF4TGVuZ3RoIHx8IHBhcnNlci5tYXhMZW5ndGg7XG4gICAgdGhpcy5taW5MZW5ndGggPSBvcHRzLm1pbkxlbmd0aDtcbiAgICB0aGlzLm1pbiA9IG9wdHMubWluO1xuICAgIHRoaXMubWF4ID0gb3B0cy5tYXg7XG4gICAgdGhpcy5wYXR0ZXJuID0gb3B0cy5wYXR0ZXJuO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VyLnR5cGU7XG4gIH1cblxuICBnZXQgbmF2aWdhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5wYXJzZXIubmF2aWdhdGlvbjtcbiAgfVxuXG4gIGdldCBjb2xsZWN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnBhcnNlci5jb2xsZWN0aW9uO1xuICB9XG5cbiAgYW5ub3RhdGVkVmFsdWU8VD4odGVybTogc3RyaW5nIHwgUmVnRXhwKSB7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VyLmFubm90YXRlZFZhbHVlPFQ+KHRlcm0pO1xuICB9XG5cbiAgY29uZmlndXJlKHtcbiAgICBvcHRpb25zRm9yVHlwZSxcbiAgICBtb2RlbEZvclR5cGUsXG4gICAgY29sbGVjdGlvbkZvclR5cGUsXG4gICAgZW51bUZvclR5cGUsXG4gICAgc3RydWN0dXJlZEZvclR5cGUsXG4gICAgY29uY3VycmVuY3ksXG4gICAgb3B0aW9ucyxcbiAgfToge1xuICAgIG9wdGlvbnNGb3JUeXBlOiAodHlwZTogc3RyaW5nKSA9PiBPRGF0YU1vZGVsT3B0aW9uczxhbnk+IHwgdW5kZWZpbmVkO1xuICAgIG1vZGVsRm9yVHlwZTogKHQ6IHN0cmluZykgPT4gdHlwZW9mIE9EYXRhTW9kZWw8YW55PiB8IHVuZGVmaW5lZDtcbiAgICBjb2xsZWN0aW9uRm9yVHlwZTogKFxuICAgICAgdDogc3RyaW5nLFxuICAgICkgPT4gdHlwZW9mIE9EYXRhQ29sbGVjdGlvbjxhbnksIGFueT4gfCB1bmRlZmluZWQ7XG4gICAgZW51bUZvclR5cGU6ICh0OiBzdHJpbmcpID0+IE9EYXRhRW51bVR5cGU8YW55PiB8IHVuZGVmaW5lZDtcbiAgICBzdHJ1Y3R1cmVkRm9yVHlwZTogKHQ6IHN0cmluZykgPT4gT0RhdGFTdHJ1Y3R1cmVkVHlwZTxhbnk+IHwgdW5kZWZpbmVkO1xuICAgIGNvbmN1cnJlbmN5OiBib29sZWFuO1xuICAgIG9wdGlvbnM6IFBhcnNlck9wdGlvbnM7XG4gIH0pIHtcbiAgICB0aGlzLm9wdGlvbnNGb3JUeXBlID0gb3B0aW9uc0ZvclR5cGU7XG4gICAgdGhpcy5tb2RlbEZvclR5cGUgPSBtb2RlbEZvclR5cGU7XG4gICAgdGhpcy5jb2xsZWN0aW9uRm9yVHlwZSA9IGNvbGxlY3Rpb25Gb3JUeXBlO1xuICAgIHRoaXMuZW51bUZvclR5cGUgPSBlbnVtRm9yVHlwZTtcbiAgICB0aGlzLnN0cnVjdHVyZWRGb3JUeXBlID0gc3RydWN0dXJlZEZvclR5cGU7XG4gICAgdGhpcy5wYXJzZXJPcHRpb25zID0gb3B0aW9ucztcbiAgICBpZiAoY29uY3VycmVuY3kpIHRoaXMuY29uY3VycmVuY3kgPSBjb25jdXJyZW5jeTtcbiAgICBpZiAodGhpcy5kZWZhdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICB0aGlzLmRlZmF1bHQgPSB0aGlzLmRlc2VyaWFsaXplKHRoaXMuZGVmYXVsdCwgb3B0aW9ucyk7XG4gIH1cblxuICBpc0tleSgpIHtcbiAgICByZXR1cm4gdGhpcy5wYXJzZXIuaXNLZXkoKTtcbiAgfVxuXG4gIGhhc1JlZmVyZW50aWFscygpIHtcbiAgICByZXR1cm4gdGhpcy5wYXJzZXIuaGFzUmVmZXJlbnRpYWxzKCk7XG4gIH1cblxuICBnZXQgcmVmZXJlbnRpYWxzKCkge1xuICAgIHJldHVybiB0aGlzLnBhcnNlci5yZWZlcmVudGlhbHM7XG4gIH1cblxuICBpc1N0cnVjdHVyZWRUeXBlKCkge1xuICAgIHJldHVybiB0aGlzLnBhcnNlci5pc1N0cnVjdHVyZWRUeXBlKCk7XG4gIH1cblxuICBzdHJ1Y3R1cmVkVHlwZSgpIHtcbiAgICBjb25zdCBzdHJ1Y3R1cmVkVHlwZSA9IHRoaXMuc3RydWN0dXJlZEZvclR5cGVcbiAgICAgID8gdGhpcy5zdHJ1Y3R1cmVkRm9yVHlwZSh0aGlzLnR5cGUpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICAvL1Rocm93IGVycm9yIGlmIG5vdCBmb3VuZFxuICAgIGlmICghc3RydWN0dXJlZFR5cGUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIHN0cnVjdHVyZWQgdHlwZSBmb3IgJHt0aGlzLnBhcnNlci50eXBlfWApO1xuICAgIHJldHVybiBzdHJ1Y3R1cmVkVHlwZTtcbiAgfVxuXG4gIGlzRW51bVR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VyLmlzRW51bVR5cGUoKTtcbiAgfVxuXG4gIGVudW1UeXBlKCkge1xuICAgIGNvbnN0IGVudW1UeXBlID0gdGhpcy5lbnVtRm9yVHlwZSA/IHRoaXMuZW51bUZvclR5cGUodGhpcy50eXBlKSA6IHVuZGVmaW5lZDtcbiAgICAvL1Rocm93IGVycm9yIGlmIG5vdCBmb3VuZFxuICAgIGlmICghZW51bVR5cGUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIGVudW0gdHlwZSBmb3IgJHt0aGlzLnBhcnNlci50eXBlfWApO1xuICAgIHJldHVybiBlbnVtVHlwZTtcbiAgfVxuXG4gIHZhbGlkYXRlKFxuICAgIHZhbHVlOiBhbnksXG4gICAge1xuICAgICAgbWV0aG9kLFxuICAgICAgbmF2aWdhdGlvbiA9IGZhbHNlLFxuICAgIH06IHtcbiAgICAgIG1ldGhvZD86ICdjcmVhdGUnIHwgJ3VwZGF0ZScgfCAnbW9kaWZ5JztcbiAgICAgIG5hdmlnYXRpb24/OiBib29sZWFuO1xuICAgIH0gPSB7fSxcbiAgKSB7XG4gICAgaWYgKE9EYXRhTW9kZWxPcHRpb25zLmlzTW9kZWwodmFsdWUpKSB7XG4gICAgICByZXR1cm4gIXZhbHVlLmlzVmFsaWQoeyBtZXRob2QsIG5hdmlnYXRpb24gfSkgPyB2YWx1ZS5fZXJyb3JzIDogdW5kZWZpbmVkO1xuICAgIH0gZWxzZSBpZiAoT0RhdGFNb2RlbE9wdGlvbnMuaXNDb2xsZWN0aW9uKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgIC5tb2RlbHMoKVxuICAgICAgICAuc29tZSgobTogT0RhdGFNb2RlbDxhbnk+KSA9PiAhbS5pc1ZhbGlkKHsgbWV0aG9kLCBuYXZpZ2F0aW9uIH0pKVxuICAgICAgICA/IHZhbHVlLm1vZGVscygpLm1hcCgobTogT0RhdGFNb2RlbDxhbnk+KSA9PiBtLl9lcnJvcnMpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBjb21wdXRlZCA9IHRoaXMuYW5ub3RhdGVkVmFsdWU8Ym9vbGVhbj4oQ09NUFVURUQpO1xuICAgICAgY29uc3QgZXJyb3JzID0gdGhpcy5wYXJzZXI/LnZhbGlkYXRlKHZhbHVlLCB7IG1ldGhvZCwgbmF2aWdhdGlvbiB9KSB8fCBbXTtcbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5yZXF1aXJlZCAmJlxuICAgICAgICAodmFsdWUgPT09IG51bGwgfHwgKHZhbHVlID09PSB1bmRlZmluZWQgJiYgbWV0aG9kICE9PSAnbW9kaWZ5JykpICYmIC8vIElzIG51bGwgb3IgdW5kZWZpbmVkIHdpdGhvdXQgcGF0Y2g/XG4gICAgICAgICEoY29tcHV0ZWQgJiYgbWV0aG9kID09PSAnY3JlYXRlJykgLy8gTm90IChJcyBDb21wdXRlZCBmaWVsZCBhbmQgY3JlYXRlKSA/XG4gICAgICApIHtcbiAgICAgICAgZXJyb3JzWydwdXNoJ10oYHJlcXVpcmVkYCk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMubWF4TGVuZ3RoICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJlxuICAgICAgICB2YWx1ZS5sZW5ndGggPiB0aGlzLm1heExlbmd0aFxuICAgICAgKSB7XG4gICAgICAgIGVycm9yc1sncHVzaCddKGBtYXhsZW5ndGhgKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5taW5MZW5ndGggIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmXG4gICAgICAgIHZhbHVlLmxlbmd0aCA8IHRoaXMubWluTGVuZ3RoXG4gICAgICApIHtcbiAgICAgICAgZXJyb3JzWydwdXNoJ10oYG1pbmxlbmd0aGApO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICB0aGlzLm1pbiAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiZcbiAgICAgICAgdmFsdWUgPCB0aGlzLm1pblxuICAgICAgKSB7XG4gICAgICAgIGVycm9yc1sncHVzaCddKGBtaW5gKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5tYXggIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmXG4gICAgICAgIHZhbHVlID4gdGhpcy5tYXhcbiAgICAgICkge1xuICAgICAgICBlcnJvcnNbJ3B1c2gnXShgbWF4YCk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMucGF0dGVybiAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgIXRoaXMucGF0dGVybi50ZXN0KHZhbHVlKVxuICAgICAgKSB7XG4gICAgICAgIGVycm9yc1sncHVzaCddKGBwYXR0ZXJuYCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gIVR5cGVzLmlzRW1wdHkoZXJyb3JzKSA/IGVycm9ycyA6IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBkZWZhdWx0cygpOiBhbnkge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLm9wdGlvbnNGb3JUeXBlXG4gICAgICA/IHRoaXMub3B0aW9uc0ZvclR5cGUodGhpcy50eXBlKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHRoaXMuaXNTdHJ1Y3R1cmVkVHlwZSgpICYmIG1ldGEgIT09IHVuZGVmaW5lZFxuICAgICAgPyBtZXRhLmRlZmF1bHRzKClcbiAgICAgIDogdGhpcy5kZWZhdWx0O1xuICB9XG5cbiAgZGVzZXJpYWxpemUodmFsdWU6IGFueSwgb3B0aW9ucz86IFBhcnNlck9wdGlvbnMpOiBGIHtcbiAgICBjb25zdCBwYXJzZXJPcHRpb25zID0gb3B0aW9ucyA/PyB0aGlzLnBhcnNlck9wdGlvbnM7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VyLmRlc2VyaWFsaXplKHZhbHVlLCBwYXJzZXJPcHRpb25zKTtcbiAgfVxuXG4gIHNlcmlhbGl6ZSh2YWx1ZTogRiwgb3B0aW9ucz86IFBhcnNlck9wdGlvbnMpOiBhbnkge1xuICAgIGNvbnN0IHBhcnNlck9wdGlvbnMgPSBvcHRpb25zID8/IHRoaXMucGFyc2VyT3B0aW9ucztcbiAgICByZXR1cm4gdGhpcy5wYXJzZXIuc2VyaWFsaXplKHZhbHVlLCBwYXJzZXJPcHRpb25zKTtcbiAgfVxuXG4gIGVuY29kZSh2YWx1ZTogRiwgb3B0aW9ucz86IFBhcnNlck9wdGlvbnMpOiBhbnkge1xuICAgIGNvbnN0IHBhcnNlck9wdGlvbnMgPSBvcHRpb25zID8/IHRoaXMucGFyc2VyT3B0aW9ucztcbiAgICByZXR1cm4gdGhpcy5wYXJzZXIuZW5jb2RlKHZhbHVlLCBwYXJzZXJPcHRpb25zKTtcbiAgfVxuXG4gIHJlc291cmNlRmFjdG9yeTxULCBGPihcbiAgICBiYXNlOiBPRGF0YVJlc291cmNlPFQ+LFxuICApOiBPRGF0YU5hdmlnYXRpb25Qcm9wZXJ0eVJlc291cmNlPEY+IHwgT0RhdGFQcm9wZXJ0eVJlc291cmNlPEY+IHtcbiAgICBpZiAoXG4gICAgICAhKFxuICAgICAgICBiYXNlIGluc3RhbmNlb2YgT0RhdGFFbnRpdHlSZXNvdXJjZSB8fFxuICAgICAgICBiYXNlIGluc3RhbmNlb2YgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZSB8fFxuICAgICAgICBiYXNlIGluc3RhbmNlb2YgT0RhdGFQcm9wZXJ0eVJlc291cmNlXG4gICAgICApXG4gICAgKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgYnVpbGQgcmVzb3VyY2UgZm9yIG5vbiBjb21wYXRpYmxlIGJhc2UgdHlwZVwiKTtcbiAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uXG4gICAgICA/IChiYXNlIGFzIE9EYXRhRW50aXR5UmVzb3VyY2U8VD4pLm5hdmlnYXRpb25Qcm9wZXJ0eTxGPih0aGlzLnBhcnNlci5uYW1lKVxuICAgICAgOiAoYmFzZSBhcyBPRGF0YUVudGl0eVJlc291cmNlPFQ+KS5wcm9wZXJ0eTxGPih0aGlzLnBhcnNlci5uYW1lKTtcbiAgfVxuXG4gIGFubm90YXRpb25zRmFjdG9yeTxULCBGPihcbiAgICBiYXNlOiBPRGF0YUVudGl0eUFubm90YXRpb25zPFQ+LFxuICApOiBPRGF0YUVudGl0eUFubm90YXRpb25zPEY+IHwgT0RhdGFFbnRpdGllc0Fubm90YXRpb25zPEY+IHtcbiAgICByZXR1cm4gdGhpcy5wYXJzZXIuY29sbGVjdGlvblxuICAgICAgPyBiYXNlLnByb3BlcnR5KHRoaXMucGFyc2VyLm5hbWUgYXMga2V5b2YgVCwgJ2NvbGxlY3Rpb24nKVxuICAgICAgOiBiYXNlLnByb3BlcnR5KHRoaXMucGFyc2VyLm5hbWUgYXMga2V5b2YgVCwgJ3NpbmdsZScpO1xuICB9XG5cbiAgbW9kZWxGYWN0b3J5PEY+KHtcbiAgICBwYXJlbnQsXG4gICAgdmFsdWUsXG4gICAgcmVzZXQsXG4gIH06IHtcbiAgICBwYXJlbnQ6IE9EYXRhTW9kZWw8YW55PjtcbiAgICB2YWx1ZT86IFBhcnRpYWw8Rj4gfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfTtcbiAgICByZXNldD86IGJvb2xlYW47XG4gIH0pOiBPRGF0YU1vZGVsPEY+IHtcbiAgICAvLyBNb2RlbFxuICAgIGNvbnN0IGFubm90cyA9IHRoaXMuYW5ub3RhdGlvbnNGYWN0b3J5KFxuICAgICAgcGFyZW50LmFubm90cygpLFxuICAgICkgYXMgT0RhdGFFbnRpdHlBbm5vdGF0aW9uczxGPjtcbiAgICBsZXQgTW9kZWwgPSB0aGlzLm1vZGVsRm9yVHlwZSA/IHRoaXMubW9kZWxGb3JUeXBlKHRoaXMudHlwZSkgOiB1bmRlZmluZWQ7XG4gICAgaWYgKE1vZGVsID09PSB1bmRlZmluZWQpIHRocm93IEVycm9yKGBObyBNb2RlbCB0eXBlIGZvciAke3RoaXMubmFtZX1gKTtcbiAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYW5ub3RzLnVwZGF0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYgKGFubm90cz8udHlwZSAhPT0gdW5kZWZpbmVkICYmIE1vZGVsLm1ldGEgIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IG1ldGEgPSBNb2RlbC5tZXRhLmZpbmRDaGlsZE9wdGlvbnMoKG8pID0+XG4gICAgICAgIG8uaXNUeXBlT2YoYW5ub3RzLnR5cGUgYXMgc3RyaW5nKSxcbiAgICAgICk/LnN0cnVjdHVyZWRUeXBlO1xuICAgICAgaWYgKG1ldGEgIT09IHVuZGVmaW5lZCAmJiBtZXRhLm1vZGVsICE9PSB1bmRlZmluZWQpXG4gICAgICAgIC8vIENoYW5nZSB0byBjaGlsZCBtb2RlbFxuICAgICAgICBNb2RlbCA9IG1ldGEubW9kZWw7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBNb2RlbCgodmFsdWUgfHwge30pIGFzIFBhcnRpYWw8Rj4gfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSwge1xuICAgICAgYW5ub3RzLFxuICAgICAgcmVzZXQsXG4gICAgICBwYXJlbnQ6IFtwYXJlbnQsIHRoaXNdLFxuICAgIH0pIGFzIE9EYXRhTW9kZWw8Rj47XG4gIH1cblxuICBjb2xsZWN0aW9uRmFjdG9yeTxGPih7XG4gICAgcGFyZW50LFxuICAgIHZhbHVlLFxuICAgIHJlc2V0LFxuICB9OiB7XG4gICAgcGFyZW50OiBPRGF0YU1vZGVsPGFueT47XG4gICAgdmFsdWU/OiBQYXJ0aWFsPEY+W10gfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfVtdO1xuICAgIHJlc2V0PzogYm9vbGVhbjtcbiAgfSk6IE9EYXRhQ29sbGVjdGlvbjxGLCBPRGF0YU1vZGVsPEY+PiB7XG4gICAgLy8gQ29sbGVjdGlvbiBGYWN0b3J5XG4gICAgY29uc3QgYW5ub3RzID0gdGhpcy5hbm5vdGF0aW9uc0ZhY3RvcnkoXG4gICAgICBwYXJlbnQuYW5ub3RzKCksXG4gICAgKSBhcyBPRGF0YUVudGl0aWVzQW5ub3RhdGlvbnM8Rj47XG4gICAgY29uc3QgQ29sbGVjdGlvbiA9IHRoaXMuY29sbGVjdGlvbkZvclR5cGVcbiAgICAgID8gdGhpcy5jb2xsZWN0aW9uRm9yVHlwZSh0aGlzLnR5cGUpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBpZiAoQ29sbGVjdGlvbiA9PT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgRXJyb3IoYE5vIENvbGxlY3Rpb24gdHlwZSBmb3IgJHt0aGlzLm5hbWV9YCk7XG4gICAgcmV0dXJuIG5ldyBDb2xsZWN0aW9uKFxuICAgICAgKHZhbHVlIHx8IFtdKSBhcyBQYXJ0aWFsPEY+W10gfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfVtdLFxuICAgICAge1xuICAgICAgICBhbm5vdHM6IGFubm90cyxcbiAgICAgICAgcmVzZXQsXG4gICAgICAgIHBhcmVudDogW3BhcmVudCwgdGhpc10sXG4gICAgICB9LFxuICAgICkgYXMgT0RhdGFDb2xsZWN0aW9uPEYsIE9EYXRhTW9kZWw8Rj4+O1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBPRGF0YU1vZGVsQXR0cmlidXRlPFQ+IHtcbiAgcHJpdmF0ZSBzdGF0ZTogT0RhdGFNb2RlbFN0YXRlID0gT0RhdGFNb2RlbFN0YXRlLlVuY2hhbmdlZDtcbiAgcHJpdmF0ZSB2YWx1ZT86IFQgfCBPRGF0YU1vZGVsPFQ+IHwgT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+IHwgbnVsbDtcbiAgcHJpdmF0ZSBjaGFuZ2U/OiBUIHwgT0RhdGFNb2RlbDxUPiB8IE9EYXRhQ29sbGVjdGlvbjxULCBPRGF0YU1vZGVsPFQ+PiB8IG51bGw7XG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xuICBldmVudHMkID0gbmV3IE9EYXRhTW9kZWxFdmVudEVtaXR0ZXI8VD4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9tb2RlbDogT0RhdGFNb2RlbDxhbnk+LFxuICAgIHByaXZhdGUgX2ZpZWxkOiBPRGF0YU1vZGVsRmllbGQ8VD4sXG4gICkge31cblxuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZmllbGQudHlwZTtcbiAgfVxuXG4gIGdldCBuYXZpZ2F0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl9maWVsZC5uYXZpZ2F0aW9uO1xuICB9XG5cbiAgZ2V0IGNvbXB1dGVkKCkge1xuICAgIHJldHVybiB0aGlzLl9maWVsZC5hbm5vdGF0ZWRWYWx1ZTxib29sZWFuPihDT01QVVRFRCk7XG4gIH1cblxuICBnZXQgY29uY3VycmVuY3koKSB7XG4gICAgcmV0dXJuIEJvb2xlYW4odGhpcy5fZmllbGQuY29uY3VycmVuY3kpO1xuICB9XG5cbiAgZ2V0IHJlZmVyZW50aWFscygpIHtcbiAgICByZXR1cm4gdGhpcy5fZmllbGQucmVmZXJlbnRpYWxzO1xuICB9XG5cbiAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2ZpZWxkLm9wdGlvbnM7XG4gIH1cblxuICBnZXQgbmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZmllbGQubmFtZTtcbiAgfVxuXG4gIGdldCBmaWVsZE5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2ZpZWxkLmZpZWxkO1xuICB9XG5cbiAgZ2V0KCk6XG4gICAgfCBUXG4gICAgfCBPRGF0YU1vZGVsPFQ+XG4gICAgfCBPRGF0YUNvbGxlY3Rpb248VCwgT0RhdGFNb2RlbDxUPj5cbiAgICB8IG51bGxcbiAgICB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGUgPT09IE9EYXRhTW9kZWxTdGF0ZS5DaGFuZ2VkID8gdGhpcy5jaGFuZ2UgOiB0aGlzLnZhbHVlO1xuICB9XG5cbiAgc2V0KFxuICAgIHZhbHVlOlxuICAgICAgfCBUXG4gICAgICB8IE9EYXRhTW9kZWw8VD5cbiAgICAgIHwgT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+XG4gICAgICB8IG51bGxcbiAgICAgIHwgdW5kZWZpbmVkLFxuICAgIHJlc2V0OiBib29sZWFuID0gZmFsc2UsXG4gICAgcmVwYXJlbnQ6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKSB7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuZ2V0KCk7XG5cbiAgICBpZiAoXG4gICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc01vZGVsKGN1cnJlbnQpIHx8XG4gICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24oY3VycmVudClcbiAgICApXG4gICAgICB0aGlzLnVubGluayhcbiAgICAgICAgY3VycmVudCBhcyBPRGF0YU1vZGVsPFQ+IHwgT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+LFxuICAgICAgICAvL3RoaXMudmFsdWUgIT09IGN1cnJlbnRcbiAgICAgICk7XG5cbiAgICBjb25zdCBjaGFuZ2VkID1cbiAgICAgIE9EYXRhTW9kZWxPcHRpb25zLmlzTW9kZWwoY3VycmVudCkgJiYgT0RhdGFNb2RlbE9wdGlvbnMuaXNNb2RlbCh2YWx1ZSlcbiAgICAgICAgPyAhKGN1cnJlbnQgYXMgT0RhdGFNb2RlbDxUPikuZXF1YWxzKHZhbHVlIGFzIE9EYXRhTW9kZWw8VD4pXG4gICAgICAgIDogT0RhdGFNb2RlbE9wdGlvbnMuaXNDb2xsZWN0aW9uKGN1cnJlbnQpICYmXG4gICAgICAgICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24odmFsdWUpXG4gICAgICAgICAgPyAhKGN1cnJlbnQgYXMgT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+KS5lcXVhbHMoXG4gICAgICAgICAgICAgIHZhbHVlIGFzIE9EYXRhQ29sbGVjdGlvbjxULCBPRGF0YU1vZGVsPFQ+PixcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6ICFUeXBlcy5pc0VxdWFsKGN1cnJlbnQsIHZhbHVlKTtcbiAgICBpZiAocmVzZXQpIHtcbiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgIHRoaXMuc3RhdGUgPSBPRGF0YU1vZGVsU3RhdGUuVW5jaGFuZ2VkO1xuICAgIH0gZWxzZSBpZiAoVHlwZXMuaXNFcXVhbCh2YWx1ZSwgdGhpcy52YWx1ZSkpIHtcbiAgICAgIHRoaXMuc3RhdGUgPSBPRGF0YU1vZGVsU3RhdGUuVW5jaGFuZ2VkO1xuICAgIH0gZWxzZSBpZiAoY2hhbmdlZCkge1xuICAgICAgdGhpcy5jaGFuZ2UgPSB2YWx1ZTtcbiAgICAgIHRoaXMuc3RhdGUgPSBPRGF0YU1vZGVsU3RhdGUuQ2hhbmdlZDtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgT0RhdGFNb2RlbE9wdGlvbnMuaXNNb2RlbCh2YWx1ZSkgfHxcbiAgICAgIE9EYXRhTW9kZWxPcHRpb25zLmlzQ29sbGVjdGlvbih2YWx1ZSlcbiAgICApIHtcbiAgICAgIHRoaXMubGluayhcbiAgICAgICAgdmFsdWUgYXMgT0RhdGFNb2RlbDxUPiB8IE9EYXRhQ29sbGVjdGlvbjxULCBPRGF0YU1vZGVsPFQ+PixcbiAgICAgICAgcmVwYXJlbnQsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY2hhbmdlZDtcbiAgfVxuXG4gIGlzQ2hhbmdlZCh7XG4gICAgaW5jbHVkZV9uYXZpZ2F0aW9uID0gZmFsc2UsXG4gIH06IHsgaW5jbHVkZV9uYXZpZ2F0aW9uPzogYm9vbGVhbiB9ID0ge30pOiBib29sZWFuIHtcbiAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5nZXQoKTtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5zdGF0ZSA9PT0gT0RhdGFNb2RlbFN0YXRlLkNoYW5nZWQgfHxcbiAgICAgICgoT0RhdGFNb2RlbE9wdGlvbnMuaXNNb2RlbChjdXJyZW50KSB8fFxuICAgICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24oY3VycmVudCkpICYmXG4gICAgICAgIChcbiAgICAgICAgICBjdXJyZW50IGFzIE9EYXRhTW9kZWw8VD4gfCBPRGF0YUNvbGxlY3Rpb248VCwgT0RhdGFNb2RlbDxUPj5cbiAgICAgICAgKS5oYXNDaGFuZ2VkKHsgaW5jbHVkZV9uYXZpZ2F0aW9uIH0pKVxuICAgICk7XG4gIH1cblxuICByZXNldCgpIHtcbiAgICBpZiAoXG4gICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc01vZGVsKHRoaXMuY2hhbmdlKSB8fFxuICAgICAgT0RhdGFNb2RlbE9wdGlvbnMuaXNDb2xsZWN0aW9uKHRoaXMuY2hhbmdlKVxuICAgIClcbiAgICAgIHRoaXMudW5saW5rKFxuICAgICAgICB0aGlzLmNoYW5nZSBhcyBPRGF0YU1vZGVsPFQ+IHwgT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+LFxuICAgICAgKTtcbiAgICB0aGlzLnN0YXRlID0gT0RhdGFNb2RlbFN0YXRlLlVuY2hhbmdlZDtcbiAgICBpZiAoXG4gICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc01vZGVsKHRoaXMudmFsdWUpIHx8XG4gICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24odGhpcy52YWx1ZSlcbiAgICApXG4gICAgICB0aGlzLmxpbmsoXG4gICAgICAgIHRoaXMudmFsdWUgYXMgT0RhdGFNb2RlbDxUPiB8IE9EYXRhQ29sbGVjdGlvbjxULCBPRGF0YU1vZGVsPFQ+PixcbiAgICAgICk7XG4gIH1cblxuICBwcml2YXRlIGxpbmsoXG4gICAgdmFsdWU6IE9EYXRhTW9kZWw8VD4gfCBPRGF0YUNvbGxlY3Rpb248VCwgT0RhdGFNb2RlbDxUPj4sXG4gICAgcmVwYXJlbnQ6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24gPSB2YWx1ZS5ldmVudHMkLnN1YnNjcmliZSgoZSkgPT4gdGhpcy5ldmVudHMkLmVtaXQoZSkpO1xuICAgIGlmIChyZXBhcmVudCkge1xuICAgICAgdmFsdWUuX3BhcmVudCA9IFt0aGlzLl9tb2RlbCwgdGhpcy5fZmllbGRdO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdW5saW5rKFxuICAgIHZhbHVlOiBPRGF0YU1vZGVsPFQ+IHwgT0RhdGFDb2xsZWN0aW9uPFQsIE9EYXRhTW9kZWw8VD4+LFxuICAgIHJlcGFyZW50OiBib29sZWFuID0gZmFsc2UsXG4gICkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgIGlmIChyZXBhcmVudCkge1xuICAgICAgdmFsdWUuX3BhcmVudCA9IG51bGw7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCB0eXBlIE9EYXRhTW9kZWxFbnRyeTxULCBNIGV4dGVuZHMgT0RhdGFNb2RlbDxUPj4gPSB7XG4gIHN0YXRlOiBPRGF0YU1vZGVsU3RhdGU7XG4gIG1vZGVsOiBNO1xuICBrZXk/OiBFbnRpdHlLZXk8VD4gfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfTtcbiAgc3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xufTtcblxuZXhwb3J0IGNsYXNzIE9EYXRhTW9kZWxPcHRpb25zPFQ+IHtcbiAgbmFtZTogc3RyaW5nO1xuICBjaWQ6IHN0cmluZztcbiAgYmFzZT86IHN0cmluZztcbiAgcHJpdmF0ZSBfZmllbGRzOiBPRGF0YU1vZGVsRmllbGQ8YW55PltdID0gW107XG4gIHN0cnVjdHVyZWRUeXBlOiBPRGF0YVN0cnVjdHVyZWRUeXBlPFQ+O1xuICBlbnRpdHlTZXQ/OiBPRGF0YUVudGl0eVNldDtcbiAgLy8gSGllcmFyY2h5XG4gIHBhcmVudD86IE9EYXRhTW9kZWxPcHRpb25zPGFueT47XG4gIGNoaWxkcmVuOiBPRGF0YU1vZGVsT3B0aW9uczxhbnk+W10gPSBbXTtcbiAgZXZlbnRzJCA9IG5ldyBPRGF0YU1vZGVsRXZlbnRFbWl0dGVyPFQ+KCk7XG5cbiAgY29uc3RydWN0b3Ioe1xuICAgIGNvbmZpZyxcbiAgICBzdHJ1Y3R1cmVkVHlwZSxcbiAgfToge1xuICAgIGNvbmZpZzogTW9kZWxPcHRpb25zO1xuICAgIHN0cnVjdHVyZWRUeXBlOiBPRGF0YVN0cnVjdHVyZWRUeXBlPFQ+O1xuICB9KSB7XG4gICAgdGhpcy5uYW1lID0gc3RydWN0dXJlZFR5cGUubmFtZTtcbiAgICB0aGlzLmJhc2UgPSBzdHJ1Y3R1cmVkVHlwZS5iYXNlO1xuICAgIHRoaXMuc3RydWN0dXJlZFR5cGUgPSBzdHJ1Y3R1cmVkVHlwZTtcbiAgICB0aGlzLmNpZCA9IGNvbmZpZz8uY2lkID8/IENJRF9GSUVMRF9OQU1FO1xuICAgIGNvbmZpZy5maWVsZHMuZm9yRWFjaCgodmFsdWUsIGtleSkgPT4gdGhpcy5hZGRGaWVsZDxhbnk+KGtleSwgdmFsdWUpKTtcbiAgfVxuXG4gIGdldCBhcGkoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RydWN0dXJlZFR5cGUuYXBpO1xuICB9XG5cbiAgdHlwZSh7IGFsaWFzID0gZmFsc2UgfTogeyBhbGlhcz86IGJvb2xlYW4gfSA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuc3RydWN0dXJlZFR5cGUudHlwZSh7IGFsaWFzIH0pO1xuICB9XG5cbiAgaXNPcGVuVHlwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zdHJ1Y3R1cmVkVHlwZS5pc09wZW5UeXBlKCk7XG4gIH1cblxuICBpc0VudGl0eVR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RydWN0dXJlZFR5cGUuaXNFbnRpdHlUeXBlKCk7XG4gIH1cblxuICBpc0NvbXBsZXhUeXBlKCkge1xuICAgIHJldHVybiB0aGlzLnN0cnVjdHVyZWRUeXBlLmlzQ29tcGxleFR5cGUoKTtcbiAgfVxuXG4gIGlzVHlwZU9mKHR5cGU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLnN0cnVjdHVyZWRUeXBlLnR5cGUoKSA9PT0gdHlwZTtcbiAgfVxuXG4gIGlzTW9kZWxGb3IoZW50aXR5OiBUIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH0pIHtcbiAgICAvLyBSZXNvbHZlIEJ5IFR5cGVcbiAgICBjb25zdCB0eXBlID0gdGhpcy5hcGkub3B0aW9ucy5oZWxwZXIudHlwZShcbiAgICAgIGVudGl0eSBhcyB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSxcbiAgICApO1xuICAgIGlmICh0eXBlICYmIHRoaXMuaXNUeXBlT2YodHlwZSkpIHJldHVybiB0cnVlO1xuICAgIC8vIFJlc29sdmUgQnkgZmllbGRzXG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGVudGl0eSBhcyB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSk7XG4gICAgY29uc3QgbmFtZXMgPSB0aGlzLmZpZWxkcyh7XG4gICAgICBpbmNsdWRlX25hdmlnYXRpb246IHRydWUsXG4gICAgICBpbmNsdWRlX3BhcmVudHM6IHRydWUsXG4gICAgfSkubWFwKChmKSA9PiBmLm5hbWUpO1xuICAgIHJldHVybiBrZXlzLmV2ZXJ5KChrZXkpID0+IG5hbWVzLmluY2x1ZGVzKGtleSkpO1xuICB9XG5cbiAgZmluZENoaWxkT3B0aW9ucyhcbiAgICBwcmVkaWNhdGU6IChvcHRpb25zOiBPRGF0YU1vZGVsT3B0aW9uczxhbnk+KSA9PiBib29sZWFuLFxuICApOiBPRGF0YU1vZGVsT3B0aW9uczxhbnk+IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAocHJlZGljYXRlKHRoaXMpKSByZXR1cm4gdGhpcztcbiAgICBsZXQgbWF0Y2g6IE9EYXRhTW9kZWxPcHRpb25zPGFueT4gfCB1bmRlZmluZWQ7XG4gICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLmNoaWxkcmVuKSB7XG4gICAgICBtYXRjaCA9IGNoLmZpbmRDaGlsZE9wdGlvbnMocHJlZGljYXRlKTtcbiAgICAgIGlmIChtYXRjaCAhPT0gdW5kZWZpbmVkKSBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoO1xuICB9XG5cbiAgY29uZmlndXJlKHsgb3B0aW9ucyB9OiB7IG9wdGlvbnM6IFBhcnNlck9wdGlvbnMgfSkge1xuICAgIGlmICh0aGlzLmJhc2UpIHtcbiAgICAgIGNvbnN0IHBhcmVudCA9IHRoaXMuYXBpLm9wdGlvbnNGb3JUeXBlKFxuICAgICAgICB0aGlzLmJhc2UsXG4gICAgICApIGFzIE9EYXRhTW9kZWxPcHRpb25zPGFueT47XG4gICAgICBwYXJlbnQuY2hpbGRyZW4ucHVzaCh0aGlzKTtcbiAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgIH1cbiAgICB0aGlzLmVudGl0eVNldCA9IHRoaXMuYXBpLmZpbmRFbnRpdHlTZXRGb3JFbnRpdHlUeXBlKHRoaXMudHlwZSgpKTtcbiAgICBsZXQgY29uY3VycmVuY3lGaWVsZHM6IHN0cmluZ1tdID0gW107XG4gICAgaWYgKHRoaXMuZW50aXR5U2V0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbmN1cnJlbmN5RmllbGRzID1cbiAgICAgICAgdGhpcy5lbnRpdHlTZXQuYW5ub3RhdGVkVmFsdWU8c3RyaW5nW10+KE9QVElNSVNUSUNfQ09OQ1VSUkVOQ1kpIHx8IFtdO1xuICAgIH1cbiAgICB0aGlzLl9maWVsZHMuZm9yRWFjaCgoZmllbGQpID0+IHtcbiAgICAgIGNvbnN0IGNvbmN1cnJlbmN5ID0gY29uY3VycmVuY3lGaWVsZHMuaW5kZXhPZihmaWVsZC5maWVsZCkgIT09IC0xO1xuICAgICAgZmllbGQuY29uZmlndXJlKHtcbiAgICAgICAgb3B0aW9uc0ZvclR5cGU6ICh0OiBzdHJpbmcpID0+IHRoaXMuYXBpLm9wdGlvbnNGb3JUeXBlKHQpLFxuICAgICAgICBtb2RlbEZvclR5cGU6ICh0OiBzdHJpbmcpID0+IHRoaXMuYXBpLm1vZGVsRm9yVHlwZSh0KSxcbiAgICAgICAgY29sbGVjdGlvbkZvclR5cGU6ICh0OiBzdHJpbmcpID0+IHRoaXMuYXBpLmNvbGxlY3Rpb25Gb3JUeXBlKHQpLFxuICAgICAgICBlbnVtRm9yVHlwZTogKHQ6IHN0cmluZykgPT4gdGhpcy5hcGkuZmluZEVudW1UeXBlKHQpLFxuICAgICAgICBzdHJ1Y3R1cmVkRm9yVHlwZTogKHQ6IHN0cmluZykgPT4gdGhpcy5hcGkuZmluZFN0cnVjdHVyZWRUeXBlKHQpLFxuICAgICAgICBjb25jdXJyZW5jeSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZmllbGRzKHtcbiAgICBpbmNsdWRlX25hdmlnYXRpb24sXG4gICAgaW5jbHVkZV9wYXJlbnRzLFxuICB9OiB7XG4gICAgaW5jbHVkZV9wYXJlbnRzOiBib29sZWFuO1xuICAgIGluY2x1ZGVfbmF2aWdhdGlvbjogYm9vbGVhbjtcbiAgfSk6IE9EYXRhTW9kZWxGaWVsZDxhbnk+W10ge1xuICAgIHJldHVybiBbXG4gICAgICAuLi4oaW5jbHVkZV9wYXJlbnRzICYmIHRoaXMucGFyZW50ICE9PSB1bmRlZmluZWRcbiAgICAgICAgPyB0aGlzLnBhcmVudC5maWVsZHMoeyBpbmNsdWRlX25hdmlnYXRpb24sIGluY2x1ZGVfcGFyZW50cyB9KVxuICAgICAgICA6IFtdKSxcbiAgICAgIC4uLnRoaXMuX2ZpZWxkcy5maWx0ZXIoXG4gICAgICAgIChmaWVsZCkgPT4gaW5jbHVkZV9uYXZpZ2F0aW9uIHx8ICFmaWVsZC5uYXZpZ2F0aW9uLFxuICAgICAgKSxcbiAgICBdO1xuICB9XG5cbiAgZmllbGQ8Rj4obmFtZToga2V5b2YgVCB8IHN0cmluZykge1xuICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maW5kRmllbGQ8Rj4obmFtZSk7XG4gICAgLy9UaHJvdyBlcnJvciBpZiBub3QgZm91bmRcbiAgICBpZiAoIWZpZWxkKSB0aHJvdyBuZXcgRXJyb3IoYE5vIGZpZWxkIHdpdGggbmFtZSAke25hbWUgYXMgc3RyaW5nfWApO1xuICAgIHJldHVybiBmaWVsZCBhcyBPRGF0YU1vZGVsRmllbGQ8Rj47XG4gIH1cblxuICBmaW5kRmllbGQ8Rj4oXG4gICAgbmFtZToga2V5b2YgVCB8IHN0cmluZyxcbiAgICB7IHJlc2V0IH06IHsgcmVzZXQ/OiBib29sZWFuIH0gPSB7fSxcbiAgKTogT0RhdGFNb2RlbEZpZWxkPEY+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5maWVsZHMoe1xuICAgICAgaW5jbHVkZV9wYXJlbnRzOiB0cnVlLFxuICAgICAgaW5jbHVkZV9uYXZpZ2F0aW9uOiB0cnVlLFxuICAgIH0pLmZpbmQoXG4gICAgICAobW9kZWxGaWVsZDogT0RhdGFNb2RlbEZpZWxkPEY+KSA9PlxuICAgICAgICAocmVzZXQgJiYgbW9kZWxGaWVsZC5maWVsZCA9PT0gbmFtZSkgfHwgbW9kZWxGaWVsZC5uYW1lID09PSBuYW1lLFxuICAgICkgYXMgT0RhdGFNb2RlbEZpZWxkPEY+IHwgdW5kZWZpbmVkO1xuICB9XG5cbiAgYWRkRmllbGQ8Rj4obmFtZTogc3RyaW5nLCBvcHRpb25zOiBNb2RlbEZpZWxkT3B0aW9ucykge1xuICAgIGNvbnN0IHsgZmllbGQsIHBhcnNlciwgLi4ub3B0cyB9ID0gb3B0aW9ucztcbiAgICBpZiAoZmllbGQgPT09IHVuZGVmaW5lZCB8fCBuYW1lID09PSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vZGVsIFByb3BlcnRpZXMgbmVlZCBuYW1lIGFuZCBmaWVsZCcpO1xuICAgIGNvbnN0IGZpZWxkUGFyc2VyID1cbiAgICAgIHBhcnNlciA/PyB0aGlzLnN0cnVjdHVyZWRUeXBlLmZpZWxkPEY+KGZpZWxkIGFzIGtleW9mIFQpO1xuICAgIGlmIChmaWVsZFBhcnNlciA9PT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBwYXJzZXIgZm9yICR7ZmllbGR9IHdpdGggbmFtZSA9ICR7bmFtZX1gKTtcbiAgICBjb25zdCBtb2RlbEZpZWxkID0gbmV3IE9EYXRhTW9kZWxGaWVsZDxGPih0aGlzLCB7XG4gICAgICBuYW1lLFxuICAgICAgZmllbGQsXG4gICAgICBwYXJzZXI6IGZpZWxkUGFyc2VyLFxuICAgICAgLi4ub3B0cyxcbiAgICB9KTtcbiAgICB0aGlzLl9maWVsZHMucHVzaChtb2RlbEZpZWxkKTtcbiAgICByZXR1cm4gbW9kZWxGaWVsZDtcbiAgfVxuXG4gIHRzVG9FZG06IFJlY29yZDxzdHJpbmcsIEVkbVR5cGU+ID0ge1xuICAgIHN0cmluZzogRWRtVHlwZS5TdHJpbmcsXG4gICAgbnVtYmVyOiBFZG1UeXBlLkludDMyLFxuICAgIGJpZ2ludDogRWRtVHlwZS5JbnQ2NCxcbiAgICBib29sZWFuOiBFZG1UeXBlLkJvb2xlYW4sXG4gIH07XG4gIHByaXZhdGUgbW9kZWxGaWVsZEZhY3Rvcnk8Rj4oXG4gICAgc2VsZjogT0RhdGFNb2RlbDxUPixcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgdHlwZTogRWRtVHlwZSB8IHN0cmluZyxcbiAgKSB7XG4gICAgY29uc3Qgc3RydWN0dXJlZEZpZWxkUGFyc2VyID0gdGhpcy5zdHJ1Y3R1cmVkVHlwZS5hZGRGaWVsZDxGPihuYW1lLCB7XG4gICAgICB0eXBlLFxuICAgIH0pO1xuICAgIHN0cnVjdHVyZWRGaWVsZFBhcnNlci5jb25maWd1cmUoe1xuICAgICAgcGFyc2VyRm9yVHlwZTogKHR5cGU6IEVkbVR5cGUgfCBzdHJpbmcpID0+IHRoaXMuYXBpLnBhcnNlckZvclR5cGUodHlwZSksXG4gICAgICBvcHRpb25zOiB0aGlzLmFwaS5vcHRpb25zLFxuICAgIH0pO1xuICAgIGNvbnN0IG1vZGVsRmllbGQgPSB0aGlzLmFkZEZpZWxkPEY+KG5hbWUsIHtcbiAgICAgIGZpZWxkOiBuYW1lLFxuICAgICAgcGFyc2VyOiBzdHJ1Y3R1cmVkRmllbGRQYXJzZXIsXG4gICAgfSk7XG4gICAgbW9kZWxGaWVsZC5jb25maWd1cmUoe1xuICAgICAgb3B0aW9uc0ZvclR5cGU6ICh0OiBzdHJpbmcpID0+IHRoaXMuYXBpLm9wdGlvbnNGb3JUeXBlKHQpLFxuICAgICAgbW9kZWxGb3JUeXBlOiAodDogc3RyaW5nKSA9PiB0aGlzLmFwaS5tb2RlbEZvclR5cGUodCksXG4gICAgICBjb2xsZWN0aW9uRm9yVHlwZTogKHQ6IHN0cmluZykgPT4gdGhpcy5hcGkuY29sbGVjdGlvbkZvclR5cGUodCksXG4gICAgICBlbnVtRm9yVHlwZTogKHQ6IHN0cmluZykgPT4gdGhpcy5hcGkuZmluZEVudW1UeXBlKHQpLFxuICAgICAgc3RydWN0dXJlZEZvclR5cGU6ICh0OiBzdHJpbmcpID0+IHRoaXMuYXBpLmZpbmRTdHJ1Y3R1cmVkVHlwZSh0KSxcbiAgICAgIG9wdGlvbnM6IHRoaXMuYXBpLm9wdGlvbnMsXG4gICAgICBjb25jdXJyZW5jeTogZmFsc2UsXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHNlbGYsIG1vZGVsRmllbGQubmFtZSwge1xuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgZ2V0OiAoKSA9PiB0aGlzLmdldChzZWxmLCBtb2RlbEZpZWxkIGFzIE9EYXRhTW9kZWxGaWVsZDxhbnk+KSxcbiAgICAgIHNldDogKHZhbHVlOiBhbnkpID0+XG4gICAgICAgIHRoaXMuc2V0KHNlbGYsIG1vZGVsRmllbGQgYXMgT0RhdGFNb2RlbEZpZWxkPGFueT4sIHZhbHVlKSxcbiAgICB9KTtcbiAgICByZXR1cm4gbW9kZWxGaWVsZDtcbiAgfVxuXG4gIGF0dGFjaChcbiAgICBzZWxmOiBPRGF0YU1vZGVsPFQ+LFxuICAgIHJlc291cmNlOlxuICAgICAgfCBPRGF0YUVudGl0eVJlc291cmNlPFQ+XG4gICAgICB8IE9EYXRhTmF2aWdhdGlvblByb3BlcnR5UmVzb3VyY2U8VD5cbiAgICAgIHwgT0RhdGFQcm9wZXJ0eVJlc291cmNlPFQ+XG4gICAgICB8IE9EYXRhU2luZ2xldG9uUmVzb3VyY2U8VD4sXG4gICkge1xuICAgIGlmIChcbiAgICAgIHNlbGYuX3Jlc291cmNlICE9PSBudWxsICYmXG4gICAgICByZXNvdXJjZS5vdXRnb2luZ1R5cGUoKSAhPT0gc2VsZi5fcmVzb3VyY2Uub3V0Z29pbmdUeXBlKCkgJiZcbiAgICAgICFzZWxmLl9yZXNvdXJjZS5pc1N1YnR5cGVPZihyZXNvdXJjZSlcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW4ndCBhdHRhY2ggJHtyZXNvdXJjZS5vdXRnb2luZ1R5cGUoKX0gdG8gJHtzZWxmLl9yZXNvdXJjZS5vdXRnb2luZ1R5cGUoKX1gLFxuICAgICAgKTtcblxuICAgIGNvbnN0IGN1cnJlbnQgPSBzZWxmLl9yZXNvdXJjZTtcbiAgICBpZiAoY3VycmVudCA9PT0gbnVsbCB8fCAhY3VycmVudC5pc0VxdWFsVG8ocmVzb3VyY2UpKSB7XG4gICAgICBzZWxmLl9yZXNvdXJjZSA9IHJlc291cmNlO1xuICAgICAgc2VsZi5ldmVudHMkLnRyaWdnZXIoT0RhdGFNb2RlbEV2ZW50VHlwZS5BdHRhY2gsIHtcbiAgICAgICAgcHJldmlvdXM6IGN1cnJlbnQsXG4gICAgICAgIHZhbHVlOiByZXNvdXJjZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIyByZWdpb24gUmVzb3VyY2VcbiAgc3RhdGljIGNoYWluKFxuICAgIGNoaWxkOiBPRGF0YU1vZGVsPGFueT4gfCBPRGF0YUNvbGxlY3Rpb248YW55LCBPRGF0YU1vZGVsPGFueT4+LFxuICApOiBbXG4gICAgT0RhdGFNb2RlbDxhbnk+IHwgT0RhdGFDb2xsZWN0aW9uPGFueSwgT0RhdGFNb2RlbDxhbnk+PixcbiAgICBPRGF0YU1vZGVsRmllbGQ8YW55PiB8IG51bGwsXG4gIF1bXSB7XG4gICAgY29uc3QgY2hhaW4gPSBbXSBhcyBhbnlbXTtcbiAgICBsZXQgdHVwbGU6XG4gICAgICB8IFtcbiAgICAgICAgICBPRGF0YU1vZGVsPGFueT4gfCBPRGF0YUNvbGxlY3Rpb248YW55LCBPRGF0YU1vZGVsPGFueT4+LFxuICAgICAgICAgIE9EYXRhTW9kZWxGaWVsZDxhbnk+IHwgbnVsbCxcbiAgICAgICAgXVxuICAgICAgfCBudWxsID0gW2NoaWxkLCBudWxsXTtcbiAgICB3aGlsZSAodHVwbGUgIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IHBhcmVudCA9IHR1cGxlIGFzIFtcbiAgICAgICAgT0RhdGFNb2RlbDxhbnk+IHwgT0RhdGFDb2xsZWN0aW9uPGFueSwgT0RhdGFNb2RlbDxhbnk+PixcbiAgICAgICAgT0RhdGFNb2RlbEZpZWxkPGFueT4gfCBudWxsLFxuICAgICAgXTtcbiAgICAgIGlmIChjaGFpbi5zb21lKChwKSA9PiBwWzBdID09PSBwYXJlbnRbMF0pKSBicmVhaztcbiAgICAgIGNoYWluLnNwbGljZSgwLCAwLCBwYXJlbnQpO1xuICAgICAgdHVwbGUgPSB0dXBsZVswXS5fcGFyZW50O1xuICAgIH1cbiAgICByZXR1cm4gY2hhaW47XG4gIH1cblxuICBzdGF0aWMgcmVzb3VyY2U8VD4oXG4gICAgY2hpbGQ6IE9EYXRhTW9kZWw8VD4gfCBPRGF0YUNvbGxlY3Rpb248VCwgT0RhdGFNb2RlbDxUPj4sXG4gICk6IE9EYXRhUmVzb3VyY2U8VD4gfCBudWxsIHtcbiAgICBsZXQgcmVzb3VyY2U6IE9EYXRhUmVzb3VyY2U8YW55PiB8IG51bGwgPSBudWxsO1xuICAgIGxldCBwcmV2RmllbGQ6IE9EYXRhTW9kZWxGaWVsZDxhbnk+IHwgbnVsbCA9IG51bGw7XG4gICAgZm9yIChjb25zdCBbbW9kZWwsIGZpZWxkXSBvZiBPRGF0YU1vZGVsT3B0aW9ucy5jaGFpbihjaGlsZCkpIHtcbiAgICAgIHJlc291cmNlID0gcmVzb3VyY2UgfHwgKG1vZGVsLl9yZXNvdXJjZSBhcyBPRGF0YVJlc291cmNlPFQ+KTtcbiAgICAgIGlmIChyZXNvdXJjZSA9PT0gbnVsbCkgYnJlYWs7XG4gICAgICBpZiAoXG4gICAgICAgIE9EYXRhTW9kZWxPcHRpb25zLmlzTW9kZWwobW9kZWwpICYmXG4gICAgICAgIChwcmV2RmllbGQgPT09IG51bGwgfHwgcHJldkZpZWxkLmNvbGxlY3Rpb24pXG4gICAgICApIHtcbiAgICAgICAgY29uc3QgbSA9IG1vZGVsIGFzIE9EYXRhTW9kZWw8YW55PjtcbiAgICAgICAgLy8gUmVzb2x2ZSBzdWJ0eXBlIGlmIGNvbGxlY3Rpb24gbm90IGlzIGZyb20gZmllbGRcbiAgICAgICAgLy8gRklYTUVcbiAgICAgICAgLypcbiAgICAgICAgaWYgKGZpZWxkID09PSBudWxsKSB7XG4gICAgICAgICAgY29uc3QgciA9IG0uX21ldGEubW9kZWxSZXNvdXJjZUZhY3RvcnkocmVzb3VyY2UuY2xvbmVRdWVyeTxUPigpKTtcbiAgICAgICAgICBpZiAociAhPT0gbnVsbCAmJiAhci5pc1R5cGVPZihyZXNvdXJjZSkgJiYgci5pc1N1YnR5cGVPZihyZXNvdXJjZSkpIHtcbiAgICAgICAgICAgIHJlc291cmNlID0gcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgKi9cbiAgICAgICAgLy8gUmVzb2x2ZSBrZXlcbiAgICAgICAgY29uc3QgbUtleSA9IG0ua2V5KHsgZmllbGRfbWFwcGluZzogdHJ1ZSB9KSBhcyBFbnRpdHlLZXk8YW55PjtcbiAgICAgICAgaWYgKG1LZXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJlc291cmNlID1cbiAgICAgICAgICAgIHJlc291cmNlIGluc3RhbmNlb2YgT0RhdGFFbnRpdHlTZXRSZXNvdXJjZVxuICAgICAgICAgICAgICA/IHJlc291cmNlLmVudGl0eShtS2V5KVxuICAgICAgICAgICAgICA6IChyZXNvdXJjZSBhcyBPRGF0YUVudGl0eVJlc291cmNlPFQ+KS5rZXkobUtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHByZXZGaWVsZCA9IGZpZWxkO1xuICAgICAgaWYgKGZpZWxkID09PSBudWxsICYmIG1vZGVsLl9yZXNvdXJjZSAhPT0gbnVsbCkge1xuICAgICAgICAvLyBBcHBseSB0aGUgcXVlcnkgZnJvbSBtb2RlbCB0byBuZXcgcmVzb3VyY2VcbiAgICAgICAgbW9kZWwuX3Jlc291cmNlLnF1ZXJ5KChxcykgPT5cbiAgICAgICAgICByZXNvdXJjZT8ucXVlcnkoKHFkKSA9PiBxZC5yZXN0b3JlKHFzLnN0b3JlKCkpKSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQgIT09IG51bGwpIHtcbiAgICAgICAgcmVzb3VyY2UgPSBmaWVsZC5yZXNvdXJjZUZhY3Rvcnk8YW55LCBhbnk+KHJlc291cmNlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc291cmNlO1xuICB9XG5cbiAgY29sbGVjdGlvblJlc291cmNlRmFjdG9yeShcbiAgICBxdWVyeT86IE9EYXRhUXVlcnlPcHRpb25zPFQ+LFxuICApOlxuICAgIHwgT0RhdGFFbnRpdHlTZXRSZXNvdXJjZTxUPlxuICAgIHwgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZTxUPlxuICAgIHwgT0RhdGFQcm9wZXJ0eVJlc291cmNlPFQ+XG4gICAgfCBudWxsIHtcbiAgICBpZiAodGhpcy5lbnRpdHlTZXQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIE9EYXRhRW50aXR5U2V0UmVzb3VyY2UuZmFjdG9yeTxUPih0aGlzLmFwaSwge1xuICAgICAgcGF0aDogdGhpcy5lbnRpdHlTZXQubmFtZSxcbiAgICAgIHR5cGU6IHRoaXMuZW50aXR5U2V0LmVudGl0eVR5cGUsXG4gICAgICBxdWVyeSxcbiAgICB9KTtcbiAgfVxuXG4gIG1vZGVsUmVzb3VyY2VGYWN0b3J5KFxuICAgIHF1ZXJ5PzogT0RhdGFRdWVyeU9wdGlvbnM8VD4sXG4gICk6XG4gICAgfCBPRGF0YUVudGl0eVJlc291cmNlPFQ+XG4gICAgfCBPRGF0YU5hdmlnYXRpb25Qcm9wZXJ0eVJlc291cmNlPFQ+XG4gICAgfCBPRGF0YVByb3BlcnR5UmVzb3VyY2U8VD5cbiAgICB8IE9EYXRhU2luZ2xldG9uUmVzb3VyY2U8VD5cbiAgICB8IG51bGwge1xuICAgIGNvbnN0IHJlc291cmNlID0gdGhpcy5jb2xsZWN0aW9uUmVzb3VyY2VGYWN0b3J5KHF1ZXJ5KTtcbiAgICBpZiAocmVzb3VyY2UgaW5zdGFuY2VvZiBPRGF0YUVudGl0eVNldFJlc291cmNlKSByZXR1cm4gcmVzb3VyY2UuZW50aXR5KCk7XG4gICAgcmV0dXJuIHJlc291cmNlIGFzXG4gICAgICB8IE9EYXRhRW50aXR5UmVzb3VyY2U8VD5cbiAgICAgIHwgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZTxUPlxuICAgICAgfCBPRGF0YVByb3BlcnR5UmVzb3VyY2U8VD5cbiAgICAgIHwgT0RhdGFTaW5nbGV0b25SZXNvdXJjZTxUPlxuICAgICAgfCBudWxsO1xuICB9XG4gIC8vI2VuZHJlZ2lvblxuXG4gIGJpbmQoXG4gICAgc2VsZjogT0RhdGFNb2RlbDxUPixcbiAgICB7XG4gICAgICBwYXJlbnQsXG4gICAgICByZXNvdXJjZSxcbiAgICAgIGFubm90cyxcbiAgICB9OiB7XG4gICAgICBwYXJlbnQ/OiBbXG4gICAgICAgIE9EYXRhTW9kZWw8YW55PiB8IE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4sXG4gICAgICAgIE9EYXRhTW9kZWxGaWVsZDxhbnk+IHwgbnVsbCxcbiAgICAgIF07XG4gICAgICByZXNvdXJjZT86IE9EYXRhUmVzb3VyY2U8VD4gfCBudWxsO1xuICAgICAgYW5ub3RzPzogT0RhdGFFbnRpdHlBbm5vdGF0aW9uczxUPjtcbiAgICB9ID0ge30sXG4gICkge1xuICAgIC8vIEV2ZW50c1xuICAgIHNlbGYuZXZlbnRzJC5zdWJzY3JpYmUoKGUpID0+IHRoaXMuZXZlbnRzJC5lbWl0KGUpKTtcblxuICAgIC8vIFBhcmVudFxuICAgIGlmIChwYXJlbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc2VsZi5fcGFyZW50ID0gcGFyZW50O1xuICAgIH1cblxuICAgIC8vIFJlc291cmNlXG4gICAgaWYgKHNlbGYuX3BhcmVudCA9PT0gbnVsbCAmJiByZXNvdXJjZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgcmVzb3VyY2UgPSB0aGlzLm1vZGVsUmVzb3VyY2VGYWN0b3J5KCk7XG4gICAgaWYgKHJlc291cmNlKSB7XG4gICAgICB0aGlzLmF0dGFjaChcbiAgICAgICAgc2VsZixcbiAgICAgICAgcmVzb3VyY2UgYXNcbiAgICAgICAgICB8IE9EYXRhRW50aXR5UmVzb3VyY2U8VD5cbiAgICAgICAgICB8IE9EYXRhUHJvcGVydHlSZXNvdXJjZTxUPlxuICAgICAgICAgIHwgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZTxUPlxuICAgICAgICAgIHwgT0RhdGFTaW5nbGV0b25SZXNvdXJjZTxUPixcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gQW5ub3RhdGlvbnNcbiAgICBzZWxmLl9hbm5vdGF0aW9ucyA9XG4gICAgICBhbm5vdHMgPz8gbmV3IE9EYXRhRW50aXR5QW5ub3RhdGlvbnMoT0RhdGFIZWxwZXJbREVGQVVMVF9WRVJTSU9OXSk7XG5cbiAgICAvLyBGaWVsZHNcbiAgICB0aGlzLmZpZWxkcyh7XG4gICAgICBpbmNsdWRlX25hdmlnYXRpb246IHRydWUsXG4gICAgICBpbmNsdWRlX3BhcmVudHM6IHRydWUsXG4gICAgfSkuZm9yRWFjaCgoZmllbGQpID0+IHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShzZWxmLCBmaWVsZC5uYW1lLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZ2V0OiAoKSA9PiB0aGlzLmdldChzZWxmLCBmaWVsZCBhcyBPRGF0YU1vZGVsRmllbGQ8YW55PiksXG4gICAgICAgIHNldDogKHZhbHVlOiBhbnkpID0+XG4gICAgICAgICAgdGhpcy5zZXQoc2VsZiwgZmllbGQgYXMgT0RhdGFNb2RlbEZpZWxkPGFueT4sIHZhbHVlKSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcXVlcnkoXG4gICAgc2VsZjogT0RhdGFNb2RlbDxUPixcbiAgICByZXNvdXJjZTpcbiAgICAgIHwgT0RhdGFFbnRpdHlSZXNvdXJjZTxUPlxuICAgICAgfCBPRGF0YVByb3BlcnR5UmVzb3VyY2U8VD5cbiAgICAgIHwgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZTxUPlxuICAgICAgfCBPRGF0YVNpbmdsZXRvblJlc291cmNlPFQ+LFxuICAgIGZ1bmM6IChxOiBPRGF0YVF1ZXJ5T3B0aW9uc0hhbmRsZXI8VD4sIHM/OiBPRGF0YVN0cnVjdHVyZWRUeXBlPFQ+KSA9PiB2b2lkLFxuICApIHtcbiAgICByZXNvdXJjZS5xdWVyeShmdW5jKTtcbiAgICB0aGlzLmF0dGFjaChzZWxmLCByZXNvdXJjZSk7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH1cblxuICByZXNvbHZlS2V5KFxuICAgIHZhbHVlOiBPRGF0YU1vZGVsPFQ+IHwgVCB8IHsgW25hbWU6IHN0cmluZ106IGFueSB9LFxuICAgIHtcbiAgICAgIGZpZWxkX21hcHBpbmcgPSBmYWxzZSxcbiAgICAgIHJlc29sdmUgPSB0cnVlLFxuICAgICAgc2luZ2xlID0gdHJ1ZSxcbiAgICB9OiB7IGZpZWxkX21hcHBpbmc/OiBib29sZWFuOyByZXNvbHZlPzogYm9vbGVhbjsgc2luZ2xlPzogYm9vbGVhbiB9ID0ge30sXG4gICk6IEVudGl0eUtleTxUPiB8IHsgW25hbWU6IHN0cmluZ106IGFueSB9IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBrZXlUeXBlcyA9IHRoaXMuc3RydWN0dXJlZFR5cGUua2V5cyh7IGluY2x1ZGVfcGFyZW50czogdHJ1ZSB9KTtcbiAgICBjb25zdCBrZXkgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuICAgIGZvciAoY29uc3Qga3Qgb2Yga2V5VHlwZXMpIHtcbiAgICAgIGxldCB2ID0gdmFsdWUgYXMgYW55O1xuICAgICAgbGV0IG9wdGlvbnMgPSB0aGlzIGFzIE9EYXRhTW9kZWxPcHRpb25zPGFueT4gfCB1bmRlZmluZWQ7XG4gICAgICBsZXQgZmllbGQ6IE9EYXRhTW9kZWxGaWVsZDxhbnk+IHwgdW5kZWZpbmVkO1xuICAgICAgZm9yIChjb25zdCBuYW1lIG9mIGt0Lm5hbWUuc3BsaXQoJy8nKSkge1xuICAgICAgICBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkKSBicmVhaztcbiAgICAgICAgZmllbGQgPSBvcHRpb25zXG4gICAgICAgICAgLmZpZWxkcyh7IGluY2x1ZGVfbmF2aWdhdGlvbjogZmFsc2UsIGluY2x1ZGVfcGFyZW50czogdHJ1ZSB9KVxuICAgICAgICAgIC5maW5kKChmaWVsZDogT0RhdGFNb2RlbEZpZWxkPGFueT4pID0+IGZpZWxkLmZpZWxkID09PSBuYW1lKTtcbiAgICAgICAgaWYgKGZpZWxkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB2ID1cbiAgICAgICAgICAgIFR5cGVzLmlzUGxhaW5PYmplY3QodikgfHwgT0RhdGFNb2RlbE9wdGlvbnMuaXNNb2RlbCh2KVxuICAgICAgICAgICAgICA/IHZbZmllbGQubmFtZV1cbiAgICAgICAgICAgICAgOiB2O1xuICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLmFwaS5vcHRpb25zRm9yVHlwZShmaWVsZC50eXBlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZpZWxkID09PSB1bmRlZmluZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBsZXQgbmFtZSA9IGZpZWxkX21hcHBpbmcgPyBmaWVsZC5maWVsZCA6IGZpZWxkLm5hbWU7XG4gICAgICBpZiAoa3QuYWxpYXMgIT09IHVuZGVmaW5lZCkgbmFtZSA9IGt0LmFsaWFzO1xuICAgICAga2V5LnNldChuYW1lLCB2KTtcbiAgICB9XG4gICAgaWYgKGtleS5zaXplID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiByZXNvbHZlXG4gICAgICA/IE9iamVjdHMucmVzb2x2ZUtleShrZXksIHsgc2luZ2xlIH0pXG4gICAgICA6IE9iamVjdC5mcm9tRW50cmllcyhrZXkpO1xuICB9XG5cbiAgcmVzb2x2ZVJlZmVyZW50aWFsKFxuICAgIHZhbHVlOiBPRGF0YU1vZGVsPFQ+IHwgVCB8IHsgW25hbWU6IHN0cmluZ106IGFueSB9IHwgbnVsbCxcbiAgICBhdHRyOiBPRGF0YU1vZGVsQXR0cmlidXRlPGFueT4gfCBPRGF0YU1vZGVsRmllbGQ8YW55PixcbiAgICB7XG4gICAgICBmaWVsZF9tYXBwaW5nID0gZmFsc2UsXG4gICAgICByZXNvbHZlID0gdHJ1ZSxcbiAgICAgIHNpbmdsZSA9IGZhbHNlLFxuICAgIH06IHsgZmllbGRfbWFwcGluZz86IGJvb2xlYW47IHJlc29sdmU/OiBib29sZWFuOyBzaW5nbGU/OiBib29sZWFuIH0gPSB7fSxcbiAgKTogeyBbbmFtZTogc3RyaW5nXTogYW55IH0gfCBudWxsIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCByZWZlcmVudGlhbCA9IG5ldyBNYXA8c3RyaW5nLCBhbnk+KCk7XG4gICAgZm9yIChjb25zdCByZWYgb2YgYXR0ci5yZWZlcmVudGlhbHMpIHtcbiAgICAgIGNvbnN0IGZyb20gPSB0aGlzLmZpZWxkcyh7XG4gICAgICAgIGluY2x1ZGVfbmF2aWdhdGlvbjogZmFsc2UsXG4gICAgICAgIGluY2x1ZGVfcGFyZW50czogdHJ1ZSxcbiAgICAgIH0pLmZpbmQoKHA6IGFueSkgPT4gcC5maWVsZCA9PT0gcmVmLnJlZmVyZW5jZWRQcm9wZXJ0eSk7XG4gICAgICBjb25zdCB0byA9IGF0dHIub3B0aW9uc1xuICAgICAgICAuZmllbGRzKHsgaW5jbHVkZV9uYXZpZ2F0aW9uOiBmYWxzZSwgaW5jbHVkZV9wYXJlbnRzOiB0cnVlIH0pXG4gICAgICAgIC5maW5kKChmaWVsZDogT0RhdGFNb2RlbEZpZWxkPGFueT4pID0+IGZpZWxkLmZpZWxkID09PSByZWYucHJvcGVydHkpO1xuICAgICAgaWYgKGZyb20gIT09IHVuZGVmaW5lZCAmJiB0byAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBmaWVsZF9tYXBwaW5nID8gdG8uZmllbGQgOiB0by5uYW1lO1xuICAgICAgICByZWZlcmVudGlhbC5zZXQobmFtZSwgdmFsdWUgJiYgKHZhbHVlIGFzIGFueSlbZnJvbS5uYW1lXSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChyZWZlcmVudGlhbC5zaXplID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChyZWZlcmVudGlhbC5zaXplID09PSAxICYmIEFycmF5LmZyb20ocmVmZXJlbnRpYWwudmFsdWVzKCkpWzBdID09PSBudWxsKVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHJlc29sdmVcbiAgICAgID8gT2JqZWN0cy5yZXNvbHZlS2V5KHJlZmVyZW50aWFsLCB7IHNpbmdsZSB9KVxuICAgICAgOiBPYmplY3QuZnJvbUVudHJpZXMocmVmZXJlbnRpYWwpO1xuICB9XG5cbiAgcmVzb2x2ZVJlZmVyZW5jZWQoXG4gICAgdmFsdWU6IE9EYXRhTW9kZWw8VD4gfCBUIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH0gfCBudWxsLFxuICAgIGF0dHI6IE9EYXRhTW9kZWxBdHRyaWJ1dGU8YW55PiB8IE9EYXRhTW9kZWxGaWVsZDxhbnk+LFxuICAgIHtcbiAgICAgIGZpZWxkX21hcHBpbmcgPSBmYWxzZSxcbiAgICAgIHJlc29sdmUgPSB0cnVlLFxuICAgICAgc2luZ2xlID0gZmFsc2UsXG4gICAgfTogeyBmaWVsZF9tYXBwaW5nPzogYm9vbGVhbjsgcmVzb2x2ZT86IGJvb2xlYW47IHNpbmdsZT86IGJvb2xlYW4gfSA9IHt9LFxuICApOiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSB8IG51bGwgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHJlZmVyZW5jZWQgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuICAgIGZvciAoY29uc3QgcmVmIG9mIGF0dHIucmVmZXJlbnRpYWxzKSB7XG4gICAgICBjb25zdCBmcm9tID0gdGhpcy5maWVsZHMoe1xuICAgICAgICBpbmNsdWRlX25hdmlnYXRpb246IGZhbHNlLFxuICAgICAgICBpbmNsdWRlX3BhcmVudHM6IHRydWUsXG4gICAgICB9KS5maW5kKChmaWVsZDogT0RhdGFNb2RlbEZpZWxkPGFueT4pID0+IGZpZWxkLmZpZWxkID09PSByZWYucHJvcGVydHkpO1xuICAgICAgY29uc3QgbWV0YSA9IHRoaXMuYXBpLm9wdGlvbnNGb3JUeXBlPGFueT4oYXR0ci50eXBlKTtcbiAgICAgIGNvbnN0IHRvID0gbWV0YVxuICAgICAgICA/LmZpZWxkcyh7IGluY2x1ZGVfbmF2aWdhdGlvbjogZmFsc2UsIGluY2x1ZGVfcGFyZW50czogdHJ1ZSB9KVxuICAgICAgICAuZmluZChcbiAgICAgICAgICAoZmllbGQ6IE9EYXRhTW9kZWxGaWVsZDxhbnk+KSA9PlxuICAgICAgICAgICAgZmllbGQuZmllbGQgPT09IHJlZi5yZWZlcmVuY2VkUHJvcGVydHksXG4gICAgICAgICk7XG4gICAgICBpZiAoZnJvbSAhPT0gdW5kZWZpbmVkICYmIHRvICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IGZpZWxkX21hcHBpbmcgPyB0by5maWVsZCA6IHRvLm5hbWU7XG4gICAgICAgIHJlZmVyZW5jZWQuc2V0KG5hbWUsIHZhbHVlICYmICh2YWx1ZSBhcyBhbnkpW2Zyb20ubmFtZV0pO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocmVmZXJlbmNlZC5zaXplID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChyZWZlcmVuY2VkLnNpemUgPT09IDEgJiYgQXJyYXkuZnJvbShyZWZlcmVuY2VkLnZhbHVlcygpKVswXSA9PT0gbnVsbClcbiAgICAgIHJldHVybiBudWxsO1xuICAgIHJldHVybiByZXNvbHZlXG4gICAgICA/IE9iamVjdHMucmVzb2x2ZUtleShyZWZlcmVuY2VkLCB7IHNpbmdsZSB9KVxuICAgICAgOiBPYmplY3QuZnJvbUVudHJpZXMocmVmZXJlbmNlZCk7XG4gIH1cblxuICB2YWxpZGF0ZShcbiAgICBzZWxmOiBPRGF0YU1vZGVsPFQ+LFxuICAgIHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIG5hdmlnYXRpb24gPSBmYWxzZSxcbiAgICB9OiB7XG4gICAgICBtZXRob2Q/OiAnY3JlYXRlJyB8ICd1cGRhdGUnIHwgJ21vZGlmeSc7XG4gICAgICBuYXZpZ2F0aW9uPzogYm9vbGVhbjtcbiAgICB9ID0ge30sXG4gICk6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZ1tdIH0gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGVycm9ycyA9IHRoaXMuZmllbGRzKHtcbiAgICAgIGluY2x1ZGVfcGFyZW50czogdHJ1ZSxcbiAgICAgIGluY2x1ZGVfbmF2aWdhdGlvbjogbmF2aWdhdGlvbixcbiAgICB9KS5yZWR1Y2UoKGFjYywgZmllbGQpID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gKHNlbGYgYXMgYW55KVtmaWVsZC5uYW1lXTtcbiAgICAgIGNvbnN0IGVycnMgPSBmaWVsZC52YWxpZGF0ZSh2YWx1ZSwgeyBtZXRob2QgfSk7XG4gICAgICByZXR1cm4gZXJycyAhPT0gdW5kZWZpbmVkXG4gICAgICAgID8gT2JqZWN0LmFzc2lnbihhY2MsIHsgW2ZpZWxkLm5hbWVdOiBlcnJzIH0pXG4gICAgICAgIDogYWNjO1xuICAgIH0sIHt9KTtcbiAgICByZXR1cm4gIVR5cGVzLmlzRW1wdHkoZXJyb3JzKSA/IGVycm9ycyA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGRlZmF1bHRzKCk6IFQgfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZGVmcyA9IHRoaXMuZmllbGRzKHtcbiAgICAgIGluY2x1ZGVfbmF2aWdhdGlvbjogZmFsc2UsXG4gICAgICBpbmNsdWRlX3BhcmVudHM6IHRydWUsXG4gICAgfSkucmVkdWNlKChhY2MsIGZpZWxkKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGZpZWxkLmRlZmF1bHRzKCk7XG4gICAgICByZXR1cm4gdmFsdWUgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IE9iamVjdC5hc3NpZ24oYWNjLCB7IFtmaWVsZC5uYW1lXTogdmFsdWUgfSlcbiAgICAgICAgOiBhY2M7XG4gICAgfSwge30pO1xuICAgIHJldHVybiAhVHlwZXMuaXNFbXB0eShkZWZzKSA/IGRlZnMgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBoYXNDaGFuZ2VkKFxuICAgIHNlbGY6IE9EYXRhTW9kZWw8VD4sXG4gICAgeyBpbmNsdWRlX25hdmlnYXRpb24gPSBmYWxzZSB9OiB7IGluY2x1ZGVfbmF2aWdhdGlvbj86IGJvb2xlYW4gfSA9IHt9LFxuICApOiBib29sZWFuIHtcbiAgICByZXR1cm4gWy4uLnNlbGYuX2F0dHJpYnV0ZXMudmFsdWVzKCldXG4gICAgICAuZmlsdGVyKChhdHRyKSA9PiAhYXR0ci5uYXZpZ2F0aW9uIHx8IGluY2x1ZGVfbmF2aWdhdGlvbilcbiAgICAgIC5zb21lKChhdHRyKSA9PiBhdHRyLmlzQ2hhbmdlZCh7IGluY2x1ZGVfbmF2aWdhdGlvbiB9KSk7XG4gIH1cblxuICBoYXNLZXkoc2VsZjogT0RhdGFNb2RlbDxUPikge1xuICAgIHJldHVybiB0aGlzLnJlc29sdmVLZXkoc2VsZikgIT09IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHdpdGhSZXNvdXJjZTxSLCBNIGV4dGVuZHMgT0RhdGFNb2RlbDxUPj4oXG4gICAgc2VsZjogTSxcbiAgICByZXNvdXJjZTpcbiAgICAgIHwgT0RhdGFFbnRpdHlSZXNvdXJjZTxUPlxuICAgICAgfCBPRGF0YVByb3BlcnR5UmVzb3VyY2U8VD5cbiAgICAgIHwgT0RhdGFOYXZpZ2F0aW9uUHJvcGVydHlSZXNvdXJjZTxUPlxuICAgICAgfCBPRGF0YVNpbmdsZXRvblJlc291cmNlPFQ+XG4gICAgICB8IG51bGwsXG4gICAgY3R4OiAobW9kZWw6IE0pID0+IFIsXG4gICk6IFIge1xuICAgIC8vIFB1c2hcbiAgICBzZWxmLnB1c2hSZXNvdXJjZShyZXNvdXJjZSk7XG4gICAgLy8gRXhlY3V0ZSBmdW5jdGlvblxuICAgIGNvbnN0IHJlc3VsdCA9IGN0eChzZWxmKTtcbiAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgT2JzZXJ2YWJsZSkge1xuICAgICAgcmV0dXJuIChyZXN1bHQgYXMgYW55KS5waXBlKFxuICAgICAgICBmaW5hbGl6ZSgoKSA9PiB7XG4gICAgICAgICAgLy8gUG9wXG4gICAgICAgICAgc2VsZi5wb3BSZXNvdXJjZSgpO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFBvcFxuICAgICAgc2VsZi5wb3BSZXNvdXJjZSgpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cbiAgYXNFbnRpdHk8UiwgTSBleHRlbmRzIE9EYXRhTW9kZWw8VD4+KHNlbGY6IE0sIGN0eDogKG1vZGVsOiBNKSA9PiBSKTogUiB7XG4gICAgLy8gQ2xvbmUgcXVlcnkgZnJvbSBoaW0gb3IgcGFyZW50XG4gICAgbGV0IHF1ZXJ5ID0gc2VsZi5fcmVzb3VyY2U/LmNsb25lUXVlcnk8VD4oKTtcbiAgICBpZiAoXG4gICAgICBxdWVyeSA9PT0gdW5kZWZpbmVkICYmXG4gICAgICBzZWxmLl9wYXJlbnQgJiZcbiAgICAgIHNlbGYuX3BhcmVudFswXSBpbnN0YW5jZW9mIE9EYXRhQ29sbGVjdGlvblxuICAgIClcbiAgICAgIHF1ZXJ5ID0gc2VsZi5fcGFyZW50WzBdLl9yZXNvdXJjZT8uY2xvbmVRdWVyeTxUPigpO1xuICAgIC8vIEJ1aWxkIG5ldyByZXNvdXJjZVxuICAgIGNvbnN0IHJlc291cmNlID0gdGhpcy5tb2RlbFJlc291cmNlRmFjdG9yeShxdWVyeSk7XG4gICAgcmV0dXJuIHRoaXMud2l0aFJlc291cmNlKHNlbGYsIHJlc291cmNlLCBjdHgpO1xuICB9XG5cbiAgdG9FbnRpdHkoXG4gICAgc2VsZjogT0RhdGFNb2RlbDxUPixcbiAgICB7XG4gICAgICBjbGllbnRfaWQgPSBmYWxzZSxcbiAgICAgIGluY2x1ZGVfbmF2aWdhdGlvbiA9IGZhbHNlLFxuICAgICAgaW5jbHVkZV9jb25jdXJyZW5jeSA9IGZhbHNlLFxuICAgICAgaW5jbHVkZV9jb21wdXRlZCA9IGZhbHNlLFxuICAgICAgaW5jbHVkZV9rZXkgPSB0cnVlLFxuICAgICAgaW5jbHVkZV9pZCA9IGZhbHNlLFxuICAgICAgaW5jbHVkZV9ub25fZmllbGQgPSBmYWxzZSxcbiAgICAgIGNoYW5nZXNfb25seSA9IGZhbHNlLFxuICAgICAgZmllbGRfbWFwcGluZyA9IGZhbHNlLFxuICAgICAgY2hhaW4gPSBbXSxcbiAgICB9OiB7XG4gICAgICBjbGllbnRfaWQ/OiBib29sZWFuO1xuICAgICAgaW5jbHVkZV9uYXZpZ2F0aW9uPzogYm9vbGVhbjtcbiAgICAgIGluY2x1ZGVfY29uY3VycmVuY3k/OiBib29sZWFuO1xuICAgICAgaW5jbHVkZV9jb21wdXRlZD86IGJvb2xlYW47XG4gICAgICBpbmNsdWRlX2tleT86IGJvb2xlYW47XG4gICAgICBpbmNsdWRlX2lkPzogYm9vbGVhbjtcbiAgICAgIGluY2x1ZGVfbm9uX2ZpZWxkPzogYm9vbGVhbjtcbiAgICAgIGNoYW5nZXNfb25seT86IGJvb2xlYW47XG4gICAgICBmaWVsZF9tYXBwaW5nPzogYm9vbGVhbjtcbiAgICAgIGNoYWluPzogKE9EYXRhTW9kZWw8YW55PiB8IE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4pW107XG4gICAgfSA9IHt9LFxuICApOiBUIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH0ge1xuICAgIGxldCBlbnRpdHk6IGFueSA9IFsuLi5zZWxmLl9hdHRyaWJ1dGVzLnZhbHVlcygpXVxuICAgICAgLmZpbHRlcihcbiAgICAgICAgLy8gQ2hhaW5cbiAgICAgICAgKGF0dHIpID0+IGNoYWluLmV2ZXJ5KChjKSA9PiBjICE9PSBhdHRyLmdldCgpKSxcbiAgICAgIClcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIC8vIENoYW5nZXMgb25seVxuICAgICAgICAoYXR0cikgPT5cbiAgICAgICAgICAhY2hhbmdlc19vbmx5IHx8XG4gICAgICAgICAgKGNoYW5nZXNfb25seSAmJiBhdHRyLmlzQ2hhbmdlZCh7IGluY2x1ZGVfbmF2aWdhdGlvbiB9KSksXG4gICAgICApXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoYXR0cikgPT5cbiAgICAgICAgICAvLyBOYXZpZ2F0aW9uXG4gICAgICAgICAgKGluY2x1ZGVfbmF2aWdhdGlvbiAmJiBhdHRyLm5hdmlnYXRpb24gJiYgYXR0ci5nZXQoKSAhPT0gbnVsbCkgfHxcbiAgICAgICAgICAhYXR0ci5uYXZpZ2F0aW9uLFxuICAgICAgKVxuICAgICAgLnJlZHVjZSgoYWNjLCBhdHRyKSA9PiB7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBmaWVsZF9tYXBwaW5nID8gYXR0ci5maWVsZE5hbWUgOiBhdHRyLm5hbWU7XG4gICAgICAgIGxldCB2YWx1ZTogYW55ID0gYXR0ci5nZXQoKTtcbiAgICAgICAgY29uc3QgY29tcHV0ZWQgPSBhdHRyLmNvbXB1dGVkO1xuICAgICAgICBjb25zdCBuYXZpZ2F0aW9uID0gYXR0ci5uYXZpZ2F0aW9uO1xuICAgICAgICBjb25zdCBjb25jdXJyZW5jeSA9IGF0dHIuY29uY3VycmVuY3k7XG4gICAgICAgIGlmIChPRGF0YU1vZGVsT3B0aW9ucy5pc01vZGVsKHZhbHVlKSkge1xuICAgICAgICAgIHZhbHVlID0gKHZhbHVlIGFzIE9EYXRhTW9kZWw8YW55PikudG9FbnRpdHkoe1xuICAgICAgICAgICAgY2xpZW50X2lkLFxuICAgICAgICAgICAgaW5jbHVkZV9uYXZpZ2F0aW9uLFxuICAgICAgICAgICAgaW5jbHVkZV9jb25jdXJyZW5jeSxcbiAgICAgICAgICAgIGluY2x1ZGVfY29tcHV0ZWQsXG4gICAgICAgICAgICBpbmNsdWRlX25vbl9maWVsZCxcbiAgICAgICAgICAgIGZpZWxkX21hcHBpbmcsXG4gICAgICAgICAgICBjaGFuZ2VzX29ubHk6IGNoYW5nZXNfb25seSAmJiAhIW5hdmlnYXRpb24sXG4gICAgICAgICAgICBpbmNsdWRlX2tleTogaW5jbHVkZV9rZXkgJiYgISFuYXZpZ2F0aW9uLFxuICAgICAgICAgICAgaW5jbHVkZV9pZDogaW5jbHVkZV9pZCAmJiAhIW5hdmlnYXRpb24sXG4gICAgICAgICAgICBjaGFpbjogW3NlbGYsIC4uLmNoYWluXSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24odmFsdWUpKSB7XG4gICAgICAgICAgdmFsdWUgPSAodmFsdWUgYXMgT0RhdGFDb2xsZWN0aW9uPGFueSwgT0RhdGFNb2RlbDxhbnk+PikudG9FbnRpdGllcyh7XG4gICAgICAgICAgICBjbGllbnRfaWQsXG4gICAgICAgICAgICBpbmNsdWRlX25hdmlnYXRpb24sXG4gICAgICAgICAgICBpbmNsdWRlX2NvbmN1cnJlbmN5LFxuICAgICAgICAgICAgaW5jbHVkZV9jb21wdXRlZCxcbiAgICAgICAgICAgIGluY2x1ZGVfbm9uX2ZpZWxkLFxuICAgICAgICAgICAgZmllbGRfbWFwcGluZyxcbiAgICAgICAgICAgIGNoYW5nZXNfb25seTogY2hhbmdlc19vbmx5ICYmICEhbmF2aWdhdGlvbixcbiAgICAgICAgICAgIGluY2x1ZGVfa2V5OiBpbmNsdWRlX2tleSAmJiAhIW5hdmlnYXRpb24sXG4gICAgICAgICAgICBpbmNsdWRlX2lkOiBpbmNsdWRlX2lkICYmICEhbmF2aWdhdGlvbixcbiAgICAgICAgICAgIGNoYWluOiBbc2VsZiwgLi4uY2hhaW5dLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpbmNsdWRlX2NvbmN1cnJlbmN5ICYmIGNvbmN1cnJlbmN5KSB7XG4gICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oYWNjLCB7IFtuYW1lXTogdmFsdWUgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZV9jb21wdXRlZCAmJiBjb21wdXRlZCkge1xuICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKGFjYywgeyBbbmFtZV06IHZhbHVlIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKGNoYW5nZXNfb25seSAmJiBhdHRyLmlzQ2hhbmdlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oYWNjLCB7IFtuYW1lXTogdmFsdWUgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIWNoYW5nZXNfb25seSAmJiAhY29uY3VycmVuY3kgJiYgIWNvbXB1dGVkKSB7XG4gICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oYWNjLCB7IFtuYW1lXTogdmFsdWUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sIHt9KTtcblxuICAgIGlmIChpbmNsdWRlX25vbl9maWVsZCkge1xuICAgICAgY29uc3QgbmFtZXMgPSBPYmplY3Qua2V5cyhlbnRpdHkpO1xuICAgICAgLy8gQXR0cmlidXRlcyBmcm9tIG9iamVjdCAoYXR0cmlidXRlcyBmb3Igb2JqZWN0KVxuICAgICAgY29uc3Qgbm9uRmllbGRBdHRycyA9IE9iamVjdC5lbnRyaWVzKHNlbGYpXG4gICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgKFtrXSkgPT5cbiAgICAgICAgICAgIG5hbWVzLmluZGV4T2YoaykgPT09IC0xICYmICFrLnN0YXJ0c1dpdGgoJ18nKSAmJiAhay5lbmRzV2l0aCgnJCcpLFxuICAgICAgICApXG4gICAgICAgIC5yZWR1Y2UoKGFjYywgW2ssIHZdKSA9PiBPYmplY3QuYXNzaWduKGFjYywgeyBba106IHYgfSksIHt9KTtcbiAgICAgIGVudGl0eSA9IHsgLi4uZW50aXR5LCAuLi5ub25GaWVsZEF0dHJzIH07XG4gICAgfVxuXG4gICAgLy8gQWRkIGNsaWVudF9pZFxuICAgIGlmIChjbGllbnRfaWQpIHtcbiAgICAgICg8YW55PmVudGl0eSlbdGhpcy5jaWRdID0gKDxhbnk+c2VsZilbdGhpcy5jaWRdO1xuICAgIH1cblxuICAgIC8vIEFkZCBrZXlcbiAgICBpZiAoaW5jbHVkZV9rZXkpIHtcbiAgICAgIGVudGl0eSA9IHtcbiAgICAgICAgLi4uZW50aXR5LFxuICAgICAgICAuLi4odGhpcy5yZXNvbHZlS2V5KHNlbGYsIHsgZmllbGRfbWFwcGluZywgcmVzb2x2ZTogZmFsc2UgfSkgYXMge30pLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBBZGQgaWRcbiAgICBpZiAoaW5jbHVkZV9pZCkge1xuICAgICAgc2VsZi5hc0VudGl0eSgoZSkgPT4ge1xuICAgICAgICBjb25zdCByZXNvdXJjZSA9IGUucmVzb3VyY2UoKTtcbiAgICAgICAgaWYgKHJlc291cmNlKVxuICAgICAgICAgIGVudGl0eVt0aGlzLmFwaS5vcHRpb25zLmhlbHBlci5PREFUQV9JRF0gPSBgJHtyZXNvdXJjZS5jbGVhclF1ZXJ5KCl9YDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFkZCB0eXBlXG4gICAgaWYgKFxuICAgICAgc2VsZi5fcGFyZW50ICE9PSBudWxsICYmXG4gICAgICAoKE9EYXRhTW9kZWxPcHRpb25zLmlzTW9kZWwoc2VsZi5fcGFyZW50WzBdKSAmJlxuICAgICAgICBzZWxmLl9wYXJlbnRbMV0gIT09IG51bGwgJiZcbiAgICAgICAgdGhpcy5hcGkub3B0aW9uc0ZvclR5cGUoc2VsZi5fcGFyZW50WzFdLnR5cGUpICE9PSBzZWxmLl9tZXRhKSB8fFxuICAgICAgICAoT0RhdGFNb2RlbE9wdGlvbnMuaXNDb2xsZWN0aW9uKHNlbGYuX3BhcmVudFswXSkgJiZcbiAgICAgICAgICAoc2VsZi5fcGFyZW50WzBdIGFzIE9EYXRhQ29sbGVjdGlvbjxhbnksIE9EYXRhTW9kZWw8YW55Pj4pLl9tb2RlbFxuICAgICAgICAgICAgLm1ldGEgIT09IHNlbGYuX21ldGEpKVxuICAgICkge1xuICAgICAgZW50aXR5W3RoaXMuYXBpLm9wdGlvbnMuaGVscGVyLk9EQVRBX1RZUEVdID1cbiAgICAgICAgYCMke3RoaXMuc3RydWN0dXJlZFR5cGUudHlwZSgpfWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVudGl0eSBhcyBUIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH07XG4gIH1cblxuICByZXNldChcbiAgICBzZWxmOiBPRGF0YU1vZGVsPFQ+LFxuICAgIHsgbmFtZSwgc2lsZW50ID0gZmFsc2UgfTogeyBuYW1lPzogc3RyaW5nOyBzaWxlbnQ/OiBib29sZWFuIH0gPSB7fSxcbiAgKSB7XG4gICAgbGV0IGNoYW5nZXM6IHN0cmluZ1tdID0gW107XG4gICAgaWYgKG5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gUmVzZXQgdmFsdWVcbiAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IHNlbGYuX2F0dHJpYnV0ZXMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKFxuICAgICAgICBhdHRyaWJ1dGUgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICBhdHRyaWJ1dGUuaXNDaGFuZ2VkKHsgaW5jbHVkZV9uYXZpZ2F0aW9uOiB0cnVlIH0pXG4gICAgICApIHtcbiAgICAgICAgYXR0cmlidXRlLnJlc2V0KCk7XG4gICAgICAgIGNoYW5nZXMgPSBbbmFtZV07XG4gICAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZT8uaXNDaGFuZ2VkKCkpIHtcbiAgICAgICAgYXR0cmlidXRlLnJlc2V0KCk7XG4gICAgICAgIGNoYW5nZXMgPSBbbmFtZV07XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHJlc2V0IGFsbFxuICAgICAgY2hhbmdlcyA9IFsuLi5zZWxmLl9hdHRyaWJ1dGVzLmtleXMoKV07XG4gICAgICAvL3NlbGYuX2NoYW5nZXMuY2xlYXIoKTtcbiAgICAgIHNlbGYuX2F0dHJpYnV0ZXMuZm9yRWFjaCgoYXR0ciwga2V5KSA9PiB7XG4gICAgICAgIGlmIChhdHRyLmlzQ2hhbmdlZCh7IGluY2x1ZGVfbmF2aWdhdGlvbjogdHJ1ZSB9KSkge1xuICAgICAgICAgIGF0dHIucmVzZXQoKTtcbiAgICAgICAgICBjaGFuZ2VzLnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICghc2lsZW50ICYmIGNoYW5nZXMubGVuZ3RoID4gMCkge1xuICAgICAgc2VsZi5ldmVudHMkLnRyaWdnZXIoT0RhdGFNb2RlbEV2ZW50VHlwZS5SZXNldCwgeyBvcHRpb25zOiB7IGNoYW5nZXMgfSB9KTtcbiAgICB9XG4gIH1cblxuICBhc3NpZ24oXG4gICAgc2VsZjogT0RhdGFNb2RlbDxUPixcbiAgICBlbnRpdHk6IFBhcnRpYWw8VD4gfCB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSxcbiAgICB7XG4gICAgICBhZGQgPSB0cnVlLFxuICAgICAgbWVyZ2UgPSB0cnVlLFxuICAgICAgcmVtb3ZlID0gdHJ1ZSxcbiAgICAgIHJlc2V0ID0gZmFsc2UsXG4gICAgICByZXBhcmVudCA9IGZhbHNlLFxuICAgICAgc2lsZW50ID0gZmFsc2UsXG4gICAgfToge1xuICAgICAgYWRkPzogYm9vbGVhbjtcbiAgICAgIG1lcmdlPzogYm9vbGVhbjtcbiAgICAgIHJlbW92ZT86IGJvb2xlYW47XG4gICAgICByZXNldD86IGJvb2xlYW47XG4gICAgICByZXBhcmVudD86IGJvb2xlYW47XG4gICAgICBzaWxlbnQ/OiBib29sZWFuO1xuICAgIH0gPSB7fSxcbiAgKSB7XG4gICAgY29uc3QgY2hhbmdlczogc3RyaW5nW10gPSBbXTtcblxuICAgIC8vIFVwZGF0ZSBhbm5vdGF0aW9uc1xuICAgIHNlbGYuYW5ub3RzKCkudXBkYXRlKGVudGl0eSk7XG4gICAgLy8gVXBkYXRlIGF0dHJpYnV0ZXNcbiAgICBjb25zdCBhdHRycyA9IHNlbGYuYW5ub3RzKCkuYXR0cmlidXRlcyhlbnRpdHksICdmdWxsJyk7XG4gICAgT2JqZWN0LmVudHJpZXMoYXR0cnMpXG4gICAgICAuZmlsdGVyKChbLCB2YWx1ZV0pID0+IHZhbHVlICE9PSB1bmRlZmluZWQpIC8vIEZpbHRlciB1bmRlZmluZWRcbiAgICAgIC5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZChrZXksIHsgcmVzZXQgfSk7XG5cbiAgICAgICAgaWYgKGZpZWxkICE9PSB1bmRlZmluZWQgfHwgdGhpcy5pc09wZW5UeXBlKCkpIHtcbiAgICAgICAgICAvLyBEZWxlZ2F0ZWQgdG8gcHJpdmF0ZSBzZXR0ZXJcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLnNldChzZWxmLCBmaWVsZCA/PyBrZXksIHZhbHVlLCB7XG4gICAgICAgICAgICAgIGFkZCxcbiAgICAgICAgICAgICAgbWVyZ2UsXG4gICAgICAgICAgICAgIHJlbW92ZSxcbiAgICAgICAgICAgICAgcmVzZXQsXG4gICAgICAgICAgICAgIHJlcGFyZW50LFxuICAgICAgICAgICAgICBzaWxlbnQsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY2hhbmdlcy5wdXNoKGZpZWxkPy5uYW1lID8/IGtleSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEJhc2ljIGFzc2lnbm1lbnRcbiAgICAgICAgICBjb25zdCBjdXJyZW50ID0gKDxhbnk+c2VsZilba2V5XTtcbiAgICAgICAgICAoPGFueT5zZWxmKVtrZXldID0gdmFsdWU7XG4gICAgICAgICAgaWYgKGN1cnJlbnQgIT09IHZhbHVlKSBjaGFuZ2VzLnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBpZiAoIXNpbGVudCAmJiBjaGFuZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgIHNlbGYuZXZlbnRzJC50cmlnZ2VyKFxuICAgICAgICByZXNldCA/IE9EYXRhTW9kZWxFdmVudFR5cGUuUmVzZXQgOiBPRGF0YU1vZGVsRXZlbnRUeXBlLlVwZGF0ZSxcbiAgICAgICAgeyBvcHRpb25zOiB7IGNoYW5nZXMgfSB9LFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlbGY7XG4gIH1cblxuICBzdGF0aWMgaXNNb2RlbChvYmo6IGFueSkge1xuICAgIHJldHVybiBUeXBlcy5yYXdUeXBlKG9iaikgPT09ICdNb2RlbCc7XG4gIH1cblxuICBzdGF0aWMgaXNDb2xsZWN0aW9uKG9iajogYW55KSB7XG4gICAgcmV0dXJuIFR5cGVzLnJhd1R5cGUob2JqKSA9PT0gJ0NvbGxlY3Rpb24nO1xuICB9XG5cbiAgZ2V0PEY+KFxuICAgIHNlbGY6IE9EYXRhTW9kZWw8VD4sXG4gICAgZmllbGQ6IE9EYXRhTW9kZWxGaWVsZDxGPiB8IHN0cmluZyxcbiAgKTogRiB8IE9EYXRhTW9kZWw8Rj4gfCBPRGF0YUNvbGxlY3Rpb248RiwgT0RhdGFNb2RlbDxGPj4gfCBudWxsIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBhdHRyID0gc2VsZi5fYXR0cmlidXRlcy5nZXQoXG4gICAgICBmaWVsZCBpbnN0YW5jZW9mIE9EYXRhTW9kZWxGaWVsZCA/IGZpZWxkLm5hbWUgOiBmaWVsZCxcbiAgICApO1xuICAgIGlmIChhdHRyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gYXR0ci5nZXQoKTtcbiAgICAgIGlmIChcbiAgICAgICAgKGF0dHIubmF2aWdhdGlvbiAmJiB2YWx1ZSA9PT0gbnVsbCkgfHxcbiAgICAgICAgT0RhdGFNb2RlbE9wdGlvbnMuaXNNb2RlbCh2YWx1ZSlcbiAgICAgICkge1xuICAgICAgICAvLyBDaGVjayBmb3IgcmVmZXJlbmNlXG4gICAgICAgIGNvbnN0IHJlZmVyZW5jZWQgPSB0aGlzLnJlc29sdmVSZWZlcmVuY2VkKHNlbGYsIGF0dHIsIHtcbiAgICAgICAgICByZXNvbHZlOiBmYWxzZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiByZWZlcmVuY2VkICE9PSBudWxsICYmIHJlZmVyZW5jZWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICh2YWx1ZSBhcyBPRGF0YU1vZGVsPEY+KS5hc3NpZ24ocmVmZXJlbmNlZCBhcyBQYXJ0aWFsPEY+LCB7XG4gICAgICAgICAgICBzaWxlbnQ6IHRydWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAodmFsdWUgIT09IG51bGwgJiYgcmVmZXJlbmNlZCA9PT0gbnVsbCkge1xuICAgICAgICAgIC8vIE5ldyB2YWx1ZSBpcyBudWxsXG4gICAgICAgICAgKGF0dHIgYXMgT0RhdGFNb2RlbEF0dHJpYnV0ZTxGPikuc2V0KG51bGwpO1xuICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBudWxsICYmIHJlZmVyZW5jZWQgIT09IG51bGwpIHtcbiAgICAgICAgICAvLyBOZXcgdmFsdWUgaXMgdW5kZWZpbmVkXG4gICAgICAgICAgKGF0dHIgYXMgT0RhdGFNb2RlbEF0dHJpYnV0ZTxGPikuc2V0KHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgdHlwZW9mIGZpZWxkID09PSAnc3RyaW5nJyAmJlxuICAgICAgIWZpZWxkLnN0YXJ0c1dpdGgoJ18nKSAmJlxuICAgICAgIWZpZWxkLmVuZHNXaXRoKCckJylcbiAgICApIHtcbiAgICAgIHJldHVybiAoc2VsZiBhcyBhbnkpW2ZpZWxkXTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHNldDxGPihcbiAgICBzZWxmOiBPRGF0YU1vZGVsPFQ+LFxuICAgIGZpZWxkOiBPRGF0YU1vZGVsRmllbGQ8Rj4gfCBzdHJpbmcsXG4gICAgdmFsdWU6XG4gICAgICB8IEZcbiAgICAgIHwgRltdXG4gICAgICB8IHsgW25hbWU6IHN0cmluZ106IGFueSB9XG4gICAgICB8IHsgW25hbWU6IHN0cmluZ106IGFueSB9W11cbiAgICAgIHwgT0RhdGFNb2RlbDxGPlxuICAgICAgfCBPRGF0YUNvbGxlY3Rpb248RiwgT0RhdGFNb2RlbDxGPj5cbiAgICAgIHwgbnVsbCxcbiAgICB7XG4gICAgICBhZGQsXG4gICAgICBtZXJnZSxcbiAgICAgIHJlbW92ZSxcbiAgICAgIHJlc2V0LFxuICAgICAgcmVwYXJlbnQsXG4gICAgICBzaWxlbnQsXG4gICAgICB0eXBlLFxuICAgIH06IHtcbiAgICAgIGFkZD86IGJvb2xlYW47XG4gICAgICBtZXJnZT86IGJvb2xlYW47XG4gICAgICByZW1vdmU/OiBib29sZWFuO1xuICAgICAgcmVzZXQ/OiBib29sZWFuO1xuICAgICAgcmVwYXJlbnQ/OiBib29sZWFuO1xuICAgICAgc2lsZW50PzogYm9vbGVhbjtcbiAgICAgIHR5cGU/OiBFZG1UeXBlIHwgc3RyaW5nO1xuICAgIH0gPSB7fSxcbiAgKTogYm9vbGVhbiB7XG4gICAgbGV0IG1vZGVsRmllbGQgPVxuICAgICAgZmllbGQgaW5zdGFuY2VvZiBPRGF0YU1vZGVsRmllbGQgPyBmaWVsZCA6IHRoaXMuZmluZEZpZWxkPEY+KGZpZWxkKTtcbiAgICBpZiAoXG4gICAgICBtb2RlbEZpZWxkID09PSB1bmRlZmluZWQgJiZcbiAgICAgIHRoaXMuaXNPcGVuVHlwZSgpICYmXG4gICAgICB0eXBlb2YgZmllbGQgPT09ICdzdHJpbmcnXG4gICAgKSB7XG4gICAgICB0eXBlID0gdHlwZSA/PyB0aGlzLnRzVG9FZG1bdHlwZW9mIHZhbHVlXSA/PyBFZG1UeXBlLlN0cmluZztcbiAgICAgIG1vZGVsRmllbGQgPSB0aGlzLm1vZGVsRmllbGRGYWN0b3J5PEY+KHNlbGYsIGZpZWxkLCB0eXBlKTtcbiAgICB9XG4gICAgaWYgKG1vZGVsRmllbGQgPT09IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gZmllbGQgd2l0aCBuYW1lICR7ZmllbGQgYXMgc3RyaW5nfWApO1xuXG4gICAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcbiAgICBsZXQgYXR0ciA9IHNlbGYuX2F0dHJpYnV0ZXMuZ2V0KG1vZGVsRmllbGQubmFtZSk7XG5cbiAgICAvLyBFbnN1cmVzIHRoYXQgdGhlIGF0dHJpYnV0ZSBleGlzdHNcbiAgICBpZiAoYXR0ciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBhdHRyID0gbmV3IE9EYXRhTW9kZWxBdHRyaWJ1dGUoc2VsZiwgbW9kZWxGaWVsZCk7XG4gICAgICB0aGlzLl9saW5rKHNlbGYsIGF0dHIpO1xuICAgICAgc2VsZi5fYXR0cmlidXRlcy5zZXQobW9kZWxGaWVsZC5uYW1lLCBhdHRyKTtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50ID0gYXR0ci5nZXQoKTtcblxuICAgIGlmIChtb2RlbEZpZWxkLmlzU3RydWN0dXJlZFR5cGUoKSkge1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgIC8vIE5ldyB2YWx1ZSBpcyBudWxsXG4gICAgICAgIGNoYW5nZWQgPSBhdHRyLnNldCh2YWx1ZSBhcyBudWxsLCByZXNldCwgcmVwYXJlbnQpO1xuICAgICAgfSBlbHNlIGlmIChPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24oY3VycmVudCkpIHtcbiAgICAgICAgLy8gQ3VycmVudCBpcyBjb2xsZWN0aW9uXG4gICAgICAgIGNvbnN0IGN1cnJlbnRDb2xsZWN0aW9uID0gY3VycmVudCBhcyBPRGF0YUNvbGxlY3Rpb248RiwgT0RhdGFNb2RlbDxGPj47XG4gICAgICAgIGlmIChPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24odmFsdWUpKSB7XG4gICAgICAgICAgLy8gTmV3IHZhbHVlIGlzIGNvbGxlY3Rpb25cbiAgICAgICAgICBjaGFuZ2VkID0gYXR0ci5zZXQoXG4gICAgICAgICAgICB2YWx1ZSBhcyBPRGF0YUNvbGxlY3Rpb248RiwgT0RhdGFNb2RlbDxGPj4sXG4gICAgICAgICAgICByZXNldCxcbiAgICAgICAgICAgIHJlcGFyZW50LFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoVHlwZXMuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAvLyBOZXcgdmFsdWUgaXMgYXJyYXlcbiAgICAgICAgICBjdXJyZW50Q29sbGVjdGlvbi5fYW5ub3RhdGlvbnMgPSBtb2RlbEZpZWxkLmFubm90YXRpb25zRmFjdG9yeShcbiAgICAgICAgICAgIHNlbGYuYW5ub3RzKCksXG4gICAgICAgICAgKSBhcyBPRGF0YUVudGl0aWVzQW5ub3RhdGlvbnM8Rj47XG4gICAgICAgICAgY3VycmVudENvbGxlY3Rpb24uYXNzaWduKFxuICAgICAgICAgICAgdmFsdWUgYXMgUGFydGlhbDxUPltdIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH1bXSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWRkLFxuICAgICAgICAgICAgICBtZXJnZSxcbiAgICAgICAgICAgICAgcmVtb3ZlLFxuICAgICAgICAgICAgICByZXNldCxcbiAgICAgICAgICAgICAgcmVwYXJlbnQsXG4gICAgICAgICAgICAgIHNpbGVudCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjaGFuZ2VkID0gY3VycmVudENvbGxlY3Rpb24uaGFzQ2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKE9EYXRhTW9kZWxPcHRpb25zLmlzTW9kZWwoY3VycmVudCkpIHtcbiAgICAgICAgLy8gQ3VycmVudCBpcyBtb2RlbFxuICAgICAgICBjb25zdCBjdXJyZW50TW9kZWwgPSBjdXJyZW50IGFzIE9EYXRhTW9kZWw8Rj47XG4gICAgICAgIGlmIChPRGF0YU1vZGVsT3B0aW9ucy5pc01vZGVsKHZhbHVlKSkge1xuICAgICAgICAgIC8vIE5ldyB2YWx1ZSBpcyBtb2RlbFxuICAgICAgICAgIGNoYW5nZWQgPSBhdHRyLnNldCh2YWx1ZSBhcyBPRGF0YU1vZGVsPEY+LCByZXNldCwgcmVwYXJlbnQpO1xuICAgICAgICB9IGVsc2UgaWYgKFR5cGVzLmlzUGxhaW5PYmplY3QodmFsdWUpKSB7XG4gICAgICAgICAgY3VycmVudE1vZGVsLl9hbm5vdGF0aW9ucyA9IG1vZGVsRmllbGQuYW5ub3RhdGlvbnNGYWN0b3J5KFxuICAgICAgICAgICAgc2VsZi5hbm5vdHMoKSxcbiAgICAgICAgICApIGFzIE9EYXRhRW50aXR5QW5ub3RhdGlvbnM8Rj47XG4gICAgICAgICAgY3VycmVudE1vZGVsLmFzc2lnbih2YWx1ZSBhcyBGIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH0sIHtcbiAgICAgICAgICAgIGFkZCxcbiAgICAgICAgICAgIG1lcmdlLFxuICAgICAgICAgICAgcmVtb3ZlLFxuICAgICAgICAgICAgcmVzZXQsXG4gICAgICAgICAgICByZXBhcmVudCxcbiAgICAgICAgICAgIHNpbGVudCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjaGFuZ2VkID0gY3VycmVudE1vZGVsLmhhc0NoYW5nZWQoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQ3VycmVudCBpcyBudWxsIG9yIHVuZGVmaW5lZFxuICAgICAgICAvLyBjcmVhdGUgbmV3IG1vZGVsL2NvbGxlY3Rpb24gZm9yIGdpdmVuIHZhbHVlXG4gICAgICAgIGNoYW5nZWQgPSBhdHRyLnNldChcbiAgICAgICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc0NvbGxlY3Rpb24odmFsdWUpIHx8XG4gICAgICAgICAgICBPRGF0YU1vZGVsT3B0aW9ucy5pc01vZGVsKHZhbHVlKVxuICAgICAgICAgICAgPyAodmFsdWUgYXMgT0RhdGFNb2RlbDxGPiB8IE9EYXRhQ29sbGVjdGlvbjxGLCBPRGF0YU1vZGVsPEY+PilcbiAgICAgICAgICAgIDogbW9kZWxGaWVsZC5jb2xsZWN0aW9uXG4gICAgICAgICAgICAgID8gbW9kZWxGaWVsZC5jb2xsZWN0aW9uRmFjdG9yeTxGPih7XG4gICAgICAgICAgICAgICAgICBwYXJlbnQ6IHNlbGYsXG4gICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUgYXMgRltdIHwgeyBbbmFtZTogc3RyaW5nXTogYW55IH1bXSxcbiAgICAgICAgICAgICAgICAgIHJlc2V0OiByZXNldCxcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICA6IG1vZGVsRmllbGQubW9kZWxGYWN0b3J5PEY+KHtcbiAgICAgICAgICAgICAgICAgIHBhcmVudDogc2VsZixcbiAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgIHJlc2V0OiByZXNldCxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICByZXNldCxcbiAgICAgICAgICByZXBhcmVudCxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVzb2x2ZSByZWZlcmVudGlhbHNcbiAgICAgIGlmICghT0RhdGFNb2RlbE9wdGlvbnMuaXNDb2xsZWN0aW9uKGF0dHIuZ2V0KCkpKSB7XG4gICAgICAgIGNvbnN0IG1ldGEgPSB0aGlzLmFwaS5vcHRpb25zRm9yVHlwZTxGPihtb2RlbEZpZWxkLnR5cGUpO1xuICAgICAgICBjb25zdCByZWYgPSBtZXRhPy5yZXNvbHZlUmVmZXJlbnRpYWwoYXR0ci5nZXQoKSwgYXR0ciwge1xuICAgICAgICAgIHJlc29sdmU6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlZiAhPT0gbnVsbCAmJiByZWYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIE9iamVjdC5hc3NpZ24oc2VsZiwgcmVmKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjaGFuZ2VkID0gYXR0ci5zZXQodmFsdWUsIHJlc2V0LCByZXBhcmVudCk7XG4gICAgfVxuXG4gICAgaWYgKCFzaWxlbnQgJiYgY2hhbmdlZCkge1xuICAgICAgc2VsZi5ldmVudHMkLnRyaWdnZXIoT0RhdGFNb2RlbEV2ZW50VHlwZS5DaGFuZ2UsIHtcbiAgICAgICAgYXR0cixcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIHByZXZpb3VzOiBjdXJyZW50LFxuICAgICAgICBvcHRpb25zOiB7IGtleTogbW9kZWxGaWVsZC5pc0tleSgpIH0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2hhbmdlZDtcbiAgfVxuXG4gIHByaXZhdGUgX2xpbms8Rj4oc2VsZjogT0RhdGFNb2RlbDxUPiwgYXR0cjogT0RhdGFNb2RlbEF0dHJpYnV0ZTxGPikge1xuICAgIGF0dHIuZXZlbnRzJC5zdWJzY3JpYmUoKGV2ZW50OiBPRGF0YU1vZGVsRXZlbnQ8YW55PikgPT4ge1xuICAgICAgaWYgKGV2ZW50LmNhbkNvbnRpbnVlV2l0aChzZWxmKSkge1xuICAgICAgICBpZiAoZXZlbnQubW9kZWwgPT09IGF0dHIuZ2V0KCkpIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBldmVudC50eXBlID09PSBPRGF0YU1vZGVsRXZlbnRUeXBlLkNoYW5nZSAmJlxuICAgICAgICAgICAgYXR0ci5uYXZpZ2F0aW9uICYmXG4gICAgICAgICAgICBldmVudC5vcHRpb25zPy5rZXlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IHJlZiA9IChhdHRyLmdldCgpIGFzIE9EYXRhTW9kZWw8YW55PikucmVmZXJlbnRpYWwoYXR0cik7XG4gICAgICAgICAgICBpZiAocmVmICE9PSBudWxsICYmIHJlZiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oc2VsZiwgcmVmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZWxmLmV2ZW50cyQuZW1pdChldmVudC5wdXNoKHNlbGYsIGF0dHIpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19