/**
*
* Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
*
* Licensed 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 com.speedment.runtime.core.internal.util.java9;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import static java.util.Objects.requireNonNull;
import java.util.function.DoublePredicate;
import java.util.function.IntPredicate;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
*
* @author Per Minborg
*/
public final class Java9StreamUtil {
private static final MethodType DOUBLE_METHOD_TYPE = MethodType.methodType(DoubleStream.class, DoublePredicate.class);
private static final MethodHandle DOUBLE_TAKE_WHILE_METHOD_HANDLE
= createMethodHandle("takeWhile", DoubleStream.class, DOUBLE_METHOD_TYPE);
private static final MethodHandle DOUBLE_DROP_WHILE_METHOD_HANDLE
= createMethodHandle("dropWhile", DoubleStream.class, DOUBLE_METHOD_TYPE);
static final MethodHandle DOUBLE_FILTER_METHOD_HANDLE
= createMethodHandle("filter", DoubleStream.class, DOUBLE_METHOD_TYPE); // Just for Java 8 testing
private static final MethodType INT_METHOD_TYPE = MethodType.methodType(IntStream.class, IntPredicate.class);
private static final MethodHandle INT_TAKE_WHILE_METHOD_HANDLE
= createMethodHandle("takeWhile", IntStream.class, INT_METHOD_TYPE);
private static final MethodHandle INT_DROP_WHILE_METHOD_HANDLE
= createMethodHandle("dropWhile", IntStream.class, INT_METHOD_TYPE);
static final MethodHandle INT_FILTER_METHOD_HANDLE
= createMethodHandle("filter", IntStream.class, INT_METHOD_TYPE); // Just for Java 8 testing
private static final MethodType LONG_METHOD_TYPE = MethodType.methodType(LongStream.class, LongPredicate.class);
private static final MethodHandle LONG_TAKE_WHILE_METHOD_HANDLE
= createMethodHandle("takeWhile", LongStream.class, LONG_METHOD_TYPE);
private static final MethodHandle LONG_DROP_WHILE_METHOD_HANDLE
= createMethodHandle("dropWhile", LongStream.class, LONG_METHOD_TYPE);
static final MethodHandle LONG_FILTER_METHOD_HANDLE
= createMethodHandle("filter", LongStream.class, LONG_METHOD_TYPE); // Just for Java 8 testing
private static final MethodType METHOD_TYPE
= MethodType.methodType(Stream.class, Predicate.class);
private static final MethodHandle TAKE_WHILE_METHOD_HANDLE
= createMethodHandle("takeWhile", Stream.class, METHOD_TYPE);
private static final MethodHandle DROP_WHILE_METHOD_HANDLE
= createMethodHandle("dropWhile", Stream.class, METHOD_TYPE);
static final MethodHandle FILTER_METHOD_HANDLE
= createMethodHandle("filter", Stream.class, METHOD_TYPE); // Just for Java 8 testing
/**
* Delegates a DoubleStream::takeWhile operation to the Java platforms
* underlying default Stream implementation. If run under Java 8, this
* method will throw an UnsupportedOperationException.
*
* @param stream to apply the takeWhile operation to
* @param predicate to use for takeWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the takeWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static DoubleStream takeWhile(DoubleStream stream, DoublePredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (DOUBLE_TAKE_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::takeWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = DOUBLE_TAKE_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (DoubleStream) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
/**
* Delegates a DoubleStream::dropWhile operation to the Java platforms
* underlying default Stream implementation. If run under Java 8, this
* method will throw an UnsupportedOperationException.
*
* @param stream to apply the dropWhile operation to
* @param predicate to use for dropWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the dropWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static DoubleStream dropWhile(DoubleStream stream, DoublePredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (DOUBLE_DROP_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::dropWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = DOUBLE_DROP_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (DoubleStream) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
// just for Java 8 testing
static DoubleStream filter(DoubleStream stream, DoublePredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
try {
return (DoubleStream) DOUBLE_FILTER_METHOD_HANDLE.invoke(stream, predicate);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
/**
* Delegates an IntStream::takeWhile operation to the Java platforms
* underlying default Stream implementation. If run under Java 8, this
* method will throw an UnsupportedOperationException.
*
* @param stream to apply the takeWhile operation to
* @param predicate to use for takeWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the takeWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static IntStream takeWhile(IntStream stream, IntPredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (INT_TAKE_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::takeWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = INT_TAKE_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (IntStream) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
/**
* Delegates an InteStream::dropWhile operation to the Java platforms
* underlying default Stream implementation. If run under Java 8, this
* method will throw an UnsupportedOperationException.
*
* @param stream to apply the dropWhile operation to
* @param predicate to use for dropWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the dropWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static IntStream dropWhile(IntStream stream, IntPredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (INT_DROP_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::dropWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = INT_DROP_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (IntStream) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
// just for Java 8 testing
static IntStream filter(IntStream stream, IntPredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
try {
return (IntStream) INT_FILTER_METHOD_HANDLE.invoke(stream, predicate);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
/**
* Delegates a LongStream::takeWhile operation to the Java platforms
* underlying default Stream implementation. If run under Java 8, this
* method will throw an UnsupportedOperationException.
*
* @param stream to apply the takeWhile operation to
* @param predicate to use for takeWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the takeWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static LongStream takeWhile(LongStream stream, LongPredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (LONG_TAKE_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::takeWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = LONG_TAKE_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (LongStream) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
/**
* Delegates a LongStream::dropWhile operation to the Java platforms
* underlying default Stream implementation. If run under Java 8, this
* method will throw an UnsupportedOperationException.
*
* @param stream to apply the dropWhile operation to
* @param predicate to use for dropWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the dropWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static LongStream dropWhile(LongStream stream, LongPredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (LONG_DROP_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::dropWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = LONG_DROP_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (LongStream) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
// just for Java 8 testing
static LongStream filter(LongStream stream, LongPredicate predicate) {
requireNonNull(stream);
requireNonNull(predicate);
try {
return (LongStream) LONG_FILTER_METHOD_HANDLE.invoke(stream, predicate);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
/**
* Delegates a Stream::takeWhile operation to the Java platforms underlying
* default Stream implementation. If run under Java 8, this method will
* throw an UnsupportedOperationException.
*
* @param <T> Element type in the Stream
* @param stream to apply the takeWhile operation to
* @param predicate to use for takeWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the takeWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (TAKE_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::takeWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = TAKE_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (Stream<T>) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
/**
* Delegates a Stream::dropWhile operation to the Java platforms underlying
* default Stream implementation. If run under Java 8, this method will
* throw an UnsupportedOperationException.
*
* @param <T> Element type in the Stream
* @param stream to apply the dropWhile operation to
* @param predicate to use for dropWhile
* @throws UnsupportedOperationException if run under Java 8
* @return a Stream where the dropWhile(predicate) has been applied
*/
@SuppressWarnings("unchecked")
public static <T> Stream<T> dropWhile(Stream<T> stream, Predicate<? super T> predicate) {
requireNonNull(stream);
requireNonNull(predicate);
if (DROP_WHILE_METHOD_HANDLE == null) {
throw new UnsupportedOperationException("Stream::dropWhile is not supported by this Java version. Use Java 9 or greater.");
}
try {
final Object obj = DROP_WHILE_METHOD_HANDLE.invoke(stream, predicate);
return (Stream<T>) obj;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
// just for Java 8 testing
static <T> Stream<T> filter(Stream<T> stream, Predicate<? super T> predicate) {
requireNonNull(stream);
requireNonNull(predicate);
try {
return (Stream<T>) FILTER_METHOD_HANDLE.invoke(stream, predicate);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
private Java9StreamUtil() {
throw new UnsupportedOperationException();
}
private static MethodHandle createMethodHandle(String methodName, Class<?> refc, MethodType methodType) {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
return lookup.findVirtual(refc, methodName, methodType);
} catch (IllegalAccessException | NoSuchMethodException e) {
// We are running under Java 8
return null;
}
}
}