/*******************************************************************************
* Copyright (C) 2011 by Harry Blauberg
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package org.jaml.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.jaml.api.Defaults;
import org.jaml.container.ClassCache;
import org.jaml.container.ParameterContainer;
import org.jaml.container.PropertyContainer;
import org.jaml.structs.ClassInfo;
public class ReflectionUtils {
public static boolean contains(Object obj, Class<?> clazz) {
return contains(obj.getClass(), clazz);
}
public static boolean contains(Class<?> objClazz, Class<?> clazz) {
for (Class<?> oneClass : getAllInterfacesAndSubClasses(objClazz)) {
if (oneClass == clazz) {
return true;
}
}
return false;
}
public static List<Class<?>> getAllInterfacesAndSubClasses(Object obj) {
return getAllInterfacesAndSubClasses(obj.getClass());
}
public static List<Class<?>> getAllInterfacesAndSubClasses(Class<?> clazz) {
List<Class<?>> allClasses = new LinkedList<Class<?>>();
Class<?> actual = correctIfArray(clazz);
while (actual != null) {
addUniqueClassToList(allClasses, actual.getInterfaces());
addUniqueClassToList(allClasses, actual);
actual = actual.getSuperclass();
}
return allClasses;
}
public static Class<?> correctIfArray(Class<?> clazz) {
return clazz.isArray() ? clazz.getComponentType() : clazz;
}
protected static void addUniqueClassToList(List<Class<?>> list,
Class<?>... classes) {
for (Class<?> clazz : classes) {
if (clazz != null && !list.contains(clazz)) {
list.add(clazz);
}
}
}
public static boolean containsOneOfThem(Class<?> type, Class<?>[] classes) {
for (Class<?> clazz : classes) {
if (contains(type, clazz)) {
return true;
}
}
return false;
}
public static ClassInfo getClassByNamespace(String namespace,
String elementName) {
String classPackage = namespace;
String classSource = null;
if (classPackage.contains(Defaults.namespaceSourceSeparator)) {
String[] parts = classPackage.replace(
Defaults.namespaceSourceSeparator, "#").split("#");
classPackage = parts[0].trim();
classSource = parts[1].trim();
}
classPackage = classPackage.replace(Defaults.namespacePrefix, "")
.replace('/', '.');
return new ClassInfo(classPackage, elementName, classSource);
}
public static String getXMLNamespaceByObject(Object object) {
return Defaults.namespacePrefix
+ object.getClass().getPackage().getName().replace('.', '/');
}
public static ClassInfo getClassByNamespace(QName name) {
return getClassByNamespace(name.getNamespaceURI(), name.getLocalPart());
}
public static Field findFieldByClass(Class<?> clazz, String name) {
Field[] allFields = clazz.getFields();
for (Field field : allFields) {
if (field.getName().equalsIgnoreCase(name)) {
return field;
}
}
return null;
}
public static Map<String, Object> getDifferencingMethodsAndValuesOnly(
Object instance) {
Map<String, Object> map = new HashMap<String, Object>();
Map<String, PropertyContainer> methodMap = createMethodMap(instance
.getClass());
Object[] args = new Object[] {};
Object instanceValue = null;
Object compareValue = null;
Method method = null;
PropertyContainer propContainer = null;
ParameterContainer paramContainer = null;
try {
Object compareObj = instance.getClass().newInstance();
for (String property : methodMap.keySet()) {
propContainer = methodMap.get(property);
if (propContainer.isRW()) {
paramContainer = new ParameterContainer();
paramContainer.add(propContainer.getGetters());
List<Class<?>[]> paramList = paramContainer
.filterByNumber(0);
if (!paramList.isEmpty()) {
method = paramContainer.get(paramList.get(0));
try {
instanceValue = method.invoke(instance, args);
compareValue = method.invoke(compareObj, args);
if (instanceValue != null && compareValue != null
&& !instanceValue.equals(compareValue)
&& !instanceValue.toString().contains("@")) {
map.put(method.getName().substring(3),
instanceValue);
}
} catch (Exception e) {
throw new NullPointerException(property + " -> "
+ e.getClass().getSimpleName() + " ("
+ e.getMessage() + ")");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
public static Map<String, PropertyContainer> createMethodMap(Class<?> clazz) {
Map<String, PropertyContainer> map = new HashMap<String, PropertyContainer>();
String propertyName = null;
PropertyContainer container = null;
for (Method method : clazz.getMethods()) {
if (!Modifier.isStatic(method.getModifiers())
&& method.getName().length() > 3) {
if (method.getName().startsWith("get")
|| method.getName().startsWith("set")
|| method.getName().startsWith("add")) {
propertyName = method.getName().substring(3);
if (!map.containsKey(propertyName)) {
map.put(propertyName, new PropertyContainer());
}
container = map.get(propertyName);
container.add(method);
}
}
}
return map;
}
public static Method searchSetterMethodWithInterface(ClassCache cache,
String attribute, Class<?> interfaceClazz) {
Iterator<Method> iterator = cache.set(attribute);
List<Class<?>> typeList = getAllInterfacesAndSubClasses(interfaceClazz);
Method setter = null;
while (iterator.hasNext()) {
setter = iterator.next();
if (setter.getParameterTypes().length == 1
&& setter.getParameterTypes()[0].isInterface()
&& typeList.contains(setter.getParameterTypes()[0])) {
return setter;
}
}
return null;
}
public static Method searchSetterMethod(ClassCache cache, String attribute,
Class<?> clazz) {
Iterator<Method> iterator = cache.set(attribute);
Method setter = null;
while (iterator.hasNext()) {
setter = iterator.next();
if (setter.getParameterTypes().length == 1
&& (setter.getParameterTypes()[0] == clazz || setter
.getParameterTypes()[0] == getPrimitiveTypeIfFound(clazz))) {
return setter;
}
}
return searchSetterMethodWithInterface(cache, attribute, clazz);
}
public static Class<?> getPrimitiveTypeIfFound(Class<?> clazz) {
try {
Class<?> primitive = (Class<?>) clazz.getField("TYPE").get(null);
return primitive;
} catch (Exception ex) {
return clazz;
}
}
}