001 /*
002 // $Id: OlapException.java 125 2008-11-02 07:43:12Z jhyde $
003 // This software is subject to the terms of the Common Public License
004 // Agreement, available at the following URL:
005 // http://www.opensource.org/licenses/cpl.html.
006 // Copyright (C) 2006-2008 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 125 2008-11-02 07:43:12Z 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 throw new IllegalArgumentException(
124 "expected Cell or Position");
125 }
126 this.context = context;
127 }
128
129 /**
130 * Returns the context where the exception occurred.
131 * Typically a {@link Cell} or a {@link Position}, or null.
132 *
133 * @return context where the exception occurred, or null
134 */
135 public Object getContext() {
136 return context;
137 }
138
139 /**
140 * Description of the position of a syntax or validation error in the source
141 * MDX string.
142 *
143 * <p>Row and column positions are 1-based and inclusive. For example,
144 * in</p>
145 *
146 * <blockquote>
147 * <pre>
148 * SELECT { [Measures].MEMBERS } ON COLUMNS,
149 * { } ON ROWS
150 * FROM [Sales]
151 * </pre>
152 * </blockquote>
153 *
154 * <p>the <code>SELECT</code> keyword occupies positions (1, 1) through
155 * (1, 6), and would have a <code>Region(startLine=1, startColumn=1,
156 * endColumn=1, endLine=6)</code>.</p>
157 */
158 public static final class Region {
159 public final int startLine;
160 public final int startColumn;
161 public final int endLine;
162 public final int endColumn;
163
164 protected Region(
165 int startLine,
166 int startColumn,
167 int endLine,
168 int endColumn)
169 {
170 this.startLine = startLine;
171 this.startColumn = startColumn;
172 this.endColumn = endLine;
173 this.endLine = endColumn;
174 }
175
176 public String toString() {
177 if (startLine == endColumn && startColumn == endLine) {
178 return "line " + startLine + ", column " + startColumn;
179 } else {
180 return "line " + startLine + ", column " + startColumn +
181 " through line " + endLine + ", column " + endColumn;
182 }
183 }
184 }
185 }
186
187 // End OlapException.java