package creator;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import de.ust.skill.common.java.internal.SkillObject;

public class SkillObjectCreator {

	private static final String FIELD_DECLARATION_CLASS_NAME = "de.ust.skill.common.java.api.FieldDeclaration";

	public static void main(String[] args) {
		String className = "age.Age";
		String fieldToSet = "age";
		String fieldTypeToSet = "long";
		Long valueToSet = 255L;
		Map<String, Object> values = new HashMap<>();
		Map<String, String> fieldTypes = new HashMap<>();

		values.put(fieldToSet, valueToSet);
		fieldTypes.put(fieldToSet, fieldTypeToSet);

		try {
			SkillObject obj = instantiateSkillObject(className, values, fieldTypes);

			System.out.println(obj.prettyString());
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Create an empty SkillObject from a fully specified class name
	 * 
	 * @param className
	 *            fully classified class name incl. package identifier
	 * @return empty SkillObject of the specified class
	 */
	public static SkillObject createSkillObject(String className)
			throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<?> refClass = Class.forName(className);
		Constructor<?> refConstructor = refClass.getConstructor();
		SkillObject refVar = (SkillObject) refConstructor.newInstance();
		return refVar;
	}

	/**
	 * Create and fill a SkillObject with the provided values
	 * 
	 * @param className
	 *            fully specified class name incl. package identifier of the
	 *            object to be created
	 * @param values
	 *            mapping of field names to values
	 * @param fieldTypes
	 *            mapping of field names to the corresponding types of values
	 * @return a SkillObject with the provided values as attributes
	 */
	public static SkillObject instantiateSkillObject(String className, Map<String, Object> values,
			Map<String, String> fieldTypes) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
			InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		SkillObject obj = createSkillObject(className);
		Map<String, Type> fieldMapping = getFieldMapping(className);

		for (String key : fieldMapping.keySet()) {
			String type = fieldMapping.get(key).getTypeName();
			System.out.println("Present field: " + key + "(Type: " + type + ")");
			if (values.containsKey(key)) {
				System.out.println("Setting field '" + key + "'");
				reflectiveSetValue(obj, values.get(key), key, fieldTypes.get(key));
			}
		}
		return obj;
	}

	/**
	 * Set the specified field of a SkillObject to a given value
	 * 
	 * @param obj
	 *            the SkillObject for which the field is to be set
	 * @param value
	 *            the value to set the field of the SkillObject to
	 * @param fieldName
	 *            the name of the field to be set
	 * @param fieldType
	 *            fully qualified class name of the field to be set
	 * @return the provided SkillObject with a set new value
	 */
	public static SkillObject reflectiveSetValue(SkillObject obj, Object value, String fieldName, String fieldType) {
		try {
			Method setterMethod = obj.getClass().getMethod(getSetterName(fieldName), getAptClass(fieldType));
			System.out.println("Found method " + setterMethod.getName());
			setterMethod.invoke(obj, value);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Get a Class object from a fully qualified class name incl. package
	 * identifier
	 * 
	 * @param type
	 *            fully qualified class name
	 * @return Class object for the provided class name
	 * @throws ClassNotFoundException
	 */
	private static Class<?> getAptClass(String type) throws ClassNotFoundException {
		if (!SKilLType.isPrimitive(type)) {
			return Class.forName(type);
		} else {
			switch (type) {
			case "byte":
				return byte.class;
			case "short":
				return short.class;
			case "int":
				return int.class;
			case "long":
				return long.class;
			case "float":
				return float.class;
			case "double":
				return double.class;
			case "boolean":
				return boolean.class;
			case "char":
				return char.class;
			default:
				return null;
			}
		}
	}

	/**
	 * Parse a value encoded in a string to the specified type
	 * 
	 * @param type
	 * @param valueString
	 * @return instance of the actual class of the provided value
	 */
	public static Object valueOf(String type, String valueString) {
		switch (type) {
		case "byte":
			return Byte.valueOf(valueString);
		case "short":
			return Short.valueOf(valueString);
		case "int":
			return Integer.valueOf(valueString);
		case "long":
			return Long.valueOf(valueString);
		case "float":
			return Float.valueOf(valueString);
		case "double":
			return Double.valueOf(valueString);
		case "boolean":
			return Boolean.valueOf(valueString);
		case "char":
			return Character.valueOf(valueString.charAt(0));
		default:
			return null;
		}
	}


	
	/**
	 * Return the method name of the setter method responsible for the field
	 * with the name 'fieldName'.
	 * 
	 * @param fieldName
	 *            the name of the field for which to get the name of the setter
	 *            method
	 * @return the name of the setter method
	 */
	public static String getSetterName(String fieldName) {

		return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
	}

	/**
	 * Create a mapping of field names and their corresponding types of the
	 * given class.
	 * 
	 * @param className
	 *            the name of the class for which to generate the mapping
	 * @return a mapping of field names to Type objects
	 */
	public static Map<String, Type> getFieldMapping(String className) {
		Map<String, Type> fieldTypeMapping;
		try {
			Class<?> cls = Class.forName(className);
			Field[] declaredFields = cls.getDeclaredFields();
			fieldTypeMapping = new HashMap<>(declaredFields.length);
			for (Field field : declaredFields) {
				fieldTypeMapping.put(field.getName(), field.getGenericType());
			}
			return fieldTypeMapping;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Create a mapping of field names and their corresponding types of the
	 * given class.
	 * 
	 * @param cls
	 *            the class for which to generate the mapping
	 * @return a mapping of field names to Type objects
	 */
	public static Map<String, Type> getFieldMapping(Class<?> cls) {
		Map<String, Type> fieldTypeMapping;
		Field[] declaredFields = cls.getDeclaredFields();
		fieldTypeMapping = new HashMap<>(declaredFields.length);
		for (Field field : declaredFields) {
			fieldTypeMapping.put(field.getName(), field.getGenericType());
		}
		return fieldTypeMapping;
	}
}

@@ -3148,17 +3148,42 @@
 key + %22'
-%22
+ to be %22 + values.get(key)
 );%0A%09%09%09%09r

Improve Debug output