Class CommandNode<NCS>

java.lang.Object
io.github.theword.queqiao.core.command.CommandNode<NCS>
Type Parameters:
NCS - Native Command Source,平台原生命令来源类型
Direct Known Subclasses:
ClientCommand, HelpCommand, InfoCommand, ListCommand, ReconnectAllCommand, ReconnectCommand, ReloadCommand, RootCommand, ServerCommand

public abstract class CommandNode<NCS> extends Object
命令树节点

命令树中的一个节点,既可以是根节点,也可以是任意层级的子节点。

命令来源:命令层只认识 CommandExecutionContext —— 不认识任何平台类型,也不通过 AbstractPlatformContext 回执或判断权限。

扩展点

第三方命令只需覆盖以下方法:

其余方法均为 final:它们承担 Core 不变量(结构封装、注册校验、执行模板), 不允许通过覆盖绕过。

线程安全契约(重要)

同一个 CommandNode 实例可能处理多个命令调用,实现不得把单次 invocation 的可变状态(当前 sender / args / context / player)存储在实例字段中。 Invocation 状态必须全部来自方法参数;实例字段只允许存放构造期注入的不可变依赖。

注册生命周期

 registration phase(可 addChild)
         ↓
 command tree completed(freeze)
         ↓
 dispatch phase(execute / tabComplete;不得再修改结构)
 
结构进入 dispatch 阶段后不得并发修改。freeze() 之后任何 addChild(io.github.theword.queqiao.core.command.CommandNode<NCS>) 都会快速失败,因此上述不变量无法被绕过。
Since:
0.5.0
  • Field Details

    • logger

      protected final org.slf4j.Logger logger
      日志实现
  • Constructor Details

    • CommandNode

      protected CommandNode(org.slf4j.Logger logger)
      构造命令节点
      Parameters:
      logger - 日志实现,不得为 null
  • Method Details

    • addChild

      public final void addChild(CommandNode<NCS> child)
      添加子命令

      注册不变量(全部 fail-fast,抛 IllegalArgumentException):

      1. child 不得为 null;
      2. 子命令名称不得为 null 或空白;
      3. 同一父节点下名称不得重复(忽略大小写,与路由的匹配规则一致);
      4. child 不得已经属于另一个父节点 —— 不自动 detach;
      5. 不得形成环(child 不能是自己或自己的祖先);
      6. 结构已冻结时不得再注册。

      刻意不做静默覆盖:重复注册属于装配错误,应在构建期就暴露, 而不是等到运行期表现为"某个子命令神秘消失"。

      Parameters:
      child - 子命令,不得为 null
      Throws:
      IllegalArgumentException - 违反上述任一不变量
      IllegalStateException - 结构已冻结
    • freeze

      public final void freeze()
      冻结整棵命令树的结构

      幂等:重复调用无副作用。

      冻结后:addChild(io.github.theword.queqiao.core.command.CommandNode<NCS>) 抛 IllegalStateException, 从而保证 dispatch 阶段不会与结构修改并发。

      CommandRouter.execute(io.github.theword.queqiao.core.command.CommandExecutionContext<NCS>, java.lang.String[]) / CommandRouter.tabComplete(io.github.theword.queqiao.core.command.CommandExecutionContext<NCS>, java.lang.String[]) 会在首次调用时 自动冻结,因此正常路径无需手动调用本方法;需要在装配完成后立即封板时可显式调用。

    • isFrozen

      public final boolean isFrozen()
      Returns:
      结构是否已冻结
    • getChildren

      public final List<CommandNode<NCS>> getChildren()
      获取所有子命令
      Returns:
      只读的子命令列表
    • getParent

      public final CommandNode<NCS> getParent()
      获取父命令
      Returns:
      父命令节点,根节点返回 null
    • isRoot

      public final boolean isRoot()
      判断是否为根命令
      Returns:
      是否为根命令
    • getFullPath

      public final String getFullPath()
      获取完整命令路径

      示例:/queqiao client list

      Returns:
      完整命令路径
    • getFullPermissionNode

      public final String getFullPermissionNode()
      获取完整权限节点

      从根节点开始拼接,示例:queqiao.client.list

      Returns:
      完整权限节点
    • getName

      public abstract String getName()
      获取命令名称
      Returns:
      命令名称
    • getDescription

      public abstract String getDescription()
      获取命令描述
      Returns:
      命令描述
    • getUsage

      public String getUsage()
      获取命令用法

      默认返回完整路径,子类可以覆盖以添加参数说明

      Returns:
      命令用法
    • getPermissionNode

      public String getPermissionNode()
      获取命令权限节点

      默认返回完整权限节点,子类可以覆盖以自定义权限

      Returns:
      权限节点
    • execute

      public final int execute(CommandExecutionContext<NCS> context, List<String> args)
      执行命令

      模板方法:权限判定、分隔线、异常兜底都由本方法负责, 子类不应覆盖(本方法为 final),业务逻辑写在 onExecute(io.github.theword.queqiao.core.command.CommandExecutionContext<NCS>, java.util.List<java.lang.String>)。

      异常处理:命令体的异常只回执一句通用提示,完整堆栈写入日志 —— 不把第三方命令的异常信息(可能含文件路径、内部状态、token / URL)暴露给命令调用者。

      Parameters:
      context - 本次命令调用的执行上下文,不得为 null
      args - 命令参数,不得为 null(无参数传空列表)
      Returns:
      执行信号(见 CommandConstant)
      Throws:
      NullPointerException - context 或 args 为 null
      Since:
      0.5.0
    • onExecute

      protected abstract void onExecute(CommandExecutionContext<NCS> context, List<String> args)
      执行命令逻辑

      这是实际命令业务的唯一扩展点。

      入参均已由 execute(io.github.theword.queqiao.core.command.CommandExecutionContext<NCS>, java.util.List<java.lang.String>) 校验非 null;实现不得把 context / args 保存到实例字段(见类级线程安全契约)。

      Parameters:
      context - 本次命令调用的执行上下文,永不为 null
      args - 命令参数,永不为 null
    • sendCommandTree

      public final void sendCommandTree(CommandExecutionContext<NCS> context, CommandNode<NCS> command)
      递归发送指定命令以及所有子命令的树形结构
      Parameters:
      context - 本次命令调用的执行上下文,不得为 null
      command - 当前命令节点,不得为 null
      Throws:
      NullPointerException - context 或 command 为 null