javax0.jamal.api.BadSyntax Maven / Gradle / Ivy
package javax0.jamal.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static java.util.stream.Collectors.joining;
/**
* This exception, as the name suggest, is thrown when the processor or a macro finds something it cannot interpret.
* This exception is always captured inside Jamal and then rethrown as a {@link BadSyntaxAt} exception adding the line
* reference information. This exception is used at code locations where it is not possible to identify the actual input
* location where the erroneous syntax started. See also {@link BadSyntaxAt}.
*/
public class BadSyntax extends Exception {
public BadSyntax() {
}
public BadSyntax(String message) {
super(message);
}
public BadSyntax(String message, Throwable cause) {
super(message, cause);
}
public BadSyntax(String message, List suppressed) {
super(message);
for (final var s : suppressed) {
this.addSuppressed(s);
}
}
public static RuntimeException rt(final String message) {
return new RuntimeException(new BadSyntax(message));
}
public static RuntimeException rt(final String message, Throwable cause) {
return new RuntimeException(new BadSyntax(message, cause));
}
final private List parameters = new ArrayList<>();
public List getParameters() {
return parameters;
}
public BadSyntax parameter(String param) {
parameters.add(param);
return this;
}
public BadSyntax parameters(List param) {
parameters.addAll(param);
return this;
}
private static String abbreviate(String longParam) {
if (longParam.length() > 60) {
return longParam.substring(0, 60) + "...";
}
return longParam;
}
public String getShortMessage() {
return super.getMessage();
}
@Override
public String getMessage() {
if (parameters.isEmpty()) {
return super.getMessage();
} else {
return super.getMessage() + "\n" +
parameters.stream()
.map(BadSyntax::abbreviate)
.map(m -> ">>>" + m + "\n")
.collect(joining());
}
}
/**
* A simple supplier where the "get()" can throw {@code BadSyntax}.
*
* @param
*/
public interface ThrowingSupplier {
T get() throws BadSyntax;
}
/**
* This method throws a {@code BadSyntax} exception when the {@code condition} is {@code true}.
* The message of the exception is provided by a supplier.
*
* There are two versions of the static method {@code when()}. Use this version when the calculation of the
* exception message is expensive.
*
* @param condition when this parameter is {@code true} the method throws {@code BadSyntax} exception.
* when the parameter is {@code false} the method returns.
* @param message is the supplier that provides the message for the exception.
* @throws BadSyntax when the {@code condition} is {@code true}.
*/
public static void when(final boolean condition, final ThrowingSupplier message) throws BadSyntax {
if (condition) {
throw castrated(new BadSyntax(message.get()));
}
}
/**
* This method throws a {@code BadSyntax} exception when the {@code condition} is {@code true}.
* The message of the exception is created using the {@code format} and the {@code parameters}.
*
* The message formatting happens only when the {@code condition} is {@code true}. The arguments are, however,
* evaluated before the call.
*
* @param condition when this parameter is {@code true} the method throws {@code BadSyntax} exception.
* when the parameter is {@code false} the method returns.
* @param format is message format
* @param parameters the parameter for the message format
* @throws BadSyntax when the {@code condition} is {@code true}.
*/
public static void when(final boolean condition, final String format, final Object... parameters) throws BadSyntax {
if (condition) {
throw format(String.format(format, parameters));
}
}
public static BadSyntax format(final Exception e, final String format, final Object... parameters) throws BadSyntax {
throw castrated(new BadSyntax(String.format(format, parameters), e));
}
public static BadSyntax format(final String format, final Object... parameters) throws BadSyntax {
throw castrated(new BadSyntax(String.format(format, parameters)));
}
/**
* Remove the elements from the stack trace that are in this class. This all belongs to the exception throwing
* and not relevant for the error itself.
*
* @param e the exception to remove the few top stack trace elements
* @return the exception with the modified stack trace
*/
private static BadSyntax castrated(final BadSyntax e) {
final var st = Arrays.stream(e.getStackTrace()).filter(s -> !s.getClassName().equals(BadSyntax.class.getName())).toArray(StackTraceElement[]::new);
e.setStackTrace(st);
return e;
}
}