TransactionInterceptors.java

/*
 * SPDX-FileCopyrightText: 2026 kaumei.io
 * SPDX-License-Identifier: Apache-2.0
 */
package io.kaumei.jdbc.tx.internal;

import io.kaumei.jdbc.tx.KaumeiTxDefinition;
import io.kaumei.jdbc.tx.KaumeiTxManager;
import org.jspecify.annotations.Nullable;

import static java.util.Objects.requireNonNull;

/**
 * Transaction interceptors for {@link InterfaceWrapper}.
 * They are primarily intended for tests that need a small transactional wrapper around an
 * existing Java object without changing that object's implemented interfaces.
 *
 * <p>For example:
 * <pre>{@code
 * AccountApi account = InterfaceWrapper.wrap(
 *         AccountApi.class,
 *         new ExistingAccountService(),
 *         TransactionInterceptors.required(txManager, KaumeiTxDefinition.DEFAULT));
 *
 * account.updateBalance();
 * }</pre>
 *
 * <p>The abstract API method is executed inside the configured transaction and forwarded to the
 * matching public target method.
 */
public final class TransactionInterceptors {

    private TransactionInterceptors() {
    }

    public static InterfaceWrapper.Interceptor required(KaumeiTxManager txManager, KaumeiTxDefinition definition) {
        requireNonNull(txManager, "txManager");
        requireNonNull(definition, "definition");
        return invocation -> txManager.requiredOpt(definition, context -> proceed(invocation));
    }

    @SuppressWarnings("unchecked")
    private static <E extends Throwable> @Nullable Object proceed(InterfaceWrapper.Invocation invocation) throws E {
        try {
            return invocation.proceed();
        } catch (Throwable e) {
            throw (E) e;
        }
    }
}