/* * Copyright 2011 Eric F. Savage, code@efsavage.com * * 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.ajah.util.reflect; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Date; import java.util.logging.Level; import lombok.extern.java.Log; import com.ajah.util.AjahUtils; import com.ajah.util.Identifiable; import com.ajah.util.StringUtils; import com.ajah.util.date.DateUtils; /** * @author <a href="http://efsavage.com">Eric F. Savage</a>, <a * href="mailto:code@efsavage.com">code@efsavage.com</a>. */ @Log public class ReflectionUtils { /** * Finds the enum where the getId() value matches the value of the field for * this particular object. * * @param field * The field to get the value of. * @param value * The value of the field. * @return The value, null if the field value is null, also null on error. */ public static Object findEnumById(final Field field, final Object value) { if (!IntrospectionUtils.isIdentifiableEnum(field)) { throw new IllegalArgumentException("Field " + field.getName() + " is not an Identifiable enum"); } if (value == null) { return null; } final Object[] elements = field.getType().getEnumConstants(); for (final Object element : elements) { if (((Identifiable<?>) element).getId().equals(value)) { if (log.isLoggable(Level.FINEST)) { log.finest("Matched: " + element.toString()); } return element; } } if (log.isLoggable(Level.FINEST)) { log.finest("No Match for " + value); } return null; } /** * Executes the read method for a property descriptor, and returns as a * {@link Date}. If any errors occur they are logged, and will result in * null return value. * * @param instance * The instance on which the Property Descriptor is. * @param propertyDescriptor * The property descriptor for the property sought. * @return The value of the objects read method for the property specified * (which may be null), or null if an error occurs. */ public static Date propGetDateSafe(final Object instance, final PropertyDescriptor propertyDescriptor) { final Object value = ReflectionUtils.propGetSafe(instance, propertyDescriptor); if (value == null || !(value instanceof Date)) { return null; } return (Date) value; } /** * Executes the read method for a property descriptor. If any errors occur * they are logged, and will result in null return value. * * @param instance * @param propertyDescriptor * @return The value of the objects read method for the property specified * (which may be null), or null if an error occurs. */ public static Object propGetSafe(final Object instance, final PropertyDescriptor propertyDescriptor) { AjahUtils.requireParam(instance, "instance"); AjahUtils.requireParam(propertyDescriptor, "propertyDescriptor"); try { final Method getter = propertyDescriptor.getReadMethod(); if (getter != null) { return getter.invoke(instance); } log.log(Level.SEVERE, "No read method found for " + propertyDescriptor.getName() + " on class " + instance.getClass().getName()); } catch (final RuntimeException e) { log.log(Level.SEVERE, propertyDescriptor.getName() + ": " + e.getMessage(), e); } catch (final IllegalAccessException e) { log.log(Level.SEVERE, propertyDescriptor.getName() + ": " + e.getMessage(), e); } catch (final InvocationTargetException e) { log.log(Level.SEVERE, propertyDescriptor.getName() + ": " + e.getMessage(), e); } return null; } /** * Returns the value of a property descriptor, or null if an error occurs. * * @param object * The object instance to invoke the property descriptor on * @param field * The field of the class of the object that corresponds with the * property descriptor. * @param propertyDescriptor * The property descriptor to invoke on the object. * @return The value of a property descriptor, or null if an error occurs. */ public static Object propGetSafeAuto(final Object object, final Field field, final PropertyDescriptor propertyDescriptor) { if (IntrospectionUtils.isString(field)) { // It's a string return ReflectionUtils.propGetSafe(object, propertyDescriptor); } else if (IntrospectionUtils.isDate(field)) { // It's a date return DateUtils.safeToLong(ReflectionUtils.propGetDateSafe(object, propertyDescriptor)); } else if (IntrospectionUtils.isToStringable(field)) { // It's toStringable return StringUtils.safeToString(ReflectionUtils.propGetSafe(object, propertyDescriptor)); } else if (IntrospectionUtils.isIdentifiable(field)) { // It's identifiable final Identifiable<?> identifiable = ((Identifiable<?>) ReflectionUtils.propGetSafe(object, propertyDescriptor)); if (identifiable == null) { return null; } return StringUtils.safeToString(identifiable.getId()); } else if (IntrospectionUtils.isInt(field)) { // It's an int return ReflectionUtils.propGetSafe(object, propertyDescriptor); } else if (IntrospectionUtils.isLong(field)) { // It's a long return ReflectionUtils.propGetSafe(object, propertyDescriptor); } else if (IntrospectionUtils.isDouble(field)) { // It's a double return ReflectionUtils.propGetSafe(object, propertyDescriptor); } else if (IntrospectionUtils.isBoolean(field)) { // It's a boolean return ReflectionUtils.propGetSafe(object, propertyDescriptor); } else if (IntrospectionUtils.isBigDecimal(field)) { // It's a BigDecimal return ReflectionUtils.propGetSafe(object, propertyDescriptor); } else { log.warning("Can't handle property getting of type " + field.getType() + " for field " + field.getName()); return ReflectionUtils.propGetSafe(object, propertyDescriptor); } } }