package com.hubspot.jinjava.interpret; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang3.exception.ExceptionUtils; import com.google.common.collect.ImmutableMap; import com.hubspot.jinjava.interpret.errorcategory.BasicTemplateErrorCategory; import com.hubspot.jinjava.interpret.errorcategory.TemplateErrorCategory; public class TemplateError { public enum ErrorType { FATAL, WARNING } public enum ErrorReason { SYNTAX_ERROR, UNKNOWN, BAD_URL, EXCEPTION, MISSING, DISABLED, OTHER } public enum ErrorItem { TEMPLATE, TOKEN, TAG, FUNCTION, PROPERTY, FILTER, EXPRESSION_TEST, OTHER } private final ErrorType severity; private final ErrorReason reason; private final ErrorItem item; private final String message; private final String fieldName; private final int lineno; private final TemplateErrorCategory category; private final Map<String, String> categoryErrors; private final Exception exception; public static TemplateError fromSyntaxError(InterpretException ex) { return new TemplateError(ErrorType.FATAL, ErrorReason.SYNTAX_ERROR, ErrorItem.OTHER, ExceptionUtils.getMessage(ex), null, ex.getLineNumber(), ex); } public static TemplateError fromException(TemplateSyntaxException ex) { return new TemplateError(ErrorType.FATAL, ErrorReason.SYNTAX_ERROR, ErrorItem.OTHER, ExceptionUtils.getMessage(ex), null, ex.getLineNumber(), ex); } public static TemplateError fromException(Exception ex) { int lineNumber = -1; if (ex instanceof InterpretException) { lineNumber = ((InterpretException) ex).getLineNumber(); } return new TemplateError(ErrorType.FATAL, ErrorReason.EXCEPTION, ErrorItem.OTHER, ExceptionUtils.getMessage(ex), null, lineNumber, ex, BasicTemplateErrorCategory.UNKNOWN, ImmutableMap.of()); } public static TemplateError fromException(Exception ex, int lineNumber) { return new TemplateError(ErrorType.FATAL, ErrorReason.EXCEPTION, ErrorItem.OTHER, ExceptionUtils.getMessage(ex), null, lineNumber, ex); } public static TemplateError fromUnknownProperty(Object base, String variable, int lineNumber) { return new TemplateError(ErrorType.WARNING, ErrorReason.UNKNOWN, ErrorItem.PROPERTY, String.format("Cannot resolve property '%s' in '%s'", variable, friendlyObjectToString(base)), variable, lineNumber, null, BasicTemplateErrorCategory.UNKNOWN_PROPERTY, ImmutableMap.of("property", variable, "lineNumber", String.valueOf(lineNumber))); } private static String friendlyObjectToString(Object o) { if (o == null) { return "null"; } String s = o.toString(); if (!GENERIC_TOSTRING_PATTERN.matcher(s).find()) { return s; } Class<?> c = o.getClass(); return c.getSimpleName(); } private static final Pattern GENERIC_TOSTRING_PATTERN = Pattern.compile("@[0-9a-z]{4,}$"); public TemplateError(ErrorType severity, ErrorReason reason, ErrorItem item, String message, String fieldName, int lineno, Exception exception) { this.severity = severity; this.reason = reason; this.item = item; this.message = message; this.fieldName = fieldName; this.lineno = lineno; this.exception = exception; this.category = BasicTemplateErrorCategory.UNKNOWN; this.categoryErrors = null; } public TemplateError(ErrorType severity, ErrorReason reason, ErrorItem item, String message, String fieldName, int lineno, Exception exception, TemplateErrorCategory category, Map<String, String> categoryErrors) { this.severity = severity; this.reason = reason; this.item = item; this.message = message; this.fieldName = fieldName; this.lineno = lineno; this.exception = exception; this.category = category; this.categoryErrors = categoryErrors; } public TemplateError(ErrorType severity, ErrorReason reason, String message, String fieldName, int lineno, Exception exception) { this.severity = severity; this.reason = reason; this.item = ErrorItem.OTHER; this.message = message; this.fieldName = fieldName; this.lineno = lineno; this.exception = exception; this.category = BasicTemplateErrorCategory.UNKNOWN; this.categoryErrors = null; } public ErrorType getSeverity() { return severity; } public ErrorReason getReason() { return reason; } public ErrorItem getItem() { return item; } public String getMessage() { return message; } public String getFieldName() { return fieldName; } public int getLineno() { return lineno; } public Exception getException() { return exception; } public TemplateErrorCategory getCategory() { return category; } public Map<String, String> getCategoryErrors() { return categoryErrors; } public TemplateError serializable() { return new TemplateError(severity, reason, item, message, fieldName, lineno, null, category, categoryErrors); } @Override public String toString() { return "TemplateError{" + "severity=" + severity + ", reason=" + reason + ", item=" + item + ", message='" + message + '\'' + ", fieldName='" + fieldName + '\'' + ", lineno=" + lineno + ", category=" + category + ", categoryErrors=" + categoryErrors + '}'; } }