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

Java tutorial

Introduction

Here is the source code for org.nextframework.persistence.exception.PostgreSQLErrorCodeSQLExceptionTranslator.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.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 PostgreSQLErrorCodeSQLExceptionTranslator extends SQLErrorCodeSQLExceptionTranslator {

    static String errorRegexInglesNull = "ERROR: null value in column \"(.*)\" violates not-null constraint";
    static Pattern patternInglesNull = Pattern.compile(errorRegexInglesNull);
    static String errorRegexNull = "ERRO: valor nulo na coluna \"(.*)\" viola a restrio no-nula";
    static Pattern patternNull = Pattern.compile(errorRegexNull);

    static String errorRegex = "ERRO: atualizao ou excluso em \"(.*)\" viola restrio de chave estrangeira \"(.*)\" em \"(.*)\".*?";
    static String errorRegexIngles = "ERROR: update or delete on (?:table)? \"(.*)\" violates foreign key constraint \"(.*)\" on (?:table)? \"(.*)\".*?";
    //   static String errorRegex = "(.*) statement conflicted with COLUMN REFERENCE constraint '(.*?)'. The conflict occurred in database '(?:.*?)', table '(.*?)', column '(.*?)'.";
    static Pattern pattern = Pattern.compile(errorRegex);
    static Pattern patternIngles = Pattern.compile(errorRegexIngles);

    static final Log log = LogFactory.getLog(PostgreSQLErrorCodeSQLExceptionTranslator.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();
    }

    public static class ApplicationDatabaseException extends DataAccessException {

        private static final long serialVersionUID = 1L;

        public ApplicationDatabaseException(String msg) {
            super(msg);
        }

    }

    @Override
    protected DataAccessException customTranslate(String task, String sql, SQLException sqlEx) {
        //TODO ARRUMAR ESSA ALGORITMO (FAZER HIGH COHESION.. LOW COUPLING)
        //System.out.println(task+" - "+sql);
        if (sqlEx.getNextException() != null) {
            sqlEx = sqlEx.getNextException();//tentar buscar a excecao mais especifica
        }
        String errorMessage = sqlEx.getMessage();
        Matcher matcher = pattern.matcher(errorMessage);
        Matcher matcherIngles = patternIngles.matcher(errorMessage);
        Matcher matcherNullIngles = patternInglesNull.matcher(errorMessage);
        Matcher matcherNull = patternNull.matcher(errorMessage);
        System.out.println(">>> " + errorMessage);
        if (!matcher.find()) {
            matcher = matcherIngles;
        } else {
            matcher.reset();
        }
        if (matcher.find()) {
            //exceo de FK
            //String fk_name = matcher.group(2);
            String fk_table_name = matcher.group(3).toUpperCase();
            String pk_table_name = matcher.group(1).toUpperCase();
            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;
            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.";
            }
            return new ForeignKeyException(mensagem);
        } else if (matcherNullIngles.find()) {
            return new ApplicationDatabaseException(errorMessage);
        } else if (matcherNull.find()) {
            return new ApplicationDatabaseException(errorMessage);
        } else {
            int indexOf = errorMessage.indexOf("APP");
            if (indexOf > 0) {
                errorMessage = errorMessage.substring(indexOf + 3);
                return new ApplicationDatabaseException(errorMessage);
            }
        }
        return null;
    }

    public static void main(String[] args) {
        String msg = "ERROR: update or delete on \"campus\" violates foreign key constraint \"fk_curso_campus\" on \"curso\"\n  Detalhe: Key (cdcampus)=(1) is still referenced from table \"curso\".";
        Matcher matcher = patternIngles.matcher(msg);
        if (matcher.find()) {
            //exceo de FK
            String fk_name = matcher.group(2);
            System.out.println(fk_name);
            String fk_table_name = matcher.group(3).toUpperCase();
            System.out.println(fk_table_name);
            String pk_table_name = matcher.group(1).toUpperCase();
            System.out.println(pk_table_name);
        } else {
            System.out.println("false");
        }
    }
}