aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/iciql/IciqlException.java
blob: 7d6f152fd0d62a12624e1dde2d404ca908126a24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2011 James Moger.
 *
 * 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 com.iciql;

import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.regex.Pattern;

/**
 * Iciql wraps all exceptions with this class.
 */
public class IciqlException extends RuntimeException {

	public static final int CODE_UNMAPPED_FIELD = 1;
	public static final int CODE_DUPLICATE_KEY = 2;
	public static final int CODE_TABLE_NOT_FOUND = 3;
	public static final int CODE_TABLE_ALREADY_EXISTS = 4;
	public static final int CODE_INDEX_ALREADY_EXISTS = 5;

	private static final String TOKEN_UNMAPPED_FIELD = "\\? (=|\\>|\\<|\\<\\>|!=|\\>=|\\<=|LIKE|BETWEEN) \\?";

	private static final long serialVersionUID = 1L;

	private String sql;

	private int iciqlCode;

	public IciqlException(Throwable t) {
		super(t.getMessage(), t);
		configureCode(t);
	}

	public IciqlException(String message, Object... parameters) {
		super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message);
	}

	public IciqlException(Throwable t, String message, Object... parameters) {
		super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message, t);
		configureCode(t);
	}

	public static void checkUnmappedField(String sql) {
		if (Pattern.compile(IciqlException.TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {
			IciqlException e = new IciqlException("unmapped field in statement!");
			e.sql = sql;
			e.iciqlCode = CODE_UNMAPPED_FIELD;
			throw e;
		}
	}

	public static IciqlException fromSQL(String sql, Throwable t) {
		if (Pattern.compile(TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {
			IciqlException e = new IciqlException(t, "unmapped field in statement!");
			e.sql = sql;
			e.iciqlCode = CODE_UNMAPPED_FIELD;
			return e;
		} else {
			IciqlException e = new IciqlException(t, t.getMessage());
			e.sql = sql;
			return e;
		}
	}

	public void setSQL(String sql) {
		this.sql = sql;
	}

	public String getSQL() {
		return sql;
	}

	public int getIciqlCode() {
		return iciqlCode;
	}

	private void configureCode(Throwable t) {
		if (t == null) {
			return;
		}
		if (t instanceof SQLException) {
			// http://developer.mimer.com/documentation/html_92/Mimer_SQL_Mobile_DocSet/App_Return_Codes2.html
			SQLException s = (SQLException) t;
			String state = s.getSQLState();
			if ("23505".equals(state)) {
				iciqlCode = CODE_DUPLICATE_KEY;
			} else if ("42X05".equals(state)) {
				// Derby
				iciqlCode = CODE_TABLE_NOT_FOUND;
			} else if ("42S02".equals(state)) {
				// H2
				iciqlCode = CODE_TABLE_NOT_FOUND;
			} else if ("42501".equals(state)) {
				// HSQL
				iciqlCode = CODE_TABLE_NOT_FOUND;
			} else if ("X0Y32".equals(state)) {
				// Derby
				iciqlCode = CODE_TABLE_ALREADY_EXISTS;
			} else if ("42S11".equals(state)) {
				// H2
				iciqlCode = CODE_INDEX_ALREADY_EXISTS;
			} else if ("42504".equals(state)) {
				// HSQL
				iciqlCode = CODE_INDEX_ALREADY_EXISTS;
			}
		}
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(getClass().getName());
		String message = getLocalizedMessage();
		if (message != null) {
			sb.append(": ").append(message);
		}
		if (sql != null) {
			sb.append('\n').append(sql);
		}
		return sb.toString();
	}
}