This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-lang.git
commit a4ec38801f599ff54982f11fd9b81bd74a07fb36 Author: Gary D. Gregory <[email protected]> AuthorDate: Tue Sep 9 16:24:42 2025 -0700 Add FailableByteConsumer --- src/changes/changes.xml | 1 + .../lang3/function/FailableByteConsumer.java | 70 ++++++++++++++++++++++ .../lang3/function/FailableFunctionsTest.java | 49 +++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a00e4adf5..d15bc90c6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -85,6 +85,7 @@ The <action> type attribute can be add,update,fix,remove. <action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.lang3.time.DateUtils.toOffsetDateTime(Date[, TimeZone]).</action> <action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.lang3.time.DateUtils.toZonedDateTime(Date[, TimeZone]).</action> <action type="add" dev="ggregory" due-to="Gary Gregory">Add ByteConsumer.</action> + <action type="add" dev="ggregory" due-to="Gary Gregory">Add FailableByteConsumer.</action> <!-- UPDATE --> <action type="update" dev="ggregory" due-to="Gary Gregory">[test] Bump org.apache.commons:commons-text from 1.13.1 to 1.14.0.</action> <action type="update" dev="ggregory" due-to="Gary Gregory">Bump org.apache.commons:commons-parent from 85 to 87.</action> diff --git a/src/main/java/org/apache/commons/lang3/function/FailableByteConsumer.java b/src/main/java/org/apache/commons/lang3/function/FailableByteConsumer.java new file mode 100644 index 000000000..af435249a --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/function/FailableByteConsumer.java @@ -0,0 +1,70 @@ +/* + * 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 + * + * https://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 org.apache.commons.lang3.function; + +import java.util.Objects; +import java.util.function.IntConsumer; + +/** + * A functional interface like {@link ByteConsumer} that declares a {@link Throwable}. + * + * @param <E> The kind of thrown exception or error. + * @since 3.11 + */ +@FunctionalInterface +public interface FailableByteConsumer<E extends Throwable> { + + /** NOP singleton */ + @SuppressWarnings("rawtypes") + FailableByteConsumer NOP = t -> { /* NOP */ }; + + /** + * Gets the NOP singleton. + * + * @param <E> The kind of thrown exception or error. + * @return The NOP singleton. + */ + @SuppressWarnings("unchecked") + static <E extends Throwable> FailableByteConsumer<E> nop() { + return NOP; + } + + /** + * Accepts the given arguments. + * + * @param value the parameter for the consumable to accept + * @throws E Thrown when the consumer fails. + */ + void accept(byte value) throws E; + + /** + * Returns a composed {@link FailableByteConsumer} like {@link IntConsumer#andThen(IntConsumer)}. + * + * @param after the operation to perform after this one. + * @return a composed {@link FailableByteConsumer} like {@link IntConsumer#andThen(IntConsumer)}. + * @throws NullPointerException if {@code after} is null + */ + default FailableByteConsumer<E> andThen(final FailableByteConsumer<E> after) { + Objects.requireNonNull(after); + return (final byte t) -> { + accept(t); + after.accept(t); + }; + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java b/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java index 4e5259eb5..bee264458 100644 --- a/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java +++ b/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java @@ -761,6 +761,24 @@ void testBiPredicateOr() throws Throwable { () -> assertTrue(FailableBiPredicate.truePredicate().or(null).test(null, null))); } + @Test + void testByteConsumerAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableByteConsumer<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + }; + final FailableByteConsumer<Throwable> nop = FailableByteConsumer.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept((byte) 0)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept((byte) 0)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertNullPointerException(() -> failing.andThen(null)); + } + @Test void testCallable() { FailureOnOddInvocations.invocations = 0; @@ -1629,6 +1647,37 @@ public boolean getAsBoolean() throws Throwable { }.getAsBoolean()); } + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + void testThrows_FailableByteConsumer_IOException() { + assertThrows(IOException.class, () -> new FailableByteConsumer<IOException>() { + + @Override + public void accept(final byte value) throws IOException { + throw new IOException("test"); + } + }.accept((byte) 0)); + } + + /** + * Tests that our failable interface is properly defined to throw any exception using the top level generic types + * Object and Throwable. + */ + @Test + void testThrows_FailableByteConsumer_Throwable() { + assertThrows(IOException.class, () -> new FailableByteConsumer<Throwable>() { + + @Override + public void accept(final byte value) throws Throwable { + throw new IOException("test"); + + } + }.accept((byte) 0)); + } + /** * Tests that our failable interface is properly defined to throw any exception using the top level generic types * Object and Throwable.
