org.nextframework.persistence.exception.SQLServerSQLErrorCodeSQLExceptionTranslator.java Source code

Java tutorial

Introduction

Here is the source code for org.nextframework.persistence.exception.SQLServerSQLErrorCodeSQLExceptionTranslator.java

Source

/*
 * Next Framework http://www.nextframework.org
 * Copyright (C) 2009 the original author or authors.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * You may obtain a copy of the license at
 * 
 *     http://www.gnu.org/copyleft/lesser.html
 * 
 */
package org.nextframework.persistence.exception;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nextframework.bean.BeanDescriptorFactory;
import org.nextframework.classmanager.ClassManagerFactory;
import org.nextframework.util.ReflectionCache;
import org.nextframework.util.ReflectionCacheFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;

public class SQLServerSQLErrorCodeSQLExceptionTranslator extends SQLErrorCodeSQLExceptionTranslator {

    static String errorRegex = "(.*) statement conflicted with COLUMN (?:SAME TABLE )?REFERENCE constraint '(.*?)'. The conflict occurred in database '(?:.*?)', table '(.*?)', column '(.*?)'.";
    static String errorRegex2 = "The (.*) statement conflicted with the REFERENCE constraint \"(.*)\". The conflict occurred in database \"(?:.*)\", table \"(.*)\", column '(.*)'.";
    static Pattern pattern = Pattern.compile(errorRegex);
    static Pattern pattern2 = Pattern.compile(errorRegex2);

    static final Log log = LogFactory.getLog(SQLServerSQLErrorCodeSQLExceptionTranslator.class);

    private DataSource dataSource;

    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public void setDataSource(DataSource dataSource) {
        super.setDataSource(dataSource);
        this.dataSource = dataSource;
    }

    private String getTableName(Class<?> entityClass) {
        ReflectionCache reflectionCache = ReflectionCacheFactory.getReflectionCache();
        Table table = reflectionCache.getAnnotation(entityClass, Table.class);
        if (table != null) {
            return table.name().toUpperCase();
        }
        return entityClass.getSimpleName().toUpperCase();
    }

    @Override
    protected DataAccessException customTranslate(String task, String sql, SQLException sqlEx) {
        //TODO ARRUMAR ESSA DESORDEM (FAZER HIGH COHESION.. LOW COUPLING)
        //System.out.println(task+" - "+sql);
        //      boolean matcher2 = false;
        if (sqlEx.getErrorCode() == 547) {
            //exceo de FK
            Matcher matcher = pattern.matcher(sqlEx.getMessage());
            if (!matcher.find()) {
                //tentar segundo pattern
                matcher = pattern2.matcher(sqlEx.getMessage());
                if (!matcher.find()) {
                    return null;
                } else {
                    //               matcher2 = true;
                }
            }
            String fk_name = matcher.group(2);
            String fk_table_name = matcher.group(3).toUpperCase();
            if (fk_table_name.lastIndexOf('.') > 0) {
                fk_table_name = fk_table_name.substring(fk_table_name.lastIndexOf('.') + 1);
            }
            String pk_table_name = null;
            String fkTableDisplayName = null;
            String pkTableDisplayName = null;
            try {
                DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
                ResultSet importedKeys = metaData.getImportedKeys(null, null, fk_table_name);

                while (importedKeys.next()) {
                    if (importedKeys.getString("FK_NAME").equals(fk_name)) {
                        pk_table_name = importedKeys.getString("PKTABLE_NAME");
                        if (pk_table_name != null) {
                            pk_table_name = pk_table_name.toUpperCase();
                        }
                    }
                }
            } catch (SQLException e) {
                //se nao conseguir o metadata .. vazar
                log.warn("No foi possvel conseguir o metadata do banco para ler informacoes de FK.");
                return null;
            }

            Class<?>[] entities = ClassManagerFactory.getClassManager().getClassesWithAnnotation(Entity.class);
            pkTableDisplayName = pk_table_name;
            fkTableDisplayName = fk_table_name;
            for (Class<?> entityClass : entities) {
                String tableName = getTableName(entityClass);
                if (tableName.equals(pk_table_name)) {
                    pkTableDisplayName = BeanDescriptorFactory.forClass(entityClass).getDisplayName();
                }
                if (tableName.equals(fk_table_name)) {
                    fkTableDisplayName = BeanDescriptorFactory.forClass(entityClass).getDisplayName();
                }
            }

            String mensagem = null;
            sql = matcher.group(1);
            if (sql.toLowerCase().trim().startsWith("delete")) {
                mensagem = "No foi possvel remover " + pkTableDisplayName
                        + ". Existe(m) registro(s) vinculado(s) em " + fkTableDisplayName + ".";
            } else if (sql.toLowerCase().trim().startsWith("update")) {
                mensagem = "No foi possvel atualizar " + fkTableDisplayName + ". A referncia para "
                        + pkTableDisplayName + "  invlida.";
            } else if (sql.toLowerCase().trim().startsWith("insert")) {
                mensagem = "No foi possvel inserir " + fkTableDisplayName + ". A referncia para "
                        + pkTableDisplayName + "  invlida.";
            } else {
                mensagem = "No foi possvel efetuar operao em " + pkTableDisplayName
                        + ". Existe(m) registro(s) vinculado(s) em " + fkTableDisplayName + ".";
            }
            return new ForeignKeyException(mensagem, new ForeignKeyException(task));
        }

        return null;
    }
}