package jnpf.bizcommon.audit.service.title;
|
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.List;
|
|
/** 一次操作的记录标题:主表一行 + 子表每条记录一行。 */
|
public final class AuditRecordTitle {
|
|
/** {@link #subScope()} 的取值:输入侧没看全——还有子表行(甚至整张子表)根本没读。 */
|
public static final String SCOPE_SCAN_TRUNCATED = "scanTruncated";
|
|
/** {@link #subScope()} 的取值:扫描完整,但产出的标题条数撞了上限被截。 */
|
public static final String SCOPE_ROWS_TRUNCATED = "rowsTruncated";
|
|
public static final AuditRecordTitle EMPTY =
|
new AuditRecordTitle(null, Collections.<String>emptyList(), null, false, null);
|
|
private final String mainTitle;
|
private final List<String> subTitles;
|
private final String subTable;
|
private final boolean subDataUnavailable;
|
private final String subScope;
|
|
public AuditRecordTitle(String mainTitle, List<String> subTitles,
|
String subTable, boolean subDataUnavailable, String subScope) {
|
this.mainTitle = mainTitle == null || mainTitle.trim().isEmpty() ? null : mainTitle;
|
this.subTitles = subTitles == null || subTitles.isEmpty()
|
? Collections.<String>emptyList()
|
: Collections.unmodifiableList(new ArrayList<String>(subTitles));
|
this.subTable = subTable;
|
this.subDataUnavailable = subDataUnavailable;
|
this.subScope = subScope;
|
}
|
|
/** 主表标题行;一个字段都没勾、或勾了但全为空时返回 null(调用方回落 bizCode)。 */
|
public String mainTitle() {
|
return mainTitle;
|
}
|
|
/** 子表标题行,一条子记录一行。**未必是全量**,看 {@link #subScope()}。 */
|
public List<String> subTitles() {
|
return subTitles;
|
}
|
|
/**
|
* 子表标题的完整性。{@code null} = 完整;否则是 {@link #SCOPE_SCAN_TRUNCATED}
|
* 或 {@link #SCOPE_ROWS_TRUNCATED}。
|
*
|
* <p><b>为什么必须有这个</b>(2026-08-05 Codex 复审 Low):两道上限一直是**悄悄**截的,
|
* 读的人看到 200 条会以为那就是全部。资源上界下推之后又多了一种截法——额度耗尽时
|
* 后面整张子表都不碰,连「事件里没带这批数据」({@link #subDataUnavailable()})都测不出来,
|
* 于是「判不了」被伪装成了「没发生」(L075,本批反复在防的同一个形状)。
|
*
|
* <p><b>为什么不是「把没看的补看完」</b>:那要为每张剩余子表整份反序列化一遍,
|
* 正是资源上界刚拆掉的那笔开销。诚实地说「我没看全」比花大价钱看全更划算——
|
* 真要全量,读的人可以去查那条记录本身。
|
*
|
* <p>{@code scanTruncated} 优先于 {@code rowsTruncated}:输入侧就没看全时,
|
* 产出侧截没截已经不是最重要的信息了。
|
*/
|
public String subScope() {
|
return subScope;
|
}
|
|
public String subTable() {
|
return subTable;
|
}
|
|
/** 表单配了子表标题字段,但事件里取不到子表数据——如实留痕,不能当成"没有子表"。 */
|
public boolean subDataUnavailable() {
|
return subDataUnavailable;
|
}
|
|
public boolean isEmpty() {
|
return mainTitle == null && subTitles.isEmpty() && !subDataUnavailable;
|
}
|
}
|