gu.sql2java.BeanConverter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sql2java-base Show documentation
Show all versions of sql2java-base Show documentation
sql2java common class package
package gu.sql2java;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import com.google.common.primitives.Primitives;
/**
* implementation of {@link IBeanConverter} by reflect
* generic type converter between L and R
* @author guyadong
* @param left type extends BaseBean
* @param right type
*
*/
public class BeanConverter extends IBeanConverter.AbstractHandle implements Constant{
static final String GET_INITIALIZED = "getInitialized";
static final String SET_INITIALIZED = "setInitialized";
static final String GET_MODIFIED = "getModified";
static final String SET_MODIFIED = "setModified";
static final String SET_NEW = "setNew";
static final String IS_NEW = "isNew";
private final Map methods = new Hashtable();
private final Map rightIndexs = new Hashtable();
private final Map> setterParams = new Hashtable>();
private final RowMetaData metaData;
private boolean bitCheck(String name,int...bits){
Integer id = rightIndexs.get(name);
return (null == id)?false:bitCheck(id.intValue(),bits);
}
private int[] bitOR(String name,int... bits){
return bitOR(rightIndexs.get(name),bits);
}
private void getGetter(String name){
try{
methods.put(name,rightType.getMethod(name));
}catch(NoSuchMethodException e){}
}
private void getSetter(String name, Class>...types) throws NoSuchMethodException{
for(Class>paramType:types){
try{
methods.put(name,rightType.getMethod(name,paramType));
setterParams.put(name, paramType);
return;
}catch(NoSuchMethodException e){
continue;
}
}
throw new NoSuchMethodException();
}
private void getSetterNoThrow(String name, Class>...types){
try{
getSetter(name,types);
}catch(NoSuchMethodException e){}
}
/**
* constructor
* @param leftClass
* @param rightClass
* @param javaFields a comma splice string,including all field name of R,
* if null or empty, use default string:{@link RowMetaData#columnJavaNames}
*/
public BeanConverter (Class leftClass, Class rightClass,String javaFields){
super(leftClass,rightClass);
this.metaData = RowMetaData.getMetaData(leftClass);
init(javaFields);
}
/** @see #BeanConverter(Class,Class,String) */
public BeanConverter (Class leftClass, Class rightClass){
this(leftClass,rightClass,null);
}
private void init(String javaFields){
ListrightFields;
if(null == javaFields || javaFields.isEmpty()){
rightFields = metaData.columnJavaNames;
}else{
rightFields = Arrays.asList(javaFields.split(","));
}
for(int i = 0 ; i < rightFields.size(); ++i){
String field = rightFields.get(i).trim();
if(!field.matches("\\w+")){
throw new IllegalArgumentException("invalid 'javaFields':" + javaFields);
}
rightIndexs.put(field,i);
}
try{
methods.put(IS_NEW,rightType.getMethod(IS_NEW));
methods.put(GET_INITIALIZED,rightType.getMethod(GET_INITIALIZED));
getSetter(SET_NEW,boolean.class);
if(rightIndexs.size() > STATE_BIT_NUM){
getSetter(SET_INITIALIZED,int[].class,List.class);
}else{
getSetter(SET_INITIALIZED,int.class);
}
getGetter(GET_MODIFIED);
if(rightIndexs.size() > STATE_BIT_NUM){
getSetter(SET_MODIFIED,int[].class,List.class);
}else{
getSetter(SET_MODIFIED,int.class);
}
}catch(NoSuchMethodException e){
throw new RuntimeException(e);
}
for(int i =0; i type = setter.getParameterTypes()[0];
if(type.isPrimitive()){
if(Date.class.isAssignableFrom(type)){
getSetterNoThrow(setter.getName(),type,long.class);
}
else{
getSetterNoThrow(setter.getName(),type,Primitives.unwrap(type));
}
}else if(ByteBuffer.class.isAssignableFrom(type) || byte[].class.isAssignableFrom(type)){
getSetterNoThrow(setter.getName(),type,ByteBuffer.class,byte[].class);
} else {
getSetterNoThrow(setter.getName(),type);
}
}
}
@Override
protected void doFromRight(L left, R right) {
try{
Method getterMethod;
left.resetIsModified();
int selfModified = 0;
int[] initialized;
int[] modified;
if(rightIndexs.size() > STATE_BIT_NUM){
initialized = (int[])methods.get(GET_INITIALIZED).invoke(right);
modified = (int[])methods.get(GET_MODIFIED).invoke(right);
}else{
initialized = new int[]{(Integer)methods.get(GET_INITIALIZED).invoke(right)};
modified = new int[]{(Integer)methods.get(GET_MODIFIED).invoke(right)};
}
for(int columnId = 0; columnId < metaData.columnCount; ++columnId){
String columnName = metaData.columnNameOf(columnId);
if(bitCheck(columnName,initialized)){
String getterName = metaData.getterMethods.get(columnId).getName();
if(null != (getterMethod = methods.get(getterName))){
left.setValue(columnId, getterMethod.invoke(right));
if(bitCheck(columnName,modified)){
selfModified |= (1<>STATE_BIT_SHIFT];
int[] modified = new int[(rightIndexs.size() + STATE_BIT_NUM - 1)>>STATE_BIT_SHIFT];
Arrays.fill(initialized, 0);
Arrays.fill(modified, 0);
for(int columnId = 0; columnId < metaData.columnCount; ++columnId){
String columnName = metaData.columnNameOf(columnId);
String setterName = metaData.setterMethods.get(columnId).getName();
if(null != (setterMethod = methods.get(setterName)) && left.isInitialized(columnId)){
try{
setterMethod.invoke(right,cast(setterParams.get(setterName),left.getValue(columnId)));
bitOR(columnName,initialized);
if(left.isModified(columnId)){
bitOR(columnName,modified);
}
}catch(NullCastPrimitiveException e){}
}
}
// IGNORE field fl_device.create_time , controlled by 'general.beanconverter.tonative.ignore' in properties file
/*
if(null != (setterMethod = methods.get(Column.createTime.setter)) && left.checkCreateTimeInitialized()){
try{
setterMethod.invoke(right,cast(setterParams.get(Column.createTime.setter),left.getCreateTime()));
bitOR(Column.createTime.name(),initialized);
if(left.checkCreateTimeModified()){
bitOR(Column.createTime.name(),modified);
}
}catch(NullCastPrimitiveException e){}
}
*/
// IGNORE field fl_device.update_time , controlled by 'general.beanconverter.tonative.ignore' in properties file
/*
if(null != (setterMethod = methods.get(Column.updateTime.setter)) && left.checkUpdateTimeInitialized()){
try{
setterMethod.invoke(right,cast(setterParams.get(Column.updateTime.setter),left.getUpdateTime()));
bitOR(Column.updateTime.name(),initialized);
if(left.checkUpdateTimeModified()){
bitOR(Column.updateTime.name(),modified);
}
}catch(NullCastPrimitiveException e){}
}
*/
if(null != (setterMethod = methods.get(SET_MODIFIED))){
if( initialized.length > 1){
setterMethod.invoke(right,cast(setterParams.get(SET_MODIFIED),initialized));
}else{
setterMethod.invoke(right,initialized[0]);
}
}
methods.get(SET_NEW).invoke(right,left.isNew());
if( initialized.length > 1){
methods.get(SET_INITIALIZED).invoke(right,cast(setterParams.get(SET_INITIALIZED),initialized));
methods.get(SET_MODIFIED).invoke(right,cast(setterParams.get(SET_MODIFIED),modified));
}else{
methods.get(SET_INITIALIZED).invoke(right,initialized[0]);
methods.get(SET_MODIFIED).invoke(right,modified[0]);
}
}catch(RuntimeException e){
throw e;
}catch(Exception e){
throw new RuntimeException(e);
}
}
private static final List toList(long[] array) {
ArrayList result = new ArrayList(array.length);
for (int i = 0; i < array.length; i++) {
result.add(new Long(array[i]));
}
return result;
}
private static final long[] toPrimitive(List list) {
long[] dst = new long[list.size()];
Long element;
for (int i = 0; i < dst.length; i++) {
if(null == (element = list.get(i))){
throw new IllegalArgumentException("can't cast List to long[] because of null element");
}
dst[i] = element.longValue();
}
return dst;
}
/**
* {@code source}转为{@code type}指定的类型
* @param type destination type
* @param source source object
* @return T instance
*/
@SuppressWarnings({ "unchecked" })
static final T cast(Class type,Object source){
try{
if(null ==source && type.isPrimitive()){
throw new NullCastPrimitiveException(String.format("can't convert null to primitive type %s",type.getSimpleName()));
}
return (T) source;
}catch(ClassCastException cce){
// long[] -> List
if(List.class.isAssignableFrom(type) && null != source && source instanceof long[]){
return (T) toList((long[]) source);
}
// List -> long[]
if(long[].class == type && null != source && source instanceof List){
return (T) toPrimitive( (List) source);
}
// Long -> Date
if(java.util.Date.class.isAssignableFrom(type) && null != source && source instanceof Long){
try {
// call constructor,such as java.util.Date#Date(long), java.sql.Time.Time(long)
return type.getConstructor(long.class).newInstance(source);
} catch (Exception e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
throw new ClassCastException(writer.toString());
}
}
// Date -> Long,long
if( long.class == type || Long.class == type){
if(null != source && source instanceof java.util.Date){
Long time = ((java.util.Date)source).getTime();
return (T)time;
}
}
// byte[] -> ByteBuffer
if(ByteBuffer.class == type && null != source && source instanceof byte[]){
return (T) ByteBuffer.wrap((byte[]) source);
}
// ByteBuffer -> byte[]
if(byte[].class == type && null != source && source instanceof ByteBuffer){
return (T) Sql2javaSupport.getBytesInBuffer((ByteBuffer) source);
}
throw cce;
}
}
static final boolean bitCheck(int index,int...bits){
return 0 != (bits[index>>STATE_BIT_SHIFT]&(1<<(index&0x1f)));
}
static final int[] bitOR(int index,int... bits){
bits[index>>STATE_BIT_SHIFT] |= (1<<(index&0x1f));
return bits;
}
private static class NullCastPrimitiveException extends ClassCastException {
private static final long serialVersionUID = 1L;
NullCastPrimitiveException(String message) {
super(message);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy