Blame | Last modification | View Log | RSS feed
package com.spice.profitmandi.dao.exception;import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;import org.springframework.dao.DataIntegrityViolationException;import java.sql.DataTruncation;import java.sql.SQLException;import java.util.regex.Matcher;import java.util.regex.Pattern;public final class DbErrorTranslator {public static final String CODE_TRUNCATION = "DB_TRUNCATION";public static final String CODE_DUPLICATE = "DB_DUPLICATE";public static final String CODE_FK_VIOLATION = "DB_FK_VIOLATION";public static final String CODE_CONSTRAINT = "DB_CONSTRAINT";private static final Pattern TRUNCATION_COLUMN = Pattern.compile("Data too long for column '([^']+)'");private static final Pattern DUPLICATE_KEY = Pattern.compile("for key '(?:[^.]+\\.)?([^']+)'");private static final Pattern FK_COLUMN = Pattern.compile("FOREIGN KEY \\(`([^`]+)`\\)");private static final int MYSQL_DUPLICATE_KEY = 1062;private static final int MYSQL_FK_NO_REFERENCED = 1452;private static final int MYSQL_FK_STILL_REFERENCED = 1451;private static final int MAX_CAUSE_DEPTH = 20;private DbErrorTranslator() {}public static ProfitMandiBusinessException translate(DataIntegrityViolationException ex) {DataTruncation truncation = findInChain(ex, DataTruncation.class);if (truncation != null) {String column = extract(truncation.getMessage(), TRUNCATION_COLUMN);return new ProfitMandiBusinessException(prettifyCamelCase(column), null, CODE_TRUNCATION, ex);}SQLException sqlEx = findInChain(ex, SQLException.class);if (sqlEx != null) {int vendorCode = sqlEx.getErrorCode();String message = sqlEx.getMessage();if (vendorCode == MYSQL_DUPLICATE_KEY) {String key = extract(message, DUPLICATE_KEY);return new ProfitMandiBusinessException(prettifyCamelCase(key), null, CODE_DUPLICATE, ex);}if (vendorCode == MYSQL_FK_NO_REFERENCED || vendorCode == MYSQL_FK_STILL_REFERENCED) {String column = extract(message, FK_COLUMN);return new ProfitMandiBusinessException(prettifyCamelCase(column), null, CODE_FK_VIOLATION, ex);}}return new ProfitMandiBusinessException(null, null, CODE_CONSTRAINT, ex);}private static <T extends Throwable> T findInChain(Throwable root, Class<T> type) {Throwable cur = root;int depth = 0;while (cur != null && depth++ < MAX_CAUSE_DEPTH) {if (type.isInstance(cur)) {return type.cast(cur);}Throwable next = cur.getCause();if (next == cur) {break;}cur = next;}return null;}private static String extract(String message, Pattern pattern) {if (message == null) {return null;}Matcher m = pattern.matcher(message);return m.find() ? m.group(1) : null;}static String prettifyCamelCase(String raw) {if (raw == null || raw.isEmpty()) {return raw;}String withSpaces = raw.replace('_', ' ');StringBuilder spaced = new StringBuilder(withSpaces.length() + 4);for (int i = 0; i < withSpaces.length(); i++) {char c = withSpaces.charAt(i);if (i > 0 && Character.isUpperCase(c) && Character.isLowerCase(withSpaces.charAt(i - 1))) {spaced.append(' ');}spaced.append(c);}String[] parts = spaced.toString().split("\\s+");StringBuilder result = new StringBuilder();for (String part : parts) {if (part.isEmpty()) {continue;}if (result.length() > 0) {result.append(' ');}result.append(Character.toUpperCase(part.charAt(0)));if (part.length() > 1) {result.append(part.substring(1).toLowerCase());}}return result.toString();}}