package ch.vorburger.el.engine; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * Error occurring in some expression related stuff. * * @author Michael Vorburger */ public abstract class ExpressionException extends Exception { private static final long serialVersionUID = -4155948282895039148L; private String expressionText; private final List<ExpressionError> errors; protected ExpressionException(String message) { super(message); this.errors = new ArrayList<ExpressionError>(1); errors.add(new ExpressionError(message, 0, 0, -1)); } /** * @param message * @param cause */ protected ExpressionException(final String message, final String expressionText, final Throwable cause) { super(message, cause); this.expressionText = expressionText; this.errors = new LinkedList<ExpressionError>(); } protected ExpressionException(final String message, final String expressionText) { super(message); this.expressionText = expressionText; this.errors = new LinkedList<ExpressionError>(); } public ExpressionException(final String message, final String expressionText, final int line, final int offset, final int length) { this(expressionText, new ExpressionError(message, line, offset, length)); } public ExpressionException(final Throwable cause, final String message, final String expressionText, final int line, final int offset, final int length) { this(cause, expressionText, new ExpressionError(message, line, offset, length)); } private ExpressionException(final Throwable cause, final String expressionText, final ExpressionError error) { super(error.getMessage(), cause); // ? this.expressionText = expressionText; this.errors = new ArrayList<ExpressionError>(1); errors.add(error); } /** * Creates a ExpressionException with one Error. * @param errors */ private ExpressionException(final String expressionText, final ExpressionError error) { super(error.getMessage()); // ? this.expressionText = expressionText; this.errors = new ArrayList<ExpressionError>(1); errors.add(error); } public ExpressionException(String message, Throwable cause) { super(message, cause); this.errors = new ArrayList<ExpressionError>(0); } /** * All Errors that lead to this Exception. * @return List of Error. Size >= 1, there is at last one ExpressionError. */ public List<ExpressionError> getErrors() { return errors; } public void setExpressionText(final String expressionText) { this.expressionText = expressionText; } /** * Returns a concatenation of all errors in contained ExpressionError instances. * Separated by newline, except for last error; no \n if only one error. * * @return The Message. * * @see ExpressionError#getMessage() */ @Override public String getMessage() { StringBuilder sb = new StringBuilder(); sb.append(super.getMessage()); if(expressionText!=null) { sb.append('\n'); int l = 1; int c = 0; for (int x = 0; x < expressionText.length(); x++) { if (hasMatchingError(l, c)) { sb.append(" ___ "); } sb.append(expressionText.charAt(x)); if (expressionText.charAt(x) == '\n') { ++l; c = 0; } else { ++c; } } } int i = 1; for (ExpressionError e : getErrors()) { if (sb.length() > 0) { sb.append('\n'); } sb.append(" "); if (getErrors().size() > 1) { sb.append(i++); sb.append(". "); } sb.append(e.getMessage()); if (e.getException() != null) { sb.append("\n "); final Writer stackTrace = new StringWriter(); final PrintWriter printWriter = new PrintWriter(stackTrace); e.getException().printStackTrace(printWriter); sb.append(stackTrace.toString()); } } return sb.toString(); } private boolean hasMatchingError(int l, int c) { for (ExpressionError e : getErrors()) { if (e.getLineNumber() == l && e.getColumnNumber() == c) { return true; } } return false; } }