001 /*
002 // $Id: OlapException.java 247 2009-06-20 05:52:40Z jhyde $
003 // This software is subject to the terms of the Eclipse Public License v1.0
004 // Agreement, available at the following URL:
005 // http://www.eclipse.org/legal/epl-v10.html.
006 // Copyright (C) 2006-2009 Julian Hyde
007 // All Rights Reserved.
008 // You must accept the terms of that agreement to use this software.
009 */
010 package org.olap4j;
011
012 import java.sql.SQLException;
013
014 /**
015 * <p>An exception describing an error accessing an OLAP database.</p>
016 *
017 * <p>Since olap4j extends JDBC, it is natural that <code>OlapException</code>
018 * should extend JDBC's {@link SQLException}. The implementation by an olap4j
019 * driver of a JDBC method which is declared to throw a SQLException may, if the
020 * driver chooses, throw instead an OlapException.</p>
021 *
022 * <p>OlapException provides some additional information to help an OLAP client
023 * identify the location of the error. This information is
024 *
025 * @author jhyde
026 * @version $Id: OlapException.java 247 2009-06-20 05:52:40Z jhyde $
027 * @since Oct 23, 2006
028 */
029 public class OlapException extends SQLException {
030 private Region region;
031 private Object context;
032
033 /**
034 * Constructs a fully-specified <code>SQLException</code> object.
035 *
036 * @param reason a description of the exception
037 * @param sqlState an XOPEN or SQL 99 code identifying the exception
038 * @param vendorCode a database vendor-specific exception code
039 */
040 public OlapException(String reason, String sqlState, int vendorCode) {
041 super(reason, sqlState, vendorCode);
042 }
043
044 /**
045 * Constructs an <code>SQLException</code> object with the given reason and
046 * SQLState; the <code>vendorCode</code> field defaults to 0.
047 *
048 * @param reason a description of the exception
049 * @param sqlState an XOPEN or SQL 99 code identifying the exception
050 */
051 public OlapException(String reason, String sqlState) {
052 super(reason, sqlState);
053 }
054
055 /**
056 * Constructs an <code>SQLException</code> object with a reason;
057 * the <code>sqlState</code> field defaults to <code>null</code>, and
058 * the <code>vendorCode</code> field defaults to 0.
059 *
060 * @param reason a description of the exception
061 */
062 public OlapException(String reason) {
063 super(reason);
064 }
065
066 /**
067 * Constructs an <code>SQLException</code> object;
068 * the <code>reason</code> field defaults to null,
069 * the <code>sqlState</code> field defaults to <code>null</code>, and
070 * the <code>vendorCode</code> field defaults to 0.
071 */
072 public OlapException() {
073 super();
074 }
075
076 /**
077 * Constructs an <code>OlapException</code> object with a given
078 * <code>reason</code> and <code>cause</code>.
079 *
080 * @param reason the detail message (which is saved for later retrieval
081 * by the {@link #getMessage()} method).
082 * @param cause the cause (which is saved for later retrieval by the
083 * {@link #getCause()} method). (A <tt>null</tt> value is
084 * permitted, and indicates that the cause is nonexistent or
085 * unknown.)
086 */
087 public OlapException(String reason, Throwable cause) {
088 // Cannot call super(reason, cause) because
089 // SQLException(String, Throwable) only exists from JDK 1.6.
090 super(reason);
091 initCause(cause);
092 }
093
094 /**
095 * Sets the textual region where the exception occurred.
096 *
097 * @param region Textual region
098 */
099 public void setRegion(Region region) {
100 this.region = region;
101 }
102
103 /**
104 * Returns the textual region where the exception occurred, or null if no
105 * region can be identified.
106 *
107 * @return Region where the exception occurred
108 */
109 public Region getRegion() {
110 return region;
111 }
112
113 /**
114 * Sets the context where the exception occurred.
115 *
116 * @param context Context where the exception occurred
117 * @throws IllegalArgumentException If context is not a {@link Cell}
118 * or a {@link Position}
119 */
120 public void setContext(Object context) {
121 if (!(context instanceof Cell)
122 && !(context instanceof Position))
123 {
124 throw new IllegalArgumentException(
125 "expected Cell or Position");
126 }
127 this.context = context;
128 }
129
130 /**
131 * Returns the context where the exception occurred.
132 * Typically a {@link Cell} or a {@link Position}, or null.
133 *
134 * @return context where the exception occurred, or null
135 */
136 public Object getContext() {
137 return context;
138 }
139
140 /**
141 * Description of the position of a syntax or validation error in the source
142 * MDX string.
143 *
144 * <p>Row and column positions are 1-based and inclusive. For example,
145 * in</p>
146 *
147 * <blockquote>
148 * <pre>
149 * SELECT { [Measures].MEMBERS } ON COLUMNS,
150 * { } ON ROWS
151 * FROM [Sales]
152 * </pre>
153 * </blockquote>
154 *
155 * <p>the <code>SELECT</code> keyword occupies positions (1, 1) through
156 * (1, 6), and would have a <code>Region(startLine=1, startColumn=1,
157 * endColumn=1, endLine=6)</code>.</p>
158 */
159 public static final class Region {
160 public final int startLine;
161 public final int startColumn;
162 public final int endLine;
163 public final int endColumn;
164
165 protected Region(
166 int startLine,
167 int startColumn,
168 int endLine,
169 int endColumn)
170 {
171 this.startLine = startLine;
172 this.startColumn = startColumn;
173 this.endColumn = endLine;
174 this.endLine = endColumn;
175 }
176
177 public String toString() {
178 if (startLine == endColumn && startColumn == endLine) {
179 return "line " + startLine + ", column " + startColumn;
180 } else {
181 return "line " + startLine + ", column " + startColumn
182 + " through line " + endLine + ", column " + endColumn;
183 }
184 }
185 }
186 }
187
188 // End OlapException.java