| 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 |
}
|