/******************************************************************************* * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * committers of openArchitectureWare - initial API and implementation *******************************************************************************/ package org.eclipse.emf.mwe.internal.core.debug.mwe; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Provides static helper methods to deal with element fields using reflection. */ public class ReflectionUtil { private static final Map<String, Map<String, Field>> fieldDictionary = new HashMap<String, Map<String, Field>>(); // ------------------------------------------------------------------------- private ReflectionUtil() { } // ------------------------------------------------------------------------- /** * return a String representation of the element. It is "null", the content of a String or the simple class * name for all other types.<br> * Hint: Primitives wrapper classes are not handled specially, so the result is not the primitive value but * the class name. But since getFieldValue(..) returns a String representation of primitives, this should not * be a problem here. * * @param element the element * @return the string representation */ public static String getSimpleName(Object element) { return (element == null ? "null" : (element instanceof String) ? (String) element : getSimpleClassName(element)); } /** * Null save toString * @param element the element * @return the string representation */ public static String getNameToString(Object element) { return (element == null ? "null" : element.toString()); } /** * check if the element has member fields. For an array it checks if it is not empty. * * @param element the element * @return yes or no */ public static boolean checkFields(Object element) { if (element == null || element instanceof String) return false; if (Object[].class.isAssignableFrom(element.getClass())) return ((Object[]) element).length > 0; Map<String, Field> fields = getFieldMap(element.getClass()); return !fields.isEmpty(); } /** * returns a list of names of the fields. For an array it returns "[i]" as name where i is the position in the * array. * * @param element * @return */ public static List<String> getFieldNames(Object element) { List<String> result = new ArrayList<String>(); if (element instanceof Object[]) for (int i = 0; i < ((Object[]) element).length; i++) result.add("[" + i + "]"); else result.addAll(getFieldMap(element.getClass()).keySet()); return result; } /** * Returns the value of a field of an object.<br> * For primitives it returns a string representation.<br> * It returns null in case of any exceptions. * * @param object the questioned object * @param name the name of the field * @return the value */ public static Object getFieldValue(Object object, String name) { try { Field field = getField(object, name); Class<?> type = field.getType(); if (type.isPrimitive() || (type == String.class)) return field.get(object).toString(); return field.get(object); } catch (Exception e) { // IllegalAccessException and NullPointerException } return null; } // ------------------------------------------------------------------------- // similar to getClass().getSimpleName(), but handles arrays differently private static String getSimpleClassName(Object element) { String fqn = element.getClass().getName(); int index = fqn.lastIndexOf('.'); if (element instanceof Object[]) return fqn.substring(index + 1, fqn.length() - 1) + "[" + ((Object[]) element).length + "]"; return fqn.substring(index + 1); } private static Field getField(Object object, String name) { try { return getFieldMap(object.getClass()).get(name); } catch (Exception e) { } return null; } // collect all declared fields (also private and static) of a class and it's super classes // cache the map by class for multiple use. private static synchronized Map<String, Field> getFieldMap(final Class<?> cls) { final String clsName = cls.getName(); if (!fieldDictionary.containsKey(clsName)) { final Map<String, Field> fieldMap = new HashMap<String, Field>(); Class<?> clazz = cls; while (!Object.class.equals(clazz)) { Field[] fields = cls.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; field.setAccessible(true); // super class fields are not considered if the same name was already in an inheriting class if (!fieldMap.containsKey(field.getName())) fieldMap.put(field.getName(), field); } clazz = clazz.getSuperclass(); } fieldDictionary.put(clsName, fieldMap); } return fieldDictionary.get(clsName); } }