Package org.nutz.dao

Source Code of org.nutz.dao.Chain$DefaultChain$Entry

package org.nutz.dao;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.MappingField;
import org.nutz.dao.jdbc.ValueAdaptor;
import org.nutz.json.Json;
import org.nutz.lang.Mirror;

/**
* 名值链。
* <p>
* 通过 add 方法,建立一条名值对的链表
*
* @author zozoh(zozohtnt@gmail.com)
* @author Wendal(wendal1985@gmail.com)
* @author lzxz1234
*/
public abstract class Chain {
   
    /**
     * 建立一条名值链开始的一环
     *
     * @param name
     *            名称
     * @param value
     *            值
     * @return 链头
     */
    public static Chain make(String name, Object value) {
        DefaultChain chain = new DefaultChain(name, value);
        return chain;
    }

    /**
     * @return 链的长度
     */
    public abstract int size();

    /**
     * 改变当前节点的名称
     *
     * @param name
     *            新名称
     * @return 当前节点
     */
    public abstract Chain name(String name);

    /**
     * 改变当前节点的值
     *
     * @param value
     *            新值
     * @return 当前节点
     */
    public abstract Chain value(Object value);

    /**
     * 设置节点的参考适配器
     *
     * @param adaptor
     *            适配器
     * @return 当前节点
     */
    public abstract Chain adaptor(ValueAdaptor adaptor);

    /**
     * @return 当前节点的参考适配器
     */
    public abstract ValueAdaptor adaptor();

    /**
     * 将一个名值对,添加为本链节点的下一环
     *
     * @param name
     *            名
     * @param value
     *            值
     * @return 新增加的节点
     */
    public abstract Chain add(String name, Object value);
   
    /**
     * @return 当前节点的名称
     */
    public abstract String name();

    /**
     * @return 当前节点的值
     */
    public abstract Object value();

    /**
     * @return 往后移动一个结点,到达末尾返回空,否则返回当前对象
     */
    public abstract Chain next();

    /**
     * @return 整个链的第一环(头节点)
     */
    public abstract Chain head();

    /**
     * 根据 Entity 里的设定,更新整个链所有节点的名称。
     * <p>
     * 如果节点的名称是 Entity 的一个字段,则采用数据库字段的名称
     *
     * @param entity
     *            实体
     * @return 链头节点
     */
    public abstract Chain updateBy(Entity<?> entity);

    /**
     * 由当前的名值链,生成一个对象
     *
     * @param classOfT
     *            对象类型
     * @return 对象实例
     */
    public abstract <T> T toObject(Class<T> classOfT);

    /**
     * 由当前名值链,生成一个 Map
     *
     * @return Map
     */
    public abstract Map<String, Object> toMap();


    /**
     * 整个Chain是否为特殊Chain,只要有一个特殊结点,就是特殊Chain
     * @see org.nutz.dao.Chain#addSpecial(String, Object)
     * @since 1.b.44
     */
    public abstract boolean isSpecial();
   
    /**
     * 当前结点是不是特殊结点
     * @return
     */
    public abstract boolean special();
   
    /**
     * 由当前的值链生成一个可被实体化的 Map。 即有 '.table' 属性
     *
     * @param tableName
     *            表名
     * @return 可被实体化的 Map
     */
    public Map<String, Object> toEntityMap(String tableName) {
        Map<String, Object> map = toMap();
        map.put(".table", tableName);
        return map;
    }

    /**
     * 生成一个 JSON 字符串
     */
    public String toString() {
        return Json.toJson(toMap());
    }

    /**
     * 根据一个对象的字段 生成一个 Chain 对象
     * <p>
     * 这个对象可以是一个 POJO 或者是一个 Map。
     * <p>
     * 支持 FieldMatcher,即你可以通过 FieldMatcher 来指定你需要哪些字段加入 Chain
     *
     * @param obj
     *            对象,可以是一个 POJO 或者是一个 Map
     * @param fm
     *            指明可用字段,null 表示全部字段可用
     * @return Chain 对象,null 表示对象中没有可用字段
     *
     * @see org.nutz.dao.FieldMatcher
     */
    public static Chain from(Object obj, FieldMatcher fm) {
        if (null == obj)
            return null;
        Chain c = null;
        /*
         * Is Map
         */
        if (obj instanceof Map<?, ?>) {
            for (Map.Entry<?, ?> en : ((Map<?, ?>) obj).entrySet()) {
                Object key = en.getKey();
                if (null == key)
                    continue;
                String name = key.toString();
                if (null != fm && !fm.match(name))
                    continue;
                Object v = en.getValue();
                if (null != fm && null == v && fm.isIgnoreNull())
                    continue;
                if (c == null) {
                    c = Chain.make(name, v);
                } else {
                    c = c.add(name, v);
                }
            }
        }
        /*
         * Is POJO
         */
        else {
            Mirror<?> mirror = Mirror.me(obj.getClass());
            for (Field f : mirror.getFields()) {
                if (null != fm && !fm.match(f.getName()))
                    continue;
                Object v = mirror.getValue(obj, f.getName());
                if (null != fm && null == v && fm.isIgnoreNull())
                    continue;
                if (c == null) {
                    c = Chain.make(f.getName(), v);
                } else {
                    c = c.add(f.getName(), v);
                }
            }
        }
        return c;
    }

    /**
     * 根据一个 POJO 对象的字段 生成一个 Chain 对象
     * <p>
     * 相当于 Chain.from(obj,null)
     *
     * @param obj
     *            POJO 对象
     * @return Chain 对象
     */
    public static Chain from(Object obj) {
        return from(obj, null);
    }
   
    //=============================================================
    //===========update语句使用特定的值,例如+1 -1 toDate()等========
    //=============================================================
   
    /**
     * 添加一个特殊节点, 如果value非空,则有3个情况:<p>
     * <li>+1 效果如age=age+1</li>
     * <li>-1 效果如count=count-1</li>
     * <li>其他值, 则对value.toString(),效果如 time=todate("XXXXX")</li>
     *
     * @since 1.b.44
     */
    public abstract Chain addSpecial(String name, Object value);
   
    /**
     * @see org.nutz.dao.Chain#addSpecial(String, Object)
     * @since 1.b.44
     */
    public static Chain makeSpecial(String name, Object value) {
        DefaultChain chain = new DefaultChain(name, value);
        chain.head.special = true;
        return chain;
    }
   
    private static class DefaultChain extends Chain {
        private Entry head;
        private Entry current;
        private Entry tail;
        private int size;
       
        public DefaultChain(String name, Object value) {
           
            this.head = new Entry(name, value);
            this.current = head;
            this.tail = head;
            this.size = 1;
        }
        public int size() {
            return size;
        }
        public Chain name(String name) {
            current.name = name;
            return this;
        }
        public Chain value(Object value) {
            current.value = value;
            return this;
        }
        public Chain adaptor(ValueAdaptor adaptor) {
            current.adaptor = adaptor;
            return this;
        }
        public ValueAdaptor adaptor() {
            return current.adaptor;
        }
        public Chain add(String name, Object value) {
            tail.next = new Entry(name, value);
            tail = tail.next;
            size ++;
            return this;
        }
        public String name() {
            return current.name;
        }
        public Object value() {
            return current.value;
        }
        public Chain next() {
            current = current.next;
            return current == null ? null : this;
        }
        public Chain head() {
            current = head;
            return this;
        }
        public Chain addSpecial(String name, Object value) {
            add(name, value);
            tail.special = true;
            return this;
        }
        public boolean special() {
            return current.special;
        }
        public boolean isSpecial() {
            Entry entry = head;
            do {
                if(entry.special) return true;
            } while ((entry = entry.next) != null);
            return false;
        }
        public Map<String, Object> toMap() {
            Map<String, Object> map = new HashMap<String, Object>();
            Entry current = head;
            while (current != null) {
                map.put(current.name, current.value);
                current = current.next;
            }
            return map;
        }
        public Chain updateBy(Entity<?> entity) {
            if (null != entity) {
                Entry current = head;
                while (current != null) {
                    MappingField ef = entity.getField(current.name);
                    if (null != ef) {
                        current.name = ef.getColumnName();
                    }
                    current = current.next;
                }
            }
            return head();
        }
        public <T> T toObject(Class<T> classOfT) {
            Mirror<T> mirror = Mirror.me(classOfT);
            T re = mirror.born();
            Entry current = head;
            while (current != null) {
                mirror.setValue(re, current.name, current.value);
                current = current.next;
            }
            return re;
        }
       
        private static class Entry {
            protected String name;
            Object value;
            ValueAdaptor adaptor;
            boolean special;
            Entry next;
            public Entry(String name, Object value) {
                this.name = name;
                this.value = value;
            }
        }
    }
}
TOP

Related Classes of org.nutz.dao.Chain$DefaultChain$Entry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.