Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
36383 amit 1
package com.spice.profitmandi.dao.exception;
2
 
3
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
4
import org.springframework.dao.DataIntegrityViolationException;
5
 
6
import java.sql.DataTruncation;
7
import java.sql.SQLException;
8
import java.util.regex.Matcher;
9
import java.util.regex.Pattern;
10
 
11
public final class DbErrorTranslator {
12
 
13
	public static final String CODE_TRUNCATION = "DB_TRUNCATION";
14
	public static final String CODE_DUPLICATE = "DB_DUPLICATE";
15
	public static final String CODE_FK_VIOLATION = "DB_FK_VIOLATION";
16
	public static final String CODE_CONSTRAINT = "DB_CONSTRAINT";
17
 
18
	private static final Pattern TRUNCATION_COLUMN = Pattern.compile("Data too long for column '([^']+)'");
19
	private static final Pattern DUPLICATE_KEY = Pattern.compile("for key '(?:[^.]+\\.)?([^']+)'");
20
	private static final Pattern FK_COLUMN = Pattern.compile("FOREIGN KEY \\(`([^`]+)`\\)");
21
 
22
	private static final int MYSQL_DUPLICATE_KEY = 1062;
23
	private static final int MYSQL_FK_NO_REFERENCED = 1452;
24
	private static final int MYSQL_FK_STILL_REFERENCED = 1451;
25
 
26
	private static final int MAX_CAUSE_DEPTH = 20;
27
 
28
	private DbErrorTranslator() {
29
	}
30
 
31
	public static ProfitMandiBusinessException translate(DataIntegrityViolationException ex) {
32
		DataTruncation truncation = findInChain(ex, DataTruncation.class);
33
		if (truncation != null) {
34
			String column = extract(truncation.getMessage(), TRUNCATION_COLUMN);
35
			return new ProfitMandiBusinessException(prettifyCamelCase(column), null, CODE_TRUNCATION, ex);
36
		}
37
 
38
		SQLException sqlEx = findInChain(ex, SQLException.class);
39
		if (sqlEx != null) {
40
			int vendorCode = sqlEx.getErrorCode();
41
			String message = sqlEx.getMessage();
42
			if (vendorCode == MYSQL_DUPLICATE_KEY) {
43
				String key = extract(message, DUPLICATE_KEY);
44
				return new ProfitMandiBusinessException(prettifyCamelCase(key), null, CODE_DUPLICATE, ex);
45
			}
46
			if (vendorCode == MYSQL_FK_NO_REFERENCED || vendorCode == MYSQL_FK_STILL_REFERENCED) {
47
				String column = extract(message, FK_COLUMN);
48
				return new ProfitMandiBusinessException(prettifyCamelCase(column), null, CODE_FK_VIOLATION, ex);
49
			}
50
		}
51
 
52
		return new ProfitMandiBusinessException(null, null, CODE_CONSTRAINT, ex);
53
	}
54
 
55
	private static <T extends Throwable> T findInChain(Throwable root, Class<T> type) {
56
		Throwable cur = root;
57
		int depth = 0;
58
		while (cur != null && depth++ < MAX_CAUSE_DEPTH) {
59
			if (type.isInstance(cur)) {
60
				return type.cast(cur);
61
			}
62
			Throwable next = cur.getCause();
63
			if (next == cur) {
64
				break;
65
			}
66
			cur = next;
67
		}
68
		return null;
69
	}
70
 
71
	private static String extract(String message, Pattern pattern) {
72
		if (message == null) {
73
			return null;
74
		}
75
		Matcher m = pattern.matcher(message);
76
		return m.find() ? m.group(1) : null;
77
	}
78
 
79
	static String prettifyCamelCase(String raw) {
80
		if (raw == null || raw.isEmpty()) {
81
			return raw;
82
		}
83
		String withSpaces = raw.replace('_', ' ');
84
		StringBuilder spaced = new StringBuilder(withSpaces.length() + 4);
85
		for (int i = 0; i < withSpaces.length(); i++) {
86
			char c = withSpaces.charAt(i);
87
			if (i > 0 && Character.isUpperCase(c) && Character.isLowerCase(withSpaces.charAt(i - 1))) {
88
				spaced.append(' ');
89
			}
90
			spaced.append(c);
91
		}
92
		String[] parts = spaced.toString().split("\\s+");
93
		StringBuilder result = new StringBuilder();
94
		for (String part : parts) {
95
			if (part.isEmpty()) {
96
				continue;
97
			}
98
			if (result.length() > 0) {
99
				result.append(' ');
100
			}
101
			result.append(Character.toUpperCase(part.charAt(0)));
102
			if (part.length() > 1) {
103
				result.append(part.substring(1).toLowerCase());
104
			}
105
		}
106
		return result.toString();
107
	}
108
}