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