Skip to content

Commit

Permalink
Upgrade BTException to be a structured (Seltzer) exception.
Browse files Browse the repository at this point in the history
  • Loading branch information
io7m committed Aug 8, 2023
1 parent 7e7ba41 commit 1aa05a7
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,64 +16,156 @@

package com.io7m.blackthorne.core;

import com.io7m.seltzer.api.SStructuredErrorExceptionType;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
* An exception raised by convenience methods.
*/

public final class BTException extends Exception
implements SStructuredErrorExceptionType<String>
{
private final List<BTParseError> errors;
private final String errorCode;
private final Map<String, String> attributes;
private final Optional<String> remediatingAction;

/**
* Construct an exception.
*
* @param inMessage The exception message
* @param inErrors The parse errors
* @param message The message
* @param inErrorCode The error code
* @param inAttributes The error attributes
* @param inRemediatingAction The remediating action, if any
* @param inErrors The parse errors
*/

public BTException(
final String inMessage,
final String message,
final String inErrorCode,
final Map<String, String> inAttributes,
final Optional<String> inRemediatingAction,
final List<BTParseError> inErrors)
{
super(Objects.requireNonNull(inMessage, "message"));
this.errors = Objects.requireNonNull(inErrors, "errors");
super(Objects.requireNonNull(message, "message"));

this.errors =
List.copyOf(Objects.requireNonNull(inErrors, "errors"));
this.errorCode =
Objects.requireNonNull(inErrorCode, "errorCode");
this.attributes =
Map.copyOf(Objects.requireNonNull(inAttributes, "attributes"));
this.remediatingAction =
Objects.requireNonNull(inRemediatingAction, "remediatingAction");
}

/**
* Construct an exception.
*
* @param inMessage The exception message
* @param inCause The cause
* @param inErrors The parse errors
* @param message The message
* @param cause The cause
* @param inErrorCode The error code
* @param inAttributes The error attributes
* @param inRemediatingAction The remediating action, if any
* @param inErrors The parse errors
*/

public BTException(
final String inMessage,
final Throwable inCause,
final String message,
final Throwable cause,
final String inErrorCode,
final Map<String, String> inAttributes,
final Optional<String> inRemediatingAction,
final List<BTParseError> inErrors)
{
super(
Objects.requireNonNull(inMessage, "message"),
Objects.requireNonNull(inCause, "cause"));
this.errors = Objects.requireNonNull(inErrors, "errors");
Objects.requireNonNull(message, "message"),
Objects.requireNonNull(cause, "cause")
);

this.errors =
List.copyOf(Objects.requireNonNull(inErrors, "errors"));
this.errorCode =
Objects.requireNonNull(inErrorCode, "errorCode");
this.attributes =
Map.copyOf(Objects.requireNonNull(inAttributes, "attributes"));
this.remediatingAction =
Objects.requireNonNull(inRemediatingAction, "remediatingAction");
}

/**
* Construct an exception.
*
* @param message The message
* @param inErrorCode The error code
* @param inAttributes The error attributes
* @param inErrors The parse errors
*/

public BTException(
final String message,
final String inErrorCode,
final Map<String, String> inAttributes,
final List<BTParseError> inErrors)
{
this(
message,
inErrorCode,
inAttributes,
Optional.empty(),
inErrors
);
}

/**
* Construct an exception.
*
* @param inCause The cause
* @param inErrors The parse errors
* @param message The message
* @param inErrorCode The error code
* @param inErrors The parse errors
*/

public BTException(
final Throwable inCause,
final String message,
final String inErrorCode,
final List<BTParseError> inErrors)
{
super(Objects.requireNonNull(inCause, "cause"));
this.errors = Objects.requireNonNull(inErrors, "errors");
this(
message,
inErrorCode,
Map.of(),
Optional.empty(),
inErrors
);
}

@Override
public String errorCode()
{
return this.errorCode;
}

@Override
public Map<String, String> attributes()
{
return this.attributes;
}

@Override
public Optional<String> remediatingAction()
{
return this.remediatingAction;
}

@Override
public Optional<Throwable> exception()
{
return Optional.of(this);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
Expand Down Expand Up @@ -423,7 +422,7 @@ public static <T> T parse(
});

if (resultOpt.isEmpty() || anyErrors) {
throw new BTException("Parse failed.", new IOException(), errors);
throw new BTException("Parsing failed.", "parse-failed", errors);
}

return resultOpt.get();
Expand All @@ -437,7 +436,7 @@ public static <T> T parse(
Optional.of(source)
);

errors.add(
final var mainError =
new BTParseError(
position,
BTParseError.Severity.ERROR,
Expand All @@ -446,16 +445,25 @@ public static <T> T parse(
Map.of(),
Optional.empty(),
Optional.of(e)
));
);

errors.add(mainError);

throw new BTException(e.getMessage(), e, errors);
throw new BTException(
e.getMessage(),
e,
mainError.errorCode(),
mainError.attributes(),
mainError.remediatingAction(),
errors
);
} catch (final Exception e) {
LOG.error("error encountered during parsing: ", e);
LOG.error("Error encountered during parsing: ", e);

final var position =
LexicalPosition.of(-1, -1, Optional.of(source));

errors.add(
final var mainError =
new BTParseError(
position,
BTParseError.Severity.ERROR,
Expand All @@ -464,9 +472,18 @@ public static <T> T parse(
Map.of(),
Optional.empty(),
Optional.of(e)
));
);

errors.add(mainError);

throw new BTException(e.getMessage(), e, errors);
throw new BTException(
e.getMessage(),
e,
mainError.errorCode(),
mainError.attributes(),
mainError.remediatingAction(),
errors
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public final class BTListMonoHandler<S> implements BTElementHandlerType<S, List<
* @param inElementName The list element name
* @param inChildElementName The name of child elements
* @param inItemHandler The handler used for child elements
* @param inIgnoreUnrecognized Whether or not to ignore unrecognized elements
* @param inIgnoreUnrecognized Whether to ignore unrecognized elements
*/

public BTListMonoHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public final class BTListPolyHandler<S> implements BTElementHandlerType<S, List<
*
* @param inElementName The list element name
* @param inItemHandlers The child item handlers
* @param inIgnoreUnrecognized Whether or not to ignore unrecognized elements
* @param inIgnoreUnrecognized Whether to ignore unrecognized elements
*/

public BTListPolyHandler(
Expand Down
6 changes: 6 additions & 0 deletions spotbugs-filter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@
<Bug pattern="SE_BAD_FIELD"/>
</Match>

<!-- The interface exists to be implemented. -->
<Match>
<Class name="com.io7m.blackthorne.core.BTException"/>
<Bug pattern="SCII_SPOILED_CHILD_INTERFACE_IMPLEMENTOR"/>
</Match>

<Match>
<Or>
<Bug pattern="OPM_OVERLY_PERMISSIVE_METHOD"/>
Expand Down

0 comments on commit 1aa05a7

Please sign in to comment.