silentbalanceyh/vertx-zero

View on GitHub
vertx-pin/zero-vie/src/main/java/io/mature/extension/scaffold/plugin/AspectSwitcher.java

Summary

Maintainability
A
3 hrs
Test Coverage
package io.mature.extension.scaffold.plugin;

import io.horizon.spi.plugin.AspectPlugin;
import io.mature.extension.refine.Ox;
import io.vertx.core.Future;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.mod.atom.modeling.builtin.DataAtom;
import io.vertx.up.atom.exchange.DFabric;
import io.vertx.up.eon.KName;
import io.vertx.up.unity.Ux;
import io.vertx.up.util.Ut;

import java.util.Objects;
import java.util.function.Function;

import static io.mature.extension.refine.Ox.LOG;

/*
 * 横切专用处理,用于加载
 * 1)前置插件
 * 2)后置插件
 * 目前整个 Ox 支持的插件
 * - plugin.component:     主插件
 * - plugin.compressor:    批量执行插件(JsonArray -> JsonObject)
 * - plugin.todo:           生成TODO待办的插件
 * - plugin.activity:       生成变更历史专用插件
 */
public class AspectSwitcher {
    private final transient JsonObject options;
    private final transient AspectPlugin plugin;

    public AspectSwitcher(final DataAtom atom, final JsonObject optionsInput, final DFabric fabric) {
        /* 合并横切配置 */
        final JsonObject options = new JsonObject();
        options.mergeIn(Ut.valueJObject(optionsInput));
        this.options = options;
        /* identifier 真实替换 */
        this.options.put(KName.IDENTIFIER, atom.identifier());
        /*
         * 使用横切配置初始化插件
         * 如果初始化成功:plugin != null,则绑定 DataAtom 到插件中
         * */
        this.plugin = Ox.pluginComponent(options);
        if (Objects.nonNull(this.plugin)) {
            this.plugin.bind(atom);
            if (Objects.nonNull(fabric)) {
                /*
                 * 「字典翻译器的BUG」
                 * 每个插件的字典翻译器使用直接构造时的拷贝
                 * 1. 每个插件共享的是字典翻译器的拷贝
                 * 2. 由于某个字典翻译器很有可能被重设,每个插件在执行时相互之间不影响
                 * 3. 防止字典翻译器穿透的情况发生
                 *
                 * 每个插件必须使用独立的字典翻译器,插件使用的字典翻译器由通道组件来创建拷贝
                 */
                this.plugin.bind(fabric.copy());
            }
            LOG.Hub.info(this.getClass(), "( plugin.component ) 核心插件: 模型 identifier = {0}, 插件:{1},配置:{2}",
                atom.identifier(), this.getClass().getName(), optionsInput.encode());
        }
    }

    /*
     * 前置处理
     */
    private Future<JsonArray> beforeAsync(final JsonArray input) {
        if (Objects.isNull(this.plugin)) {
            return Ux.future(input);
        } else {
            return this.plugin.beforeAsync(input, this.options);
        }
    }

    /*
     * 后置处理
     */
    private Future<JsonArray> afterAsync(final JsonArray input) {
        if (Objects.isNull(this.plugin)) {
            return Ux.future(input);
        } else {
            return this.plugin.afterAsync(input, this.options);
        }
    }

    /*
     * 前置处理
     */
    private Future<JsonObject> beforeAsync(final JsonObject input) {
        if (Objects.isNull(this.plugin)) {
            return Ux.future(input);
        } else {
            return this.plugin.beforeAsync(input, this.options);
        }
    }

    /*
     * 后置处理
     */
    private Future<JsonObject> afterAsync(final JsonObject input) {
        if (Objects.isNull(this.plugin)) {
            return Ux.future(input);
        } else {
            return this.plugin.afterAsync(input, this.options);
        }
    }

    /*
     * 单条记录执行前后插件
     */
    public Future<JsonObject> run(final JsonObject input, final Function<JsonObject, Future<JsonObject>> runner) {
        final JsonObject params = Ut.valueJObject(input);
        return Ux.future(params)
            /*
             * 前置处理
             */
            .compose(this::beforeAsync)
            /*
             * 主逻辑
             */
            .compose(runner)
            /*
             * 后置请求处理,只有 Success 时执行
             */
            .compose(this::afterAsync);
    }

    /*
     * 多条记录执行前后插件
     */
    public Future<JsonArray> run(final JsonArray input, final Function<JsonArray, Future<JsonArray>> runner) {
        final JsonArray params = Ut.valueJArray(input);
        return Ux.future(params)
            /*
             * 前置处理
             */
            .compose(this::beforeAsync)
            /*
             * 主逻辑
             */
            .compose(runner)
            /*
             * 后置请求处理,只有 Success 时执行
             */
            .compose(this::afterAsync);
    }
}