stimulsoft-forms
Version:
Stimulsoft PDF Forms
622 lines (605 loc) • 78.9 kB
JavaScript
/*
{*******************************************************************}
{ }
{ }
{ }
{ 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