package com.jqmobile.core.server.db.orm;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.sql.ResultSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import com.jqmobile.core.orm.DBColumn;
import com.jqmobile.core.orm.RsAccessor;
import com.jqmobile.core.orm.exception.ORMNotDBColumnException;
import com.jqmobile.core.orm.exception.ORMParamNotRecognitionException;
import com.jqmobile.core.utils.plain.GUIDUtils;
import com.jqmobile.core.utils.plain.UUIDUtils;
public class BaseDBColumn {
private final Field field;
private DBColumn dbLable;
private final static Map<Field, BaseDBColumn> map = new HashMap<Field, BaseDBColumn>();
public static BaseDBColumn getInstance(Field f) {
synchronized (map) {
if(!map.containsKey(f)){
map.put(f, new BaseDBColumn(f));
}
}
return map.get(f);
}
public BaseDBColumn(Field f){
this.field = f;
this.dbLable = f.getAnnotation(DBColumn.class);
}
public Field getField() {
return field;
}
public boolean isCascadeAll(){
return null==dbLable||dbLable.cascadeAll();
}
public boolean isCascadeDelete(){
if(!isCascadeAll()){
return false;
}
return null==dbLable||dbLable.cascadeDelete();
}
public boolean isCascadeFind(){
if(!isCascadeAll()){
return false;
}
return null==dbLable||dbLable.cascadeFind();
}
public boolean isCascadeInsert(){
if(!isCascadeAll()){
return false;
}
return null==dbLable||dbLable.cascadeInsert();
}
public boolean isCascadeUpdate(){
if(!isCascadeAll()){
return false;
}
return null==dbLable||dbLable.cascadeUpdate();
}
public boolean isMapping(){
if(!isCascadeAll()){
return false;
}
return null == dbLable || dbLable.mapping();
}
public String getColumnName(){
valiColumn();
String fieldType=field.getType().toString();
String[] temp=fieldType.split(" ");
if(temp.length>1){
if(!temp[1].startsWith("java")||Collection.class.isAssignableFrom(field.getType())) return "";
}
if(null == dbLable || DBColumn.DefaultValue.equals(dbLable.name())) return field.getName();
return dbLable.name();
}
public DBColumn getDBColumn(){
return dbLable;
}
public boolean isPaimaryId() {
valiColumn();
return null != dbLable && dbLable.primaryId();
}
public String getColumnType() {
valiColumn();
//主键或者id为二进制
if(null != dbLable && (dbLable.primaryId() || dbLable.id())){
return "binary(16)";
}else if(null == dbLable || DBColumn.DefaultValue.equals(dbLable.type())){
Class<?> fieldType = field.getType();
if (isIn(fieldType.getName(),"java.lang.Long","long")&&field.getAnnotation(DBColumn.class)!=null&&field.getAnnotation(DBColumn.class).date()) {
return "timestamp";
}else if(isIn(fieldType.getName(),"java.lang.Long","long")){
return "bigint(20)";
} else if (isIn(fieldType.getName(),"java.lang.Double","double")) {
return "decimal(17,5)";
} else if (isIn(fieldType.getName(),"java.lang.Integer","int")) {
return "int";
} else if (isIn(fieldType.getName(),"java.lang.Float","float")) {
return "float";
}else if(isIn(fieldType.getName(), "java.util.Date","Date")){
return "timestamp";
} else if(isIn(fieldType.getName(), "java.sql.Date","Date")){
return "timestamp";
}else {
int length = null==dbLable?DBColumn.DefaultLength:dbLable.length();
if (isIn(fieldType.getName(),"java.lang.Byte","byte")) {
return "binary("+length+")";
} else if (isIn(fieldType.getName(),"java.lang.Short", "short")) {
return "smallint";
} else if (isIn(fieldType.getName(),"java.lang.Boolean", "boolean")) {
return "boolean";
} else if (isIn(fieldType.getName(),"java.util.UUID")) {
return "binary(16)";
} else if (isIn(fieldType.getName(),"java.lang.String")) {
return "varchar("+length+")";
} else{
if(!String.class.isAssignableFrom(field.getType())&&!UUID.class.isAssignableFrom(field.getType())&&!field.getType().isPrimitive()){
return "";
}
}
}
}
return dbLable.type()+getColumnOther(field, dbLable, getColumnType(), getColumnName());
}
private String getColumnOther(Field f, DBColumn lable, String columnType,
String columnName) {
String str;
if(columnType.contains("varchar")){
str = "CHARACTER SET utf8 DEFAULT "+getColumnDefault(lable);
}else if(columnName.toUpperCase().equals("RECID")){
str = "NOT NULL";
}else if(!lable.canNull()){
str = "NOT Null";
}else{
str = "";
}
if(null != lable.comment() && !"".equals(lable.comment().trim())){
str = str + " COMMENT '"+ lable.comment()+"'";
}
return str;
}
private static String getColumnDefault(DBColumn lable) {
return "NULL";
}
/**
*
* @param obj
* @return 返回byte数组
*/
@SuppressWarnings("deprecation")
public Object getFormatObj(Object obj){
if(null == obj){
return null;
}
if(null != dbLable && (dbLable.primaryId() || dbLable.id())){
if(obj instanceof UUID){
return GUIDUtils.getBytes((UUID)obj);
}else if(obj instanceof String){
return GUIDUtils.getBytes((String)obj);
}else{
throw new ORMParamNotRecognitionException("guid类型:"+obj);
}
}
return obj;
}
/**
* 设置属性值
* @param obj 对象
* @param value 值
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException{
field.set(obj, value);
}
//
private void valiColumn() throws ORMNotDBColumnException{
if(!isMapping()) throw new ORMNotDBColumnException();
}
//
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((field == null) ? 0 : field.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseDBColumn other = (BaseDBColumn) obj;
if (field == null) {
if (other.field != null)
return false;
} else if (!field.equals(other.field))
return false;
return true;
}
/**
* 从结果集中获取当前属性的值
* @param rs
* @return
*/
public Object getValue(ResultSet rs) {
return getFieldValue(this, rs);
}
private static Object getFieldValue(BaseDBColumn field, ResultSet rs) {
Object obj = null;
String name = field.getColumnName();
Class<?> fieldType = field.getField().getType();
DBColumn lable = field.getDBColumn();
if(null != lable && (lable.id() || lable.primaryId()) && isIn(fieldType.getName(),"java.lang.String")){
try {
obj = UUIDUtils.getUUID(rs.getBytes(name)).toString();
} catch (Throwable e) {
return null;
}
}
else if (isIn(fieldType.getName(),"java.lang.Long","long")) {
if(null != lable && field.getField().getAnnotation(DBColumn.class).date()){
try {
obj = rs.getTimestamp(name).getTime();
} catch (Exception e) {
obj = getLong(rs, obj, name, fieldType);
}
}else{
obj = getLong(rs, obj, name, fieldType);
}
} else if (isIn(fieldType.getName(),"java.lang.Double","double")) {
try {
obj = rs.getDouble(name);
} catch (Throwable e) {
if(fieldType.getName().equals("double"))
obj = 0d;
else
return null;
}
} else if (isIn(fieldType.getName(),"java.lang.Integer","int")) {
try {
obj = rs.getInt(name);
} catch (Throwable e) {
if(fieldType.getName().equals("int"))
obj = 0;
else
return null;
}
} else if (isIn(fieldType.getName(),"java.lang.Float","float")) {
try {
obj = rs.getFloat(name);
} catch (Throwable e) {
if(fieldType.getName().equals("float"))
obj = 0f;
else
return null;
}
} else if (isIn(fieldType.getName(),"java.lang.Byte","byte")) {
try {
obj = rs.getByte(name);
} catch (Throwable e) {
return null;
}
} else if (isIn(fieldType.getName(),"java.lang.Short", "short")) {
try {
obj = rs.getShort(name);
} catch (Throwable e) {
if(fieldType.getName().equals("short"))
obj = (short)0;
else
return null;
}
} else if (isIn(fieldType.getName(),"java.lang.Boolean", "boolean")) {
try {
obj = rs.getBoolean(name);
} catch (Throwable e) {
if(fieldType.getName().equals("boolean"))
obj = false;
else
return null;
}
} else if (isIn(fieldType.getName(),"java.util.UUID")) {
try {
obj = UUIDUtils.getUUID(rs.getBytes(name));
} catch (Throwable e) {
return null;
}
} else if (isIn(fieldType.getName(),"java.lang.String")) {
try {
obj = rs.getString(name);
} catch (Throwable e) {
return null;
}
}else if(fieldType.isArray() && isIn(fieldType.getName(), "[B", "[Ljava.lang.Byte;")){
try{
obj = rs.getBytes(name);
}catch(Throwable e){
return null;
}
}else if(isIn(fieldType.getName(),"java.math.BigInteger")){
try {
obj = new BigInteger(rs.getString(name));
} catch (Throwable e) {
return null;
}
} else{
try {
obj = rs.getObject(name);
} catch (Throwable e) {
obj = null;
}
}
return obj;
}
private static Object getLong(ResultSet rs, Object obj, String name,
Class<?> fieldType) {
try {
obj = rs.getLong(name);
} catch (Throwable e) {
if(fieldType.getName().equals("long"))
obj = 0l;
else
return null;
}
return obj;
}
@SuppressWarnings("unused")
private static Object getLong(RsAccessor rs, Object obj, int i, Class<?> fieldType) {
try {
obj = rs.getLong(i);
} catch (Throwable e) {
if(fieldType.getName().equals("long"))
obj = 0l;
else
return null;
}
return obj;
}
public static boolean isIn(String str, String...ins){
for(String s : ins){
if(s.equals(str)){
return true;
}
}
return false;
}
@Override
public String toString() {
return getColumnName();
}
}