/*
* This file is part of Alida, a Java library for
* Advanced Library for Integrated Development of Data Analysis Applications.
*
* Copyright (C) 2010 - @YEAR@
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Fore more information on Alida, visit
*
* http://www.informatik.uni-halle.de/alida/
*
*/
/*
* Most recent change(s):
*
* $Rev$
* $Date$
* $Author$
*
*/
package de.unihalle.informatik.Alida.dataio.provider.helpers;
import de.unihalle.informatik.Alida.annotations.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
/**
* Helper class to configure and handle parametrized class objects.
*
* @author posch
* @author moeller
*
*/
public class ALDParametrizedClassDataIOHelper {
/** Return all fields for member variables of <code>myclass</code> or any of its super classes
* which is annotated with {@link ALDClassParameter}.
*
* @param myclass
* @return fields of annotated member variables
*/
public static HashMap<String,Field> getAnnotatedFields( Class<?> myclass) {
HashMap<String,Field> fieldMap = new HashMap<String,Field>();
// loop for this class and all super classes over all declared fields to find Annotations
Class<?> currentClass = myclass;
do {
for ( Field field : currentClass.getDeclaredFields() ) {
String name = field.getName();
ALDClassParameter pAnnotation = field.getAnnotation( ALDClassParameter.class);
// if field is annotated as ALDClassParameter
// and not already declared in a class downstream of the inheritance hierachy
// (as we add the first field for each name we find when walking up the inheritance hierachy
// add it to the hash map
if ( pAnnotation != null && fieldMap.get( name) == null ) {
fieldMap.put( name, field);
}
}
currentClass = currentClass.getSuperclass();
} while ( currentClass != null );
return fieldMap;
}
/** Return the value of the member variable associated with <code>field</code> in
* the object <code>obj</code>.
*
* @param field field of the member variable
* @param obj from which to return the value
* @return value of the field in obj
*/
public static Object getValue( Field field, Object obj) {
try {
field.setAccessible(true);
return field.get( obj);
} catch ( IllegalAccessException e ) {
e.printStackTrace();
}
return null;
}
/**
* Sets the value of the member variable associated with <code>field</code>
* in the object <code>obj</code>.
* <p>
* Primitive datatype can not be set from a value == null.
*
* @param field field of the member variable
* @param obj from which to return the value
* @value value to set the field in obj to
* @throws IllegalAccessException
*/
public static void setValue( Field field, Object obj, Object value)
throws IllegalAccessException {
Class<?> cl = field.getType();
if ( value != null ||
!(cl == byte.class || cl == short.class || cl == int.class ||
cl == long.class || cl == float.class || cl == double.class ||
cl == boolean.class) ) {
field.setAccessible(true);
field.set( obj, value);
// call the value change hook, if defined
ALDClassParameter pAnnotation =
field.getAnnotation( ALDClassParameter.class);
String hookFunction = pAnnotation.changeValueHook();
if (hookFunction != null && !hookFunction.isEmpty()) {
try {
Method method = obj.getClass().getDeclaredMethod(hookFunction);
// change accessibility, if method is protected or private
method.setAccessible(true);
method.invoke(obj);
} catch (SecurityException e) {
e.printStackTrace();
new IllegalAccessException("[ALDParametrizedClassDataIOHelper] " +
" couldn't call hook, object state maybe inconsistent...!");
} catch (NoSuchMethodException e) {
e.printStackTrace();
new IllegalAccessException("[ALDParametrizedClassDataIOHelper] " +
" couldn't call hook, object state maybe inconsistent...!");
} catch (IllegalArgumentException e) {
e.printStackTrace();
new IllegalAccessException("[ALDParametrizedClassDataIOHelper] " +
" couldn't call hook, object state maybe inconsistent...!");
} catch (InvocationTargetException e) {
e.printStackTrace();
new IllegalAccessException("[ALDParametrizedClassDataIOHelper] " +
" couldn't call hook, object state maybe inconsistent...!");
}
}
} else {
System.err.println("[ALDParametrizedClassDataIOHelper] setValue(): " +
"class of field = " + cl.getName() + " , value is null or native " +
" - skipping...!");
}
}
/**
* Sets the field with given <code>name</code> of object <code>obj</code>to <code>value</code>.
* <p>
* The method recursively iterates over all class fields and fields of
* super classes to find the requested field. An exception is thrown if
* the requested field could not be found or accessed.
*
* @param name Name of field to set.
* @param obj Object in which field is to set.
* @param value Value to set for the field.
* @throws IllegalAccessException
*/
public static void setValue( String name, Object obj, Object value)
throws IllegalAccessException {
// search the right field:
// loop for the class and all super classes over all declared fields
Class<?> myclass = obj.getClass();
do {
for ( Field field : myclass.getDeclaredFields() ) {
String fieldName = field.getName();
if (fieldName.equals(name)) {
ALDParametrizedClassDataIOHelper.setValue(field, obj, value);
return;
}
}
myclass = myclass.getSuperclass();
} while ( myclass != null );
// no field found...
throw new IllegalAccessException("ALDParametrizedClassDataIOHelper: " +
"no field with name \"" + name + "\" found!");
}
}