Skip to content

Instantly share code, notes, and snippets.

@sappenin
Last active April 6, 2017 03:39
Show Gist options
  • Save sappenin/89ee2db2d5236a52123c174161be5fc2 to your computer and use it in GitHub Desktop.
Save sappenin/89ee2db2d5236a52123c174161be5fc2 to your computer and use it in GitHub Desktop.
Example of InterledgerException
package org.interledger.ilp.exceptions;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.interledger.ilp.InterledgerAddress;
import org.interledger.ilp.InterledgerAddressBuilder;
/**
* Base ILP exception.
*
* RFC REF: https://github.com/interledger/rfcs/blob/master/0003-interledger-protocol/0003-interledger-protocol.md
*/
public class InterledgerException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final ErrorCode errorCode;
private final InterledgerAddress triggeredBy;
private final List<InterledgerAddress> forwardedBy;
private final ZonedDateTime triggeredAt;
/**
* <p>Minimal-args Constructor.</p>
*
* <p>Allows a caller to construct an instance of this class with the minimal amount of supplied
* information.</p>
*
* @param errorCode An instance of {@link ErrorCode}.
* @param triggeredBy An instance of {@link InterledgerAddress} for the entity that originally
* emitted the error (MAY be an address prefix if the entity that originally omitted the error is
* a ledger).
*/
public InterledgerException(
final ErrorCode errorCode,
final InterledgerAddress triggeredBy
) {
this.errorCode = Objects.requireNonNull(errorCode);
this.triggeredBy = Objects.requireNonNull(triggeredBy);
this.triggeredAt = ZonedDateTime.now();
this.forwardedBy = Collections.EMPTY_LIST; // immutable
}
/**
* <p>All-args Constructor.</p>
*
* <p>Allows a caller to construct an instance of this class by specifying all required
* fields.</p>
*
* @param errorCode An instance of {@link ErrorCode}.
* @param triggeredBy An instance of {@link InterledgerAddress} for the entity that originally
* emitted the error (MAY be an address prefix if the entity that originally omitted the error is
* a ledger).
* @param triggeredAt A {@link ZonedDateTime} indicating when the error was initially emitted.
* @param forwardedBy A {@link List} of type {@link InterledgerAddress} that contains the
*/
public InterledgerException(
final ErrorCode errorCode,
final InterledgerAddress triggeredBy,
final ZonedDateTime triggeredAt,
final List<InterledgerAddress> forwardedBy
) {
this.errorCode = Objects.requireNonNull(errorCode);
this.triggeredBy = Objects.requireNonNull(triggeredBy);
this.triggeredAt = Objects.requireNonNull(triggeredAt);
// Deep-copy the incoming list to normalize the InternetAddress, and then make it immutable.
final List<InterledgerAddress> newList = deepCopyAndNormalize(forwardedBy);
this.forwardedBy = Collections.unmodifiableList(newList);
}
/**
* <p>All-args Constructor.</p>
*
* <p>Allows a caller to construct an instance of this class by specifying all required
* fields.</p>
*
* @param errorCode An instance of {@link ErrorCode}.
* @param triggeredBy An instance of {@link InterledgerAddress} for the entity that originally
* emitted the error (MAY be an address prefix if the entity that originally omitted the error is
* a ledger).
* @param triggeredAt A {@link ZonedDateTime} indicating when the error was initially emitted.
* @param forwardedBy A {@link List} of type {@link InterledgerAddress} that contains the
* addresses of ILP connectors that relayed the error message.
* @param data A {@link String} containing error data for debugging purposes.
* @param cause An instance of {@link Throwable} that caused this exception. Used for debugging.
*/
public InterledgerException(
final ErrorCode errorCode,
final InterledgerAddress triggeredBy,
final ZonedDateTime triggeredAt,
final List<InterledgerAddress> forwardedBy,
final String data,
final Throwable cause
) {
super(data, cause);
this.errorCode = Objects.requireNonNull(errorCode);
this.triggeredBy = Objects.requireNonNull(triggeredBy);
this.triggeredAt = Objects.requireNonNull(triggeredAt);
// Deep-copy the incoming list to normalize the InternetAddress, and then make it immutable.
final List<InterledgerAddress> newList = deepCopyAndNormalize(forwardedBy);
this.forwardedBy = Collections.unmodifiableList(newList);
}
/**
* Construct for adding an additional forwardedBy.
*
* @param interledgerException An instance of {@link InterledgerException}.
* @param forwardedBy An instance of {@link InterledgerAddress} that contains an address to be
* added to the list of forwarded -by addresses in the supplied {@code interledgerException}.
*/
public InterledgerException(
final InterledgerException interledgerException,
final InterledgerAddress forwardedBy
) {
super(interledgerException.getMessage(), interledgerException.getCause());
this.errorCode = interledgerException.getErrorCode();
this.triggeredBy = interledgerException.getTriggeredBy();
this.triggeredAt = interledgerException.getTriggeredAt();
// Deep-copy the incoming list to normalize the InternetAddress, and then make it immutable.
final List<InterledgerAddress> newList = deepCopyAndNormalize(
interledgerException.getForwardedBy());
newList.add(forwardedBy);
this.forwardedBy = Collections.unmodifiableList(newList);
}
/**
* Deep-copy the {@link List} supplied by {@code addresses} and return a new list with normalized
* instances of {@link InterledgerAddress}.
*/
private List<InterledgerAddress> deepCopyAndNormalize(final List<InterledgerAddress> addresses) {
return addresses.stream()
.map(InterledgerAddressBuilder::new)
.map(InterledgerAddressBuilder::build)
.collect(Collectors.toList());
}
public ErrorCode getErrorCode() {
return errorCode;
}
public InterledgerAddress getTriggeredBy() {
return triggeredBy;
}
public List<InterledgerAddress> getForwardedBy() {
return forwardedBy;
}
public ZonedDateTime getTriggeredAt() {
return triggeredAt;
}
public enum ErrorCode {
// FINAL ERRORS
F00_BAD_REQUEST("F00", "BAD REQUEST"),
F01_INVALID_PAQUET("F01", "INVALID PAQUET"),
F02_UNREACHABLE("F02", "UNREACHABLE"),
F03_INVALID_AMOUNT("F03", "INVALID AMOUNT"),
F04_INSUFFICIENT_DST_AMOUNT("F04", "INSUFFICIENT DST. AMOUNT"),
F05_WRONG_CONDITION("F05", "WRONG CONDITION"),
F06_UNEXPECTED_PAYMENT("F06", "UNEXPECTED PAYMENT"),
F07_CANNOT_RECEIVE("F07", "CANNOT RECEIVE"),
F99_APPLICATION_ERROR("F99", "APPLICATION ERROR"),
T00_INTERNAL_ERROR("T00", "INTERNAL ERROR"),
T01_LEDGER_UNREACHABLE("T01", "LEDGER UNREACHABLE"),
T02_LEDGER_BUSY("T02", "LEDGER BUSY"),
T03_CONNECTOR_BUSY("T03", "CONNECTOR BUSY"),
T04_INSUFFICIENT_LIQUIDITY("T04", "INSUFFICIENT LIQUIDITY"),
T05_RATE_LIMITED("T05", "RATE LIMITED"),
T99_APPLICATION_ERROR("T99", "APPLICATION ERROR"),
R00_TRANSFER_TIMED_OUT("R00", "TRANSFER TIMED OUT"),
R01_INSUFFICEINT_SOURCE_AMOUNT("R01", "INSUFFICEINT SOURCE AMOUNT"),
R02_INSUFFICIENT_TIMEOUT("R02", "INSUFFICIENT TIMEOUT"),
R99_APPLICATION_ERROR("R99", "APPLICATION ERROR");
private final String code;
private final String name;
ErrorCode(String code, String name) {
if (code == null || name == null) {
throw new RuntimeException("code and/or name can not be null");
}
code = code.trim();
name = name.trim();
if (code.length() != 3) {
throw new RuntimeException("error code length must be equal to 3");
}
char type = code.charAt(0);
if (type != 'F' && type != 'T' && type != 'R') {
throw new RuntimeException("error code must be := 'F' | 'T' | 'R'");
}
this.code = code;
this.name = name;
}
@Override
public String toString() {
return this.code + "-" + this.name();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment