All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.torodb.backend.AbstractErrorHandler Maven / Gradle / Ivy

There is a newer version: 0.50.3
Show newest version
/*
 * ToroDB
 * Copyright © 2014 8Kdata Technology (www.8kdata.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see .
 */

package com.torodb.backend;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.torodb.backend.exceptions.BackendException;
import com.torodb.core.exceptions.ToroRuntimeException;
import com.torodb.core.exceptions.user.UserException;
import com.torodb.core.transaction.RollbackException;
import org.jooq.exception.DataAccessException;

import java.sql.SQLException;
import java.util.Optional;
import java.util.function.Function;

import javax.inject.Singleton;

/**
 *
 */
@Singleton
public abstract class AbstractErrorHandler implements ErrorHandler {

  private final ImmutableList rollbackRules;
  private final ImmutableList userRules;

  protected AbstractErrorHandler(Rule... rules) {
    ImmutableList.Builder rollbackRulesBuilder =
        ImmutableList.builder();
    ImmutableList.Builder userRulesBuilder =
        ImmutableList.builder();

    for (Rule rule : rules) {
      if (rule instanceof RollbackRule) {
        rollbackRulesBuilder.add((RollbackRule) rule);
      } else if (rule instanceof UserRule) {
        userRulesBuilder.add((UserRule) rule);
      }
    }

    this.rollbackRules = rollbackRulesBuilder.build();
    this.userRules = userRulesBuilder.build();
  }

  @Override
  public ToroRuntimeException handleException(Context context, SQLException sqlException) throws
      RollbackException {
    try {
      return handleUserException(context, sqlException);
    } catch (UserException userException) {
      return new BackendException(context, sqlException);
    }
  }

  @Override
  public ToroRuntimeException handleException(Context context,
      DataAccessException dataAccessException) throws RollbackException {
    try {
      return handleUserException(context, dataAccessException);
    } catch (UserException userException) {
      return new BackendException(context, dataAccessException);
    }
  }

  @Override
  public ToroRuntimeException handleUserException(Context context, SQLException sqlException) throws
      UserException, RollbackException {
    if (applyToUserRule(context, sqlException.getSQLState())) {
      throw createUserException(context, sqlException.getSQLState(), new BackendException(context,
          sqlException));
    }

    if (applyToRollbackRule(context, sqlException.getSQLState())) {
      throw new RollbackException(sqlException);
    }

    return new BackendException(context, sqlException);
  }

  @Override
  public ToroRuntimeException handleUserException(Context context,
      DataAccessException dataAccessException) throws UserException, RollbackException {
    if (applyToUserRule(context, dataAccessException.sqlState())) {
      throw createUserException(context, dataAccessException.sqlState(), new BackendException(
          context, dataAccessException));
    }

    if (applyToRollbackRule(context, dataAccessException.sqlState())) {
      throw new RollbackException(dataAccessException);
    }

    return new BackendException(context, dataAccessException);
  }

  private boolean applyToRollbackRule(Context context, String sqlState) {
    return rollbackRules.stream()
        .anyMatch(r ->
            r.getSqlCode().equals(sqlState) && (r.getContexts().isEmpty() || r.getContexts()
            .contains(context)));
  }

  private boolean applyToUserRule(Context context, String sqlState) {
    return userRules.stream()
        .anyMatch(r ->
            r.getSqlCode().equals(sqlState) && (r.getContexts().isEmpty() || r.getContexts()
            .contains(context)));
  }

  private UserException createUserException(Context context, String sqlState,
      BackendException backendException) {
    Optional userRule = userRules.stream()
        .filter(r ->
            r.getSqlCode().equals(sqlState) && (r.getContexts().isEmpty() || r.getContexts()
            .contains(context)))
        .findFirst();
    if (userRule.isPresent()) {
      return userRule.get().translate(backendException);
    }

    throw new IllegalArgumentException("User exception not found for context " + context
        + " and sqlState " + sqlState);
  }

  protected static Rule rollbackRule(String sqlCode, Context... contexts) {
    return new RollbackRule(sqlCode, contexts);
  }

  protected static Rule userRule(
      String sqlCode, Function translateFunction,
      Context... contexts) {
    return new UserRule(sqlCode, contexts, translateFunction);
  }

  protected abstract static class Rule {

    private final String sqlCode;
    private final ImmutableSet contexts;

    private Rule(String code, Context[] contexts) {
      this.sqlCode = code;
      this.contexts = ImmutableSet.copyOf(contexts);
    }

    public String getSqlCode() {
      return sqlCode;
    }

    public ImmutableSet getContexts() {
      return contexts;
    }
  }

  protected static class RollbackRule extends Rule {

    private RollbackRule(String code, Context[] contexts) {
      super(code, contexts);
    }
  }

  protected static class UserRule extends Rule {

    private final Function translateFunction;

    private UserRule(String code, Context[] contexts,
        Function translateFunction) {
      super(code, contexts);

      this.translateFunction = translateFunction;
    }

    public UserException translate(BackendException backendException) {
      return translateFunction.apply(backendException);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy