/* * AndFHEM - Open Source Android application to control a FHEM home automation * server. * * Copyright (c) 2011, Matthias Klass or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU GENERAL PUBLIC LICENSE, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU GENERAL PUBLIC LICENSE * for more details. * * You should have received a copy of the GNU GENERAL PUBLIC LICENSE * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package li.klass.fhem.util; import android.content.Context; import android.util.Log; import com.google.common.collect.Lists; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import li.klass.fhem.AndFHEMApplication; import static com.google.common.collect.Lists.newArrayList; public class ReflectionUtil { public static final String TAG = ReflectionUtil.class.getName(); public static List<Field> getFieldsWithAnnotation(Class<?> clazz, Class<? extends Annotation> annotation) { List<Field> result = newArrayList(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); if (field.isAnnotationPresent(annotation)) { result.add(field); } } return result; } public static String getStringForAnnotation(Object object, Class<? extends Annotation> annotation) { List<Field> fields = getFieldsWithAnnotation(object.getClass(), annotation); if (fields.size() != 1) { throw new IllegalArgumentException("expected exactly one occurence for annotation " + annotation.getName() + " in object " + object.toString() + ", but found " + fields.size()); } return getFieldValueAsString(object, fields.get(0)); } public static <T extends Annotation> String getValueAndDescriptionForAnnotation(Object object, Class<T> annotationCls) { Context context = AndFHEMApplication.getContext(); List<Field> fields = getFieldsWithAnnotation(object.getClass(), annotationCls); if (fields.size() == 0) return null; if (fields.size() != 1) { throw new IllegalArgumentException("expected exactly one occurence for annotationCls " + annotationCls.getName() + " in object " + object.toString() + ", but found " + fields.size()); } Field field = fields.get(0); field.setAccessible(true); T annotation = field.getAnnotation(annotationCls); String fieldValue = ""; try { Object value = field.get(object); fieldValue = value == null ? "" : value.toString(); } catch (IllegalAccessException e) { Log.e(ReflectionUtil.class.getName(), "this should never ever happen", e); } try { Method descriptionMethod = annotationCls.getDeclaredMethod("description"); Object result = descriptionMethod.invoke(annotation); if (result != null) { int stringId = Integer.valueOf(result.toString()); if (stringId != -1) fieldValue += " " + context.getString(stringId); } } catch (Exception e) { // don't care. This might be a common case, unfortunately ... } return fieldValue; } public static Object getFieldValue(Object object, Field field) { try { field.setAccessible(true); return field.get(object); } catch (IllegalAccessException e) { Log.e(TAG, "cannot read field " + field.getName(), e); return null; } } public static void setFieldValue(Object object, Field field, Object value) { try { field.setAccessible(true); field.set(object, value); } catch (IllegalAccessException e) { Log.e(TAG, "cannot set field " + field.getName(), e); } } public static void setFieldValue(Object object, String fieldName, Object value) { try { Field field = object.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(object, value); } catch (Exception e) { Log.e(TAG, "cannot set field " + fieldName, e); } } public static String getFieldValueAsString(Object object, Field field) { Object value = getFieldValue(object, field); return String.valueOf(value); } public static String methodNameToFieldName(String methodName) { if (methodName.startsWith("get")) { methodName = methodName.substring("get".length()); } char firstChar = methodName.charAt(0); if (firstChar >= 'A' && firstChar <= 'Z') { methodName = ((char) (firstChar - 'A' + 'a')) + methodName.substring(1); } return methodName; } public static Field findField(Class<?> clazz, String fieldName) { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field; } catch (NoSuchFieldException e) { if (clazz.getSuperclass() != null) { return findField(clazz.getSuperclass(), fieldName); } } return null; } public static List<Field> getAllDeclaredFields(Class<?> type) { return getAllDeclaredFields(Lists.<Field>newArrayList(), type); } private static List<Field> getAllDeclaredFields(List<Field> fields, Class<?> type) { fields.addAll(Arrays.asList(type.getDeclaredFields())); if (type.getSuperclass() != null) { fields = getAllDeclaredFields(fields, type.getSuperclass()); } return fields; } public static List<Method> getAllDeclaredMethods(Class<?> type) { return getAllDeclaredMethods(Lists.<Method>newArrayList(), type); } private static List<Method> getAllDeclaredMethods(List<Method> methods, Class<?> type) { methods.addAll(Arrays.asList(type.getDeclaredMethods())); if (type.getSuperclass() != null) { methods = getAllDeclaredMethods(methods, type.getSuperclass()); } return methods; } public static Class<?> classForName(String className) { try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("cannot find " + className, e); } } }