Skip to content

Commit

Permalink
Merge pull request #49 from aNNiMON/exceptional-map
Browse files Browse the repository at this point in the history
Add map function to Exceptional
  • Loading branch information
aNNiMON authored Jun 23, 2016
2 parents 338dbab + b614a0c commit 09e3947
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
19 changes: 19 additions & 0 deletions stream/src/main/java/com/annimon/stream/Exceptional.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.annimon.stream;

import com.annimon.stream.function.Consumer;
import com.annimon.stream.function.ThrowableFunction;
import com.annimon.stream.function.ThrowableSupplier;

/**
Expand Down Expand Up @@ -129,6 +130,24 @@ public <E extends Throwable> T getOrThrow(E exception) throws E {
}
return value;
}

/**
* Invokes mapping function on inner value if there were no exceptions.
*
* @param <U> the type of result value
* @param mapper mapping function
* @return an {@code Exceptional} with transformed value if there were no exceptions
*/
public <U> Exceptional<U> map(ThrowableFunction<? super T, ? extends U, Throwable> mapper) {
if (throwable != null) {
return new Exceptional<U>(null, throwable);
}
try {
return new Exceptional<U>(mapper.apply(value), null);
} catch (Throwable throwable) {
return new Exceptional<U>(null, throwable);
}
}

/**
* Invokes consumer function if there were any exception.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.annimon.stream.function;

/**
* Represents a function which produces result from input arguments and can throw an exception.
*
* @param <I> the type of the input of the function
* @param <R> the type of the result of the function
* @param <E> the type of the exception
*/
@FunctionalInterface
public interface ThrowableFunction<I, R, E extends Throwable> {

/**
* Applies this function to the given argument.
*
* @param value an argument
* @return the function result
* @throws E an exception
*/
R apply(I value) throws E;
}
43 changes: 42 additions & 1 deletion stream/src/test/java/com/annimon/stream/ExceptionalTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.annimon.stream;

import com.annimon.stream.function.Consumer;
import com.annimon.stream.function.ThrowableFunction;
import com.annimon.stream.function.ThrowableSupplier;
import java.io.FileNotFoundException;
import java.io.IOException;
Expand Down Expand Up @@ -104,7 +105,47 @@ public void testGetOrThrowNewExceptionTestCause() {
assertThat(ae.getCause(), instanceOf(IOException.class));
}
}


@Test
public void testMapWithoutException() {
String value = Exceptional
.of(tenSupplier)
.map(new ThrowableFunction<Integer, String, Throwable>() {
@Override
public String apply(Integer value) throws Throwable {
return Integer.toString(value);
}
})
.get();
assertEquals("10", value);
}

@Test(expected = NumberFormatException.class)
public void testMapWithException() throws Throwable {
Exceptional
.of(tenSupplier)
.map(new ThrowableFunction<Integer, String, Throwable>() {
@Override
public String apply(Integer value) throws Throwable {
throw new NumberFormatException();
}
})
.getOrThrow();
}

@Test(expected = IOException.class)
public void testMapOnAlreadyFailedExceptional() throws Throwable {
Exceptional
.of(ioExceptionSupplier)
.map(new ThrowableFunction<Integer, String, Throwable>() {
@Override
public String apply(Integer value) throws Throwable {
return Integer.toString(value);
}
})
.getOrThrow();
}

@Test
public void testIfException() {
for (final ExceptionType type : ExceptionType.values()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.annimon.stream.function;

import org.junit.Test;
import static org.junit.Assert.*;

/**
* Tests {@code ThrowableFunction}.
*
* @see com.annimon.stream.function.ThrowableFunction
*/
public class ThrowableFunctionTest {

@Test
public void testApply() {
assertEquals(100, (int) toInt.apply("100"));
}


@Test(expected = NumberFormatException.class)
public void testApplyWithRuntimeException() {
toInt.apply("oops");
}

private static final ThrowableFunction<String, Integer, NumberFormatException> toInt
= new ThrowableFunction<String, Integer, NumberFormatException>() {
@Override
public Integer apply(String value) throws NumberFormatException {
return Integer.parseInt(value);
}
};

}

0 comments on commit 09e3947

Please sign in to comment.