XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEServerManager

【Java】我的世界XFE服务器管理器

公开
关注 0 Fork 0 Star 0
UTF-8
package com.xfestudio.xfeservermanager.core.spi;

import com.xfestudio.xfeservermanager.api.command.CommandAnalysisRequest;
import com.xfestudio.xfeservermanager.api.command.InvocationAst;
import com.xfestudio.xfeservermanager.api.spi.CommandSemanticAdapter;
import com.xfestudio.xfeservermanager.api.spi.SemanticAnalysisException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.ServiceLoader;

/** Deterministic dispatcher for built-in and service-loaded semantic adapters. */
public final class CommandSemanticRegistry {
    private static final Comparator<CommandSemanticAdapter> ORDER = Comparator
            .comparingInt(CommandSemanticAdapter::priority).reversed()
            .thenComparing(adapter -> adapter.getClass().getName());

    private final List<CommandSemanticAdapter> adapters;

    public CommandSemanticRegistry(Collection<? extends CommandSemanticAdapter> adapters) {
        this.adapters = adapters.stream().sorted(ORDER).map(adapter -> (CommandSemanticAdapter) adapter).toList();
    }

    public static CommandSemanticRegistry discover(ClassLoader classLoader) {
        List<CommandSemanticAdapter> discovered = new ArrayList<>();
        ServiceLoader.load(CommandSemanticAdapter.class, classLoader).forEach(discovered::add);
        return new CommandSemanticRegistry(discovered);
    }

    public Optional<InvocationAst> analyze(CommandAnalysisRequest request) throws SemanticAnalysisException {
        for (CommandSemanticAdapter adapter : adapters) {
            if (!adapter.supports(request.commandId())) {
                continue;
            }
            Optional<InvocationAst> result = adapter.analyze(request);
            if (result.isPresent()) {
                InvocationAst invocation = result.orElseThrow();
                if (!invocation.commandId().equals(request.commandId())) {
                    throw new SemanticAnalysisException("Adapter " + adapter.getClass().getName()
                            + " returned a different command id");
                }
                if (!invocation.semanticsKnown()) {
                    throw new SemanticAnalysisException("Semantic adapters must mark successful analysis as known");
                }
                return result;
            }
        }
        return Optional.empty();
    }

    public List<CommandSemanticAdapter> adapters() {
        return adapters;
    }
}