package cn.dreampie.common.entity;
import cn.dreampie.common.entity.exception.EntityException;
import cn.dreampie.common.util.Maper;
import cn.dreampie.common.util.json.Jsoner;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Created by ice on 14-12-31.
*/
public abstract class Entity<M extends Entity> {
private Map<String, Object> attrs = new CaseInsensitiveMap<Object>();
/**
* Flag of attr has been modified. update need this flag
*/
private Map<String, Object> modifyAttrs = new CaseInsensitiveMap<Object>();
/**
* getMessage Conversion to convert attr
*
* @param attr
* @return
*/
public abstract Conversion getConversion(String attr);
/**
* Return attribute Map.
* Danger! The update method will ignore the attribute if you change it directly.
* You must use set method to change attribute that update method can handle it.
*/
public Map<String, Object> getAttrs() {
return attrs;
}
/**
* Set attributes with other entity.
*
* @param entity the Model
* @return this Model
*/
public M setAttrs(M entity) {
return (M) setAttrs(entity.getAttrs());
}
/**
* Set attributes with Map.
*
* @param attrs attributes of this entity
* @return this Model
*/
public M setAttrs(Map<String, Object> attrs) {
for (Map.Entry<String, Object> e : attrs.entrySet())
set(e.getKey(), e.getValue());
return (M) this;
}
/**
* 获取更新的属性列表
*
* @return Map<String, Object>
*/
public Map<String, Object> getModifyAttrs() {
return modifyAttrs;
}
/**
* check method for to json
*
* @return boolean
*/
public boolean checkMethod() {
return false;
}
/**
* 判断数据库是否拥有该列
*
* @param attr 属性名
* @return boolean
*/
public abstract boolean hasColumn(String attr);
/**
* 获取改数据库列对应的java类型
*
* @param attr 属性名
* @return class
*/
public abstract Class getColumnType(String attr);
/**
* Set attribute to entity.
*
* @param attr the attribute name of the entity
* @param value the value of the attribute
* @return this entity
* @throws cn.dreampie.common.entity.exception.EntityException if the attribute is not exists of the entity
*/
public M set(String attr, Object value) {
if (hasColumn(attr)) {
attrs.put(attr, value);
modifyAttrs.put(attr, value); // Add modify flag, update() need this flag.
return (M) this;
}
throw new EntityException("The attribute name is not exists: " + attr);
}
/**
* 初始化属性 不会添加到modify
*
* @param attr
* @param value
* @return
*/
public M init(String attr, Object value) {
attrs.put(attr, value);
return (M) this;
}
public M initAttrs(Map<String, Object> attrs) {
for (Map.Entry<String, Object> e : attrs.entrySet()) {
init(e.getKey(), e.getValue());
}
return (M) this;
}
public M initAttrs(M entity) {
return (M) initAttrs(entity.getAttrs());
}
/**
* Put key value pair to the entity when the key is not attribute of the entity.
*
* @param attr 属性名称
* @param value 属性值
* @return 当前entity对象
*/
public M put(String attr, Object value) {
if (hasColumn(attr)) {
modifyAttrs.put(attr, value);
}
attrs.put(attr, value);
return (M) this;
}
public M putAttrs(Map<String, Object> attrs) {
for (Map.Entry<String, Object> e : attrs.entrySet()) {
put(e.getKey(), e.getValue());
}
return (M) this;
}
/**
* Set attrs value with entity.
*
* @param entity the entity
*/
public M putAttrs(M entity) {
return (M) putAttrs(entity.getAttrs());
}
/**
* Get attr of any sql type
*/
public <T> T get(String attr) {
return (T) attrs.get(attr);
}
/**
* Parse attr to any type
*/
public <T> T get(String attr, Class<T> clazz) {
if (attrs.containsKey(attr)) {
Object value = attrs.get(attr);
T result = null;
if (value != null) {
if (clazz.isAssignableFrom(value.getClass())) {
result = (T) value;
} else {
result = Jsoner.toObject(Jsoner.toJSON(value), clazz);
}
}
return result;
} else {
throw new EntityException("Attribute '" + attr + "' could not found.");
}
}
/**
* Get attr of any sql type. Returns defaultValue if null.
*/
public <T> T get(String attr, Object defaultValue) {
Object result = get(attr);
return (T) (result != null ? result : defaultValue);
}
/**
* Get attr for clazz. Returns defaultValue if null.
*/
public <T> T get(String attr, Class<T> clazz, Object defaultValue) {
Object result = get(attr, clazz);
return (T) (result != null ? result : defaultValue);
}
/**
* Remove attribute of this entity.
*
* @param attr the attr name of the entity
*/
public M remove(String attr) {
this.attrs.remove(attr);
this.modifyAttrs.remove(attr);
return (M) this;
}
/**
* Remove attrs of this entity.
*
* @param attrs the attr name of the entity
*/
public M remove(String... attrs) {
if (attrs != null)
for (String attr : attrs) {
remove(attr);
}
return (M) this;
}
/**
* Remove attrs if it is null.
*/
public M removeNull() {
for (java.util.Iterator<Map.Entry<String, Object>> it = attrs.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, Object> e = it.next();
if (e.getValue() == null) {
it.remove();
}
}
return (M) this;
}
/**
* Keep attrs of this entity and remove other attrs.
*
* @param attrs the attr name of the entity
*/
public M keep(String... attrs) {
if (attrs != null && attrs.length > 0) {
Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.length);
Map<String, Object> newModifyAttrs = new HashMap<String, Object>();
for (String c : attrs) {
if (this.attrs.containsKey(c)) { // prevent put null value to the newAttrs
newAttrs.put(c, this.attrs.get(c));
if (this.modifyAttrs.containsKey(c)) {
newModifyAttrs.put(c, this.attrs.get(c));
}
}
}
this.attrs.clear();
this.attrs.putAll(newAttrs);
this.modifyAttrs.clear();
this.modifyAttrs.putAll(newModifyAttrs);
} else {
this.attrs.clear();
this.modifyAttrs.clear();
}
return (M) this;
}
/**
* Keep attr of this entity and remove other attrs.
*
* @param attr the attr name of the entity
*/
public M keep(String attr) {
if (this.attrs.containsKey(attr)) { // prevent put null value to the newAttrs
Object keepIt = this.attrs.get(attr);
this.attrs.clear();
this.attrs.put(attr, keepIt);
if (this.modifyAttrs.containsKey(attr)) {
this.modifyAttrs.clear();
this.modifyAttrs.put(attr, keepIt);
}
} else {
this.attrs.clear();
this.modifyAttrs.clear();
}
return (M) this;
}
/**
* Remove all attrs of this entity.
*/
public M clearAttrs() {
attrs.clear();
return (M) this;
}
public M clearModifyAttrs() {
modifyAttrs.clear();
return (M) this;
}
public M reSetAttrs(Map<String, Object> attrs) {
this.attrs = attrs;
return (M) this;
}
public M reSetModifyAttrs(Map<String, Object> modifyAttrs) {
this.modifyAttrs = modifyAttrs;
return (M) this;
}
/**
* Return attr name of this record.
*/
public String[] getAttrNames() {
Set<String> attrNameSet = attrs.keySet();
return attrNameSet.toArray(new String[attrNameSet.size()]);
}
/**
* Return attr values of this record.
*/
public Object[] getAttrValues() {
Collection<Object> attrValueCollection = attrs.values();
return attrValueCollection.toArray(new Object[attrValueCollection.size()]);
}
public String[] getModifyAttrNames() {
return getModifyAttrNames(null);
}
/**
* Return attribute name of this entity.
*/
public String[] getModifyAttrNames(String generatedKey) {
Set<String> attrNameSet = modifyAttrs.keySet();
if (generatedKey != null && !generatedKey.isEmpty()) {
attrNameSet.remove(generatedKey);
}
return attrNameSet.toArray(new String[attrNameSet.size()]);
}
/**
* Return attribute values of this entity.
*/
public Object[] getModifyAttrValues() {
return getModifyAttrValues(null);
}
public Object[] getModifyAttrValues(String generatedKey) {
Map<String, Object> attrValueMap = Maper.copyOf(new CaseInsensitiveMap<Object>(), modifyAttrs);
if (generatedKey != null && !generatedKey.isEmpty()) {
attrValueMap.remove(generatedKey);
}
Conversion conversion;
for (Map.Entry<String, Object> attrValueEntry : attrValueMap.entrySet()) {
conversion = getConversion(attrValueEntry.getKey());
if (conversion != null) {
attrValueEntry.setValue(conversion.write(attrValueEntry.getValue()));
}
}
Collection<Object> attrValueCollection = attrValueMap.values();
return attrValueCollection.toArray(new Object[attrValueCollection.size()]);
}
public String toString() {
return toJson();
}
/**
* Return json string of this record.
*/
public String toJson() {
return Jsoner.toJSON(attrs);
}
}