Skip to content

Commit 1583fc7

Browse files
committed
Merge pull request #229 from JLLeitschuh/feat/exceptionWitnessResponderButton
Add a button to respond to the ExceptionWitness
2 parents 64dcee7 + 6696eec commit 1583fc7

File tree

15 files changed

+446
-62
lines changed

15 files changed

+446
-62
lines changed

core/src/main/java/edu/wpi/grip/core/Step.java

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import com.google.inject.Singleton;
77
import com.thoughtworks.xstream.annotations.XStreamAlias;
88
import edu.wpi.grip.core.events.SocketChangedEvent;
9+
import edu.wpi.grip.core.util.ExceptionWitness;
910

10-
import java.util.NoSuchElementException;
1111
import java.util.Optional;
1212
import java.util.logging.Level;
1313
import java.util.logging.Logger;
@@ -20,21 +20,26 @@
2020
*/
2121
@XStreamAlias(value = "grip:Step")
2222
public class Step {
23+
private static final Logger logger = Logger.getLogger(Step.class.getName());
24+
private static final String MISSING_SOCKET_MESSAGE_END = " must have a value to run this step.";
2325

24-
private final Logger logger = Logger.getLogger(Step.class.getName());
26+
private final ExceptionWitness witness;
2527

2628
private final Operation operation;
2729
private final InputSocket<?>[] inputSockets;
2830
private final OutputSocket<?>[] outputSockets;
2931
private final Optional<?> data;
3032

33+
3134
@Singleton
3235
public static class Factory {
3336
private final EventBus eventBus;
37+
private final ExceptionWitness.Factory exceptionWitnessFactory;
3438

3539
@Inject
36-
public Factory(EventBus eventBus) {
40+
public Factory(EventBus eventBus, ExceptionWitness.Factory exceptionWitnessFactory) {
3741
this.eventBus = eventBus;
42+
this.exceptionWitnessFactory = exceptionWitnessFactory;
3843
}
3944

4045
public Step create(Operation operation) {
@@ -51,7 +56,13 @@ public Step create(Operation operation) {
5156
eventBus.register(socket);
5257
}
5358

54-
final Step step = new Step(operation, inputSockets, outputSockets, operation.createData());
59+
final Step step = new Step(
60+
operation,
61+
inputSockets,
62+
outputSockets,
63+
operation.createData(),
64+
exceptionWitnessFactory
65+
);
5566
eventBus.register(step);
5667
for (Socket<?> socket : inputSockets) {
5768
socket.setStep(Optional.of(step));
@@ -66,16 +77,22 @@ public Step create(Operation operation) {
6677
}
6778

6879
/**
69-
* @param operation The operation that is performed at this step.
70-
* @param inputSockets The input sockets from the operation.
71-
* @param outputSockets The output sockets provided by the operation.
72-
* @param data The data provided by the operation.
80+
* @param operation The operation that is performed at this step.
81+
* @param inputSockets The input sockets from the operation.
82+
* @param outputSockets The output sockets provided by the operation.
83+
* @param data The data provided by the operation.
84+
* @param exceptionWitnessFactory A factory used to create an {@link ExceptionWitness}
7385
*/
74-
Step(Operation operation, InputSocket<?>[] inputSockets, OutputSocket<?>[] outputSockets, Optional<?> data) {
86+
Step(Operation operation,
87+
InputSocket<?>[] inputSockets,
88+
OutputSocket<?>[] outputSockets,
89+
Optional<?> data,
90+
ExceptionWitness.Factory exceptionWitnessFactory) {
7591
this.operation = operation;
7692
this.inputSockets = inputSockets;
7793
this.outputSockets = outputSockets;
7894
this.data = data;
95+
this.witness = exceptionWitnessFactory.create(this);
7996
}
8097

8198
/**
@@ -115,25 +132,25 @@ private void resetOutputSockets() {
115132
* default values.
116133
*/
117134
private synchronized void runPerformIfPossible() {
118-
try {
119-
for (InputSocket<?> inputSocket : inputSockets) {
120-
inputSocket.getValue()
121-
.orElseThrow(() -> new NoSuchElementException(
122-
inputSocket.getSocketHint().getIdentifier() + " must have a value to run this step."
123-
));
135+
for (InputSocket<?> inputSocket : inputSockets) {
136+
// If there is a socket that isn't present then we have a problem.
137+
if (!inputSocket.getValue().isPresent()) {
138+
witness.flagWarning(inputSocket.getSocketHint().getIdentifier() + MISSING_SOCKET_MESSAGE_END);
139+
resetOutputSockets();
140+
return; /* Only run the perform method if all of the input sockets are present. */
124141
}
125-
} catch (NoSuchElementException e) {
126-
//TODO: show warning icon
127-
resetOutputSockets();
128-
return; /* Only run the perform method if all of the input sockets are present. */
129142
}
130143

131144
try {
132145
this.operation.perform(inputSockets, outputSockets, data);
133146
} catch (Exception e) {
134-
logger.log(Level.WARNING, e.getMessage(), e);
147+
final String operationFailedMessage = "The " + operation.getName() + " operation did not perform correctly.";
148+
logger.log(Level.WARNING, operationFailedMessage, e);
149+
witness.flagException(e, operationFailedMessage);
135150
resetOutputSockets();
151+
return;
136152
}
153+
witness.clearException();
137154
}
138155

139156
@Subscribe

core/src/main/java/edu/wpi/grip/core/events/ExceptionEvent.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,51 @@
1212
*/
1313
public final class ExceptionEvent {
1414
private final Object origin;
15-
private final Exception exception;
16-
private final Optional<String> message;
15+
private final Optional<Exception> exception;
16+
private final String message;
1717

18-
public ExceptionEvent(Object origin, Exception exception) {
19-
this(origin, exception, null);
20-
}
2118

19+
/**
20+
* @param origin The object that triggered this exception.
21+
* @param exception The exception this is handling.
22+
* @param message The message associated with this event.
23+
* If <tt>null</tt> will use {@link Exception#getMessage()}
24+
*/
2225
public ExceptionEvent(Object origin, Exception exception, String message) {
23-
this.exception = checkNotNull(exception, "The exception can not be null");
26+
this.exception = Optional.of(exception);
27+
this.origin = checkNotNull(origin, "The origin can not be null");
28+
this.message = message != null ? message : exception.getMessage();
29+
}
30+
31+
/**
32+
* @param origin The object that triggered this exception.
33+
* @param message The message associated with this event.
34+
*/
35+
public ExceptionEvent(Object origin, String message) {
2436
this.origin = checkNotNull(origin, "The origin can not be null");
25-
this.message = Optional.ofNullable(message);
37+
this.exception = Optional.empty();
38+
this.message = message;
2639
}
2740

28-
public Optional<String> getMessage() {
41+
/**
42+
* @param origin The object that triggered this exception.
43+
* @param exception The exception this is handling.
44+
* This will use {@link Exception#getMessage()} for the message.
45+
*/
46+
public ExceptionEvent(Object origin, Exception exception) {
47+
this(origin, exception, null);
48+
}
49+
50+
51+
public String getMessage() {
2952
return message;
3053
}
3154

3255
public Object getOrigin() {
3356
return origin;
3457
}
3558

36-
public Exception getException() {
59+
public Optional<Exception> getException() {
3760
return exception;
3861
}
3962
}

core/src/main/java/edu/wpi/grip/core/util/ExceptionWitness.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* </pre>
3131
* <blockquote/>
3232
*/
33-
public final class ExceptionWitness {
33+
public class ExceptionWitness {
3434
private final EventBus eventBus;
3535
private final Object origin;
3636
private final AtomicBoolean isExceptionState = new AtomicBoolean(false);
@@ -63,6 +63,17 @@ public final void flagException(Exception exception) {
6363
flagException(exception, null);
6464
}
6565

66+
/**
67+
* Allows a warning to be flagged without an exception. This should never be done when there is an exception
68+
* involved.
69+
*
70+
* @param warningMessage The message to flag.
71+
*/
72+
public final void flagWarning(final String warningMessage) {
73+
isExceptionState.set(true);
74+
this.eventBus.post(new ExceptionEvent(origin, warningMessage));
75+
}
76+
6677
/**
6778
* Indicate that there isn't currently an exception.
6879
* <p>
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package edu.wpi.grip.core;
22

33
import com.google.common.eventbus.EventBus;
4+
import edu.wpi.grip.core.util.MockExceptionWitness;
45

56
import java.util.Optional;
67

78
public class MockStep extends Step {
89

910
public MockStep() {
10-
super(null, new InputSocket[0], new OutputSocket[0], Optional.empty());
11+
super(null, new InputSocket[0], new OutputSocket[0], Optional.empty(), origin -> null);
1112
}
1213

1314
public static Step createMockStepWithOperation() {
14-
return new Step.Factory(new EventBus()).create(new MockOperation());
15+
final EventBus eventBus = new EventBus();
16+
return new Step.Factory(eventBus, origin -> new MockExceptionWitness(eventBus, origin)).create(new MockOperation());
1517
}
1618
}

core/src/test/java/edu/wpi/grip/core/PythonTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.common.eventbus.EventBus;
44
import edu.wpi.grip.core.operations.PythonScriptOperation;
5+
import edu.wpi.grip.core.util.MockExceptionWitness;
56
import org.junit.Test;
67

78
import static org.junit.Assert.assertEquals;
@@ -14,7 +15,7 @@ public class PythonTest {
1415
@Test
1516
public void testPython() throws Exception {
1617
Operation addition = new PythonScriptOperation(PythonTest.class.getResource("/edu/wpi/grip/scripts/addition.py"));
17-
Step step = new Step.Factory(eventBus).create(addition);
18+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(addition);
1819
Socket aSocket = step.getInputSockets()[0];
1920
Socket bSocket = step.getInputSockets()[1];
2021
Socket sumSocket = step.getOutputSockets()[0];
@@ -31,7 +32,7 @@ public void testPythonAdditionFromString() throws Exception {
3132
".lang.Integer\n\ninputs = [\n grip.SocketHints.createNumberSocketHint(\"a\", 0.0),\n grip.SocketHints.createNumberSocketHint(" +
3233
"\"b\", 0.0),\n]\n\noutputs = [\n grip.SocketHints.Outputs.createNumberSocketHint(\"sum\", 0.0)," +
3334
"\n]\n\ndef perform(a, b):\n return a + b\n");
34-
Step step = new Step.Factory(eventBus).create(additionFromString);
35+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(additionFromString);
3536
Socket aSocket = step.getInputSockets()[0];
3637
Socket bSocket = step.getInputSockets()[1];
3738
Socket sumSocket = step.getOutputSockets()[0];
@@ -45,7 +46,7 @@ public void testPythonAdditionFromString() throws Exception {
4546
@Test
4647
public void testPythonMultipleOutputs() throws Exception {
4748
Operation additionSubtraction = new PythonScriptOperation(PythonTest.class.getResource("/edu/wpi/grip/scripts/addition-subtraction.py"));
48-
Step step = new Step.Factory(eventBus).create(additionSubtraction);
49+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(additionSubtraction);
4950
Socket aSocket = step.getInputSockets()[0];
5051
Socket bSocket = step.getInputSockets()[1];
5152
Socket sumSocket = step.getOutputSockets()[0];
@@ -61,7 +62,7 @@ public void testPythonMultipleOutputs() throws Exception {
6162
@Test
6263
public void testPythonWrongOutputCount() throws Exception {
6364
Operation additionWrongOutputCount = new PythonScriptOperation(PythonTest.class.getResource("/edu/wpi/grip/scripts/addition-wrong-output-count.py"));
64-
Step step = new Step.Factory(eventBus).create(additionWrongOutputCount);
65+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(additionWrongOutputCount);
6566
Socket aSocket = step.getInputSockets()[0];
6667
Socket bSocket = step.getInputSockets()[1];
6768
Socket sumSocket = step.getOutputSockets()[0];
@@ -75,7 +76,7 @@ public void testPythonWrongOutputCount() throws Exception {
7576
@Test
7677
public void testPythonWrongOutputType() throws Exception {
7778
Operation additionWrongOutputType = new PythonScriptOperation(PythonTest.class.getResource("/edu/wpi/grip/scripts/addition-wrong-output-type.py"));
78-
Step step = new Step.Factory(eventBus).create(additionWrongOutputType);
79+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(additionWrongOutputType);
7980
Socket aSocket = step.getInputSockets()[0];
8081
Socket bSocket = step.getInputSockets()[1];
8182
Socket sumSocket = step.getOutputSockets()[0];

core/src/test/java/edu/wpi/grip/core/StepTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package edu.wpi.grip.core;
22

33
import com.google.common.eventbus.EventBus;
4+
import edu.wpi.grip.core.util.MockExceptionWitness;
45
import org.junit.Before;
56
import org.junit.Test;
67

@@ -18,12 +19,12 @@ public void setUp() {
1819

1920
@Test(expected = NullPointerException.class)
2021
public void testOperationNotNull() {
21-
new Step.Factory(eventBus).create(null);
22+
new Step.Factory(eventBus, (origin) -> null).create(null);
2223
}
2324

2425
@Test
2526
public void testStep() {
26-
Step step = new Step.Factory(eventBus).create(addition);
27+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(addition);
2728
Socket<Double> a = (Socket<Double>) step.getInputSockets()[0];
2829
Socket<Double> b = (Socket<Double>) step.getInputSockets()[1];
2930
Socket<Double> c = (Socket<Double>) step.getOutputSockets()[0];
@@ -37,7 +38,7 @@ public void testStep() {
3738

3839
@Test
3940
public void testSocketDirection() {
40-
Step step = new Step.Factory(eventBus).create(addition);
41+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(addition);
4142
Socket<Double> a = (Socket<Double>) step.getInputSockets()[0];
4243
Socket<Double> b = (Socket<Double>) step.getInputSockets()[1];
4344
Socket<Double> c = (Socket<Double>) step.getOutputSockets()[0];
@@ -49,7 +50,7 @@ public void testSocketDirection() {
4950

5051
@Test
5152
public void testGetOperation() {
52-
Step step = new Step.Factory(eventBus).create(addition);
53+
Step step = new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(addition);
5354

5455
assertEquals(addition, step.getOperation());
5556
}

core/src/test/java/edu/wpi/grip/core/operations/OperationsTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import edu.wpi.grip.core.Operation;
77
import edu.wpi.grip.core.Step;
88
import edu.wpi.grip.core.events.OperationAddedEvent;
9+
import edu.wpi.grip.core.util.MockExceptionWitness;
910
import edu.wpi.grip.generated.CVOperations;
1011
import org.junit.After;
1112
import org.junit.Before;
@@ -48,15 +49,15 @@ public void afterTest() {
4849
public void testCreateAllCVSteps() {
4950
CVOperations.addOperations(eventBus);
5051
for (Operation operation : operationList) {
51-
new Step.Factory(eventBus).create(operation);
52+
new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(operation);
5253
}
5354
}
5455

5556
@Test
5657
public void testCreateAllCoreSteps() {
5758
Operations.addOperations(eventBus);
5859
for (Operation operation : operationList) {
59-
new Step.Factory(eventBus).create(operation);
60+
new Step.Factory(eventBus, (origin) -> new MockExceptionWitness(eventBus, origin)).create(operation);
6061
}
6162
}
6263
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package edu.wpi.grip.core.util;
2+
3+
import com.google.common.eventbus.EventBus;
4+
import com.google.inject.assistedinject.Assisted;
5+
6+
7+
public class MockExceptionWitness extends ExceptionWitness {
8+
9+
public MockExceptionWitness(EventBus eventBus, @Assisted Object origin) {
10+
super(eventBus, origin);
11+
}
12+
}

ui/src/main/java/edu/wpi/grip/ui/GRIPUIModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.google.inject.spi.TypeListener;
1010
import edu.wpi.grip.core.Source;
1111
import edu.wpi.grip.ui.annotations.ParametrizedController;
12+
import edu.wpi.grip.ui.components.ExceptionWitnessResponderButton;
1213
import edu.wpi.grip.ui.components.StartStoppableButton;
1314
import edu.wpi.grip.ui.pipeline.OutputSocketController;
1415
import edu.wpi.grip.ui.pipeline.SocketHandleView;
@@ -62,6 +63,7 @@ public <I> void hear(final TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEnco
6263

6364
// Components
6465
install(new FactoryModuleBuilder().build(StartStoppableButton.Factory.class));
66+
install(new FactoryModuleBuilder().build(ExceptionWitnessResponderButton.Factory.class));
6567
// End Components
6668

6769
// Controllers

0 commit comments

Comments
 (0)