Merge branch 'master' of https://gitbox.apache.org/repos/asf/commons-lang.git
This commit is contained in:
commit
5f2bf30ede
3
pom.xml
3
pom.xml
|
@ -505,6 +505,9 @@
|
|||
<contributor>
|
||||
<name>Mark Dacek</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Peter Verhas</name>
|
||||
</contributor>
|
||||
</contributors>
|
||||
|
||||
<!-- Lang should depend on very little -->
|
||||
|
|
|
@ -60,6 +60,7 @@ The <action> type attribute can be add,update,fix,remove.
|
|||
<action type="update" dev="ggregory">commons.japicmp.version 0.13.1 -> 0.14.1.</action>
|
||||
<action type="update" dev="ggregory">checkstyle.version 8.18 -> 8.23.</action>
|
||||
<action type="update" dev="ggregory">junit-jupiter 5.5.0 -> 5.5.1.</action>
|
||||
<action issue="LANG-1477" type="add" dev="jochen">Added Functions.as*, and tests thereof, as suggested by Peter Verhas</action>
|
||||
</release>
|
||||
|
||||
<release version="3.9" date="2019-04-09" description="New features and bug fixes. Requires Java 8, supports Java 9, 10, 11">
|
||||
|
|
|
@ -19,6 +19,14 @@ package org.apache.commons.lang3;
|
|||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
/** This class provides utility functions, and classes for working with the
|
||||
|
@ -124,6 +132,132 @@ public class Functions {
|
|||
*/
|
||||
boolean test(O1 pObject1, O2 pObject2) throws T;
|
||||
}
|
||||
@FunctionalInterface
|
||||
public interface FailableSupplier<O, T extends Throwable> {
|
||||
/**
|
||||
* Supplies an object
|
||||
* @return the suppliers result
|
||||
* @throws T if the supplier fails
|
||||
*/
|
||||
O get() throws T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableRunnable} into a standard {@link Runnable}.
|
||||
*/
|
||||
public static Runnable asRunnable(FailableRunnable<?> pRunnable) {
|
||||
return () -> {
|
||||
try {
|
||||
pRunnable.run();
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableConsumer} into a standard {@link Consumer}.
|
||||
*/
|
||||
public static <I> Consumer<I> asConsumer(FailableConsumer<I,?> pConsumer) {
|
||||
return (pInput) -> {
|
||||
try {
|
||||
pConsumer.accept(pInput);
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableCallable} into a standard {@link Callable}.
|
||||
*/
|
||||
public static <O> Callable<O> asCallable(FailableCallable<O,?> pCallable) {
|
||||
return () -> {
|
||||
try {
|
||||
return pCallable.call();
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableBiConsumer} into a standard {@link BiConsumer}.
|
||||
*/
|
||||
public static <I1,I2> BiConsumer<I1,I2> asBiConsumer(FailableBiConsumer<I1,I2,?> pConsumer) {
|
||||
return (pInput1, pInput2) -> {
|
||||
try {
|
||||
pConsumer.accept(pInput1, pInput2);
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableFunction} into a standard {@link Function}.
|
||||
*/
|
||||
public static <I,O> Function<I,O> asFunction(FailableFunction<I,O,?> pFunction) {
|
||||
return (pInput) -> {
|
||||
try {
|
||||
return pFunction.apply(pInput);
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableBiFunction} into a standard {@link BiFunction}.
|
||||
*/
|
||||
public static <I1,I2,O> BiFunction<I1,I2,O> asBiFunction(FailableBiFunction<I1,I2,O,?> pFunction) {
|
||||
return (pInput1, pInput2) -> {
|
||||
try {
|
||||
return pFunction.apply(pInput1, pInput2);
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailablePredicate} into a standard {@link Predicate}.
|
||||
*/
|
||||
public static <I> Predicate<I> asPredicate(FailablePredicate<I,?> pPredicate) {
|
||||
return (pInput) -> {
|
||||
try {
|
||||
return pPredicate.test(pInput);
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableBiPredicate} into a standard {@link BiPredicate}.
|
||||
*/
|
||||
public static <I1,I2> BiPredicate<I1,I2> asBiPredicate(FailableBiPredicate<I1,I2,?> pPredicate) {
|
||||
return (pInput1, pInput2) -> {
|
||||
try {
|
||||
return pPredicate.test(pInput1, pInput2);
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link FailableSupplier} into a standard {@link Supplier}.
|
||||
*/
|
||||
public static <O> Supplier<O> asSupplier(FailableSupplier<O,?> pSupplier) {
|
||||
return () -> {
|
||||
try {
|
||||
return pSupplier.get();
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a runnable and rethrows any exception as a {@link RuntimeException}.
|
||||
|
@ -255,6 +389,22 @@ public class Functions {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the supplier, and returns the result.
|
||||
* @param pSupplier The supplier to invoke.
|
||||
* @param <O> The suppliers output type.
|
||||
* @param <T> The type of checked exception, which the supplier can throw.
|
||||
* @return The object, which has been created by the supplier
|
||||
*/
|
||||
public static <O,T extends Throwable> O get(FailableSupplier<O,T> pSupplier) {
|
||||
try {
|
||||
return pSupplier.get();
|
||||
} catch (Throwable t) {
|
||||
throw rethrow(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A simple try-with-resources implementation, that can be used, if your
|
||||
* objects do not implement the {@link AutoCloseable} interface. The method
|
||||
|
|
|
@ -19,8 +19,19 @@ package org.apache.commons.lang3;
|
|||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.Functions.FailableBiConsumer;
|
||||
import org.apache.commons.lang3.Functions.FailableBiFunction;
|
||||
import org.apache.commons.lang3.Functions.FailableCallable;
|
||||
import org.apache.commons.lang3.Functions.FailableConsumer;
|
||||
import org.apache.commons.lang3.Functions.FailableFunction;
|
||||
import org.apache.commons.lang3.Functions.FailableSupplier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -28,6 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
class FunctionsTest {
|
||||
public static class SomeException extends Exception {
|
||||
|
@ -127,6 +139,20 @@ class FunctionsTest {
|
|||
Functions.run(FailureOnOddInvocations::new);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAsRunnable() {
|
||||
FailureOnOddInvocations.invocation = 0;
|
||||
Runnable runnable = Functions.asRunnable(() -> new FailureOnOddInvocations());
|
||||
UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () -> runnable.run());
|
||||
final Throwable cause = e.getCause();
|
||||
assertNotNull(cause);
|
||||
assertTrue(cause instanceof SomeException);
|
||||
assertEquals("Odd Invocation: 1", cause.getMessage());
|
||||
|
||||
// Even invocation, should not throw an exception
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCallable() {
|
||||
FailureOnOddInvocations.invocation = 0;
|
||||
|
@ -139,6 +165,25 @@ class FunctionsTest {
|
|||
assertNotNull(instance);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAsCallable() {
|
||||
FailureOnOddInvocations.invocation = 0;
|
||||
final FailableCallable<FailureOnOddInvocations,SomeException> failableCallable = () -> { return new FailureOnOddInvocations(); };
|
||||
final Callable<FailureOnOddInvocations> callable = Functions.asCallable(failableCallable);
|
||||
UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () -> callable.call());
|
||||
final Throwable cause = e.getCause();
|
||||
assertNotNull(cause);
|
||||
assertTrue(cause instanceof SomeException);
|
||||
assertEquals("Odd Invocation: 1", cause.getMessage());
|
||||
final FailureOnOddInvocations instance;
|
||||
try {
|
||||
instance = callable.call();
|
||||
} catch (Exception ex) {
|
||||
throw Functions.rethrow(ex);
|
||||
}
|
||||
assertNotNull(instance);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAcceptConsumer() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
|
@ -162,6 +207,30 @@ class FunctionsTest {
|
|||
Functions.accept(Testable::test, testable);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAsConsumer() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
final Testable testable = new Testable(ise);
|
||||
final Consumer<Testable> consumer = Functions.asConsumer((t) -> t.test());
|
||||
Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable));
|
||||
assertSame(ise, e);
|
||||
|
||||
final Error error = new OutOfMemoryError();
|
||||
testable.setThrowable(error);
|
||||
e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable));
|
||||
assertSame(error, e);
|
||||
|
||||
final IOException ioe = new IOException("Unknown I/O error");
|
||||
testable.setThrowable(ioe);
|
||||
e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable));
|
||||
final Throwable t = e.getCause();
|
||||
assertNotNull(t);
|
||||
assertSame(ioe, t);
|
||||
|
||||
testable.setThrowable(null);
|
||||
Functions.accept(Testable::test, testable);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAcceptBiConsumer() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
|
@ -184,6 +253,29 @@ class FunctionsTest {
|
|||
Functions.accept(Testable::test, testable, (Throwable) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAsBiConsumer() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
final Testable testable = new Testable(null);
|
||||
final FailableBiConsumer<Testable, Throwable, Throwable> failableBiConsumer = (t, th) -> { t.setThrowable(th); t.test(); };
|
||||
final BiConsumer<Testable, Throwable> consumer = Functions.asBiConsumer(failableBiConsumer);
|
||||
Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable, ise));
|
||||
assertSame(ise, e);
|
||||
|
||||
final Error error = new OutOfMemoryError();
|
||||
e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable, error));
|
||||
assertSame(error, e);
|
||||
|
||||
final IOException ioe = new IOException("Unknown I/O error");
|
||||
testable.setThrowable(ioe);
|
||||
e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable, ioe));
|
||||
final Throwable t = e.getCause();
|
||||
assertNotNull(t);
|
||||
assertSame(ioe, t);
|
||||
|
||||
consumer.accept(testable, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyFunction() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
|
@ -209,6 +301,33 @@ class FunctionsTest {
|
|||
assertEquals(0, i.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsFunction() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
final Testable testable = new Testable(ise);
|
||||
final FailableFunction<Throwable,Integer,Throwable> failableFunction = (th) -> {
|
||||
testable.setThrowable(th);
|
||||
return Integer.valueOf(testable.testInt());
|
||||
};
|
||||
final Function<Throwable,Integer> function = Functions.asFunction(failableFunction);
|
||||
Throwable e = assertThrows(IllegalStateException.class, () -> function.apply(ise));
|
||||
assertSame(ise, e);
|
||||
|
||||
final Error error = new OutOfMemoryError();
|
||||
testable.setThrowable(error);
|
||||
e = assertThrows(OutOfMemoryError.class, () -> function.apply(error));
|
||||
assertSame(error, e);
|
||||
|
||||
final IOException ioe = new IOException("Unknown I/O error");
|
||||
testable.setThrowable(ioe);
|
||||
e = assertThrows(UncheckedIOException.class, () -> function.apply(ioe));
|
||||
final Throwable t = e.getCause();
|
||||
assertNotNull(t);
|
||||
assertSame(ioe, t);
|
||||
|
||||
assertEquals(0, function.apply(null).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyBiFunction() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
|
@ -231,6 +350,59 @@ class FunctionsTest {
|
|||
assertEquals(0, i.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsBiFunction() {
|
||||
final IllegalStateException ise = new IllegalStateException();
|
||||
final Testable testable = new Testable(ise);
|
||||
final FailableBiFunction<Testable,Throwable,Integer,Throwable> failableBiFunction = (t, th) -> {
|
||||
t.setThrowable(th);
|
||||
return Integer.valueOf(t.testInt());
|
||||
};
|
||||
final BiFunction<Testable,Throwable,Integer> biFunction = Functions.asBiFunction(failableBiFunction);
|
||||
Throwable e = assertThrows(IllegalStateException.class, () -> biFunction.apply(testable, ise));
|
||||
assertSame(ise, e);
|
||||
|
||||
final Error error = new OutOfMemoryError();
|
||||
testable.setThrowable(error);
|
||||
e = assertThrows(OutOfMemoryError.class, () -> biFunction.apply(testable, error));
|
||||
assertSame(error, e);
|
||||
|
||||
final IOException ioe = new IOException("Unknown I/O error");
|
||||
testable.setThrowable(ioe);
|
||||
e = assertThrows(UncheckedIOException.class, () -> biFunction.apply(testable, ioe));
|
||||
final Throwable t = e.getCause();
|
||||
assertNotNull(t);
|
||||
assertSame(ioe, t);
|
||||
|
||||
assertEquals(0, biFunction.apply(testable, null).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFromSupplier() {
|
||||
FailureOnOddInvocations.invocation = 0;
|
||||
UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () -> Functions.run(FailureOnOddInvocations::new));
|
||||
final Throwable cause = e.getCause();
|
||||
assertNotNull(cause);
|
||||
assertTrue(cause instanceof SomeException);
|
||||
assertEquals("Odd Invocation: 1", cause.getMessage());
|
||||
final FailureOnOddInvocations instance = Functions.call(FailureOnOddInvocations::new);
|
||||
assertNotNull(instance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsSupplier() {
|
||||
FailureOnOddInvocations.invocation = 0;
|
||||
final FailableSupplier<FailureOnOddInvocations,Throwable> failableSupplier = () -> { return new FailureOnOddInvocations(); };
|
||||
final Supplier<FailureOnOddInvocations> supplier = Functions.asSupplier(failableSupplier);
|
||||
UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () -> supplier.get());
|
||||
final Throwable cause = e.getCause();
|
||||
assertNotNull(cause);
|
||||
assertTrue(cause instanceof SomeException);
|
||||
assertEquals("Odd Invocation: 1", cause.getMessage());
|
||||
final FailureOnOddInvocations instance = supplier.get();
|
||||
assertNotNull(instance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryWithResources() {
|
||||
final CloseableObject co = new CloseableObject();
|
||||
|
|
Loading…
Reference in New Issue