Skip to content

Commit 1182ac2

Browse files
committed
add CombinedInvoker and utility methods and constants
- add default constants for Mode and Invoker - add overrides for invoke methods without mode that use the default Mode constant
1 parent cc87a22 commit 1182ac2

File tree

8 files changed

+110
-13
lines changed

8 files changed

+110
-13
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ repositories {
1313
}
1414
1515
dependencies {
16-
implementation "com.github.robinfriedli:exec:1.2.2"
16+
implementation "com.github.robinfriedli:exec:1.3"
1717
}
1818
```
1919

@@ -22,7 +22,7 @@ dependencies {
2222
<dependency>
2323
<groupId>com.github.robinfriedli</groupId>
2424
<artifactId>exec</artifactId>
25-
<version>1.2.2</version>
25+
<version>1.3</version>
2626
<type>pom</type>
2727
</dependency>
2828

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
group = "net.robinfriedli"
8-
version = "1.2.2"
8+
version = "1.3"
99
sourceCompatibility = "8"
1010
targetCompatibility = "8"
1111

src/main/kotlin/net/robinfriedli/exec/BaseInvoker.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import java.util.function.Function
55

66
open class BaseInvoker : Invoker {
77

8+
/**
9+
* Central invoke implementation called by all other methods. This method is responsible for applying [ModeWrapper]s
10+
* to the task so be sure to call this implementation when implementing a custom [Invoker].
11+
*/
812
@Throws(Exception::class)
913
override fun <T> invoke(mode: Mode, task: Callable<T>): T {
1014
val modeWrapper = mode.getWrapper()
@@ -46,4 +50,7 @@ open class BaseInvoker : Invoker {
4650
})
4751
}
4852

49-
}
53+
override fun combine(invoker: Invoker): Invoker {
54+
return CombinedInvoker(this, invoker)
55+
}
56+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package net.robinfriedli.exec
2+
3+
import java.util.concurrent.Callable
4+
5+
class CombinedInvoker(private val outer: Invoker, private val inner: Invoker) : BaseInvoker() {
6+
@Throws(Exception::class)
7+
override fun <T> invoke(mode: Mode, task: Callable<T>): T {
8+
return outer.invoke(Callable { inner.invoke(mode, task) })
9+
}
10+
}

src/main/kotlin/net/robinfriedli/exec/Invoker.kt

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@ import java.util.function.Function
66
interface Invoker {
77

88
companion object {
9+
@JvmStatic
10+
val defaultInstance = BaseInvoker()
11+
912
@JvmStatic
1013
fun newInstance(): Invoker {
1114
return BaseInvoker()
1215
}
1316
}
1417

1518
/**
16-
* Runs the given callable with the given mode applied
19+
* Runs the given callable with the given mode applied.
20+
*
21+
* The supplied mode is used to decorate the task by wrapping the task in the mode's [ModeWrapper].
1722
*
1823
* @param mode the custom mode that defines the task execution
1924
* @param task the callable to run
@@ -23,12 +28,20 @@ interface Invoker {
2328
@Throws(Exception::class)
2429
fun <T> invoke(mode: Mode, task: Callable<T>): T
2530

31+
fun <T> invoke(task: Callable<T>): T {
32+
return invoke(Mode.empty, task)
33+
}
34+
2635
/**
2736
* Same as [Invoker.invoke] but accepts a Runnable and does not throw a checked exception as Runnables
2837
* cannot throw checked exceptions
2938
*/
3039
fun invoke(mode: Mode, runnable: Runnable)
3140

41+
fun invoke(runnable: Runnable) {
42+
invoke(Mode.empty, runnable)
43+
}
44+
3245
/**
3346
* Runs the task with the given mode applied and handles checked exceptions by wrapping them into runtime exceptions
3447
* using the given function.
@@ -41,10 +54,31 @@ interface Invoker {
4154
exceptionMapper: Function<Exception, RuntimeException>
4255
): T
4356

57+
fun <T> invoke(
58+
task: Callable<T>,
59+
exceptionMapper: Function<Exception, RuntimeException>
60+
): T {
61+
return invoke(
62+
Mode.empty,
63+
task,
64+
exceptionMapper
65+
)
66+
}
67+
4468
/**
4569
* Runs the task wrapping checked exceptions into [RuntimeException]. This is equivalent to calling
4670
* `invoke(mode, task, e -> new RuntimeException(e))`
4771
*/
4872
fun <T> invokeChecked(mode: Mode, task: Callable<T>): T
4973

50-
}
74+
fun <T> invokeChecked(task: Callable<T>): T {
75+
return invokeChecked(Mode.empty, task)
76+
}
77+
78+
/**
79+
* Creates a [CombinedInvoker] that combines Invokers by calling the supplied Invoker within this Invoker. Modes are
80+
* passed to the innermost invoke call
81+
*/
82+
fun combine(invoker: Invoker): Invoker
83+
84+
}

src/main/kotlin/net/robinfriedli/exec/Mode.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ class Mode {
88
private var currentWrapper: ModeWrapper? = null
99

1010
companion object {
11+
@JvmStatic
12+
val empty = create()
13+
1114
@JvmStatic
1215
fun create(): Mode {
1316
return Mode()

src/test/java/net/robinfriedli/exec/JavaTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package net.robinfriedli.exec;
22

3-
import java.util.concurrent.Callable;
3+
import org.testng.annotations.Test;
44

5-
import org.testng.annotations.*;
5+
import java.util.concurrent.Callable;
66

7-
import static org.testng.Assert.*;
7+
import static org.testng.Assert.assertEquals;
88

99
public class JavaTest {
1010

1111
@Test
1212
public void testSimpleInvocation() {
13-
Invoker invoker = new BaseInvoker();
14-
Mode mode = Mode.create();
13+
Invoker invoker = Invoker.getDefaultInstance();
14+
Mode mode = Mode.getEmpty();
1515

1616
MutableInteger i = new MutableInteger(1);
1717
invoker.invoke(mode, () -> i.add(1));

src/test/kotlin/net/robinfriedli/exec/InvokerTest.kt

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class InvokerTest {
1111
@Test
1212
fun testSimpleInvocation() {
1313
val invoker = BaseInvoker()
14-
val mode = Mode.create()
14+
val mode = Mode.empty
1515

1616
var i = 1
1717
invoker.invoke(mode) {
@@ -25,7 +25,7 @@ class InvokerTest {
2525
fun testApplyCustomModes() {
2626
var i = 1
2727

28-
val invoker = BaseInvoker()
28+
val invoker = Invoker.defaultInstance
2929
val mode = Mode.create()
3030
.with(object : AbstractNestedModeWrapper() {
3131
override fun <T> wrap(callable: Callable<T>): Callable<T> {
@@ -77,4 +77,47 @@ class InvokerTest {
7777
assertEquals(i, 11)
7878
}
7979

80+
@Test
81+
fun testCombinedInvoker() {
82+
val mode = create()
83+
.with(object : AbstractNestedModeWrapper() {
84+
override fun <T> wrap(callable: Callable<T>): Callable<T> {
85+
return Callable {
86+
(callable.call() as Int + 7) as T
87+
}
88+
}
89+
})
90+
91+
val invoker = newInstance()
92+
.combine(MultiplyingInvoker(2))
93+
.combine(AddingInvoker(1))
94+
.combine(MultiplyingInvoker(3))
95+
.combine(AddingInvoker(2))
96+
.combine(MultiplyingInvoker(2))
97+
98+
val i = invoker.invoke<Int>(mode) { 3 }
99+
100+
// 3
101+
// + 7 (ModeWrapper is applied to the task directly, thus the innermost operation) = 10
102+
// then the invokers in reverse order because each invoker calls the super invoker first
103+
// * 2 = 20
104+
// + 2 = 22
105+
// * 3 = 66
106+
// + 1 = 67
107+
// * 2 = 134
108+
assertEquals(i, 134)
109+
}
110+
111+
class MultiplyingInvoker(private val factor: Int) : BaseInvoker() {
112+
override fun <T> invoke(mode: Mode, task: Callable<T>): T {
113+
return (super.invoke(mode, task) as Int * factor) as T
114+
}
115+
}
116+
117+
class AddingInvoker(private val summand: Int) : BaseInvoker() {
118+
override fun <T> invoke(mode: Mode, task: Callable<T>): T {
119+
return (super.invoke(mode, task) as Int + summand) as T
120+
}
121+
}
122+
80123
}

0 commit comments

Comments
 (0)