package online.jpa.transaction;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.spi.CDI;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import javax.persistence.EntityManager;

/**
 * JdbcTransactionInterceptor
 *
 * @author Tadashi Nakayama
 */
@Interceptor
@Dependent
@JdbcTransactional
public final class JdbcTransactionInterceptor {

    /**
     * invoke entry
     *
     * @param ic InvocationContext
     * @return Object
     * @throws Exception Exception
     */
    @AroundInvoke
    public Object invoke(final InvocationContext ic) throws Exception {
        final var e = CDI.current().select(EntityManager.class);
        if (e.isUnsatisfied()) {
            return ic.proceed();
        }

        final var em = e.get();
        var active = false;
        try {
            if (!em.getTransaction().isActive()) {
                em.getTransaction().begin();
                active = true;
            }
            return ic.proceed();
        } catch (final Throwable t) {
            em.getTransaction().setRollbackOnly();
            throw t;
        } finally {
            if (active && em.getTransaction().isActive()) {
                if (em.getTransaction().getRollbackOnly()) {
                    em.getTransaction().rollback();
                } else {
                    em.getTransaction().commit();
                }
            }
        }
    }
}
