org.dbflute.helper.beans.impl.DfPropertyDescImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dbflute-runtime Show documentation
Show all versions of dbflute-runtime Show documentation
The runtime library of DBFlute
/*
* Copyright 2014-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.dbflute.helper.beans.impl;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import org.dbflute.helper.beans.DfBeanDesc;
import org.dbflute.helper.beans.DfPropertyDesc;
import org.dbflute.helper.beans.exception.DfBeanIllegalPropertyException;
import org.dbflute.helper.message.ExceptionMessageBuilder;
import org.dbflute.util.DfReflectionUtil;
import org.dbflute.util.DfTypeUtil;
/**
* @author modified by jflute (originated in S2Dao)
*/
public class DfPropertyDescImpl implements DfPropertyDesc {
// ===================================================================================
// Definition
// ==========
protected static final Object[] EMPTY_ARGS = new Object[0];
// ===================================================================================
// Attribute
// =========
protected final DfBeanDesc _beanDesc;
protected final String _propertyName;
protected final Class> _propertyType;
protected Method _readMethod;
protected Method _writeMethod;
protected Field _field;
protected Constructor> _stringConstructor;
protected Method _valueOfMethod;
protected boolean _readable;
protected boolean _writable;
// ===================================================================================
// Constructor
// ===========
public DfPropertyDescImpl(DfBeanDesc beanDesc, String propertyName, Class> propertyType, Method readMethod, Method writeMethod,
Field field) {
if (propertyName == null) {
String msg = "The argument 'propertyName' should not be null!";
throw new IllegalArgumentException(msg);
}
if (propertyType == null) {
String msg = "The argument 'propertyType' should not be null!";
throw new IllegalArgumentException(msg);
}
_beanDesc = beanDesc;
_propertyName = propertyName;
_propertyType = propertyType;
setReadMethod(readMethod);
setWriteMethod(writeMethod);
setField(field);
setupStringConstructor();
setupValueOfMethod();
}
protected void setupStringConstructor() {
final Constructor>[] cons = _propertyType.getConstructors();
for (int i = 0; i < cons.length; ++i) {
final Constructor> con = cons[i];
if (con.getParameterTypes().length == 1 && con.getParameterTypes()[0].equals(String.class)) {
_stringConstructor = con;
break;
}
}
}
protected void setupValueOfMethod() {
final Method[] methods = _propertyType.getMethods();
for (int i = 0; i < methods.length; ++i) {
final Method method = methods[i];
if (DfReflectionUtil.isBridgeMethod(method) || DfReflectionUtil.isSyntheticMethod(method)) {
continue;
}
if (DfReflectionUtil.isStatic(method.getModifiers()) && method.getName().equals("valueOf")
&& method.getParameterTypes().length == 1 && method.getParameterTypes()[0].equals(String.class)) {
_valueOfMethod = method;
break;
}
}
}
// ===================================================================================
// Bean
// ====
public DfBeanDesc getBeanDesc() {
return _beanDesc;
}
// ===================================================================================
// Property
// ========
public final String getPropertyName() {
return _propertyName;
}
public final Class> getPropertyType() {
return _propertyType;
}
public final Class> getGenericType() {
if (_readMethod != null) {
return DfReflectionUtil.getGenericFirstClass(_readMethod.getGenericReturnType());
}
return null;
}
// ===================================================================================
// Method
// ======
public final Method getReadMethod() {
return _readMethod;
}
public final void setReadMethod(Method readMethod) {
_readMethod = readMethod;
if (readMethod != null) {
_readable = true;
}
}
public final boolean hasReadMethod() {
return _readMethod != null;
}
public final Method getWriteMethod() {
return _writeMethod;
}
public final void setWriteMethod(Method writeMethod) {
_writeMethod = writeMethod;
if (writeMethod != null) {
_writable = true;
}
}
public final boolean hasWriteMethod() {
return _writeMethod != null;
}
// ===================================================================================
// Field
// =====
public Field getField() {
return _field;
}
public void setField(Field field) {
_field = field;
if (field != null && DfReflectionUtil.isPublic(field.getModifiers())) {
_readable = true;
_writable = true;
}
}
// ===================================================================================
// Value
// =====
/** {@inheritDoc} */
public final Object getValue(Object target) {
if (!_readable) {
throwPropertyNotReadableException(target);
}
try {
if (hasReadMethod()) {
return DfReflectionUtil.invoke(_readMethod, target, EMPTY_ARGS);
} else {
return DfReflectionUtil.getValue(_field, target);
}
} catch (RuntimeException e) {
throwPropertyReadFailureException(target, e);
return null; // unreachable
}
}
protected void throwPropertyNotReadableException(Object target) {
final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
br.addNotice("The property is not readable.");
setupExceptionBasicInfo(br);
br.addItem("Target Object");
br.addElement(target != null ? target.getClass() : null);
br.addElement(target);
final String msg = br.buildExceptionMessage();
throw new DfBeanIllegalPropertyException(msg);
}
protected void throwPropertyReadFailureException(Object target, RuntimeException e) {
final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
br.addNotice("Failed to read the property.");
setupExceptionBasicInfo(br);
br.addItem("Target Object");
br.addElement(target != null ? target.getClass() : null);
br.addElement(target);
final String msg = br.buildExceptionMessage();
throw new DfBeanIllegalPropertyException(msg, e);
}
/** {@inheritDoc} */
public final void setValue(Object target, Object value) {
if (!_writable) {
throwPropertyNotWritableException(target, value);
}
try {
value = convertIfNeed(value);
if (hasWriteMethod()) {
DfReflectionUtil.invoke(_writeMethod, target, new Object[] { value });
} else {
DfReflectionUtil.setValue(_field, target, value);
}
} catch (RuntimeException e) {
throwPropertyWriteFailureException(target, value, e);
}
}
protected void throwPropertyNotWritableException(Object target, Object value) {
final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
br.addNotice("The property is not writable.");
setupExceptionBasicInfo(br);
br.addItem("Target Object");
br.addElement(target != null ? target.getClass() : null);
br.addElement(target);
br.addItem("Wrote Object");
br.addElement(value != null ? value.getClass() : null);
br.addElement(value);
final String msg = br.buildExceptionMessage();
throw new DfBeanIllegalPropertyException(msg);
}
protected void throwPropertyWriteFailureException(Object target, Object value, RuntimeException e) {
final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
br.addNotice("Failed to write the property.");
setupExceptionBasicInfo(br);
br.addItem("Target Object");
br.addElement(target != null ? target.getClass() : null);
br.addElement(target);
br.addItem("Wrote Object");
br.addElement(value != null ? value.getClass() : null);
br.addElement(value);
final String msg = br.buildExceptionMessage();
throw new DfBeanIllegalPropertyException(msg, e);
}
protected void setupExceptionBasicInfo(ExceptionMessageBuilder br) {
br.addItem("Bean Class");
br.addElement(_beanDesc.getBeanClass());
br.addElement("property count: " + _beanDesc.getPropertyDescSize());
br.addElement("property list: " + _beanDesc.getProppertyNameList());
br.addItem("Property");
br.addElement(_propertyName);
br.addElement(_propertyType);
br.addElement("hash: " + Integer.toHexString(hashCode()));
br.addItem("Readable?");
br.addElement(_readable);
br.addElement(_readMethod);
br.addItem("Writable?");
br.addElement(_writable);
br.addElement(_writeMethod);
br.addItem("Field?");
br.addElement(_field);
}
// ===================================================================================
// Determination
// =============
public boolean isReadable() {
return _readable;
}
public boolean isWritable() {
return _writable;
}
// ===================================================================================
// Convert
// =======
public Object convertIfNeed(Object arg) { // #date_parade
if (_propertyType.isPrimitive()) {
return DfTypeUtil.toWrapper(arg, _propertyType);
} else if (Number.class.isAssignableFrom(_propertyType)) {
return DfTypeUtil.toNumber(arg, _propertyType);
} else if (java.util.Date.class.isAssignableFrom(_propertyType)) {
return convertDate(arg);
} else if (LocalDate.class.isAssignableFrom(_propertyType)) {
return DfTypeUtil.toLocalDate(arg);
} else if (LocalDateTime.class.isAssignableFrom(_propertyType)) {
return DfTypeUtil.toLocalDateTime(arg);
} else if (LocalTime.class.isAssignableFrom(_propertyType)) {
return DfTypeUtil.toLocalTime(arg);
} else if (Boolean.class.isAssignableFrom(_propertyType)) {
return DfTypeUtil.toBoolean(arg);
} else if (arg != null && arg.getClass() != String.class && String.class == _propertyType) {
return arg.toString();
} else if (arg instanceof String && !String.class.equals(_propertyType)) {
return convertWithString(arg);
} else if (java.util.Calendar.class.isAssignableFrom(_propertyType)) {
return DfTypeUtil.toCalendar(arg);
}
return arg;
}
protected Object convertDate(Object arg) {
if (_propertyType == java.util.Date.class) {
return DfTypeUtil.toDate(arg);
} else if (_propertyType == Timestamp.class) {
return DfTypeUtil.toTimestamp(arg);
} else if (_propertyType == java.sql.Date.class) {
return DfTypeUtil.toDate(arg);
} else if (_propertyType == Time.class) {
return DfTypeUtil.toTime(arg);
}
return arg;
}
protected Object convertWithString(Object arg) {
if (_stringConstructor != null) {
return DfReflectionUtil.newInstance(_stringConstructor, new Object[] { arg });
}
if (_valueOfMethod != null) {
return DfReflectionUtil.invoke(_valueOfMethod, null, new Object[] { arg });
}
return arg;
}
// ===================================================================================
// Basic Override
// ==============
@Override
public final String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("property:{");
sb.append(_propertyName);
sb.append(", ").append(_propertyType.getName());
sb.append(", reader=").append(_readMethod != null ? _readMethod.getName() : null);
sb.append(", writer=").append(_writeMethod != null ? _writeMethod.getName() : null);
sb.append("}@").append(Integer.toHexString(hashCode()));
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy