package jnpf.flowable.service; import com.baomidou.dynamic.datasource.tx.TransactionContext; import jnpf.flowable.mapper.DmsLifecycleNativeFormMapper; import jnpf.onlinedev.VisualdevOnlineApi; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.transaction.support.TransactionSynchronizationManager; /** DMS lifecycle only; native controller still owns validation, persistence and audit. */ @Component public class DmsLifecycleNativeFormAdapter { private final DmsLifecycleNativeFormMapper mapper; private final ObjectProvider nativeForms; private final boolean enabled; public DmsLifecycleNativeFormAdapter(DmsLifecycleNativeFormMapper mapper, @Qualifier("visualdevForFlowController") ObjectProvider nativeForms, @Value("${dms.business-occupancy.enabled:false}") boolean enabled) { this.mapper = mapper; this.nativeForms = nativeForms; this.enabled = enabled; } /** Same selection for write AND immediate readback; never silently fall back on protected writes. */ public VisualdevOnlineApi select(String formId, VisualdevOnlineApi ordinary, boolean writing) { if (!enabled || formId == null || formId.isBlank()) return ordinary; NativeForm form = mapper.publishedLifecycleForm(formId); if (form == null) return ordinary; boolean dynamic = TransactionContext.getXID() != null; // Outside submission/approval transactions a normal detail read retains its existing route. if (!writing && !dynamic) return ordinary; if (!dynamic || TransactionSynchronizationManager.isActualTransactionActive()) throw new IllegalStateException("DMS 生命周期保存必须使用原生动态事务,不能混用事务管理器"); if (!Integer.valueOf(1).equals(form.getType()) || (form.getDbLinkId() != null && !form.getDbLinkId().isBlank() && !"0".equals(form.getDbLinkId()))) throw new IllegalStateException("DMS 生命周期事务适配仅支持默认数据源原生在线表单"); VisualdevOnlineApi local = nativeForms.getIfAvailable(); if (local == null) throw new IllegalStateException("DMS 生命周期事务适配需要平台聚合部署的原生表单服务"); return local; } public boolean protects(String formId) { return enabled && formId != null && mapper.publishedLifecycleForm(formId) != null; } /** Only DMS failures are tagged for the existing engine compensation branch. */ public T invoke(String formId, VisualdevOnlineApi ordinary, boolean writing, java.util.function.Function action) { if ((!writing && TransactionContext.getXID()==null) || !protects(formId)) return action.apply(ordinary); try { T result=action.apply(select(formId,ordinary,writing)); if(result==null) throw new IllegalStateException("DMS 原生表单调用未返回结果"); if(result instanceof jnpf.base.ActionResult response && response.getCode()!=200) throw new IllegalStateException(response.getMsg()); return result; } catch (RuntimeException failure) { throw new NativeFailure(failure); } } public static final class NativeFailure extends RuntimeException { public NativeFailure(Throwable cause) { super(cause.getMessage(),cause); } } public static class NativeForm { private String mainTable; private String formData; public String getMainTable() { return mainTable; } public void setMainTable(String value) { mainTable = value; } public String getFormData() { return formData; } public void setFormData(String value) { formData = value; } private Integer type; private String dbLinkId; public Integer getType() { return type; } public void setType(Integer value) { type = value; } public String getDbLinkId() { return dbLinkId; } public void setDbLinkId(String value) { dbLinkId = value; } } }