/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.optiq.runtime;
import net.hydromatic.linq4j.AbstractEnumerable;
import net.hydromatic.linq4j.Enumerable;
import net.hydromatic.linq4j.Enumerator;
import net.hydromatic.linq4j.function.EqualityComparer;
import net.hydromatic.linq4j.function.Function1;
import net.hydromatic.linq4j.function.Predicate1;
import org.eigenbase.util.Bug;
/**
* Utilities for processing {@link net.hydromatic.linq4j.Enumerable}
* collections.
*
* <p>This class is a place to put things not yet added to linq4j.
* Methods are subject to removal without notice.</p>
*/
public class Enumerables {
private Enumerables() {}
/**
* Returns elements of {@code outer} for which there is a member of
* {@code inner} with a matching key.
*/
public static <TSource, TInner, TKey> Enumerable<TSource> semiJoin(
final Enumerable<TSource> outer, final Enumerable<TInner> inner,
final Function1<TSource, TKey> outerKeySelector,
final Function1<TInner, TKey> innerKeySelector) {
Bug.upgrade("move into linq4j");
return semiJoin(outer, inner, outerKeySelector, innerKeySelector, null);
}
/**
* Returns elements of {@code outer} for which there is a member of
* {@code inner} with a matching key. A specified
* {@code EqualityComparer<TSource>} is used to compare keys.
*/
public static <TSource, TInner, TKey> Enumerable<TSource> semiJoin(
final Enumerable<TSource> outer, final Enumerable<TInner> inner,
final Function1<TSource, TKey> outerKeySelector,
final Function1<TInner, TKey> innerKeySelector,
final EqualityComparer<TKey> comparer) {
return new AbstractEnumerable<TSource>() {
public Enumerator<TSource> enumerator() {
final Enumerable<TKey> innerLookup =
comparer == null
? inner.select(innerKeySelector).distinct()
: inner.select(innerKeySelector).distinct(comparer);
return Enumerables.where(outer.enumerator(),
new Predicate1<TSource>() {
public boolean apply(TSource v0) {
final TKey key = outerKeySelector.apply(v0);
return innerLookup.contains(key);
}
});
}
};
}
/**
* Filters a sequence of values based on a
* predicate.
*/
public static <TSource> Enumerable<TSource> where(
final Enumerable<TSource> source, final Predicate1<TSource> predicate) {
assert predicate != null;
return new AbstractEnumerable<TSource>() {
public Enumerator<TSource> enumerator() {
final Enumerator<TSource> enumerator = source.enumerator();
return Enumerables.where(enumerator, predicate);
}
};
}
private static <TSource> Enumerator<TSource> where(
final Enumerator<TSource> enumerator,
final Predicate1<TSource> predicate) {
return new Enumerator<TSource>() {
public TSource current() {
return enumerator.current();
}
public boolean moveNext() {
while (enumerator.moveNext()) {
if (predicate.apply(enumerator.current())) {
return true;
}
}
return false;
}
public void reset() {
enumerator.reset();
}
public void close() {
enumerator.close();
}
};
}
}
// End Enumerables.java