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

org.nutz.mapl.impl.MaplRebuild Maven / Gradle / Ivy

package org.nutz.mapl.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.nutz.lang.Lang;
import org.nutz.lang.Strings;

/**
 * 构建新的MapList结构对象, 根据path重建MapList结构
 * 
 * @author juqkai([email protected])
 */
public class MaplRebuild {
    enum Model {
        add, del, cell
    }

    private Model model = Model.add;
    private String[] keys;
    private Object val;
    // 数组索引
    private Integer arrayItem;
    // 数组栈列表
    protected LinkedList arrayIndex = new LinkedList();
    // 新MapList结构
    private Map newobj = new LinkedHashMap();

    private Object cellObj = null;

    public MaplRebuild() {
        newobj.put("obj", null);
    }

    public MaplRebuild(Object mapl) {
        newobj.put("obj", mapl);
    }

    /**
     * 添加属性
     * 
     * @param path
     *            路径
     * @param obj
     *            值
     */
    public void put(String path, Object obj) {
        init(path, obj);
        inject(newobj, 0);
    }

    /**
     * 添加属性
     * 
     * @param path
     *            路径
     * @param obj
     *            值
     * @param arrayIndex
     *            索引队列
     */
    public void put(String path, Object obj, LinkedList arrayIndex) {
        this.arrayIndex = arrayIndex;
        put(path, obj);
    }

    /**
     * 删除结点
     * 
     * @param path
     */
    public void remove(String path) {
        model = Model.del;
        init(path, null);
        inject(newobj, 0);
    }

    /**
     * 访问结点
     * 
     * @param path
     *            路径
     */
    public Object cell(String path) {
        model = Model.cell;
        init(path, null);
        inject(newobj, 0);
        return cellObj;
    }

    /**
     * 提取重建后的MapList
     */
    public Object fetchNewobj() {
        return newobj.get("obj");
    }

    private void init(String keys, Object obj) {
        this.keys = Lang.arrayFirst("obj", Strings.split(keys, false, '.'));
        this.val = obj;
        this.arrayItem = 0;
    }

    /**
     * 注入
     * 
     * @param obj
     * @param i
     */
    @SuppressWarnings("unchecked")
    private Object inject(Object obj, int i) {
        String key = keys[i];
        // 根数组
        if (key.indexOf('[') == 0) {
            List list = new ArrayList();
            if (obj != null) {
                list = (List) obj;
            }
            injectList(list, i, fetchIndex(key));
            return list;
        }
        // 数组
        // if(key.endsWith("[]")){
        int pos = key.indexOf('[');
        if (pos > 0) {
            Map map = new LinkedHashMap();
            if (obj != null) {
                map = (Map) obj;
            }
            // 有Key的list
            String k = key.substring(0, pos);
            if (!map.containsKey(k)) {
                map.put(k, new ArrayList());
            }
            int index = fetchIndex(key.substring(key.indexOf('['), key.length()));
            injectList((List) map.get(k), i, index);
            return map;
        }
        if (obj instanceof List) {
            try {
                int index = Integer.parseInt(keys[i]);
                injectList((List) obj, i, index);
                return obj;
            }
            catch (Exception e) {
                throw new RuntimeException("路径格式不正确!");
            }
        }
        return injectMap(obj, i);
    }

    private int fetchIndex(String val) {
        int index = 0;
        if (val.indexOf(']') == 1) {
            // []格式的路径, 即索引放在arrayIndex里面的.
            if (arrayIndex.size() > arrayItem) {
                index = arrayIndex.get(arrayItem++);
            }
        } else {
            // [1]格式, 路径上自带索引
            index = Integer.parseInt(val.substring(1, val.length() - 1));
        }
        return index;
    }

    /**
     * 注入MAP
     * 
     * @param obj
     * @param i
     */
    @SuppressWarnings("unchecked")
    private Object injectMap(Object obj, int i) {
        Map map;
        String key = keys[i];
        if (obj == null) {
            map = new LinkedHashMap();
        } else {
            map = (Map) obj;
        }

        if (model == Model.add) {
            if (i == keys.length - 1) {
                map.put(key, val);
                return map;
            }
            if (!map.containsKey(key) || map.get(key) == null) {
                map.put(key, inject(null, i + 1));
                return map;
            }
        } else if (model == Model.del) {
            if (i == keys.length - 1) {
                map.remove(key);
                return map;
            }
            if (!map.containsKey(key) || map.get(key) == null) {
                return map;
            }
        } else if (model == Model.cell) {
            if (i == keys.length - 1) {
                cellObj = map.get(key);
                return map;
            }
            if (!map.containsKey(key) || map.get(key) == null) {
                return map;
            }
        }

        if (map.containsKey(key) && map.get(key) != null) {
            inject(map.get(key), i + 1);
        }
        return map;
    }

    /**
     * 注入List
     * 
     * @param list
     * @param i
     */
    @SuppressWarnings("unchecked")
    private void injectList(List list, int i, int index) {
        // 添加模式
        if (model == Model.add) {
            if (i == keys.length - 1) {
                if (val instanceof Collection) {
                    list.addAll((Collection) val);
                } else {
                    list.add(index, val);
                }
                return;
            }
            if (list.size() <= index) {
                list.add(index, new LinkedHashMap());
            }
        } else if (model == Model.del) {
            if (i == keys.length - 1) {
                if (list.size() > index) {
                    list.remove(index);
                }
                return;
            }
            if (list.size() <= index) {
                return;
            }
        } else if (model == Model.cell) {
            if (i == keys.length - 1) {
                if (list.size() > index) {
                    cellObj = list.get(index);
                }
                return;
            }
            if (list.size() <= index) {
                return;
            }
        }
        inject((Map) list.get(index), i + 1);
    }

}