/* * Copyright 2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.xd.dirt.stream.dsl; import java.util.List; /** * An extension of StreamDefinitionException that remembers the point up to which parsing went OK (signaled by a '*' in * the dumped message). * * @author Eric Bottard */ @SuppressWarnings("serial") public class CheckpointedStreamDefinitionException extends StreamDefinitionException { private int checkpointPointer = -1; private List<Token> tokens; private int tokenPointer; /** * Construct a new exception * @param expressionString the raw, untokenized text that was being parsed * @param textPosition the text offset where the error occurs * @param checkpointPointer the token-index of the last known good token * @param tokenPointer the token-index of token where the error occured * @param tokens the list of tokens that make up expressionString * @param message the error message * @param inserts variables that may be inserted in the error message */ public CheckpointedStreamDefinitionException(String expressionString, int textPosition, int tokenPointer, int checkpointPointer, List<Token> tokens, XDDSLMessages message, Object... inserts) { super(expressionString, textPosition, message, inserts); this.tokenPointer = tokenPointer; this.checkpointPointer = checkpointPointer; this.tokens = tokens; } /** * @return a formatted message with inserts applied. */ @Override public String getMessage() { StringBuilder s = new StringBuilder(); if (message != null) { s.append(message.formatMessage(position, inserts)); } else { s.append(super.getMessage()); } if (expressionString != null && expressionString.length() > 0) { s.append("\n").append(expressionString).append("\n"); } int offset = position; if (checkpointPointer > 0 && offset >= 0) { int checkpointPosition = getCheckpointPosition(); offset -= checkpointPosition; for (int i = 0; i < checkpointPosition; i++) { s.append(' '); } s.append("*"); offset--; // account for the '*' } if (offset >= 0) { for (int i = 0; i < offset; i++) { s.append(' '); } s.append("^\n"); } return s.toString(); } public int getCheckpointPosition() { return checkpointPointer == 0 ? 0 : tokens.get(checkpointPointer - 1).endpos; } /** * Return the parsed expression until the last known, well formed position. Attempting to re-parse that expression * is guaranteed to not fail. */ public String getExpressionStringUntilCheckpoint() { return expressionString.substring(0, getCheckpointPosition()); } public int getCheckpointPointer() { return checkpointPointer; } public List<Token> getTokens() { return tokens; } public int getTokenPointer() { return tokenPointer; } }