Java tutorial
/* * Copyright (C) 2008 feilong * * 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 com.feilong.core.bean; import java.util.Collection; import java.util.Map; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.beanutils.PropertyUtilsBean; import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.feilong.core.lang.ClassUtil; import static com.feilong.core.Validator.isNotNullOrEmpty; import static com.feilong.core.Validator.isNullOrEmpty; import static com.feilong.core.util.MapUtil.newLinkedHashMap; /** * {@link org.apache.commons.beanutils.PropertyUtils}??. * * <p> * ? checkedException ?? {@link BeanUtilException} * </p> * * <h3>{@link PropertyUtils} {@link BeanUtils}:</h3> * * <blockquote> * <p> * {@link PropertyUtils}{@link BeanUtils}??,??.<br> * {@link BeanUtils}??"Bean",{@link String},<br> * {@link PropertyUtils}??,{@link Object}. * </p> * </blockquote> * * @author <a href="http://feitianbenyue.iteye.com/">feilong</a> * @see org.apache.commons.beanutils.PropertyUtils * @see com.feilong.core.bean.BeanUtil * @since 1.0.0 */ public final class PropertyUtil { /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(PropertyUtil.class); /** Don't let anyone instantiate this class. */ private PropertyUtil() { //AssertionError?. ?????. ???. //see Effective Java 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } /** * <code>fromObj</code>,?<code>toObj</code>. * * <h3>??:</h3> * <blockquote> * <p> * <code>includePropertyNames</code>?,{@link PropertyUtils#copyProperties(Object, Object)},<br> * ? {@link #getProperty(Object, String)}?{@link #setProperty(Object, String, Object)}<code>toObj</code> * </p> * </blockquote> * * <h3>?:</h3> * * <blockquote> * * <ol> * <li> <code>toObj</code> null, {@link NullPointerException}</li> * <li> <code>fromObj</code> null, {@link NullPointerException}</li> * <li><code>includePropertyNames</code>,? <code>fromObj</code>??,</li> * <li><code>includePropertyNames</code>,? <code>fromObj</code>, <code>toObj</code>??,,see * {@link PropertyUtilsBean#setSimpleProperty(Object, String, Object) copyProperties} Line2078</li> * <li>Date,<span style="color:red">??converter</span></li> * <li>?copy <span style="color:red">?</span>,??2Bean???ref,??, .</li> * </ol> * </blockquote> * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * User oldUser = new User(); * oldUser.setId(5L); * oldUser.setMoney(new BigDecimal(500000)); * oldUser.setDate(new Date()); * oldUser.setNickName(ConvertUtil.toArray("feilong", "", "venusdrogon")); * * User newUser = new User(); * PropertyUtil.copyProperties(newUser, oldUser, "date", "money", "nickName"); * LOGGER.debug(JsonUtil.format(newUser)); * </pre> * * : * * <pre class="code"> * { "date": "2015-09-06 13:27:43", "id": 0, "nickName": [ "feilong", "", "venusdrogon" ], "age": 0, "name": "feilong", "money": 500000, "userInfo": {"age": 0} } * </pre> * * </blockquote> * * <h3>{@link BeanUtils#copyProperties(Object, Object)} {@link PropertyUtils#copyProperties(Object, Object)}</h3> * * <blockquote> * <ul> * <li>{@link BeanUtils#copyProperties(Object, Object) BeanUtils} ???,??JavaBean?????,???,<br> * {@link PropertyUtils#copyProperties(Object, Object) PropertyUtils}??,.</li> * <li>commons-beanutils v1.9.0? BeanUtils?? null,PropertyUtils?? null.<br> * (<b>:</b>commons-beanutils v1.9.0+?,BeanUtilsBean.copyProperties() no longer throws a ConversionException for null properties * of certain data types),?commons-beanutils * <a href="http://commons.apache.org/proper/commons-beanutils/javadocs/v1.9.2/RELEASE-NOTES.txt">RELEASE-NOTES.txt</a></li> * </ul> * </blockquote> * * @param toObj * * @param fromObj * * @param includePropertyNames * ???,(can be nested/indexed/mapped/combo)<br> * nullempty, {@link PropertyUtils#copyProperties(Object, Object)} * @see #setProperty(Object, String, Object) * @see BeanUtil#copyProperties(Object, Object, String...) * @see org.apache.commons.beanutils.PropertyUtilsBean#copyProperties(Object, Object) * @see <a href="http://www.cnblogs.com/kaka/archive/2013/03/06/2945514.html">Bean??(Apache BeanUtils?PropertyUtils,Spring * BeanUtils,Cglib BeanCopier)</a> * @since 1.4.1 */ public static void copyProperties(Object toObj, Object fromObj, String... includePropertyNames) { Validate.notNull(toObj, "toObj [destination bean] not specified!"); Validate.notNull(fromObj, "fromObj [origin bean] not specified!"); if (isNullOrEmpty(includePropertyNames)) { try { PropertyUtils.copyProperties(toObj, fromObj); return; } catch (Exception e) { throw new BeanUtilException(e); } } for (String propertyName : includePropertyNames) { Object value = getProperty(fromObj, propertyName); setProperty(toObj, propertyName, value); } } /** * <code>bean</code> <code>propertyNames</code><span style="color:green">?</span>,??/ * {@link java.util.LinkedHashMap LinkedHashMap} . * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * * User user = new User(); * user.setId(5L); * user.setDate(new Date()); * * LOGGER.debug("map:{}", JsonUtil.format(PropertyUtil.describe(user))); * * </pre> * * <b>:</b> * * <pre class="code"> { "id": 5, "name": "feilong", "age": null, "date": "2016-07-13 22:18:26" } * </pre> * * <hr> * * <p> * ???: * </p> * * <pre class="code"> * * User user = new User(); * user.setId(5L); * user.setDate(new Date()); * * LOGGER.debug("map:{}", JsonUtil.format(PropertyUtil.describe(user, "date", "id"))); * * </pre> * * ????: * * <pre class="code"> { "date": "2016-07-13 22:21:24", "id": 5 } * </pre> * * </blockquote> * * <h3>:</h3> * <blockquote> * <ol> * <li> the entire set of properties for which the specified bean provides a read method.</li> * <li>???class,Object??,classjava.lang.Object</li> * <li> <code>propertyNames</code>null empty,?</li> * <li>mapkey <code>propertyNames</code> ?</li> * </ol> * </blockquote> * * <h3>?:</h3> * * <blockquote> * <ol> * <li>?bean class {@link java.beans.PropertyDescriptor}</li> * <li>, {@link java.beans.PropertyDescriptor#getReadMethod()}</li> * <li> name and {@link org.apache.commons.beanutils.PropertyUtilsBean#getProperty(Object, String)} map</li> * </ol> * </blockquote> * * @param bean * Bean whose properties are to be extracted * @param propertyNames * ?? (can be nested/indexed/mapped/combo),?? <a href="../BeanUtil.html#propertyName">propertyName</a> * @return <code>propertyNames</code> nullempty, {@link PropertyUtils#describe(Object)}<br> * @throws NullPointerException * <code>bean</code> null * @see org.apache.commons.beanutils.BeanUtils#describe(Object) * @see org.apache.commons.beanutils.PropertyUtils#describe(Object) * @since 1.8.0 */ public static Map<String, Object> describe(Object bean, String... propertyNames) { Validate.notNull(bean, "bean can't be null!"); if (isNullOrEmpty(propertyNames)) { try { return PropertyUtils.describe(bean); } catch (Exception e) { throw new BeanUtilException(e); } } Map<String, Object> map = newLinkedHashMap(propertyNames.length); for (String propertyName : propertyNames) { map.put(propertyName, getProperty(bean, propertyName)); } return map; } /** * {@link PropertyUtils#setProperty(Object, String, Object)} ?bean(<b>??</b>). * * <p> * no matter which property reference format is used, with no type conversions. * </p> * * <h3>:</h3> * * <blockquote> * * <pre class="code"> * * User newUser = new User(); * PropertyUtil.setProperty(newUser, "name", "feilong"); * LOGGER.info(JsonUtil.format(newUser)); * * </pre> * * <b>:</b> * * <pre class="code"> * { * "age": 0, * "name": "feilong" * } * </pre> * * </blockquote> * * <h3>?:</h3> * * <blockquote> * * <ol> * <li> <code>bean</code> null, {@link NullPointerException}</li> * <li> <code>propertyName</code> null, {@link NullPointerException}</li> * <li> <code>propertyName</code> blank, {@link IllegalArgumentException}</li> * <li><code>bean</code> <code>propertyName</code>??,,see * {@link PropertyUtilsBean#setSimpleProperty(Object, String, Object) setSimpleProperty} Line2078</li> * <li>Date,<span style="color:red">??converter</span></li> * </ol> * </blockquote> * * @param bean * Bean whose property is to be modified * @param propertyName * ?? (can be nested/indexed/mapped/combo),?? <a href="../BeanUtil.html#propertyName">propertyName</a> * @param value * Value to which this property is to be set * @see org.apache.commons.beanutils.BeanUtils#setProperty(Object, String, Object) * @see org.apache.commons.beanutils.PropertyUtils#setProperty(Object, String, Object) * @see BeanUtil#setProperty(Object, String, Object) */ public static void setProperty(Object bean, String propertyName, Object value) { Validate.notNull(bean, "bean can't be null!"); Validate.notBlank(propertyName, "propertyName can't be null!"); try { PropertyUtils.setProperty(bean, propertyName, value); } catch (Exception e) { throw new BeanUtilException(e); } } /** * <code>value</code> isNotNullOrEmpty,? {@link #setProperty(Object, String, Object)}. * * <h3>?:</h3> * * <blockquote> * * <ol> * <li> <code>bean</code> null, {@link NullPointerException}</li> * <li> <code>propertyName</code> null, {@link NullPointerException}</li> * <li> <code>propertyName</code> blank, {@link IllegalArgumentException}</li> * <li><code>bean</code> <code>propertyName</code>??,,see * {@link PropertyUtilsBean#setSimpleProperty(Object, String, Object)} Line2078</li> * <li>Date,<span style="color:red">??converter</span></li> * </ol> * </blockquote> * * @param bean * Bean whose property is to be modified * @param propertyName * ?? (can be nested/indexed/mapped/combo),?? <a href="../BeanUtil.html#propertyName">propertyName</a> * @param value * Value to which this property is to be set * @since 1.5.3 */ public static void setPropertyIfValueNotNullOrEmpty(Object bean, String propertyName, Object value) { if (isNotNullOrEmpty(value)) { setProperty(bean, propertyName, value); } } /** * <code>null != value</code>,? {@link #setProperty(Object, String, Object)}. * * <h3>?:</h3> * * <blockquote> * * <ol> * <li> <code>bean</code> null, {@link NullPointerException}</li> * <li> <code>propertyName</code> null, {@link NullPointerException}</li> * <li> <code>propertyName</code> blank, {@link IllegalArgumentException}</li> * <li><code>bean</code> <code>propertyName</code>??,,see * {@link PropertyUtilsBean#setSimpleProperty(Object, String, Object)} Line2078</li> * <li>Date,<span style="color:red">??converter</span></li> * </ol> * </blockquote> * * @param bean * Bean whose property is to be modified * @param propertyName * ?? (can be nested/indexed/mapped/combo),?? <a href="../BeanUtil.html#propertyName">propertyName</a> * @param value * Value to which this property is to be set * @see #setProperty(Object, String, Object) * @since 1.5.3 */ public static void setPropertyIfValueNotNull(Object bean, String propertyName, Object value) { if (null != value) { setProperty(bean, propertyName, value); } } // [start] getProperty /** * {@link PropertyUtils#getProperty(Object, String)} bean???. * * <p> * no matter which property reference format is used, with no type conversions.<br> * For more details see {@link PropertyUtilsBean}. * </p> * * @param <T> * the generic type * @param bean * Bean whose property is to be extracted * @param propertyName * ?? (can be nested/indexed/mapped/combo),?? <a href="../BeanUtil.html#propertyName">propertyName</a> * @return <code>bean</code> null, {@link NullPointerException}<br> * <code>propertyName</code> null, {@link NullPointerException}<br> * <code>propertyName</code> blank, {@link IllegalArgumentException}<br> * ? {@link PropertyUtils#getProperty(Object, String)} ? * @see BeanUtil#getProperty(Object, String) * @see org.apache.commons.beanutils.BeanUtils#getProperty(Object, String) * @see org.apache.commons.beanutils.PropertyUtils#getProperty(Object, String) * @see org.apache.commons.beanutils.PropertyUtilsBean */ @SuppressWarnings("unchecked") public static <T> T getProperty(Object bean, String propertyName) { Validate.notNull(bean, "bean can't be null!"); Validate.notBlank(propertyName, "propertyName can't be blank!"); try { return (T) PropertyUtils.getProperty(bean, propertyName); } catch (Exception e) { throw new BeanUtilException(e); } } // [end] /** * <code>Object obj</code>,. * * <h3>:</h3> * <blockquote> * * <pre class="code"> * User user = new User(); * user.setId(5L); * Date now = new Date(); * user.setDate(now); * * user.getUserInfo().setAge(28); * * LOGGER.info(JsonUtil.format(PropertyUtil.findValueOfType(user, UserInfo.class))); * </pre> * * <b>:</b> * * <pre class="code"> * {"age": 28} * </pre> * * </blockquote> * * <h3>??:</h3> * * <blockquote> * <ol> * <li> <code>ClassUtil.isInstance(findValue, toBeFindedClassType)</code> findValue</li> * <li><code>isPrimitiveOrWrapper</code>,<code>CharSequence</code>,<code>Collection</code>,<code>Map</code></li> * <li> {@link PropertyUtil#describe(Object, String...)} ?</li> * </ol> * </blockquote> * * <p> * PS:?????,?? {@link #isDonotSupportFindType(Object)},,? {@link * "org.springframework.util.CollectionUtils#findValueOfType(Collection, Class)"} * </p> * * @param <T> * the generic type * @param obj * ? * @param toBeFindedClassType * the to be finded class type * @return ?,? <code>null</code><br> * <code>obj</code> null,null<br> * <code>toBeFindedClassType</code> null, {@link NullPointerException}<br> * <code>ClassUtil.isInstance(obj, toBeFindedClassType)</code>, <code>obj</code><br> * @see "org.springframework.util.CollectionUtils#findValueOfType(Collection, Class)" * @since 1.4.1 */ @SuppressWarnings("unchecked") public static <T> T findValueOfType(Object obj, Class<T> toBeFindedClassType) { if (isNullOrEmpty(obj)) { return null; } Validate.notNull(toBeFindedClassType, "toBeFindedClassType can't be null/empty!"); if (ClassUtil.isInstance(obj, toBeFindedClassType)) { return (T) obj; } if (isDonotSupportFindType(obj)) { LOGGER.debug("obj:[{}] not support find toBeFindedClassType:[{}]", obj.getClass().getName(), toBeFindedClassType.getName()); return null; } //****************************************************************************** Map<String, Object> describe = describe(obj); for (Map.Entry<String, Object> entry : describe.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); if (null != value && !"class".equals(key)) { //? T t = findValueOfType(value, toBeFindedClassType); if (null != t) { return t; } } } return null; } /** * command ? string int,list map. * * <p> * ,?? findedClassType * </p> * * @param obj * the obj * @return true, if checks if is can find type * @since 1.6.3 */ private static boolean isDonotSupportFindType(Object obj) { //command ? string int,list map //,?? findedClassType return ClassUtils.isPrimitiveOrWrapper(obj.getClass())// || ClassUtil.isInstanceAnyClass(obj, CharSequence.class, Collection.class, Map.class); } }