UNPKG

@openxmldev/linq-to-xml

Version:
374 lines 13.8 kB
/** * @author Thomas Barnekow * @license MIT */ import { defaultIfEmpty, skip, skipLast, skipWhile, take, takeLast, takeWhile, where, } from '@tsdotnet/linq/dist/filters.js'; import { all, any, count, first, firstOrDefault, last, lastOrDefault, single, singleOrDefault, toArray, } from '@tsdotnet/linq/dist/resolutions.js'; import { groupBy, select, selectMany } from '@tsdotnet/linq/dist/transforms.js'; import { filter } from './transformations/index.js'; /** * Abstract base class for LINQ iterables. * * @remarks * This abstract class serves as the generic base class for all LINQ iterables * provided by this library. The {@linkcode LinqIterable<T>} class just derives * from this class and adds no further features. Other classes such as * {@linkcode LinqElements} inherit from this class and provide further methods. * The generics-based pattern used in this case means that all filter methods, * returning a `TLinq`, for example, will return instances of the subclasses. * * @typeParam T The type of the elements of the sequence. * @typeParam TLinq The type of the LINQ iterable returned by filters. */ export class LinqIterableBase { /** * Initializes a new instance with the given sequence. * * @param source The source sequence. */ constructor(source, create) { this.source = source; this.create = create; } /** * Returns the sequence of elements represented by this `LinqIterable<T>`. * * @returns The sequence of elements represented by this `LinqIterable<T>`. */ [Symbol.iterator]() { return this.source[Symbol.iterator](); } /** * Filters this sequence, using zero or more filters. * * @param filters The filters to use. * @returns A filtered sequence. */ filter(...filters) { return filters.length ? this.applyFilters(filters) : this; } /** * Filters this sequence, using the given filters. * * @param filters The filters to use. * @returns A filtered sequence. */ applyFilters(filters) { return this.create(filter(this.source, filters)); } /** * Transforms this sequence, using the given transformation. * * @transform TResult The type of the elements of the transformed sequence. * @param transformation The transformation to use. * @returns A transformed sequence. */ transform(transformation) { return linqIterable(transformation(this.source)); } /** * Applies the given resolution to this sequence. * * @typeParam TResult The type of the result of the resolution. * @param resolution The resolution to use. * @returns The resolved value. */ resolve(resolution) { return resolution(this.source); } // // Filters // /** * Returns the elements of the specified sequence or the default value if the * sequence is empty. * * @param defaultValue The default value to be returned if this sequence is empty. * @returns The elements of the specified sequence or the default value if the sequence is empty. */ defaultIfEmpty(defaultValue) { return this.create(defaultIfEmpty(defaultValue)(this.source)); } /** * Returns a new sequence that contains the elements from this sequence with * the first `count` elements omitted. * * @param count The number of elements to be omitted. * @returns A new sequence that contains the elements from this sequence with * the first `count` elements omitted. */ skip(count) { return this.create(skip(count)(this.source)); } /** * Returns a new sequence that contains the elements from this sequence with * the last `count` elements omitted. * * @param count The number of elements to be omitted. * @returns A new sequence that contains the elements from this sequence with * the first `count` elements omitted. */ skipLast(count) { return this.create(skipLast(count)(this.source)); } /** * Bypasses elements in a sequence as long as a specified condition is true * and then returns the remaining elements. * * @param predicate The specified condition. * @returns A new sequence with the remaining elements. */ skipWhile(predicate) { return this.create(skipWhile(predicate)(this.source)); } /** * Returns a new sequence that contains the specified number of contiguous * elements from the start of this sequence. * * @param count The number of elements to take. * @returns a new sequence that contains the specified number of contiguous * elements from the start of this sequence. */ take(count) { return this.create(take(count)(this.source)); } /** * Returns a new sequence that contains the specified number of contiguous * elements from the end of this sequence. * * @param count The number of elements to take. * @returns A new sequence that contains the specified number of contiguous * elements from the end of this sequence. */ takeLast(count) { return this.create(takeLast(count)(this.source)); } /** * Returns a new sequence that contains elements from this sequence that occur * before the element at which the specified condition is false. * * @param predicate The specified condition. * @returns A new sequence that contains elements from this sequence that occur * before the element at which the specified condition is false. */ takeWhile(predicate) { return this.create(takeWhile(predicate)(this.source)); } /** * Filters the sequence using the given predicate. * * @param predicate The predicate. * @returns The filtered sequence. */ where(predicate) { return this.create(where(predicate)(this.source)); } // // Resolutions // /** * Returns true if the predicate is true for every element in the sequence or * if the sequence is empty. * * @param predicate The predicate. */ all(predicate) { return all(predicate)(this.source); } /** * If a predicate is provided, returns true if the predicate is true for any * element in the sequence. * If no predicate is provided, returns true if the sequence has any entries. * * @param predicate The optional predicate. */ any(predicate) { return any(predicate)(this.source); } /** * Returns the number of elements in the sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The number of elements in the sequence. */ count(predicate) { return predicate ? count(where(predicate)(this.source)) : count(this.source); } /** * Returns the first element of this sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The first element. * @throws If the (optionally filtered) sequence is empty. * @see {@linkcode last} and {@linkcode single} */ first(predicate) { return first(this.filterSequence(predicate)); } firstOrDefault(predicateOrDefault, defaultValue) { if (predicateOrDefault === undefined && defaultValue === undefined) { // firstOrDefault(): T | undefined; return firstOrDefault()(this.source); } else if (predicateOrDefault !== undefined && defaultValue === undefined) { if (typeof predicateOrDefault === 'function') { // firstOrDefault(predicate: PredicateWithIndex<T>): T | undefined; return firstOrDefault()(this.filterSequence(predicateOrDefault)); } else { // firstOrDefault(defaultValue: T): T; return firstOrDefault(predicateOrDefault)(this.source); } } else { // firstOrDefault(predicate: PredicateWithIndex<T>, defaultValue: T): T; return firstOrDefault(defaultValue)(this.filterSequence(predicateOrDefault)); } } /** * Returns the last element of the sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The last element. * @throws If the (optionally filtered) sequence is empty. * @see {@linkcode first} and {@linkcode single} */ last(predicate) { return last(this.filterSequence(predicate)); } lastOrDefault(predicateOrDefault, defaultValue) { if (predicateOrDefault === undefined && defaultValue === undefined) { // lastOrDefault(): T | undefined; return lastOrDefault()(this.source); } else if (predicateOrDefault !== undefined && defaultValue === undefined) { if (typeof predicateOrDefault === 'function') { // lastOrDefault(predicate: PredicateWithIndex<T>): T | undefined; return lastOrDefault()(this.filterSequence(predicateOrDefault)); } else { // lastOrDefault(defaultValue: T): T; return lastOrDefault(predicateOrDefault)(this.source); } } else { // lastOrDefault(predicate: PredicateWithIndex<T>, defaultValue: T): T; return lastOrDefault(defaultValue)(this.filterSequence(predicateOrDefault)); } } /** * Returns the single element of the sequence. * If a predicate is provided, filters the sequence based on the predicate. * * @param predicate The optional predicate. * @returns The single element. * @throws If the (optionally filtered) sequence does not contain exactly one element. * @see {@linkcode first} and {@linkcode last} */ single(predicate) { return single(this.filterSequence(predicate)); } singleOrDefault(predicateOrDefault, defaultValue) { if (predicateOrDefault === undefined && defaultValue === undefined) { // singleOrDefault(): T | undefined; return singleOrDefault()(this.source); } else if (predicateOrDefault !== undefined && defaultValue === undefined) { if (typeof predicateOrDefault === 'function') { // singleOrDefault(predicate: PredicateWithIndex<T>): T | undefined; return singleOrDefault()(this.filterSequence(predicateOrDefault)); } else { // singleOrDefault(defaultValue: T): T; return singleOrDefault(predicateOrDefault)(this.source); } } else { // singleOrDefault(predicate: PredicateWithIndex<T>, defaultValue: T): T; return singleOrDefault(defaultValue)(this.filterSequence(predicateOrDefault)); } } /** * Returns all the elements in the sequence as an array. */ toArray() { return toArray(this.source); } /** @internal */ filterSequence(predicate) { return predicate ? where(predicate)(this.source) : this.source; } // // Transformations // /** * Groups elements by selected key. * * @typeParam TKey The type of the grouping keys. * @param keySelector Selects the grouping keys. * @returns The grouped elements. */ groupBy(keySelector) { return this.transform(groupBy(keySelector)).select((g) => new LinqIterableGrouping(g)); } /** * Projects, or maps, each element of a sequence into a new form. * * @typeParam TResult The type of the elements of the projected, or mapped, sequence. * @param selector The selector used to project, or map, the elements. * @returns The projected, or mapped, sequence. */ select(selector) { return linqIterable(select(selector)(this.source)); } /** * Merges the selected sequences into one flat sequence. * * @typeParam TResult The type of the elements of the flat sequence. * @param selector The selector. * @returns The merged, flat sequence. */ selectMany(selector) { return linqIterable(selectMany(selector)(this.source)); } } /** * A LINQ iterable. * * @typeParam T The type of the elements of the sequence. */ export class LinqIterable extends LinqIterableBase { constructor(source) { super(source, linqIterable); } } /** * Represents a grouping of sequence elements. * * @typeParam TKey The type of the grouping keys. * @typeParam T The type of the grouped elements. */ export class LinqIterableGrouping extends LinqIterable { constructor(grouping) { super(grouping.elements); this.key = grouping.key; } } /** * Converts any `Iterable<T>` into a LINQ-style iterable. * * @typeParam T The type of the elements of the `LinqIterable<T>`. * @param source The source `Iterable<T>`. * @returns A `LinqIterable<T>` instance. */ export function linqIterable(source) { return source instanceof LinqIterable ? source : new LinqIterable(source); } //# sourceMappingURL=LinqIterable.js.map