org.nutz.dao.Chain Maven / Gradle / Ivy
package org.nutz.dao;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
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.dao.util.Daos;
import org.nutz.json.Json;
import org.nutz.lang.Mirror;
import org.nutz.lang.Strings;
import org.nutz.lang.util.Callback2;
/**
* 名值链。
*
* 通过 add 方法,建立一条名值对的链表
*
* @author zozoh([email protected])
* @author Wendal([email protected])
* @author lzxz1234
*/
public abstract class Chain {
/**
* 建立一条名值链开始的一环
*
* @param name
* 名称
* @param value
* 值
* @return 链头
*/
public static Chain make(String name, Object value) {
return new DefaultChain(name, value);
}
/**
* @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 里的设定,更新整个链所有节点的名称。
*
* 如果节点的名称是 Entity 的一个字段,则采用数据库字段的名称
*
* @param entity
* 实体
* @return 链头节点
*/
public abstract Chain updateBy(Entity> entity);
/**
* 由当前的名值链,生成一个对象
*
* @param classOfT
* 对象类型
* @return 对象实例
*/
public abstract T toObject(Class classOfT);
/**
* 由当前名值链,生成一个 Map
*
* @return Map
*/
public abstract Map 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 toEntityMap(String tableName) {
Map map = toMap();
map.put(".table", tableName);
return map;
}
/**
* 生成一个 JSON 字符串
*/
public String toString() {
return Json.toJson(toMap());
}
/**
* 根据一个对象的字段 生成一个 Chain 对象
*
* 这个对象可以是一个 POJO 或者是一个 Map。
*
* 支持 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 ) {
if (null == v) {
if (fm.isIgnoreNull())
continue;
} else if (fm.isIgnoreBlankStr() && v instanceof String && Strings.isBlank((String)v)) {
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 == v) {
if (fm != null && fm.isIgnoreNull())
continue;
} else if (fm != null && fm.isIgnoreBlankStr() && v instanceof String && Strings.isBlank((String)v)) {
continue;
}
if (c == null) {
c = Chain.make(f.getName(), v);
} else {
c = c.add(f.getName(), v);
}
}
}
return c;
}
/**
* 根据一个 POJO 对象的字段 生成一个 Chain 对象
*
* 相当于 Chain.from(obj,null)
*
* @param obj
* POJO 对象
* @return Chain 对象
*/
public static Chain from(Object obj) {
return from(obj, null);
}
public static Chain from(Object obj, FieldMatcher fm, Dao dao) {
final Chain[] chains = new Chain[1];
boolean re = Daos.filterFields(obj, fm, dao, new Callback2() {
public void invoke(MappingField mf, Object val) {
if (mf.isReadonly() || !mf.isUpdate())
return;
if (chains[0] == null)
chains[0] = Chain.make(mf.getName(), val);
else
chains[0].add(mf.getName(), val);
}
});
if (re)
return chains[0];
return null;
}
//=============================================================
//===========update语句使用特定的值,例如+1 -1 toDate()等========
//=============================================================
/**
* 添加一个特殊节点, 如果value非空而且是String类型,则有3个情况:
*
+1 效果如age=age+1
* -1 效果如count=count-1
* 支持的运算符有 + - *\/ % & ^ |
* 其他值, 则对value.toString()
*
* Chain chain = Chain.makeSpecial("age", "+1");//输出的SQL会是 age=age+1
*
* Chain chain = Chain.makeSpecial("ct", "now()");//输出的SQL会是 ct=now(),但不建议用依赖特定数据库的now(),仅供演示.
* @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;
}
public 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 toMap() {
Map map = new LinkedHashMap();
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.getColumnNameInSql();
}
current = current.next;
}
}
return head();
}
public T toObject(Class classOfT) {
Mirror 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;
}
}
public 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;
}
}
}