package org.basex.query; import static org.basex.core.Text.*; import org.basex.core.BaseXException; import org.basex.io.IO; import org.basex.query.item.Empty; import org.basex.query.item.QNm; import org.basex.query.item.Value; import org.basex.query.util.Err; import org.basex.util.InputInfo; import org.basex.util.InputParser; import org.basex.util.TokenBuilder; import org.basex.util.list.StringList; /** * This class indicates exceptions during the parsing or evaluation of a query. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class QueryException extends Exception { /** Error QName. */ private final QNm name; /** Error value. */ private transient Value value = Empty.SEQ; /** Error reference. */ private Err err; /** File reference. */ private IO file; /** Code suggestions. */ private StringList suggest; /** Error line and column. */ private int[] lineCol; /** Marked error column. */ private int markedCol; /** * Default constructor. * @param ii input info * @param er error reference * @param ext error extension */ public QueryException(final InputInfo ii, final Err er, final Object... ext) { this(ii, er.qname(), er.desc, ext); err = er; } /** * Constructor, specifying the error code and message as string. * @param ii input info * @param errc error code * @param msg error message * @param ext error extension */ public QueryException(final InputInfo ii, final QNm errc, final String msg, final Object... ext) { super(BaseXException.message(msg, ext)); name = errc; if(ii != null) info(ii); } /** * Returns the error column. * @return error column */ public int col() { return lineCol == null ? 0 : lineCol[1]; } /** * Returns the marked error column. * @return marked error column */ public int markedCol() { return markedCol; } /** * Returns the error line. * @return error line */ public int line() { return lineCol == null ? 0 : lineCol[0]; } /** * Returns the file. * @return error line */ public IO file() { return file; } /** * Returns suggestions for code suggestions. * @return suggestions */ public StringList suggest() { return suggest == null ? new StringList() : suggest; } /** * Sets code suggestions. * @param qp query parser * @param sug code suggestions * @return self reference */ public QueryException suggest(final InputParser qp, final StringList sug) { suggest = sug; pos(qp); return this; } /** * Sets input info. * @param ii input info * @return self reference */ public QueryException info(final InputInfo ii) { file = ii.file; lineCol = ii.lineCol(); return this; } /** * Sets the error value. * @param v error value * @return self reference */ public QueryException value(final Value v) { value = v; return this; } /** * Finds line and column for the specified query parser. * @param parser parser */ void pos(final InputParser parser) { markedCol = parser.qm; // check if information has already been added if(lineCol != null) return; file = parser.file; lineCol = InputInfo.lineCol(parser.query, Math.min(parser.qm, parser.ql)); } /** * Returns the error code. * @return error code */ public QNm qname() { return name; } /** * Returns the error code. * @return error code */ public Err err() { return err; } /** * Returns the error value. * @return error value */ public Value value() { return value; } @Override public String getLocalizedMessage() { return super.getMessage(); } @Override public String getMessage() { final TokenBuilder tb = new TokenBuilder(); if(lineCol != null) { tb.add(STOPPED_AT).add(' ').addExt(LINE_X, lineCol[0]); if(lineCol[1] != 0) tb.add(QueryText.SEP).addExt(COLUMN_X, lineCol[1]); if(file != null) tb.add(' ').addExt(IN_FILE_X, file); tb.add(COL).add(NL); } final byte[] code = name.local(); if(code.length != 0) tb.add('[').add(code).add("] "); return tb.add(getLocalizedMessage()).toString(); } }