Class AdmissionScope
它解决什么
需要在决策之前排除掉「不服务我这个区 / 不具备这个资格」的节点时,用它把条件带进
BeaconScheduling.acquireCandidate(String, String, AdmissionScope)——决策在生成候选的那一刻
就按本作用域收窄,「先选中、再被调用方拒掉」这条路径因此不必再走一遍。
语义(四条,钉死)
- 备选之间是 OR:
alternatives()里任一个备选被满足,该节点就算满足本作用域。 它存在的理由是「不限制 ∨ 明确受理某个取值」这类条件——调用方的真值表里 "没有收窄服务范围"与"收窄到正好包含这个取值"是并列的两种受理形态, 用单一 AND 表达不了,而不该让本仓去解释某个键的值结构(如逗号分列的清单)。 - 备选之内是 AND:一个备选里的键值对全部满足,该备选才成立。
- 精确相等:值按字符串逐字符相等比较,不做 trim、大小写折叠或任何归一化—— 归一化只在写入声明的那一方做一次(谁写标签谁把值写规范), 两边都做二次归一化会让「声明里写的是什么」与「判定用的值是什么」出现两个版本。
- 不解释 key 与值结构:本类只承载「哪些键值对是必须的、它们怎么并列」,不定义
任何 key 的业务含义,也不解释任何值的内部结构(与 FR-243 / ADR-0086 §5 同口径)。
命名空间与取值约定由调用方自持,例如接入方的
com.example.*。
与「没有标签」的关系
作用域非空、而某个节点没有声明(或声明里没有该键)时,该节点不满足本作用域 (除非另有备选成立)。这是刻意的:把「读不到声明」读成「满足」会让准入静默失效,方向不对称, 故取严格一侧。反过来,空作用域不要求任何节点有标签——只声明了容量的老节点照样进候选集合。
"空"只有一种形态:empty()、of(null)、
of(空 map)、anyOf(空列表)、含空备选的 OR、以及 anyOf(empty(), ...)
都在入口规约到同一个形态——无约束力、不排除任何候选,isEmpty() 为 true
且与 empty() 内容相等(不变式见 isEmpty() 的 javadoc)。
因此不存在"非空却恒真"的中间态,调用方读 isEmpty() 与读判定结果永远一致。
值对象不可变:备选与其中的键值对在构造时防御性拷贝并包装为不可修改视图, 构造后外部改动不影响本对象。
-
Method Summary
Modifier and TypeMethodDescriptionboolean判定一组节点自声明标签是否满足本作用域(纯逻辑,无 I/O)。OR 备选:每个元素是一组必须全部满足的键值标签。static AdmissionScope多个备选(OR 语义):任一备选被满足即准入。static AdmissionScopeanyOf(AdmissionScope... scopes) 把若干作用域并列成一个 OR 作用域(便于把of(String, String)的产物拼起来)。static AdmissionScopeempty()空作用域:不按标签收窄(与不带作用域的那条重载等价)。boolean按alternatives()的内容相等比较。inthashCode()booleanisEmpty()本作用域是否不按标签收窄(true 时决策行为与不带作用域的那条重载逐位一致)。static AdmissionScope单个要求(最常用形态:接入方给「我这台必须服务我这个区」这类单条条件)——一个备选、一条键值。static AdmissionScope一组要求(一个备选,AND 语义)。toString()诊断用:只印备选个数与各备选的键,不展开值(值可能含运维侧的业务标识)。
-
Method Details
-
empty
空作用域:不按标签收窄(与不带作用域的那条重载等价)。它不是「没有候选」的意思,也不要求节点声明过任何标签。
-
of
单个要求(最常用形态:接入方给「我这台必须服务我这个区」这类单条条件)——一个备选、一条键值。- Parameters:
key- 标签键(由调用方命名,本仓不解释其语义);非空白value- 标签值;要求与节点声明的值精确相等;非 null
-
of
一组要求(一个备选,AND 语义)。- Parameters:
requiredLabels- 必须全部满足的键值对;null或空 map = 不按标签收窄。 键非空白、值非 null。同一键只能出现一次(Map本就不允许重复键), 故「同一个键要接受多个值」不能在一个备选里表达——那种需求要么是anyOf(java.util.List)的多个备选,要么属于接入方自己的命名约定
-
anyOf
多个备选(OR 语义):任一备选被满足即准入。入口规约:列表里一旦出现空 map 备选(该备选恒成立),整个作用域就在入口处 退回
empty()——「恒真 ∨ 任意」恒真,此时它已不排除任何候选。 不做这条规约,对象会同时呈现"不收窄"(判定恒真)与"非空"(isEmpty()为 false) 两种互相矛盾的形态:调用方据此把一次本来正常的决策读成"不可用",还会把这个空备选 原样下发到线上协议。规约在拷贝并校验之后做,故非法入参(键为空白等)在任何位置 都会被如实拒绝。- Parameters:
alternatives- 备选列表;null或空列表 = 不按标签收窄。 每个备选内部的键值对是 AND;单个备选为空 map 恒成立,故整个列表 规约为empty()
-
anyOf
把若干作用域并列成一个 OR 作用域(便于把of(String, String)的产物拼起来)。OR 之下方向必须一致:任一入参
isEmpty()为 true("不按标签收窄")时, 结果就是empty()——「不限制 ∨ 某个取值」本来就是"不限制"。 若反过来把空作用域当成"零贡献"、只把其余备选取并集,调用方"配置缺失就传empty()" 的写法会静默收紧准入(本该全放行,却变成只放行剩下那几个备选), 与empty()的语义正好相反。- Parameters:
scopes- 并列的作用域;null元素视为"没有这个备选"被跳过(null数组或空数组 与空列表同义:不按标签收窄)
-
isEmpty
public boolean isEmpty()本作用域是否不按标签收窄(true 时决策行为与不带作用域的那条重载逐位一致)。不变式(本类只有这一种"空"):
isEmpty() == true与「无约束力」 严格等价——admits(Map)对任何入参(含null)恒为 true, 即不排除任何候选;并且此时本对象与empty()内容相等 (equals(Object)为 true、hashCode()相同)。所有"空"的写法 (empty()、of(null)、of(空 map)、anyOf(空列表)、anyOf(listOf(空 map))、anyOf(empty(), ...))都在入口规约到同一形态, 不存在"非空却恒真"的中间态。它不是"没有候选"的意思:判"有没有候选"读
ScheduleResult.state(),不要把本方法的结果当结论用。 -
alternatives
OR 备选:每个元素是一组必须全部满足的键值标签。- Returns:
- 不可修改的列表,元素是不可修改的 map;空列表表示「不按标签收窄」
-
admits
判定一组节点自声明标签是否满足本作用域(纯逻辑,无 I/O)。不变式:
isEmpty()为 true 时无约束力——本方法对任何入参 (含null、空 map)恒为true,即不排除任何候选。- Parameters:
declaredLabels- 节点自己声明的标签;null视为「没声明过」- Returns:
isEmpty()为 true 时恒为true(空作用域不要求节点声明过任何标签); 否则要求至少一个备选成立(备选内全部满足,精确相等,不做归一化,见类首段的语义 ③)
-
equals
按alternatives()的内容相等比较。不变式:
isEmpty()为 true 的对象与empty()相等, 因为空的写法只有一种(全部在入口规约到EMPTY单例的形态), 故"空"与"无约束力"在相等性上也是同一个东西——调用方可以用scope.equals(AdmissionScope.empty())或isEmpty()互推。 -
hashCode
public int hashCode() -
toString
诊断用:只印备选个数与各备选的键,不展开值(值可能含运维侧的业务标识)。
-