gu.sql2java.BaseRow 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.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.Map.Entry;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
import gu.sql2java.exception.UnsupportTypeException;
import static com.google.common.base.Preconditions.*;
import static gu.sql2java.BaseTypeColumnCodec.BASE_CODEC;
import static gu.sql2java.BaseTypeColumnCodec.isBaseColumnType;
import static gu.sql2java.utils.DeepCloneUtils.cloneFields;
/**
* abstract implementation of {@link BaseBean}
* @author guyadong
*
*/
public abstract class BaseRow implements BaseBean,Comparable, Cloneable {
protected final RowMetaData metaData;
private volatile Map mapView;
protected BaseRow(RowMetaData metaData) {
this.metaData = checkNotNull(metaData,"metaData is null");
}
protected BaseRow() {
this.metaData = checkNotNull(RowMetaData.getMetaData(getClass()),"metaData is null");
}
@Override
public final boolean isInitialized(String column) {
return isInitialized(metaData.columnIDOf(column));
}
@Override
public boolean beModified() {
for(int i=0; i 0) {
for(int i=0; i < columnIDs.length; ++i){
if(isModified(columnIDs[i])){
return true;
}
}
}
return false;
}
@Override
public boolean isModified(String... columns){
if(null != columns && columns.length > 0) {
for(int i=0; i < columns.length; ++i){
if(isModified(columns[i])){
return true;
}
}
}
return false;
}
@Override
public boolean isModified(String column){
return isModified(metaData.columnIDOf(column));
}
@Override
public boolean isModifiedNested(String nestedName){
if(null == nestedName){
return false;
}
if(isModified(nestedName)){
return true;
}
String prefix = metaData.tablename + ".";
if(nestedName.startsWith(prefix)){
/** remove table name */
nestedName = nestedName.substring(prefix.length());
}
int firstDot = nestedName.indexOf('.');
if(firstDot > 0){
/** 0-firstDot is column name */
return isModified(nestedName.substring(0, firstDot));
} if(firstDot == 0){
/** column name is empty */
return false;
}else {
/** only column name */
return isModified(nestedName);
}
}
@Override
public int[] modifiedColumnIDs(){
List list = Lists.newArrayListWithCapacity(metaData.columnCount);
for(int columnID = 0; columnID < metaData.columnCount;++columnID){
if(isModified(columnID)){
list.add(columnID);
}
}
return Ints.toArray(list);
}
@Override
public String[] modifiedColumns(){
return Iterables.toArray(metaData.columnNamesOf(modifiedColumnIDs()),String.class);
}
@Override
public int modifiedColumnCount(){
return modifiedColumnIDs().length;
}
@Override
public final T getValue(String column) {
return getValue(metaData.columnIDOf(column));
}
@Override
public final T getValueChecked(int columnID) {
T value = getValue(columnID);
return Preconditions.checkNotNull(value,"value of columnid %s IS NULL", columnID);
}
@Override
public final T getValueChecked(String column) {
T value = getValue(column);
return Preconditions.checkNotNull(value,"value of column %s IS NULL", column);
}
@Override
public final void setValue(String column, Object value) {
setValue(metaData.columnIDOf(column),value);
}
@Override
public final boolean setValueIfNonNull(String column, Object value)
{
return setValueIf(value != null,column,value);
}
@Override
public final boolean setValueIfNonEqual(String column, Object value)
{
return setValueIf(!Objects.equals(value, getValue(column)),column,value);
}
@Override
public final boolean setValueIf(boolean expression,String column, Object value)
{
if(expression){
setValue(column,value);
}
return expression;
}
@SuppressWarnings("unchecked")
@Override
public T getValue(int columnID)
{
try {
return (T) metaData.getterMethods.get(columnID).invoke(this);
} catch (IndexOutOfBoundsException e) {
return null;
}catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public T getOriginValue(int columnID)
{
try {
Class> fieldType = metaData.fieldTypeOf(columnID);
Method getter = metaData.getterMethods.get(columnID);
if(getter.getReturnType().isAssignableFrom(fieldType)) {
return (T)getter.invoke(this);
}else {
Method reader = metaData.readMethods.get(columnID);
checkState(null != reader,"NOT DEFINED read method for %s",metaData.columnNameOf(columnID));
return (T) reader.invoke(this);
}
} catch (IndexOutOfBoundsException e) {
return null;
}catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override
@SuppressWarnings("unchecked")
public T getJdbcValue(int columnID)
{
try {
Class> jdbcType = metaData.jdbcTypeOf(columnID);
Method getter = metaData.getterMethods.get(columnID);
if(getter.getReturnType().isAssignableFrom(jdbcType)) {
return (T)getter.invoke(this);
}
Method reader = metaData.readMethods.get(columnID);
if(null != reader) {
if(reader.getReturnType().isAssignableFrom(jdbcType)) {
return (T) reader.invoke(this);
}
if(isBaseColumnType(reader.getReturnType())) {
return (T) BASE_CODEC.serialize(reader.invoke(this), jdbcType);
}
}
ColumnCodec codec = metaData.columnCodecOf(columnID);
if(null != codec) {
return (T) codec.serialize(getOriginValue(columnID), jdbcType);
}
throw new IllegalStateException(String.format("CAN NOT GET VALUE OF %d AS %s",columnID,jdbcType));
} catch (IndexOutOfBoundsException e) {
return null;
}catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
private void setValue(Method setMethod,T value) throws IllegalArgumentException
{
try {
setMethod.invoke(this, value);
} catch ( IllegalArgumentException e) {
if(isBaseColumnType(value)) {
Class> expectType = setMethod.getParameters()[0].getType();
if(isBaseColumnType(expectType)) {
try {
setValue(setMethod,BASE_CODEC.deserialize(value, expectType));
return;
} catch (UnsupportTypeException e2) {
// DO NOTHING
}
}
}
throw e;
}catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override
public void setValue(int columnID,T value)
{
try {
setValue(metaData.setterMethods.get(columnID), value);
} catch (IndexOutOfBoundsException e) {
return ;
}catch ( IllegalArgumentException e) {
Method writeMethod = metaData.writeMethods.get(columnID);
if(null != writeMethod) {
setValue(writeMethod, value);
return;
}
throw e;
}
}
@Override
public final boolean setValueIfNonNull(int columnID,T value)
{
return setValueIf(value != null,columnID,value);
}
@Override
public final boolean setValueIfNonEqual(int columnID,T value)
{
return setValueIf(!Objects.equals(value, getValue(columnID)),columnID,value);
}
@Override
public final boolean setValueIf(boolean expression,int columnID,T value)
{
if(expression){
setValue(columnID,value);
}
return expression;
}
@Override
public Object[] primaryValues()
{
Object[] values = new Object[metaData.primaryKeyCount];
for(int i = 0; i < values.length; ++i) {
values[i] = getValue(metaData.primaryKeyIds[i]);
}
return values;
}
@Override
public T primaryValue()
{
if(metaData.primaryKeyCount != 1) {
throw new UnsupportedOperationException();
}
return getValue(metaData.primaryKeyIds[0]);
}
@Override
public Object[] asValueArray(int...columnIds)
{
if(null == columnIds || columnIds.length == 0){
columnIds = metaData.defaultColumnIdList;
}
Object[] v = new Object[columnIds.length];
for(int i=0; i< v.length; ++i){
v[i] = getValue(columnIds[i]);
}
return v;
}
@Override
public Map asNameValueMap(){
// double check
if(mapView == null){
synchronized (this) {
if(mapView == null){
mapView = new RowMapView(this);
}
}
}
return mapView;
}
@Override
public Map asNameValueMap(boolean ignoreNull,String ...ignoreColumns){
return asNameValueMap(ignoreNull, false,null != ignoreColumns ? Arrays.asList(ignoreColumns) : Collections.emptySet());
}
@Override
public Map asNameValueMap(boolean ignoreNull,IterableignoreColumns){
return asNameValueMap(ignoreNull,false,ignoreColumns);
}
@Override
public Map asNameValueMap(boolean ignoreNull,boolean include,String ...includeColumns){
return asNameValueMap(ignoreNull, include,null != includeColumns ? Arrays.asList(includeColumns) : Collections.emptySet());
}
@Override
public Map asNameValueMap(boolean ignoreNull,final boolean include,Iterablecolumns){
Map map = asNameValueMap();
if(ignoreNull){
map = Maps.filterValues(map, Predicates.notNull());
}
if(null != columns){
final Set names = Sets.filter(Sets.newHashSet(columns),Predicates.notNull());
map = Maps.filterKeys(map, new Predicate() {
@Override
public boolean apply(String input) {
return include ? names.contains(input) : !names.contains(input);
}
});
}
return Maps.newLinkedHashMap(map);
}
@Override
public B copy(B bean)
{
return copy(bean,new int[0]);
}
@SuppressWarnings("unchecked")
@Override
public B copy(B bean, int... fieldList)
{
if(bean != null && bean != this){
for (int columnId:metaData.validColumnIDsOrAll(fieldList)) {
// valid column id only
if( bean.isInitialized(columnId) && !Objects.deepEquals(bean.getValue(columnId), getValue(columnId))){
setValue(columnId, bean.getValue(columnId));
}
}
}
return (B)this;
}
@Override
public B copy(B bean, String... fieldList)
{
return copy(bean, null, fieldList);
}
@SuppressWarnings("unchecked")
@Override
public B copy(B bean, Predicate fieldFilter,int... fieldList)
{
int[] columnIds = filterColumnIDs(fieldFilter,fieldList);
if (null == columnIds || 0 == columnIds.length){
return (B) this;
}
return copy(bean, columnIds);
}
@SuppressWarnings("unchecked")
@Override
public B copy(B bean, Predicate fieldFilter,String... fieldList)
{
int[] columnIds = filterColumnIDs(fieldFilter,fieldList);
if (null == columnIds || 0 == columnIds.length){
return (B) this;
}
return copy(bean, columnIds);
}
@Override
@SuppressWarnings("unchecked")
public B copy(F from,Map columnsMap){
for(Map.Entry entry : checkNotNull(columnsMap,"columnsMap is null").entrySet()){
setValue(entry.getValue(), null == from ? null : from.getValue(entry.getKey()));
}
return (B) this;
}
@SuppressWarnings("unchecked")
public B copy(Mapvalues){
if(null != values){
for(Entry entry : values.entrySet()){
setValue(entry.getKey().intValue(), entry.getValue());
}
}
return (B) this;
}
@Override
public boolean equalColumn(Object object,int columnId)
{
if(!metaData.beanType.isInstance(object)){
return false;
}
BaseBean bean = (BaseBean)object;
if(null != bean){
if(bean != this){
if(metaData.isValidColumnID(columnId)){
// valid column id only
if( bean.isInitialized(columnId) && !Objects.deepEquals(bean.getValue(columnId), getValue(columnId))){
return false;
}
}
}
return true;
}
return false;
}
@Override
public boolean equalColumn(Object object, int... fieldList)
{
if(metaData.beanType.isInstance(object)){
BaseBean bean = (BaseBean)object;
if(bean != this && null != fieldList){
for (int columnId:fieldList) {
// valid column id only
if(metaData.isValidColumnID(columnId)){
if( bean.isInitialized(columnId) && !Objects.deepEquals(bean.getValue(columnId), getValue(columnId))){
return false;
}
}
}
}
return true;
}
return false;
}
@Override
public boolean equalColumn(Object object, Predicate fieldFilter,int... fieldList)
{
return equalColumn(object, filterColumnIDs(fieldFilter,fieldList));
}
@Override
public boolean equalColumn(Object object, Predicate fieldFilter,String... fieldList)
{
return equalColumn(object, filterColumnIDs(fieldFilter,fieldList));
}
private int[] filterColumnIDs(Predicate fieldFilter,int... fieldList){
if(null != fieldList){
if(null != fieldFilter){
Iterable columnIDs = Iterables.filter(Ints.asList(fieldList),fieldFilter);
return Ints.toArray(Lists.newArrayList(columnIDs));
}else {
return fieldList;
}
}
return null;
}
private int[] filterColumnIDs(Predicate fieldFilter,String... fieldList)
{
if(null != fieldList){
Iterable filtered = Iterables.filter(Arrays.asList(fieldList),Predicates.notNull());
if(null != fieldFilter){
filtered = Iterables.filter(filtered,fieldFilter);
}
Iterable columnIDs = Iterables.transform(filtered, metaData.COLUMNID_FUN);
return Ints.toArray(Lists.newArrayList(columnIDs));
}
return null;
}
@Override
public final String tableName() {
return metaData.tablename;
}
/**
* cast byte array to HEX string
*
* @param input
* @return {@code null} if {@code input} is null
*/
private static final String toHex(byte[] input) {
if (null == input){
return null;
}
StringBuffer sb = new StringBuffer(input.length * 2);
for (int i = 0; i < input.length; i++) {
sb.append(Character.forDigit((input[i] & 240) >> 4, 16));
sb.append(Character.forDigit(input[i] & 15, 16));
}
return sb.toString();
}
private static final StringBuilder append(StringBuilder buffer,boolean full,byte[] value){
if(full || null == value){
buffer.append(toHex(value));
}else{
buffer.append(value.length).append(" bytes");
}
return buffer;
}
private static int stringLimit = 64;
private static final int MINIMUM_LIMIT = 16;
private static final StringBuilder append(StringBuilder buffer,boolean full,String value){
if(full || null == value || value.length() <= stringLimit){
buffer.append(value);
}else{
buffer.append(value.substring(0,stringLimit - 8)).append(" ...").append(value.substring(stringLimit-4,stringLimit));
}
return buffer;
}
private static final StringBuilder append(StringBuilder buffer,boolean full,Object value){
if(value instanceof String){
return append(buffer, full, (String)value);
}
if(value instanceof byte[]){
return append(buffer, full, (byte[])value);
}
return buffer.append(value);
}
public static final void setStringLimit(int limit){
checkArgument(limit >= MINIMUM_LIMIT, "INVALID limit %s,minimum value %s",limit,MINIMUM_LIMIT);
stringLimit = limit;
}
@Override
public String toString(boolean notNull, boolean fullIfStringOrBytes) {
StringBuilder builder = new StringBuilder(this.getClass().getName()).append("@").append(Integer.toHexString(this.hashCode())).append("[");
int count = 0;
for(int i = 0; i < metaData.columnCount; ++i){
Object value = getValue(i);
if( !notNull || null != value){
if(count > 0){
builder.append(",");
}
builder.append(metaData.columnNameOf(i)).append("=");
append(builder,fullIfStringOrBytes,value);
++count;
}
}
builder.append("]");
return builder.toString();
}
@Override
public boolean equals(Object object) {
if(!metaData.beanType.isInstance(object)){
return false;
}
BaseBean bean = (BaseBean)object;
EqualsBuilder equalsBuilder = new EqualsBuilder();
for(int i=0; i 0 ? metaData.primaryKeyIds : metaData.defaultColumnIdList;
for(int i=0; i limit){
setValue(columnID, new String(bytes, 0, limit));
}
}
}else if(value instanceof byte[]) {
byte[] bytes = (byte[])value;
if(bytes.length > limit){
setValue(columnID, Arrays.copyOf(bytes,limit));
}
}else if(value instanceof ByteBuffer) {
byte[] bytes = Sql2javaSupport.getBytesInBuffer((ByteBuffer) value);
if(bytes.length > limit){
setValue(columnID, ByteBuffer.wrap(Arrays.copyOf(bytes,limit)));
}
}
}
}
}
/**
* truncate String,binary field
* @param column column name or field name
* @since 3.17.7
*/
public void truncate(String column) {
truncate(metaData.columnIDOf(column));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy