UNPKG

stimulsoft-forms

Version:
622 lines (605 loc) 78.9 kB
/* {*******************************************************************} { } { } { } { Copyright (C) Stimulsoft } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { ARE CONFIDENTIAL AND PROPRIETARY } { TRADE SECRETS OF Stimulsoft } { } { CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {*******************************************************************} */ import Hashtable from './Hashtable'; import Dictionary from './Dictionary'; import { StiObject } from './StiObject'; export default class List extends Array { constructor(items) { super(); if (typeof items == "number") { } else if (items) items.forEach(item => this.push(item)); try { this.__proto__ = List.prototype; Object.defineProperty(this, "__proto__", { enumerable: false }); } catch (e) { Object.defineProperty(this, "__proto__", { enumerable: false, writable: true }); this.__proto__ = List.prototype; } } /*static create<T>(t: Type, ...values: any[]): List<T> { let isStructure = false; if (typeof values[values.length - 1] == "boolean") isStructure = !!values.pop(); if (values.length == 0) { if (t == Number) return <any>0; if (t == Boolean) return <any>false; if (isStructure) return new (<any>t); else return null; } let newList = new List<T>(); let count: number = values.shift(); for (let i = 0; i < count; i++) { let value: any = List.create.apply(this, (<any[]>[t]).concat(values, [isStructure])); newList.push(value); } return newList; }*/ get countItems() { let properties = StiObject.keys(this); return properties.length; } //#region Range addRange(items) { for (let item of items) this.push(item); } removeRange(index, count) { this.splice(index, count); } getRange(index, count) { if (index == null || index < 0) index = 0; if (index + count > this.length) count = this.length - index; return new List(this.slice(index, index + count)); } //#endregion add(item) { this.push(item); } insert(index, item) { this.splice(index, 0, item); } getKeys() { return StiObject.keys(this).sort((a, b) => { if (a < b) return -1; else if (a > b) return 1; else return 0; }); } getByIndex(index, keys = null) { if (keys == null) keys = this.getKeys(); return this[keys[index]]; } setByIndex(index, item) { let properties = StiObject.keys(this); this[properties[index]] = item; } removeByIndex(index) { let removeIndex = this.indexOf(this.getByIndex(index, null)); delete this[removeIndex]; return this; } copyTo(array, index = 0) { let destIndex = index; for (let sourceIndex = 0; sourceIndex < this.length; sourceIndex++) { array[destIndex] = this[sourceIndex]; destIndex++; } } /** Removes all elements from the List. */ clear() { this.splice(0, this.length); } peek() { return this[this.length - 1]; } remove(item) { let index = this.indexOf(item); if (index >= 0) this.removeAt(index); } /** Removes the element at the specified index of the Lis. * @param index The zero-based index of the element to remove. * @throw index is less than 0. -or- index is equal to or greater than Count. */ removeAt(index) { this.splice(index, 1); } exists(predicate) { for (let value of this) { if (predicate(value)) return true; } return false; } fullOuterJoin(inner, outerKeySelector, innerKeySelector, resultSelector, __this) { let innerLookup = inner.toLookup(innerKeySelector, __this); let outerLookup = this.toLookup(outerKeySelector, __this); let innerJoinItems = inner .where(innerItem => !outerLookup.contains(innerKeySelector.apply(__this, [innerItem]))) .select(innerItem => resultSelector.apply(__this, [null, innerItem])); return this .selectMany2(outerItem => { let innerItems = innerLookup.get(outerKeySelector.apply(__this, [outerItem])); return innerItems.any() ? innerItems : new List(); }, resultSelector, __this) .concat(innerJoinItems); } toList() { return new List(this); } findIndex2(match) { for (let index = 0; index < this.length; index++) { if (match(this[index])) return index; } return -1; } findLastIndex2(match) { let lastIndex = -1; for (let index = 0; index < this.length; index++) { if (match(this[index])) lastIndex = index; } return lastIndex; } zip(second, resultSelector) { let result = new List(); for (let index = 0; index < this.length; index++) { result.add(resultSelector(this[index], second[index])); } return result; } static repeat(element, count) { let list = new List(); for (let i = 0; i < count; i++) { list.push(element); } return list; } //#region Filtering /** Filters a sequence of values based on a predicate. * @param predicate A function to test each element for a condition. * @returns An List that contains elements from the input sequence that satisfy the condition. */ where(predicate, __this) { let filter = new List(); for (let index = 0; index < this.length; index++) { let value = this[index]; predicate.apply(__this, [value, index]) ? filter.push(value) : null; } return filter; } //#endregion //#region Join /** Correlates the elements of two sequences based on matching keys. The default * equality comparer is used to compare keys. * @param inner The sequence to join to the first sequence. * @param outerKeySelector A function to extract the join key from each element of the first sequence. * @param innerKeySelector A function to extract the join key from each element of the second sequence. * @param resultSelector A function to create a result element from two matching elements. * @returns An List that has elements of type V * that are obtained by performing an inner join on two sequences. */ join2(inner, outerKeySelector, innerKeySelector, resultSelector, __this) { let result = new List(); let innerKeys = new Hashtable(); for (let i of inner) { let innerKey = innerKeySelector.apply(__this, [i]); innerKeys.set(innerKey, i); } for (let o of this) { let outerKey = outerKeySelector.apply(__this, [o]); let i = innerKeys.get(outerKey); if (i != null) result.push(resultSelector.apply(__this, [o, i])); } return result; } /** Correlates the elements of two sequences based on equality of keys and groups * the results. The default equality comparer is used to compare keys. * @param inner The sequence to join to the first sequence. * @param outerKeySelector A function to extract the join key from each element of the first sequence. * @param innerKeySelector A function to extract the join key from each element of the second sequence. * @param resultSelector A function to create a result element from an element from the first sequence * and a collection of matching elements from the second sequence. * @returns An List that contains elements of type V * that are obtained by performing a grouped join on two sequences. */ groupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, __this) { let result = new List(); let innerKeys = new Hashtable(); for (let i of inner) { let key = innerKeySelector.apply(__this, [i]); let innerResult = innerKeys.get(key); if (innerResult == null) { innerResult = new List(); innerKeys.set(key, innerResult); } innerResult.push(i); } for (let o of this) { let key = outerKeySelector.apply(__this, [o]); let innerResult = innerKeys.get(key); if (innerResult == null) innerResult = new List(); result.push(resultSelector.apply(__this, [o, innerResult])); } return result; } //#endregion //#region Projection /** * Projects each element of a sequence into a new form. * @param selector A transform function to apply to each element. * @returns An List whose elements are the result of invoking the transform function on each element of source. */ select(selector, __this) { let filter = new List(); this.forEach(value => filter.push(selector.apply(__this, [value]))); return filter; } selectMany(selector, __this) { let filter = new List(); this.forEach(value => { let result = selector.apply(__this, [value]); if (result != null) result.forEach(item => filter.push(item)); }); return filter; } selectMany2(collectionSelector, resultSelector, __this) { let filter = new List(); this.forEach(value => { let result = collectionSelector.apply(__this, [value]); if (result != null) result.forEach(item => filter.push(resultSelector.apply(__this, [value, item]))); }); return filter; } //#endregion //#region Sorting /** Sorts the elements of a sequence in ascending order according to a key or by using a specified comparer. * @param keySelector A function to extract a key from an element. * @param comparer An System.Collections.Generic.IComparer`1 to compare keys. * @returns An System.Linq.IOrderedEnumerable`1 whose elements are sorted according to a key. */ /*orderBy<K>(keySelector: (value: T) => K, comparer?: IComparer<K>): List<T> { let sort: T[] = this.ss.toArray(); if (comparer == null) comparer = { compare: (x: K, y: K) => { if (x != null && y == null) return 1; if (x == null && y != null) return -1; if (x == null && y == null) return 0; return x.ss.compareTo(y); } }; sort.sort((a: T, b: T) => comparer.compare(keySelector(a), keySelector(b))); return new List<T>(sort); } orderByDescending<K>(keySelector: (value: T) => K, comparer?: IComparer<K>): List<T> { let sort: T[] = this.ss.toArray(); if (comparer == null) comparer = { compare: (x: K, y: K) => { if (x != null && y == null) return -1; if (x == null && y != null) return 1; if (x == null && y == null) return 0; return y.ss.compareTo(x); } }; sort.sort((a: T, b: T) => comparer.compare(keySelector(a), keySelector(b))); return new List<T>(sort); }*/ //#endregion //#region Grouping /** Groups the elements of a sequence according to a specified key selector function * and compares the keys by using a specified comparer. * @param keySelector A function to extract the key for each element. * @param comparer An System.Collections.Generic.IEqualityComparer`1 to compare keys. * @returns An IEnumerable<IGrouping<TKey, TSource>> in C# or IEnumerable(Of IGrouping(Of * TKey, TSource)) in Visual Basic where each System.Linq.IGrouping`2 object contains * a collection of objects and a key. */ /*-groupBy<K>(keySelector: (value: T) => K, comparer?: IEqualityComparer<K>, __this?: any): List<Grouping<K, T>> { let result = new List<Grouping<K, T>>(); if (comparer == null) comparer = { equals: (x: K, y: K) => { if (x == y) return true; return false; }, getHashCode: () => 0 }; for (let item of this) { let key = keySelector.apply(__this, [item]); let group = result.firstOrDefault(g => comparer.equals(g.key, key)); if (group == null) { group = new Grouping(new List<T>([])); group.key = key; result.push(group); } group.push(item); } return result; }*/ //#endregion //#region Conversions /** Converts the elements of an List to the specified type. * @returns An List that contains each element of the source sequence converted to the specified type. */ cast() { let cast = new List(); let castFunction; /*if (typeof <S>{} == "string") castFunction = (value: T) => value.s.toString(); else if (typeof <S>{} == "number") castFunction = (value: T) => value.s.ss.toNumber(); else if (typeof <S>{} == "boolean") castFunction = (value: T) => value.s.ss.toBoolean(); else*/ castFunction = (value) => value; this.forEach(value => cast.push(castFunction(value))); return cast; } toDictionary(keySelector, elementSelector) { let dictionary = new Dictionary(); for (let index = 0; index < this.length; index++) { dictionary.add(keySelector(this[index]), elementSelector(this[index])); } return dictionary; } /** Creates a Lookup from an List * according to a specified key selector function. * @param keySelector A function to extract a key from each element. * @returns A Lookup that contains keys and values. */ toLookup(keySelector, __this) { let hashtable = new Hashtable(); for (let item of this) { let key = keySelector.apply(__this, [item]); let lookup = hashtable.get(key); if (lookup == null) { lookup = new List(); hashtable.set(key, lookup); } lookup.push(item); } return hashtable; } //#endregion //#region Concatenation /** Concatenates two sequences. * @param second The sequence to concatenate to the first sequence. * @returns An List that contains the concatenated elements * of the two input sequences. */ concat(second) { let concatedList = new List(); for (let item of this) concatedList.push(item); for (let item of second) concatedList.push(item); return concatedList; } //#endregion //#region Aggregation /** * Applies an accumulator function over a sequence. * @param func An accumulator function to be invoked on each element. * @returns The final accumulator value. */ aggregate(func) { let seed = this[0]; for (let index = 1; index < this.length; index++) { seed = func(seed, this[index]); } return seed; } aggregate2(seed, func) { for (let index = 0; index < this.length; index++) { seed = func(seed, this[index]); } return seed; } count2(selector, __this) { if (selector == null) selector = (value) => true; let count = 0; this.forEach(item => selector.apply(__this, [item]) ? count++ : null); return count; } /** Invokes a transform function on each element of a sequence and returns the maximum value. * @param selector A transform function to apply to each element. * @returns The maximum value in the sequence. */ /*max<S>(selector?: (value: T) => S): S { if (selector == null) selector = (value: T) => <S><any>value; if (this.length == 0) return null; let max = selector(this[0]); let maxFunc: Function; if (typeof max == "string") maxFunc = function (strA: string, strB: string): string { return strA.ss.compareTo(strB) >= 0 ? strA : strB; }; if (typeof max == "number") maxFunc = Math.max; if (max instanceof DateTime) maxFunc = function (dateA: DateTime, dateB: DateTime): DateTime { return DateTime.compare(dateA, dateB) >= 0 ? dateA : dateB; }; for (let index = 1; index < this.length; index++) { max = maxFunc(selector(this[index]), max); } return max; }*/ /** Invokes a transform function on each element of a sequence and returns the minimum value. * @parm selector A transform function to apply to each element. * @returns The minimum value in the sequence. */ /*min<S>(selector?: (value: T) => S): S { if (selector == null) selector = (value: T) => <S><any>value; if (this.length == 0) return null; let min = selector(this[0]); let minFunc: Function; if (typeof min == "string") minFunc = function (strA: string, strB: string): string { return strA.ss.compareTo(strB) <= 0 ? strA : strB; }; if (typeof min == "number") minFunc = Math.min; if (min instanceof DateTime) minFunc = function (dateA: DateTime, dateB: DateTime): DateTime { return DateTime.compare(dateA, dateB) <= 0 ? dateA : dateB; }; for (let index = 1; index < this.length; index++) { min = minFunc(selector(this[index]), min); } return min; }*/ /** Computes the sum of the sequence of System.Decimal values that are obtained by * invoking a transform function on each element of the input sequence. * @param selector A transform function to apply to each element. * @returns The sum of the projected values. */ /*sum(selector?: (value: T) => number): number { if (selector == null) selector = (value: T) => value.ss.toNumber(); let sum = 0; this.forEach(value => sum += selector(value)); return sum; }*/ //#endregion //#region Quantifier Operations all(predicate, __this) { if (predicate == null) predicate = (value) => true; for (let value of this) if (!predicate.apply(__this, [value])) return false; return true; } /** Determines whether any element of a sequence satisfies a condition. * @param predicate A function to test each element for a condition. * @returns true if any elements in the source sequence pass the test in the specified predicate; otherwise, false. */ any(predicate, __this) { if (predicate == null) predicate = (value) => true; for (let value of this) if (predicate.apply(__this, [value])) return true; return false; } /** Determines whether an element is in the List. * @param item The object to locate in the List. The value can be null for reference types. * @returns true if item is found in the List otherwise, false. */ contains(item) { return this.indexOf(item) >= 0; } //#endregion //#region Partition Operations skip(count) { let result = new List(); for (let index = count; index < this.length; index++) { result.add(this[index]); } return result; } take(count) { let result = new List(); if (count > this.length) count = this.length; for (let index = 0; index < count; index++) { result.add(this[index]); } return result; } //#endregion //#region Generation Operations defaultIfEmpty() { if (this.length > 0) return this; return new List([null]); } //#endregion //#region Set Operations /** Returns distinct elements from a sequence by using the default equality comparer to compare values. * @returns An List that contains distinct elements from the source sequence. */ distinct() { let filter = new List(); this.forEach(value => filter.indexOf(value) < 0 ? filter.push(value) : null); return filter; } except(second) { let result = new List(); for (let item of this) { if (second.indexOf(item) == -1) result.add(item); } return result; } union(second) { let union = new List(); this.forEach(element => union.add(element)); second.forEach(element => union.add(element)); return union.distinct(); } //#endregion //#region Equality sequenceEqual(second) { if (this.length != second.length) return false; for (let index = 0; index < this.length; index++) { if (this[index] != second[index]) return false; } return true; } //#endregion //#region Element first(selector, __this) { if (selector == null) selector = (value) => true; for (let item of this) { if (selector.apply(__this, [item])) return item; } return null; } /** Returns the first element of the sequence that satisfies a condition or a default value if no such element is found. * @param predicate A function to test each element for a condition. * @returns if source is empty or if no element passes the test specified by predicate; * otherwise, the first element in source that passes the test specified by predicate. */ firstOrDefault(predicate) { for (let value of this) { if (predicate == null) return value; if (predicate(value)) return value; } return null; } lastOrDefault() { let item; for (let value of this) { item = value; } return item; } } StiObject.disableAllEnumerable(List.prototype, new List()); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTGlzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0aW11bHNvZnQtZm9ybXMvc3JjL2xpYi9zeXN0ZW0vTGlzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUEwQkU7QUFFRixPQUFPLFNBQVMsTUFBTSxhQUFhLENBQUM7QUFDcEMsT0FBTyxVQUFVLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFeEMsTUFBTSxDQUFDLE9BQU8sT0FBTyxJQUFRLFNBQVEsS0FBUTtJQUN6QyxZQUFZLEtBQW9CO1FBQzVCLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxPQUFPLEtBQUssSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUUvQixDQUFDO2FBQ0ksSUFBSSxLQUFLO1lBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUV2RCxJQUFJLENBQUM7WUFDSyxJQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDdkMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDcEUsQ0FBQztRQUNELE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDUCxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzFFLElBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUMzQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BbUJHO0lBRUgsSUFBSSxV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cEMsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1FBQ3ZDLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsYUFBYTtRQUNULElBQUksSUFBSSxDQUFDO1FBQ1QsS0FBSyxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNyQixJQUFJLEdBQUcsS0FBSyxDQUFDO1FBQ2pCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0NBU0o7QUFFRCxTQUFTLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG57KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKn1cclxueyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG57ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxueyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbnsgICBDb3B5cmlnaHQgKEMpICBTdGltdWxzb2Z0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG57ICAgQUxMIFJJR0hUUyBSRVNFUlZFRCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxueyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbnsgICBUaGUgZW50aXJlIGNvbnRlbnRzIG9mIHRoaXMgZmlsZSBpcyBwcm90ZWN0ZWQgYnkgVS5TLiBhbmQgICAgICAgfVxyXG57ICAgSW50ZXJuYXRpb25hbCBDb3B5cmlnaHQgTGF3cy4gVW5hdXRob3JpemVkIHJlcHJvZHVjdGlvbiwgICAgICAgIH1cclxueyAgIHJldmVyc2UtZW5naW5lZXJpbmcsIGFuZCBkaXN0cmlidXRpb24gb2YgYWxsIG9yIGFueSBwb3J0aW9uIG9mICB9XHJcbnsgICB0aGUgY29kZSBjb250YWluZWQgaW4gdGhpcyBmaWxlIGlzIHN0cmljdGx5IHByb2hpYml0ZWQgYW5kIG1heSAgfVxyXG57ICAgcmVzdWx0IGluIHNldmVyZSBjaXZpbCBhbmQgY3JpbWluYWwgcGVuYWx0aWVzIGFuZCB3aWxsIGJlICAgICAgIH1cclxueyAgIHByb3NlY3V0ZWQgdG8gdGhlIG1heGltdW0gZXh0ZW50IHBvc3NpYmxlIHVuZGVyIHRoZSBsYXcuICAgICAgICB9XHJcbnsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG57ICAgUkVTVFJJQ1RJT05TICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxueyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbnsgICBUSElTIFNPVVJDRSBDT0RFIEFORCBBTEwgUkVTVUxUSU5HIElOVEVSTUVESUFURSBGSUxFUyAgICAgICAgICAgfVxyXG57ICAgQVJFIENPTkZJREVOVElBTCBBTkQgUFJPUFJJRVRBUlkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxueyAgIFRSQURFIFNFQ1JFVFMgT0YgU3RpbXVsc29mdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbnsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG57ICAgQ09OU1VMVCBUSEUgRU5EIFVTRVIgTElDRU5TRSBBR1JFRU1FTlQgRk9SIElORk9STUFUSU9OIE9OICAgICAgIH1cclxueyAgIEFERElUSU9OQUwgUkVTVFJJQ1RJT05TLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbnsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG57KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKn1cclxuKi9cclxuXHJcbmltcG9ydCBIYXNodGFibGUgZnJvbSAnLi9IYXNodGFibGUnO1xyXG5pbXBvcnQgRGljdGlvbmFyeSBmcm9tICcuL0RpY3Rpb25hcnknO1xyXG5pbXBvcnQgeyBTdGlPYmplY3QgfSBmcm9tICcuL1N0aU9iamVjdCc7XHJcblxyXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0PFQ+IGV4dGVuZHMgQXJyYXk8VD4ge1xyXG4gICAgY29uc3RydWN0b3IoaXRlbXM/OiBUW10gfCBudW1iZXIpIHtcclxuICAgICAgICBzdXBlcigpO1xyXG4gICAgICAgIGlmICh0eXBlb2YgaXRlbXMgPT0gXCJudW1iZXJcIikge1xyXG5cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoaXRlbXMpIGl0ZW1zLmZvckVhY2goaXRlbSA9PiB0aGlzLnB1c2goaXRlbSkpO1xyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAoPGFueT50aGlzKS5fX3Byb3RvX18gPSBMaXN0LnByb3RvdHlwZTtcclxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwiX19wcm90b19fXCIsIHsgZW51bWVyYWJsZTogZmFsc2UgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIl9fcHJvdG9fX1wiLCB7IGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSB9KTtcclxuICAgICAgICAgICAgKDxhbnk+dGhpcykuX19wcm90b19fID0gTGlzdC5wcm90b3R5cGU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qc3RhdGljIGNyZWF0ZTxUPih0OiBUeXBlLCAuLi52YWx1ZXM6IGFueVtdKTogTGlzdDxUPiB7XHJcbiAgICAgICAgbGV0IGlzU3RydWN0dXJlID0gZmFsc2U7XHJcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZXNbdmFsdWVzLmxlbmd0aCAtIDFdID09IFwiYm9vbGVhblwiKSBpc1N0cnVjdHVyZSA9ICEhdmFsdWVzLnBvcCgpO1xyXG5cclxuICAgICAgICBpZiAodmFsdWVzLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgICAgICAgIGlmICh0ID09IE51bWJlcikgcmV0dXJuIDxhbnk+MDtcclxuICAgICAgICAgICAgaWYgKHQgPT0gQm9vbGVhbikgcmV0dXJuIDxhbnk+ZmFsc2U7XHJcbiAgICAgICAgICAgIGlmIChpc1N0cnVjdHVyZSkgcmV0dXJuIG5ldyAoPGFueT50KTtcclxuICAgICAgICAgICAgZWxzZSByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBuZXdMaXN0ID0gbmV3IExpc3Q8VD4oKTtcclxuICAgICAgICBsZXQgY291bnQ6IG51bWJlciA9IHZhbHVlcy5zaGlmdCgpO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdmFsdWU6IGFueSA9IExpc3QuY3JlYXRlLmFwcGx5KHRoaXMsICg8YW55W10+W3RdKS5jb25jYXQodmFsdWVzLCBbaXNTdHJ1Y3R1cmVdKSk7XHJcbiAgICAgICAgICAgIG5ld0xpc3QucHVzaCh2YWx1ZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gbmV3TGlzdDtcclxuICAgIH0qL1xyXG5cclxuICAgIGdldCBjb3VudEl0ZW1zKCk6IG51bWJlciB7XHJcbiAgICAgICAgbGV0IHByb3BlcnRpZXM6IHN0cmluZ1tdID0gU3RpT2JqZWN0LmtleXModGhpcyk7XHJcbiAgICAgICAgcmV0dXJuIHByb3BlcnRpZXMubGVuZ3RoO1xyXG4gICAgfVxyXG5cclxuICAgIC8vI3JlZ2lvbiBSYW5nZVxyXG4gICAgYWRkUmFuZ2UoaXRlbXM6IExpc3Q8VD4gfCBUW10pIHtcclxuICAgICAgICBmb3IgKGxldCBpdGVtIG9mIGl0ZW1zKSB0aGlzLnB1c2goaXRlbSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmVtb3ZlUmFuZ2UoaW5kZXg6IG51bWJlciwgY291bnQ6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuc3BsaWNlKGluZGV4LCBjb3VudCk7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0UmFuZ2UoaW5kZXg6IG51bWJlciwgY291bnQ6IG51bWJlcik6IExpc3Q8VD4ge1xyXG4gICAgICAgIGlmIChpbmRleCA9PSBudWxsIHx8IGluZGV4IDwgMCkgaW5kZXggPSAwO1xyXG4gICAgICAgIGlmIChpbmRleCArIGNvdW50ID4gdGhpcy5sZW5ndGgpIGNvdW50ID0gdGhpcy5sZW5ndGggLSBpbmRleDtcclxuICAgICAgICByZXR1cm4gbmV3IExpc3QodGhpcy5zbGljZShpbmRleCwgaW5kZXggKyBjb3VudCkpO1xyXG4gICAgfVxyXG4gICAgLy8jZW5kcmVnaW9uXHJcblxyXG4gICAgYWRkKGl0ZW06IFQpIHtcclxuICAgICAgICB0aGlzLnB1c2goaXRlbSk7XHJcbiAgICB9XHJcblxyXG4gICAgaW5zZXJ0KGluZGV4OiBudW1iZXIsIGl0ZW06IFQpIHtcclxuICAgICAgICB0aGlzLnNwbGljZShpbmRleCwgMCwgaXRlbSk7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0S2V5cygpOiBzdHJpbmdbXSB7XHJcbiAgICAgICAgcmV0dXJuIFN0aU9iamVjdC5rZXlzKHRoaXMpLnNvcnQoKGEsIGIpID0+IHtcclxuICAgICAgICAgICAgaWYgKGEgPCBiKSByZXR1cm4gLTE7XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGEgPiBiKSByZXR1cm4gMTtcclxuICAgICAgICAgICAgZWxzZSByZXR1cm4gMDtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBnZXRCeUluZGV4KGluZGV4OiBudW1iZXIsIGtleXM6IHN0cmluZ1tdID0gbnVsbCk6IFQge1xyXG4gICAgICAgIGlmIChrZXlzID09IG51bGwpIGtleXMgPSB0aGlzLmdldEtleXMoKTtcclxuICAgICAgICByZXR1cm4gdGhpc1trZXlzW2luZGV4XV07XHJcbiAgICB9XHJcblxyXG4gICAgc2V0QnlJbmRleChpbmRleDogbnVtYmVyLCBpdGVtOiBUKSB7XHJcbiAgICAgICAgbGV0IHByb3BlcnRpZXM6IHN0cmluZ1tdID0gU3RpT2JqZWN0LmtleXModGhpcyk7XHJcbiAgICAgICAgdGhpc1twcm9wZXJ0aWVzW2luZGV4XV0gPSBpdGVtO1xyXG4gICAgfVxyXG5cclxuICAgIHJlbW92ZUJ5SW5kZXgoaW5kZXg6IG51bWJlcik6IExpc3Q8VD4ge1xyXG4gICAgICAgIGxldCByZW1vdmVJbmRleDogbnVtYmVyID0gdGhpcy5pbmRleE9mKHRoaXMuZ2V0QnlJbmRleChpbmRleCwgbnVsbCkpO1xyXG4gICAgICAgIGRlbGV0ZSB0aGlzW3JlbW92ZUluZGV4XTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH1cclxuXHJcbiAgICBjb3B5VG8oYXJyYXk6IGFueVtdLCBpbmRleCA9IDApIHtcclxuICAgICAgICBsZXQgZGVzdEluZGV4OiBudW1iZXIgPSBpbmRleDtcclxuICAgICAgICBmb3IgKGxldCBzb3VyY2VJbmRleCA9IDA7IHNvdXJjZUluZGV4IDwgdGhpcy5sZW5ndGg7IHNvdXJjZUluZGV4KyspIHtcclxuICAgICAgICAgICAgYXJyYXlbZGVzdEluZGV4XSA9IHRoaXNbc291cmNlSW5kZXhdO1xyXG4gICAgICAgICAgICBkZXN0SW5kZXgrKztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFJlbW92ZXMgYWxsIGVsZW1lbnRzIGZyb20gdGhlIExpc3QuICovXHJcbiAgICBjbGVhcigpIHtcclxuICAgICAgICB0aGlzLnNwbGljZSgwLCB0aGlzLmxlbmd0aCk7XHJcbiAgICB9XHJcblxyXG4gICAgcGVlaygpOiBUIHtcclxuICAgICAgICByZXR1cm4gdGhpc1t0aGlzLmxlbmd0aCAtIDFdO1xyXG4gICAgfVxyXG5cclxuICAgIHJlbW92ZShpdGVtOiBUKSB7XHJcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5pbmRleE9mKGl0ZW0pO1xyXG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB0aGlzLnJlbW92ZUF0KGluZGV4KTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogUmVtb3ZlcyB0aGUgZWxlbWVudCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4IG9mIHRoZSBMaXMuXHJcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIHplcm8tYmFzZWQgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmVtb3ZlLlxyXG4gICAgICogQHRocm93IGluZGV4IGlzIGxlc3MgdGhhbiAwLiAtb3ItIGluZGV4IGlzIGVxdWFsIHRvIG9yIGdyZWF0ZXIgdGhhbiBDb3VudC5cclxuICAgICAqL1xyXG4gICAgcmVtb3ZlQXQoaW5kZXg6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuc3BsaWNlKGluZGV4LCAxKTtcclxuICAgIH1cclxuXHJcbiAgICBleGlzdHMocHJlZGljYXRlOiAodmFsdWU6IFQpID0+IGJvb2xlYW4pOiBib29sZWFuI