All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bladecoder.engine.util.ActionUtils Maven / Gradle / Ivy

The newest version!
package com.bladecoder.engine.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonValue;
import com.badlogic.gdx.utils.SerializationException;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import com.bladecoder.engine.actions.Action;
import com.bladecoder.engine.actions.ActionDescription;
import com.bladecoder.engine.actions.ActionFactory;
import com.bladecoder.engine.actions.ActionProperty;
import com.bladecoder.engine.actions.ActionPropertyDescription;
import com.bladecoder.engine.actions.ActorAnimationRef;
import com.bladecoder.engine.actions.Param;
import com.bladecoder.engine.actions.Param.Type;
import com.bladecoder.engine.actions.SceneActorRef;
import com.bladecoder.engine.model.World;

public class ActionUtils {
	public static String getInfo(Class clazz) {
		return clazz.getAnnotation(ActionDescription.class).value();
	}

	public static boolean isDeprecated(Class clazz) {
		return clazz.getAnnotation(Deprecated.class) != null;
	}

	public static String getName(Class clazz) {
		String name = clazz.getAnnotation(ActionDescription.class).name();

		if ("".equals(name)) {
			name = clazz.getSimpleName();

			if (name.endsWith("Action")) {
				name = name.substring(0, name.length() - 6);
			}
		}

		return name;
	}

	public static Param[] getParams(Action action) {
		List params = new ArrayList<>();
		Class clazz = action.getClass();
		while (clazz != null && clazz != Object.class) {
			for (Field field : clazz.getDeclaredFields()) {
				final ActionProperty property = field.getAnnotation(ActionProperty.class);
				if (property == null) {
					continue;
				}

				final ActionPropertyDescription propertyDescription = field
						.getAnnotation(ActionPropertyDescription.class);

				// properties without description are not editables but will be
				// saved in the model.
				if (propertyDescription == null)
					continue;

				final String name = field.getName();
				Param.Type type = property.type();

				Enum[] options = null;

				if (field.getType().isEnum()) {
					final boolean accessible = field.isAccessible();
					field.setAccessible(true);
					options = (Enum[]) field.getType().getEnumConstants();
					field.setAccessible(accessible);

					type = Param.Type.OPTION;
				} else if (property.type() == Param.Type.NOT_SET) {
					type = getType(field);
				}

				params.add(new Param(name, propertyDescription != null ? propertyDescription.value() : "", type,
						property.required(), property.defaultValue(), options));
			}
			clazz = clazz.getSuperclass();
		}
		return params.toArray(new Param[params.size()]);
	}

	public static String[] getFieldNames(Action a) {
		List result = new ArrayList<>();
		Class clazz = a.getClass();
		while (clazz != null && clazz != Object.class) {
			for (Field field : clazz.getDeclaredFields()) {
				final ActionProperty property = field.getAnnotation(ActionProperty.class);
				if (property == null) {
					continue;
				}

				final String name = field.getName();
				result.add(name);
			}
			clazz = clazz.getSuperclass();
		}
		return result.toArray(new String[result.size()]);
	}

	private static Type getType(Field field) {
		if (field.getType().isAssignableFrom(String.class)) {
			return Param.Type.STRING;
		} else if (field.getType().isAssignableFrom(boolean.class)) {
			return Param.Type.BOOLEAN;
		} else if (field.getType().isAssignableFrom(Boolean.class)) {
			return Param.Type.BOOLEAN;
		} else if (field.getType().isAssignableFrom(float.class)) {
			return Param.Type.FLOAT;
		} else if (field.getType().isAssignableFrom(Float.class)) {
			return Param.Type.FLOAT;
		} else if (field.getType().isAssignableFrom(int.class)) {
			return Param.Type.INTEGER;
		} else if (field.getType().isAssignableFrom(Vector2.class)) {
			return Param.Type.VECTOR2;
		} else if (field.getType().isAssignableFrom(SceneActorRef.class)) {
			return Param.Type.SCENE_ACTOR;
		} else if (field.getType().isAssignableFrom(ActorAnimationRef.class)) {
			return Param.Type.ACTOR_ANIMATION;
		} else if (field.getType().isAssignableFrom(Color.class)) {
			return Param.Type.COLOR;
		} else if (field.getType().isEnum()) {
			return Param.Type.OPTION;
		} else {
			EngineLogger.error("ACTION FIELD TYPE NOT SUPPORTED -  type: " + field.getType());
		}

		return Param.Type.NOT_SET;
	}

	@SuppressWarnings("unchecked")
	public static void setParam(Action action, String param, String value)
			throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		Class clazz = action.getClass();

		Field field = getField(clazz, param);

		if (field == null)
			throw new NoSuchFieldException(param);

		final boolean accessible = field.isAccessible();
		field.setAccessible(true);

		if (field.getType().isAssignableFrom(String.class)) {
			field.set(action, value);
		} else if (field.getType().isAssignableFrom(boolean.class)) {
			field.setBoolean(action, Boolean.parseBoolean(value));
		} else if (field.getType().isAssignableFrom(Boolean.class)) {
			Boolean b = null;

			if (value != null)
				b = Boolean.valueOf(value);

			field.set(action, b);
		} else if (field.getType().isAssignableFrom(float.class)) {
			try {
				field.setFloat(action, Float.parseFloat(value));
			} catch (NumberFormatException ignored) {
			}
		} else if (field.getType().isAssignableFrom(Float.class)) {
			try {
				Float f = null;

				if (value != null)
					f = Float.valueOf(value);

				field.set(action, f);
			} catch (NumberFormatException ignored) {
			}
		} else if (field.getType().isAssignableFrom(int.class)) {
			try {
				Integer i = null;

				if (value != null) {
					i = Integer.parseInt(value);
					field.setInt(action, i);
				}
			} catch (NumberFormatException ignored) {
			}
		} else if (field.getType().isAssignableFrom(Integer.class)) {
			try {
				Float f = null;

				if (value != null)
					f = Float.valueOf(value);

				field.set(action, f);
			} catch (NumberFormatException ignored) {
			}
		} else if (field.getType().isAssignableFrom(Vector2.class)) {
			field.set(action, Param.parseVector2(value));
		} else if (field.getType().isAssignableFrom(SceneActorRef.class)) {
			if (value == null)
				field.set(action, null);
			else
				field.set(action, new SceneActorRef(value));
		} else if (field.getType().isAssignableFrom(ActorAnimationRef.class)) {
			if (value == null)
				field.set(action, null);
			else
				field.set(action, new ActorAnimationRef(value));
		} else if (field.getType().isAssignableFrom(Color.class)) {
			Color a = Param.parseColor(value);

			field.set(action, a);
		} else if (field.getType().isEnum()) {
			field.set(action, Enum.valueOf(field.getType().asSubclass(Enum.class), value.toUpperCase(Locale.ENGLISH)));
		} else {
			EngineLogger.error("ACTION FIELD TYPE NOT SUPPORTED -  type: " + field.getType());
		}

		field.setAccessible(accessible);
	}

	public static String getStringValue(Action a, String param)
			throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		String result = null;

		Class clazz = a.getClass();

		Field field = getField(clazz, param);

		if (field == null)
			throw new NoSuchFieldException(param);

		final boolean accessible = field.isAccessible();
		field.setAccessible(true);

		if (field.getType().isAssignableFrom(String.class)) {
			result = (String) field.get(a);
		} else if (field.getType().isAssignableFrom(boolean.class)) {
			result = Boolean.toString(field.getBoolean(a));
		} else if (field.getType().isAssignableFrom(Boolean.class)) {
			Object o = field.get(a);

			if (o != null)
				result = o.toString();
		} else if (field.getType().isAssignableFrom(float.class)) {
			result = Float.toString(field.getFloat(a));
		} else if (field.getType().isAssignableFrom(Float.class)) {
			Object o = field.get(a);

			if (o != null)
				result = o.toString();
		} else if (field.getType().isAssignableFrom(int.class)) {
			result = Integer.toString(field.getInt(a));
		} else if (field.getType().isAssignableFrom(Vector2.class)) {
			result = Param.toStringParam((Vector2) field.get(a));
		} else if (field.getType().isAssignableFrom(SceneActorRef.class)) {
			Object o = field.get(a);

			if (o != null)
				result = o.toString();
		} else if (field.getType().isAssignableFrom(ActorAnimationRef.class)) {
			Object o = field.get(a);

			if (o != null)
				result = o.toString();
		} else if (field.getType().isAssignableFrom(Color.class)) {
			Object o = field.get(a);

			if (o != null)
				result = o.toString();
		} else if (field.getType().isEnum()) {
			Object o = field.get(a);

			if (o != null)
				result = ((Enum) o).name();
		} else {
			EngineLogger.error("ACTION FIELD TYPE NOT SUPPORTED -  type: " + field.getType());
		}

		field.setAccessible(accessible);

		return result;
	}

	public static Field getField(Class clazz, String fieldName) {
		Class current = clazz;

		do {
			try {
				return current.getDeclaredField(fieldName);
			} catch (NoSuchFieldException e) {
			}
		} while ((current = current.getSuperclass()) != null);

		return null;
	}

	public static void writeJson(Action a, Json json) {
		Class clazz = a.getClass();
		json.writeObjectStart(clazz, null);
		while (clazz != null && clazz != Object.class) {
			for (Field field : clazz.getDeclaredFields()) {
				final ActionProperty property = field.getAnnotation(ActionProperty.class);
				if (property == null) {
					continue;
				}

				// json.writeField(a, field.getName());
				final boolean accessible = field.isAccessible();
				field.setAccessible(true);

				try {
					Object o = field.get(a);

					// doesn't write null fields
					if (o == null)
						continue;

					if (o instanceof SceneActorRef) {
						SceneActorRef sceneActor = (SceneActorRef) o;
						json.writeValue(field.getName(), sceneActor.toString());
					} else if (o instanceof ActorAnimationRef) {
						ActorAnimationRef aa = (ActorAnimationRef) o;
						json.writeValue(field.getName(), aa.toString());
					} else if (o instanceof Color) {
						json.writeValue(field.getName(), ((Color) o).toString());
					} else if (o instanceof Vector2) {
						json.writeValue(field.getName(), Param.toStringParam((Vector2) o));
					} else {
						json.writeValue(field.getName(), o);
					}
				} catch (IllegalArgumentException | IllegalAccessException e) {

				}

				field.setAccessible(accessible);
			}
			clazz = clazz.getSuperclass();
		}
		json.writeObjectEnd();
	}

	public static Action readJson(World w, Json json, JsonValue jsonData) {
		String className = jsonData.getString("class", null);

		Action action = null;
		if (className != null) {
			jsonData.remove("class");

			try {
				action = ActionFactory.create(className, null);
			} catch (ClassNotFoundException | ReflectionException e1) {
				throw new SerializationException(e1);
			}

			for (int j = 0; j < jsonData.size; j++) {
				JsonValue v = jsonData.get(j);
				try {
					if (v.isNull())
						ActionUtils.setParam(action, v.name, null);
					else
						ActionUtils.setParam(action, v.name, v.asString());
				} catch (NoSuchFieldException e) {
					EngineLogger.error("Action field not found - class: " + className + " field: " + v.name);
				} catch (IllegalArgumentException | IllegalAccessException e) {
					EngineLogger.error("Action field error - class: " + className + " field: " + v.name + " value: "
							+ (v == null ? "null" : v.asString()));
				}
			}

			action.init(w);
		}

		return action;
	}

	/**
	 * Utility method to compare two Strings allowing null values.
	 */
	public static boolean compareNullStr(String str1, String str2) {
		return (str1 == null ? str2 == null : str1.equals(str2));
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy