All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.isger.brick.plugin.persist.CommonPersist Maven / Gradle / Ivy

The newest version!
package net.isger.brick.plugin.persist;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.isger.brick.Constants;
import net.isger.brick.core.Console;
import net.isger.brick.core.CoreHelper;
import net.isger.brick.plugin.PluginConstants;
import net.isger.brick.plugin.PluginHelper;
import net.isger.brick.stub.StubCommand;
import net.isger.brick.stub.dialect.SqlDialect;
import net.isger.brick.stub.model.Meta;
import net.isger.brick.stub.model.Metas;
import net.isger.brick.stub.model.Model;
import net.isger.util.Callable;
import net.isger.util.Extendable;
import net.isger.util.Helpers;
import net.isger.util.Reflects;
import net.isger.util.Strings;
import net.isger.util.anno.Alias;
import net.isger.util.anno.Ignore;
import net.isger.util.anno.Ignore.Mode;
import net.isger.util.reflect.AssemblerAdapter;
import net.isger.util.reflect.BoundField;
import net.isger.util.reflect.TypeToken;
import net.isger.util.sql.Pager;

/**
 * 通用持久
 * 
 * @author issing
 */
@Ignore
public class CommonPersist extends PersistProxy {

    public static final String EXISTS = "exists";

    public static final String CREATE = "create";

    public static final String INSERT = "insert";

    public static final String DELETE = "delete";

    public static final String UPDATE = "update";

    public static final String SINGLE = "single";

    public static final String SELECT = "select";

    public static final String REMOVE = "remove";

    public static final String OPCODE_NORMAL = "normal";

    public static final String STATEMENT_BATCH = "batch";

    private static final Logger LOG;

    @Ignore(mode = Mode.INCLUDE)
    private boolean reset;

    @Ignore(mode = Mode.INCLUDE)
    @Alias(Constants.SYSTEM)
    private Console console;

    private boolean create;

    private Object[] tables;

    static {
        LOG = LoggerFactory.getLogger(CommonPersist.class);
    }

    public CommonPersist(Object... tables) {
        this(true, tables);
    }

    public CommonPersist(boolean create, Object... tables) {
        this.create = create;
        this.tables = tables;
    }

    @Ignore(mode = Mode.INCLUDE)
    public final void initial(StubCommand cmd) {
        if (create) {
            boolean hasBoostrap = create(cmd, tables[0]);
            int size = tables.length;
            for (int i = 1; i < size; i++) {
                create((StubCommand) cmd.clone(), tables[i]);
            }
            if (hasBoostrap) {
                boostrap(cmd);
            }
        }
    }

    /**
     * 创建表(含元模型)
     * 
     * @param cmd
     * @param table
     * @return
     */
    private boolean create(StubCommand cmd, Object table) {
        /* 创建基础表 */
        cmd.setTable(table);
        if (this.reset) {
            try {
                cmd.setOperate(REMOVE);
                CoreHelper.toConsole(cmd);
            } catch (Exception e) {
            }
        } else {
            try {
                cmd.setOperate(EXISTS);
                CoreHelper.toConsole(cmd);
                return false;
            } catch (Exception e) {
            }
        }
        cmd.setOperate(CREATE);
        CoreHelper.toConsole(cmd);
        /* 创建元模型 */
        Model model;
        for (Meta meta : Metas.getMetas(table).values()) {
            if ((model = meta.toModel()) != null) {
                create((StubCommand) cmd.clone(), model);
            }
        }
        return true;
    }

    /**
     * 引导
     */
    protected void boostrap(StubCommand cmd) {
    }

    /**
     * 存在
     * 
     * @param cmd
     * @param opcode
     * @param values
     * @return
     */
    @Ignore(mode = Mode.INCLUDE)
    public boolean exists(StubCommand cmd, @Alias(PluginConstants.PARAM_STATEMENT_ID) Object opcode, @Alias(PluginConstants.PARAM_STATEMENT_VALUE) Object[] values) {
        boolean result = true;
        try {
            CoreHelper.toConsole(cmd);
        } catch (Exception e) {
            result = false;
        }
        return result;
    }

    /**
     * 新增
     *
     * @param opcode
     * @param values
     * @return
     */
    @Ignore(mode = Mode.INCLUDE)
    public void insert(StubCommand cmd, @Alias(PluginConstants.PARAM_STATEMENT_ID) Object opcode, @Alias(PluginConstants.PARAM_STATEMENT_VALUE) Object[] values) {
        CoreHelper.toConsole(cmd);
    }

    /**
     * 删除
     *
     * @param opcode
     * @param values
     * @return
     */
    @Ignore(mode = Mode.INCLUDE)
    public void delete(StubCommand cmd, @Alias(PluginConstants.PARAM_STATEMENT_ID) Object opcode, @Alias(PluginConstants.PARAM_STATEMENT_VALUE) Object[] values) {
        CoreHelper.toConsole(cmd);
    }

    /**
     * 修改
     *
     * @param opcode
     * @param values
     * @return
     */
    @Ignore(mode = Mode.INCLUDE)
    public void update(StubCommand cmd, @Alias(PluginConstants.PARAM_STATEMENT_ID) Object opcode, @Alias(PluginConstants.PARAM_STATEMENT_VALUE) Object[] values) {
        CoreHelper.toConsole(cmd);
    }

    /**
     * 查询
     *
     * @param opcode
     * @param values
     */
    @Ignore(mode = Mode.INCLUDE)
    public Object select(StubCommand cmd, @Alias(PluginConstants.PARAM_STATEMENT_ID) Object opcode, @Alias(PluginConstants.PARAM_STATEMENT_VALUE) Object[] values, @Alias(PluginConstants.PARAM_STATEMENT_ARGS) Object[] args, @Alias(PluginConstants.PARAM_BEAN) Object bean, @Alias(PluginConstants.PARAM_PAGE) Pager pager) {
        boolean isMultiple = Helpers.isMultiple(cmd.getTable());
        Object result = CoreHelper.toConsole(cmd);
        if (isMultiple) {
            List pendings = new ArrayList();
            for (Object pending : (Object[]) result) {
                pendings.add(toResult(cmd, bean, pager, (Object[]) pending));
            }
            result = pendings;
        } else {
            result = toResult(cmd, bean, pager, (Object[]) result);
        }
        return result;
    }

    /**
     * 查询
     *
     * @param opcode
     * @param values
     * @return
     */
    @Ignore(mode = Mode.INCLUDE)
    public Object single(StubCommand cmd, @Alias(PluginConstants.PARAM_STATEMENT_ID) Object opcode, @Alias(PluginConstants.PARAM_STATEMENT_VALUE) Object[] values, @Alias(PluginConstants.PARAM_STATEMENT_ARGS) Object[] args, @Alias(PluginConstants.PARAM_BEAN) Object bean) {
        PluginHelper.enablePage(cmd, false); // 关闭分页功能
        boolean isMultiple = Helpers.isMultiple(cmd.getTable());
        Object result = CoreHelper.toConsole(cmd);
        if (isMultiple) {
            List pendings = new ArrayList();
            for (Object pending : (Object[]) result) {
                pendings.add(Helpers.getElement(toResult(cmd, bean, null, (Object[]) pending), 0));
            }
            result = pendings;
        } else {
            result = Helpers.getElement(toResult(cmd, bean, null, (Object[]) result), 0);
        }
        return result;
    }

    /**
     * 结果
     * 
     * @param cmd
     * @param bean
     * @param pager
     * @param grid
     * @return
     */
    @SuppressWarnings("unchecked")
    private Object toResult(StubCommand cmd, Object bean, Pager pager, Object[] grid) {
        Object result;
        Object value = grid[grid.length - 1];
        if (value instanceof Number) {
            pager.setTotal(((Number) value).intValue());
        }
        if (bean == null) {
            bean = this.tables[0];
        }
        Class rawClass = Reflects.getClass(bean);
        if (rawClass == null || Map.class.isAssignableFrom(rawClass)) {
            result = Reflects.toList(grid);
        } else if (String.class.isAssignableFrom(rawClass) || Reflects.getPrimitiveClass(rawClass) != null) {
            result = Helpers.compact(grid[1]);
        } else if (Model.class.isAssignableFrom(rawClass)) {
            result = Reflects.toList(grid);
            if (!(bean instanceof Class)) {
                List container = new ArrayList();
                Model model;
                for (Map row : (List>) result) {
                    model = ((Model) bean).clone();
                    model.metaValue(row);
                    container.add(model);
                }
                result = container;
            }
        } else {
            result = toResult(cmd, rawClass, grid);
        }
        result = toExtend(cmd, result);
        if (pager != null) {
            result = new Object[] { result, pager };
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    private Object toResult(final StubCommand cmd, Class clazz, Object[] grid) {
        final Map metas = new HashMap();
        /* 提取所有待映射的结果元 */
        Object result = Reflects.toList(clazz, grid, new AssemblerAdapter() {
            public Class assemble(Class rawClass) {
                if (rawClass.isInterface()) {
                    rawClass = console.getContainer().getInstance(Class.class, (Strings.toColumnName(rawClass.getSimpleName()).replaceAll("[_]", ".") + ".class"));
                }
                return rawClass;
            }

            public Object assemble(BoundField field, Object instance, Object value, Object... args) {
                Map data = (Map) args[0]; // 行值(原始数据)
                /* 字段结果元 */
                ResultMeta resultMeta = metas.get(field);
                if (resultMeta == null) {
                    metas.put(field, resultMeta = createResultMeta(cmd, field)); // 添加字段结果元
                }
                /* 引用数据类型 */
                if (resultMeta.meta.isReference()) {
                    switch (resultMeta.meta.getMode()) {
                    // 桥接模式处理(外部表)
                    case Meta.MODE_REFERENCE_BRIDGE:
                        Helpers.toAppend(resultMeta.mapping, data.get(resultMeta.sourceField), instance); // 向结果元添加字段值与实例映射
                        break;
                    }
                }
                /* 内联数据类型 */
                else {
                    String fieldName = Strings.toFieldName(resultMeta.sourceColumn); // 获取字段名
                    Object fieldValue = Helpers.getInstance(data, fieldName); // 获取字段值
                    if (value == Reflects.UNKNOWN) {
                        value = fieldValue; // 使用字段值替换
                    }
                    // 集合对象
                    else if (value instanceof Map) {
                        if (fieldValue == null) {
                            fieldValue = ((Map) value).get(resultMeta.sourceField);
                        } else if (fieldValue != value) {
                            ((Map) value).put(resultMeta.sourceField, fieldValue);
                        }
                    }
                    Helpers.toAppend(resultMeta.mapping, fieldValue, instance); // 向结果元添加字段值与实例映射
                }
                /* 初始置空 */
                return null;
            }
        });
        /* 映射处理 */
        if (metas.size() > 0) {
            toMapping(cmd, metas);
        }
        return result;
    }

    /**
     * 创建结果元
     * 
     * @param cmd
     * @param field
     * @return
     */
    @SuppressWarnings("unchecked")
    private ResultMeta createResultMeta(StubCommand cmd, BoundField field) {
        ResultMeta resultMeta = new ResultMeta();
        resultMeta.meta = Meta.createMeta(field); // 字段元
        resultMeta.mapping = new HashMap>(); // 映射集合
        if ((resultMeta.model = resultMeta.meta.toModel()) == null) {
            Class rawClass = field.getToken().getRawClass();
            if (rawClass.isInterface()) {
                rawClass = console.getContainer().getInstance(Class.class, (Strings.toColumnName(rawClass.getSimpleName()).replaceAll("[_]", ".") + ".class"));
            }
            resultMeta.model = rawClass == null ? null : Model.create(rawClass);
            resultMeta.sourceColumn = resultMeta.meta.getName();
            resultMeta.targetColumn = (String) resultMeta.meta.getValue();
            resultMeta.sourceField = Strings.toFieldName(resultMeta.targetColumn);
        } else {
            Map config = (Map) resultMeta.meta.getValue();
            Map source = (Map) config.get("source");
            resultMeta.sourceColumn = (String) source.get("name");
            resultMeta.sourceField = Strings.toFieldName((String) source.get("value"));
            Map target = (Map) config.get("target");
            resultMeta.targetColumn = (String) target.get("value");
            resultMeta.targetField = Strings.toFieldName((String) target.get("name"));
        }
        resultMeta.model.metaEmpty();
        return resultMeta;
    }

    /**
     * 结果元映射
     * 
     * @param cmd
     * @param metas
     */
    @SuppressWarnings("unchecked")
    private void toMapping(StubCommand cmd, Map metas) {
        StubCommand scmd;
        Model model;
        List models;
        BoundField boundField;
        ResultMeta resultMeta;
        for (Entry entry : metas.entrySet()) {
            resultMeta = entry.getValue();
            if (resultMeta.model == null) {
                continue;
            }
            scmd = cmd.clone();
            models = new ArrayList();
            boundField = entry.getKey();
            /* 获取映射目标(key为【目标对象唯一标志】,value为【源对象】) */
            final Map> targets = new HashMap>();
            final Map> targetExtends = new HashMap>();
            if (Strings.isEmpty(resultMeta.targetField)) targets.putAll(resultMeta.mapping);
            // 含映射目标字段,需要查询对应的映射数据(映射关系表)
            else {
                scmd.setTable(models);
                for (Object sourceValue : resultMeta.mapping.keySet()) {
                    models.add(model = resultMeta.model.clone());
                    model.metaValue(resultMeta.sourceColumn, sourceValue); // 列值(源字段)
                }
                Helpers.each(select(scmd, null, null, null, Map.class, null), new Callable.Runnable() {
                    public void run(Object... args) {
                        Integer index = (Integer) args[0];
                        List> values = (List>) args[1]; // 映射数据结果集
                        Object[] outerArgs = (Object[]) args[2];
                        Model mappingModel = ((List) outerArgs[0]).get(index); // 获取映射数据结果集对应模型
                        ResultMeta outerMeta = (ResultMeta) outerArgs[1];
                        List instances = outerMeta.mapping.get(mappingModel.metaValue(outerMeta.sourceColumn)); // 待映射实例集合
                        Object targetkey;
                        for (Map value : values) {
                            Helpers.toAppend(targets, targetkey = value.get(outerMeta.targetField), instances, false); // 对映射目标实例唯一标识,添加待映射实例集合
                            value.remove(Strings.toFieldName(outerMeta.sourceColumn));
                            value.remove(outerMeta.targetField);
                            targetExtends.put(targetkey, value);
                        }
                    }
                }, models, resultMeta);
            }
            /* 获取元素类型 */
            TypeToken typeToken = boundField.getToken();
            Class rawClass = typeToken.getRawClass();
            if (Collection.class.isAssignableFrom(rawClass)) {
                rawClass = (Class) Reflects.getActualType(typeToken.getType());
            } else if (rawClass.isArray()) {
                rawClass = (Class) Reflects.getComponentType(typeToken.getType());
            }
            if (rawClass.isInterface()) {
                rawClass = console.getContainer().getInstance(Class.class, (Strings.toColumnName(rawClass.getSimpleName()).replaceAll("[_]", ".") + ".class"));
            } else if (rawClass == Object.class) {
                rawClass = Map.class;
            }
            final Map> pending = new HashMap>(); // 待注入值
            String targetColumn = resultMeta.targetColumn;
            Model targetModel; // 当rawClass为Class或Class时,需要获取目标列描述值所指向的表名作为模型
            String[] targetColumnParts;
            /* 目标直接赋值(未配置目标列) */
            if (Strings.isEmpty(targetColumn) || (targetModel = (rawClass == Map.class ? ((targetColumnParts = targetColumn.split("[.]")).length == 2 && Strings.isNotEmpty(targetColumn = targetColumnParts[1]) ? SqlDialect.getModel(targetColumnParts[0]) : null) : Model.create(rawClass))) == null) {
                for (Entry> targetEntry : targets.entrySet()) {
                    for (Object instance : targetEntry.getValue()) {
                        Helpers.toAppend(pending, instance, targetEntry.getKey(), false);
                    }
                }
            }
            /* 查询目标数据(已配置目标列) */
            else {
                // 构建目标查询模型(根据唯一键)
                List sources = new ArrayList();
                targetModel.metaEmpty(); // 清空模型值
                scmd.setTable(models = new ArrayList());
                for (Object targetValue : targets.keySet()) {
                    if (Strings.isEmpty(targetValue)) {
                        continue; // 映射值为空(跳过检索)
                    }
                    // 为模型设定检索值
                    models.add(model = targetModel.clone());
                    model.metaValue(targetColumn, targetValue); // 列值(目标字段)
                    // 添加源对象(用于外部表容错)
                    Map source = new HashMap();
                    source.put(targetColumn, targetValue);
                    sources.add(Reflects.newInstance(rawClass, source));
                }
                if (models.size() > 0) {
                    Object instances;
                    try {
                        instances = single(scmd, null, null, null, rawClass); // 查询出所有映射目标对象
                    } catch (Exception e) {
                        instances = sources;
                    }
                    Helpers.each(instances, new Callable.Runnable() {
                        public void run(Object... args) {
                            Object instance = args[1];
                            Object[] outerArgs = (Object[]) args[2];
                            Object key = ((Meta) outerArgs[0]).getValue(instance); // 获取映射目标对象标识
                            if (key != null) {
                                if (targetExtends.containsKey(key)) {
                                    if (instance instanceof Extendable) {
                                        ((Extendable) instance).setExtends(targetExtends.get(key)); // 为映射目标对象添加扩展数据
                                    } else if (instance instanceof Map) {
                                        ((Map) instance).putAll(targetExtends.get(key));
                                    }
                                }
                                for (Object o : targets.get(key)) {
                                    Helpers.toAppend(pending, o, instance, false); // 为源对象建立映射目标对象
                                }
                            }
                        }
                    }, targetModel.meta(targetColumn));
                }
            }
            /* 完成数据映射 */
            for (Entry> p : pending.entrySet()) {
                Helpers.each(p.getKey(), new Callable() {
                    public Object call(Object... args) {
                        Object instance = args[1];
                        Object[] outerArgs = (Object[]) args[2];
                        ((BoundField) outerArgs[0]).setValue(instance, outerArgs[1]);
                        return instance;
                    }

                }, boundField, p.getValue());
            }
        }
    }

    /**
     * 扩展
     * 
     * @param cmd
     * @param result
     * @return
     */
    private Object toExtend(final StubCommand cmd, Object result) {
        LOG.debug("(!) The extension method for data result processing has not been implemented.");
        return result;
    }

    /**
     * 结果元数据
     * 
     * @author issing
     */
    private class ResultMeta {
        Meta meta;
        Model model;
        String sourceColumn;
        String sourceField;
        String targetColumn;
        String targetField;
        Map> mapping;
    }

}