/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package net.hydromatic.linq4j;

import net.hydromatic.linq4j.expressions.Expression;
import net.hydromatic.linq4j.expressions.Expressions;
import net.hydromatic.linq4j.expressions.FunctionExpression;
import net.hydromatic.linq4j.function.*;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;

/**
 * Default implementations for methods in the {@link Queryable} interface.
 *
 * @author jhyde
 */
public abstract class QueryableDefaults {

  /**
   * Applies an accumulator function over a
   * sequence.
   */
  public static <T> T aggregate(Queryable<T> queryable,
      FunctionExpression<Function2<T, T, T>> func) {
    throw Extensions.todo();
  }

  /**
   * Applies an accumulator function over a
   * sequence. The specified seed value is used as the initial
   * accumulator value.
   */
  public static <T, TAccumulate> TAccumulate aggregate(Queryable<T> queryable,
      TAccumulate seed,
      FunctionExpression<Function2<TAccumulate, T, TAccumulate>> func) {
    throw Extensions.todo();
  }

  /**
   * Applies an accumulator function over a
   * sequence. The specified seed value is used as the initial
   * accumulator value, and the specified function is used to select
   * the result value.
   */
  public static <T, TAccumulate, TResult> TResult aggregate(
      Queryable<T> queryable, TAccumulate seed,
      FunctionExpression<Function2<TAccumulate, T, TAccumulate>> func,
      FunctionExpression<Function1<TAccumulate, TResult>> selector) {
    throw Extensions.todo();
  }

  /**
   * Determines whether all the elements of a sequence
   * satisfy a condition.
   */
  public static <T> boolean all(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Determines whether a sequence contains any
   * elements.
   */
  public static <T> void any(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Determines whether any element of a sequence
   * satisfies a condition.
   */
  public static <T> boolean any(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Converts a generic Enumerable<T> to a generic
   * IQueryable<T>.
   */
  public static <T> Queryable<T> asQueryable(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of Decimal
   * values that is obtained by invoking a projection function on
   * each element of the input sequence.
   */
  public static <T> BigDecimal averageBigDecimal(Queryable<T> queryable,
      FunctionExpression<BigDecimalFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of nullable
   * Decimal values that is obtained by invoking a projection
   * function on each element of the input sequence.
   */
  public static <T> BigDecimal averageNullableBigDecimal(Queryable<T> queryable,
      FunctionExpression<NullableBigDecimalFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of Double
   * values that is obtained by invoking a projection function on
   * each element of the input sequence.
   */
  public static <T> double averageDouble(Queryable<T> queryable,
      FunctionExpression<DoubleFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of nullable
   * Double values that is obtained by invoking a projection
   * function on each element of the input sequence.
   */
  public static <T> Double averageNullableDouble(Queryable<T> queryable,
      FunctionExpression<NullableDoubleFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of int values
   * that is obtained by invoking a projection function on each
   * element of the input sequence.
   */
  public static <T> int averageInteger(Queryable<T> queryable,
      FunctionExpression<IntegerFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of nullable
   * int values that is obtained by invoking a projection function
   * on each element of the input sequence.
   */
  public static <T> Integer averageNullableInteger(Queryable<T> queryable,
      FunctionExpression<NullableIntegerFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of Float
   * values that is obtained by invoking a projection function on
   * each element of the input sequence.
   */
  public static <T> float averageFloat(Queryable<T> queryable,
      FunctionExpression<FloatFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of nullable
   * Float values that is obtained by invoking a projection
   * function on each element of the input sequence.
   */
  public static <T> Float averageNullableFloat(Queryable<T> queryable,
      FunctionExpression<NullableFloatFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of long values
   * that is obtained by invoking a projection function on each
   * element of the input sequence.
   */
  public static <T> long averageLong(Queryable<T> queryable,
      FunctionExpression<LongFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the average of a sequence of nullable
   * long values that is obtained by invoking a projection function
   * on each element of the input sequence.
   */
  public static <T> Long averageNullableLong(Queryable<T> queryable,
      FunctionExpression<NullableLongFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * <p>Analogous to LINQ's Enumerable.Cast extension method.</p>
   *
   * @param clazz Target type
   * @param <T2> Target type
   *
   * @return Collection of T2
   */
  public static <T, T2> Queryable<T2> cast(final Queryable<T> source,
      final Class<T2> clazz) {
    return new BaseQueryable<T2>(source.getProvider(), clazz,
        source.getExpression()) {
      public Enumerator<T2> enumerator() {
        return new EnumerableDefaults.CastingEnumerator<T2>(source.enumerator(),
            clazz);
      }
    };
  }

  /**
   * Concatenates two sequences.
   */
  public static <T> Queryable<T> concat(Queryable<T> queryable0,
      Enumerable<T> source2) {
    throw Extensions.todo();
  }

  /**
   * Determines whether a sequence contains a specified
   * element by using the default equality comparer.
   */
  public static <T> boolean contains(Queryable<T> queryable, T element) {
    throw Extensions.todo();
  }

  /**
   * Determines whether a sequence contains a specified
   * element by using a specified EqualityComparer<T>.
   */
  public static <T> boolean contains(Queryable<T> queryable, T element,
      EqualityComparer comparer) {
    throw Extensions.todo();
  }

  /**
   * Returns the number of elements in a
   * sequence.
   */
  public static <T> int count(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Returns the number of elements in the specified
   * sequence that satisfies a condition.
   */
  public static <T> int count(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> func) {
    throw Extensions.todo();
  }

  /**
   * Returns the elements of the specified sequence or
   * the type parameter's default value in a singleton collection if
   * the sequence is empty.
   */
  public static <T> Queryable<T> defaultIfEmpty(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Returns the elements of the specified sequence or
   * the specified value in a singleton collection if the sequence
   * is empty.
   */
  public static <T> T defaultIfEmpty(Queryable<T> queryable, T value) {
    throw Extensions.todo();
  }

  /**
   * Returns distinct elements from a sequence by using
   * the default equality comparer to compare values.
   */
  public static <T> Queryable<T> distinct(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Returns distinct elements from a sequence by using
   * a specified EqualityComparer<T> to compare values.
   */
  public static <T> Queryable<T> distinct(Queryable<T> queryable,
      EqualityComparer comparer) {
    throw Extensions.todo();
  }

  /**
   * Returns the element at a specified index in a
   * sequence.
   */
  public static <T> T elementAt(Queryable<T> queryable, int index) {
    throw Extensions.todo();
  }

  /**
   * Returns the element at a specified index in a
   * sequence or a default value if the index is out of
   * range.
   */
  public static <T> T elementAtOrDefault(Queryable<T> queryable, int index) {
    throw Extensions.todo();
  }

  /**
   * Produces the set difference of two sequences by
   * using the default equality comparer to compare values. (Defined
   * by Queryable.)
   */
  public static <T> Queryable<T> except(Queryable<T> queryable,
      Enumerable<T> enumerable) {
    throw Extensions.todo();
  }

  /**
   * Produces the set difference of two sequences by
   * using the specified EqualityComparer<T> to compare
   * values.
   */
  public static <T> Queryable<T> except(Queryable<T> queryable,
      Enumerable<T> enumerable, EqualityComparer<T> comparer) {
    throw Extensions.todo();
  }

  /**
   * Returns the first element of a sequence. (Defined
   * by Queryable.)
   */
  public static <T> T first(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Returns the first element of a sequence that
   * satisfies a specified condition.
   */
  public static <T> T first(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Returns the first element of a sequence, or a
   * default value if the sequence contains no elements.
   */
  public static <T> T firstOrDefault(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Returns the first element of a sequence that
   * satisfies a specified condition or a default value if no such
   * element is found.
   */
  public static <T> T firstOrDefault(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence according to a
   * specified key selector function.
   */
  public static <T, TKey> Queryable<Grouping<TKey, T>> groupBy(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence according to a
   * specified key selector function and compares the keys by using
   * a specified comparer.
   */
  public static <T, TKey> Queryable<Grouping<TKey, T>> groupBy(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector,
      EqualityComparer comparer) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence according to a
   * specified key selector function and projects the elements for
   * each group by using a specified function.
   */
  public static <T, TKey, TElement> Queryable<Grouping<TKey, TElement>> groupBy(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector,
      FunctionExpression<Function1<T, TElement>> elementSelector) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence according to a
   * specified key selector function and creates a result value from
   * each group and its key.
   *
   * <p>NOTE: Renamed from {@code groupBy} to distinguish from
   * {@link #groupBy(net.hydromatic.linq4j.Queryable, net.hydromatic.linq4j.expressions.FunctionExpression, net.hydromatic.linq4j.expressions.FunctionExpression)},
   * which has the same erasure.</p>
   */
  public static <T, TKey, TResult> Queryable<Grouping<TKey, TResult>> groupByK(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector,
      FunctionExpression<Function2<TKey, Enumerable<T>, TResult>>
        elementSelector) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence and projects the
   * elements for each group by using a specified function. Key
   * values are compared by using a specified comparer.
   */
  public static <T, TKey, TElement> Queryable<Grouping<TKey, TElement>> groupBy(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector,
      FunctionExpression<Function1<T, TElement>> elementSelector,
      EqualityComparer comparer) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence according to a
   * specified key selector function and creates a result value from
   * each group and its key. Keys are compared by using a specified
   * comparer.
   *
   * <p>NOTE: Renamed from {@code groupBy} to distinguish from
   * {@link #groupBy(net.hydromatic.linq4j.Queryable, net.hydromatic.linq4j.expressions.FunctionExpression, net.hydromatic.linq4j.expressions.FunctionExpression, net.hydromatic.linq4j.function.EqualityComparer)},
   * which has the same erasure.</p>
   */
  public static <T, TKey, TResult> Queryable<TResult> groupByK(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector,
      FunctionExpression<Function2<TKey, Enumerable<T>, TResult>>
        elementSelector,
      EqualityComparer comparer) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence according to a
   * specified key selector function and creates a result value from
   * each group and its key. The elements of each group are
   * projected by using a specified function.
   */
  public static <T, TKey, TElement, TResult> Queryable<TResult> groupBy(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector,
      FunctionExpression<Function1<T, TElement>> elementSelector,
      FunctionExpression<Function2<TKey, Enumerable<TElement>, TResult>>
        resultSelector) {
    throw Extensions.todo();
  }

  /**
   * Groups the elements of a sequence according to a
   * specified key selector function and creates a result value from
   * each group and its key. Keys are compared by using a specified
   * comparer and the elements of each group are projected by using
   * a specified function.
   */
  public static <T, TKey, TElement, TResult> Queryable<TResult> groupBy(
      Queryable<T> queryable,
      FunctionExpression<Function1<T, TKey>> keySelector,
      FunctionExpression<Function1<T, TElement>> elementSelector,
      FunctionExpression<Function2<TKey, Enumerable<TElement>, TResult>>
        resultSelector,
      EqualityComparer<TKey> comparer) {
    throw Extensions.todo();
  }

  /**
   * Correlates the elements of two sequences based on
   * key equality and groups the results. The default equality
   * comparer is used to compare keys.
   */
  public static <TOuter, TInner, TKey, TResult> Queryable<TResult> groupJoin(
      Queryable<TOuter> outer, Enumerable<TInner> inner,
      FunctionExpression<Function1<TOuter, TKey>> outerKeySelector,
      FunctionExpression<Function1<TInner, TKey>> innerKeySelector,
      FunctionExpression<Function2<TOuter, Enumerable<TInner>, TResult>>
        resultSelector) {
    throw Extensions.todo();
  }

  /**
   * Correlates the elements of two sequences based on
   * key equality and groups the results. A specified
   * EqualityComparer<T> is used to compare keys.
   */
  public static <TOuter, TInner, TKey, TResult> Enumerable<TResult> groupJoin(
      Queryable<TOuter> outer, Enumerable<TInner> inner,
      FunctionExpression<Function1<TOuter, TKey>> outerKeySelector,
      FunctionExpression<Function1<TInner, TKey>> innerKeySelector,
      FunctionExpression<Function2<TOuter, Enumerable<TInner>, TResult>>
        resultSelector,
      EqualityComparer<TKey> comparer) {
    throw Extensions.todo();
  }

  /**
   * Produces the set intersection of two sequences by
   * using the default equality comparer to compare values. (Defined
   * by Queryable.)
   */
  public static <T> Queryable<T> intersect(Queryable<T> queryable,
      Enumerable<T> enumerable) {
    throw Extensions.todo();
  }

  /**
   * Produces the set intersection of two sequences by
   * using the specified EqualityComparer<T> to compare
   * values.
   */
  public static <T> Queryable<T> intersect(Queryable<T> queryable,
      Enumerable<T> enumerable, EqualityComparer<T> comparer) {
    throw Extensions.todo();
  }

  /**
   * Correlates the elements of two sequences based on
   * matching keys. The default equality comparer is used to compare
   * keys.
   */
  public static <TOuter, TInner, TKey, TResult> Queryable<TResult> join(
      Queryable<TOuter> outer, Enumerable<TInner> inner,
      FunctionExpression<Function1<TOuter, TKey>> outerKeySelector,
      FunctionExpression<Function1<TInner, TKey>> innerKeySelector,
      FunctionExpression<Function2<TOuter, TInner, TResult>> resultSelector) {
    throw Extensions.todo();
  }

  /**
   * Correlates the elements of two sequences based on
   * matching keys. A specified EqualityComparer<T> is used to
   * compare keys.
   */
  public static <TOuter, TInner, TKey, TResult> Queryable<TResult> join(
      Queryable<TOuter> outer, Enumerable<TInner> inner,
      FunctionExpression<Function1<TOuter, TKey>> outerKeySelector,
      FunctionExpression<Function1<TInner, TKey>> innerKeySelector,
      FunctionExpression<Function2<TOuter, TInner, TResult>> resultSelector,
      EqualityComparer<TKey> comparer) {
    throw Extensions.todo();
  }

  /**
   * Returns the last element in a sequence. (Defined
   * by Queryable.)
   */
  public static <T> T last(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Returns the last element of a sequence that
   * satisfies a specified condition.
   */
  public static <T> T last(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Returns the last element in a sequence, or a
   * default value if the sequence contains no elements.
   */
  public static <T> T lastOrDefault(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Returns the last element of a sequence that
   * satisfies a condition or a default value if no such element is
   * found.
   */
  public static <T> T lastOrDefault(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Returns an long that represents the total number
   * of elements in a sequence.
   */
  public static <T> long longCount(Queryable<T> xable) {
    throw Extensions.todo();
  }

  /**
   * Returns an long that represents the number of
   * elements in a sequence that satisfy a condition.
   */
  public static <T> long longCount(Queryable<T> queryable,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Returns the maximum value in a generic
   * IQueryable<T>.
   */
  public static <T> T max(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Invokes a projection function on each element of a
   * generic IQueryable<T> and returns the maximum resulting
   * value.
   */
  public static <T, TResult> TResult max(Queryable<T> queryable,
      FunctionExpression<Function1<T, TResult>> selector) {
    throw Extensions.todo();
  }

  /**
   * Returns the minimum value in a generic
   * IQueryable<T>.
   */
  public static <T> T min(Queryable<T> queryable) {
    throw Extensions.todo();
  }

  /**
   * Invokes a projection function on each element of a
   * generic IQueryable<T> and returns the minimum resulting
   * value.
   */
  public static <T, TResult> TResult min(Queryable<T> queryable,
      FunctionExpression<Function1<T, TResult>> selector) {
    throw Extensions.todo();
  }

  /**
   * Filters the elements of an IQueryable based on a
   * specified type.
   *
   * <p>This method generates a
   * {@link net.hydromatic.linq4j.expressions.MethodCallExpression} that
   * represents calling {@code ofType} itself as a constructed generic method.
   * It then passes the {@code MethodCallExpression} to the
   * {@link net.hydromatic.linq4j.QueryProvider#createQuery createQuery} method of the
   * {@link net.hydromatic.linq4j.QueryProvider} represented by the Provider property of the source
   * parameter.</p>
   *
   * <p>The query behavior that occurs as a result of executing an expression
   * tree that represents calling OfType depends on the implementation of the
   * type of the source parameter. The expected behavior is that it filters
   * out any elements in source that are not of type TResult.
   *
   * <p>NOTE: clazz parameter not present in C# LINQ; necessary because of
   * Java type erasure.</p>
   */
  public static <TResult> Queryable<TResult> ofType(Queryable<?> queryable,
      Class<TResult> clazz) {
    throw Extensions.todo();
  }

  /**
   * Sorts the elements of a sequence in ascending
   * order according to a key.
   *
   * @see #thenBy
   */
  public static <T, TKey extends Comparable> OrderedQueryable<T> orderBy(
      Queryable<T> source, FunctionExpression<Function1<T, TKey>> keySelector) {
    throw Extensions.todo();
  }

  /**
   * Sorts the elements of a sequence in ascending
   * order by using a specified comparer.
   */
  public static <T, TKey> OrderedQueryable<T> orderBy(Queryable<T> source,
      FunctionExpression<Function1<T, TKey>> keySelector,
      Comparator<TKey> comparator) {
    throw Extensions.todo();
  }

  /**
   * Sorts the elements of a sequence in descending
   * order according to a key.
   */
  public static <T, TKey extends Comparable> OrderedQueryable<T>
  orderByDescending(Queryable<T> source,
      FunctionExpression<Function1<T, TKey>> keySelector) {
    throw Extensions.todo();
  }

  /**
   * Sorts the elements of a sequence in descending
   * order by using a specified comparer.
   */
  public static <T, TKey> OrderedQueryable<T> orderByDescending(
      Queryable<T> source, FunctionExpression<Function1<T, TKey>> keySelector,
      Comparator<TKey> comparator) {
    throw Extensions.todo();
  }

  /**
   * Inverts the order of the elements in a
   * sequence.
   */
  public static <T> Queryable<T> reverse(Queryable<T> source) {
    throw Extensions.todo();
  }

  /**
   * Projects each element of a sequence into a new form.
   */
  public static <T, TResult> Queryable<TResult> select(Queryable<T> source,
      FunctionExpression<Function1<T, TResult>> selector) {
    return source.getProvider().createQuery(
        Expressions.call(source.getExpression(), "select", selector),
        functionResultType(selector));
  }

  private static <P0, R> Type functionResultType(
      FunctionExpression<Function1<P0, R>> selector) {
    return selector.body.getType();
  }

  /**
   * Projects each element of a sequence into a new
   * form by incorporating the element's index.
   *
   * <p>NOTE: Renamed from {@code select} because had same erasure as
   * {@link #select(net.hydromatic.linq4j.Queryable, net.hydromatic.linq4j.expressions.FunctionExpression)}.</p>
   */
  public static <T, TResult> Queryable<TResult> selectN(Queryable<T> source,
      FunctionExpression<Function2<T, Integer, TResult>> selector) {
    throw Extensions.todo();
  }

  /**
   * Projects each element of a sequence to an
   * Enumerable<T> and combines the resulting sequences into one
   * sequence.
   */
  public static <T, TResult> Queryable<TResult> selectMany(Queryable<T> source,
      FunctionExpression<Function1<T, Enumerable<TResult>>> selector) {
    throw Extensions.todo();
  }

  /**
   * Projects each element of a sequence to an
   * Enumerable<T> and combines the resulting sequences into one
   * sequence. The index of each source element is used in the
   * projected form of that element.
   *
   * <p>NOTE: Renamed from {@code selectMany} because had same erasure as
   * {@link #selectMany(net.hydromatic.linq4j.Queryable, net.hydromatic.linq4j.expressions.FunctionExpression)}</p>
   */
  public static <T, TResult> Queryable<TResult> selectManyN(Queryable<T> source,
      FunctionExpression<Function2<T, Integer, Enumerable<TResult>>> selector) {
    throw Extensions.todo();
  }

  /**
   * Projects each element of a sequence to an
   * Enumerable<T> that incorporates the index of the source
   * element that produced it. A result selector function is invoked
   * on each element of each intermediate sequence, and the
   * resulting values are combined into a single, one-dimensional
   * sequence and returned.
   */
  public static <T, TCollection, TResult> Queryable<TResult> selectMany(
      Queryable<T> source,
      FunctionExpression<Function2<T, Integer, Enumerable<TCollection>>>
        collectionSelector,
      FunctionExpression<Function2<T, TCollection, TResult>> resultSelector) {
    throw Extensions.todo();
  }

  /**
   * Projects each element of a sequence to an
   * Enumerable<T> and invokes a result selector function on each
   * element therein. The resulting values from each intermediate
   * sequence are combined into a single, one-dimensional sequence
   * and returned.
   *
   * <p>NOTE: Renamed from {@code selectMany} because had same erasure as
   * {@link #selectMany(net.hydromatic.linq4j.Queryable, net.hydromatic.linq4j.expressions.FunctionExpression, net.hydromatic.linq4j.expressions.FunctionExpression)}</p>
   */
  public static <T, TCollection, TResult> Queryable<TResult> selectManyN(
      Queryable<T> source,
      FunctionExpression<Function1<T, Enumerable<TCollection>>>
        collectionSelector,
      FunctionExpression<Function2<T, TCollection, TResult>> resultSelector) {
    throw Extensions.todo();
  }

  /**
   * Determines whether two sequences are equal by
   * using the default equality comparer to compare
   * elements.
   */
  public static <T> boolean sequenceEqual(Queryable<T> queryable,
      Enumerable<T> enumerable) {
    throw Extensions.todo();
  }

  /**
   * Determines whether two sequences are equal by
   * using a specified EqualityComparer<T> to compare
   * elements.
   */
  public static <T> boolean sequenceEqual(Queryable<T> queryable,
      Enumerable<T> enumerable, EqualityComparer<T> comparer) {
    throw Extensions.todo();
  }

  /**
   * Returns the only element of a sequence, and throws
   * an exception if there is not exactly one element in the
   * sequence.
   */
  public static <T> T single(Queryable<T> source) {
    throw Extensions.todo();
  }

  /**
   * Returns the only element of a sequence that
   * satisfies a specified condition, and throws an exception if
   * more than one such element exists.
   */
  public static <T> T single(Queryable<T> source,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Returns the only element of a sequence, or a
   * default value if the sequence is empty; this method throws an
   * exception if there is more than one element in the
   * sequence.
   */
  public static <T> T singleOrDefault(Queryable<T> source) {
    throw Extensions.todo();
  }

  /**
   * Returns the only element of a sequence that
   * satisfies a specified condition or a default value if no such
   * element exists; this method throws an exception if more than
   * one element satisfies the condition.
   */
  public static <T> T singleOrDefault(Queryable<T> source,
      FunctionExpression<Predicate1<T>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Bypasses a specified number of elements in a
   * sequence and then returns the remaining elements.
   */
  public static <T> Queryable<T> skip(Queryable<T> source, int count) {
    return EnumerableDefaults.skip(source.asEnumerable(), count).asQueryable();
  }

  /**
   * Bypasses elements in a sequence as long as a
   * specified condition is true and then returns the remaining
   * elements.
   */
  public static <T> Queryable<T> skipWhile(Queryable<T> source,
      FunctionExpression<Predicate1<T>> predicate) {
    return skipWhileN(source, Expressions.lambda(
        Functions.<T, Integer>toPredicate2(predicate.getFunction())));
  }

  /**
   * Bypasses elements in a sequence as long as a
   * specified condition is true and then returns the remaining
   * elements. The element's index is used in the logic of the
   * predicate function.
   */
  public static <T> Queryable<T> skipWhileN(final Queryable<T> source,
      final FunctionExpression<Predicate2<T, Integer>> predicate) {
    return new BaseQueryable<T>(source.getProvider(), source.getElementType(),
        source.getExpression()) {
      public Enumerator<T> enumerator() {
        return new EnumerableDefaults.SkipWhileEnumerator<T>(
            source.enumerator(), predicate.getFunction());
      }
    };
  }

  /**
   * Computes the sum of the sequence of Decimal values
   * that is obtained by invoking a projection function on each
   * element of the input sequence.
   */
  public static <T> BigDecimal sumBigDecimal(Queryable<T> sources,
      FunctionExpression<BigDecimalFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of nullable
   * Decimal values that is obtained by invoking a projection
   * function on each element of the input sequence.
   */
  public static <T> BigDecimal sumNullableBigDecimal(Queryable<T> source,
      FunctionExpression<NullableBigDecimalFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of Double values
   * that is obtained by invoking a projection function on each
   * element of the input sequence.
   */
  public static <T> double sumDouble(Queryable<T> source,
      FunctionExpression<DoubleFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of nullable
   * Double values that is obtained by invoking a projection
   * function on each element of the input sequence.
   */
  public static <T> Double sumNullableDouble(Queryable<T> source,
      FunctionExpression<NullableDoubleFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of int values
   * that is obtained by invoking a projection function on each
   * element of the input sequence.
   */
  public static <T> int sumInteger(Queryable<T> source,
      FunctionExpression<IntegerFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of nullable int
   * values that is obtained by invoking a projection function on
   * each element of the input sequence.
   */
  public static <T> Integer sumNullableInteger(Queryable<T> source,
      FunctionExpression<NullableIntegerFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of long values
   * that is obtained by invoking a projection function on each
   * element of the input sequence.
   */
  public static <T> long sumLong(Queryable<T> source,
      FunctionExpression<LongFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of nullable long
   * values that is obtained by invoking a projection function on
   * each element of the input sequence.
   */
  public static <T> Long sumNullableLong(Queryable<T> source,
      FunctionExpression<NullableLongFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of Float values
   * that is obtained by invoking a projection function on each
   * element of the input sequence.
   */
  public static <T> float sumFloat(Queryable<T> source,
      FunctionExpression<FloatFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Computes the sum of the sequence of nullable
   * Float values that is obtained by invoking a projection
   * function on each element of the input sequence.
   */
  public static <T> Float sumNullableFloat(Queryable<T> source,
      FunctionExpression<NullableFloatFunction1<T>> selector) {
    throw Extensions.todo();
  }

  /**
   * Returns a specified number of contiguous elements
   * from the start of a sequence.
   */
  public static <T> Queryable<T> take(Queryable<T> source, int count) {
    return EnumerableDefaults.take(source.asEnumerable(), count).asQueryable();
  }

  /**
   * Returns elements from a sequence as long as a
   * specified condition is true.
   */
  public static <T> Queryable<T> takeWhile(Queryable<T> source,
      FunctionExpression<Predicate1<T>> predicate) {
    return takeWhileN(source, Expressions.lambda(
        Functions.<T, Integer>toPredicate2(predicate.getFunction())));
  }

  /**
   * Returns elements from a sequence as long as a
   * specified condition is true. The element's index is used in the
   * logic of the predicate function.
   */
  public static <T> Queryable<T> takeWhileN(final Queryable<T> source,
      final FunctionExpression<Predicate2<T, Integer>> predicate) {
    return new BaseQueryable<T>(source.getProvider(), source.getElementType(),
        source.getExpression()) {
      public Enumerator<T> enumerator() {
        return new EnumerableDefaults.TakeWhileEnumerator<T>(
            source.enumerator(), predicate.getFunction());
      }
    };
  }

  /**
   * Performs a subsequent ordering of the elements in a sequence in
   * ascending order according to a key.
   */
  public static <T, TKey extends Comparable<TKey>> OrderedQueryable<T> thenBy(
      OrderedQueryable<T> source,
      FunctionExpression<Function1<T, TKey>> keySelector) {
    throw Extensions.todo();
  }

  /**
   * Performs a subsequent ordering of the elements in a sequence in
   * ascending order according to a key, using a specified comparator.
   */
  public static <T, TKey> OrderedQueryable<T> thenBy(OrderedQueryable<T> source,
      FunctionExpression<Function1<T, TKey>> keySelector,
      Comparator<TKey> comparator) {
    throw Extensions.todo();
  }

  /**
   * Performs a subsequent ordering of the elements in a sequence in
   * descending order according to a key.
   */
  public static <T, TKey extends Comparable<TKey>> OrderedQueryable<T>
  thenByDescending(OrderedQueryable<T> source,
      FunctionExpression<Function1<T, TKey>> keySelector) {
    throw Extensions.todo();
  }

  /**
   * Performs a subsequent ordering of the elements in a sequence in
   * dscending order according to a key, using a specified comparator.
   */
  public static <T, TKey> OrderedQueryable<T> thenByDescending(
      OrderedQueryable<T> source,
      FunctionExpression<Function1<T, TKey>> keySelector,
      Comparator<TKey> comparator) {
    throw Extensions.todo();
  }

  /**
   * Produces the set union of two sequences by using
   * the default equality comparer.
   */
  public static <T> Queryable<T> union(Queryable<T> source0,
      Enumerable<T> source1) {
    throw Extensions.todo();
  }

  /**
   * Produces the set union of two sequences by using a
   * specified EqualityComparer<T>.
   */
  public static <T> Queryable<T> union(Queryable<T> source0,
      Enumerable<T> source1, EqualityComparer<T> comparer) {
    throw Extensions.todo();
  }

  /**
   * Filters a sequence of values based on a
   * predicate.
   */
  public static <T> Queryable<T> where(final Queryable<T> source,
      final FunctionExpression<Predicate1<T>> predicate) {
    return new NonLeafReplayableQueryable<T>(source) {
      public void replay(QueryableFactory<T> factory) {
        factory.where(source, predicate);
      }
    };
  }

  /**
   * Filters a sequence of values based on a
   * predicate. Each element's index is used in the logic of the
   * predicate function.
   */
  public static <T> Queryable<T> whereN(Queryable<T> source,
      FunctionExpression<Predicate2<T, Integer>> predicate) {
    throw Extensions.todo();
  }

  /**
   * Merges two sequences by using the specified
   * predicate function.
   */
  public static <T0, T1, TResult> Queryable<TResult> zip(Queryable<T0> source0,
      Enumerable<T1> source1,
      FunctionExpression<Function2<T0, T1, TResult>> resultSelector) {
    throw Extensions.todo();
  }

  public interface Replayable<T> extends Queryable<T> {
    void replay(QueryableFactory<T> factory);
  }

  public static abstract class ReplayableQueryable<T>
      extends DefaultQueryable<T> implements Replayable<T> {
    public void replay(QueryableFactory<T> factory) {
    }

    public Iterator<T> iterator() {
      return Linq4j.enumeratorIterator(enumerator());
    }

    public Enumerator<T> enumerator() {
      return getProvider().executeQuery(this);
    }

    /**
     * Convenience method, for {@link QueryableRecorder} methods that
     * return a scalar value such as {@code boolean} or
     * {@link BigDecimal}.
     */
    @SuppressWarnings("unchecked")
    <U> U castSingle() {
      return ((Queryable<U>) (Queryable) this).single();
    }

    /**
     * Convenience method, for {@link QueryableRecorder} methods that
     * return a Queryable of a different element type than the source.
     */
    @SuppressWarnings("unchecked")
    public <U> Queryable<U> castQueryable() {
      return (Queryable<U>) (Queryable) this;
    }
  }

  public static abstract class NonLeafReplayableQueryable<T>
      extends ReplayableQueryable<T> {
    private final Queryable<T> original;

    protected NonLeafReplayableQueryable(Queryable<T> original) {
      this.original = original;
    }

    public Type getElementType() {
      return original.getElementType();
    }

    public Expression getExpression() {
      return original.getExpression();
    }

    public QueryProvider getProvider() {
      return original.getProvider();
    }
  }
}

// End QueryableDefaults.java
