com.github.czyzby.lml.parser.action.ActionContainerWrapper Maven / Gradle / Ivy
package com.github.czyzby.lml.parser.action;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.Field;
import com.badlogic.gdx.utils.reflect.Method;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import com.github.czyzby.kiwi.util.common.Exceptions;
import com.github.czyzby.kiwi.util.gdx.reflection.Reflection;
import com.github.czyzby.lml.annotation.LmlAction;
import com.github.czyzby.lml.util.Lml;
import com.github.czyzby.lml.util.collection.IgnoreCaseStringMap;
/** Wraps around an {@link ActionContainer}, providing access to its methods and fields. Mostly for internal parsing
* use.
*
* @author MJ */
public class ActionContainerWrapper {
private final ActionContainer actionContainer;
private final ObjectMap annotatedMethods = new IgnoreCaseStringMap();
private final ObjectMap annotatedFields = new IgnoreCaseStringMap();
public ActionContainerWrapper(final ActionContainer actionContainer) {
this.actionContainer = actionContainer;
mapAnnotatedMethods();
}
private void mapAnnotatedMethods() {
try {
Class> containerClass = actionContainer.getClass();
while (containerClass != null) {
mapClassMethods(containerClass);
mapClassFields(containerClass);
containerClass = containerClass.getSuperclass();
}
} catch (final Exception exception) {
throw new GdxRuntimeException("Unable to map ActionContainer methods.", exception);
}
}
private void mapClassMethods(final Class> containerClass) {
for (final Method method : ClassReflection.getDeclaredMethods(containerClass)) {
final LmlAction actionData = Reflection.getAnnotation(method, LmlAction.class);
if (actionData != null) {
for (final String actionId : actionData.value()) {
annotatedMethods.put(actionId, method);
}
}
}
}
private void mapClassFields(final Class> containerClass) {
if (!Lml.EXTRACT_FIELDS_AS_METHODS) {
return;
}
for (final Field field : ClassReflection.getDeclaredFields(containerClass)) {
final LmlAction actionData = Reflection.getAnnotation(field, LmlAction.class);
if (actionData != null) {
for (final String actionId : actionData.value()) {
annotatedFields.put(actionId, field);
}
}
}
}
/** @return wrapped action container. */
public ActionContainer getActionContainer() {
return actionContainer;
}
/** @param methodId ID of the referenced method.
* @return method referenced directly with the selected ID or null if none. */
public Method getNamedMethod(final String methodId) {
return annotatedMethods.get(methodId);
}
/** @param fieldId ID of the referenced field.
* @return field referenced directly with the selected ID or null if none. */
public Field getNamedField(final String fieldId) {
return annotatedFields.get(fieldId);
}
/** @param methodName name of the possibly contained method.
* @param parameterClass class of the expected parameter. Optional.
* @return method with passed name and one or zero parameters. Might be null. */
public Method getMethod(final String methodName, final Class> parameterClass) {
Class> containerClass = actionContainer.getClass();
while (containerClass != null) {
try {
// If this does not throw an exception, the method is found. Null check is not needed.
return getDeclaredMethod(containerClass, methodName, parameterClass);
} catch (final Exception exception) {
Exceptions.ignore(exception); // Expected. Method unavailable.
}
containerClass = containerClass.getSuperclass();
}
return null;
}
private static Method getDeclaredMethod(final Class> containerClass, final String methodName,
final Class> parameterClass) throws ReflectionException {
if (parameterClass == null) {
return ClassReflection.getDeclaredMethod(containerClass, methodName);
}
return ClassReflection.getDeclaredMethod(containerClass, methodName, parameterClass);
}
/** @param fieldName name of the field.
* @return field with the selected name or null. */
public Field getField(final String fieldName) {
Class> containerClass = actionContainer.getClass();
while (containerClass != null) {
try {
// If this does not throw an exception, the field is found. Null check is not needed.
return ClassReflection.getDeclaredField(actionContainer.getClass(), fieldName);
} catch (final Exception exception) {
Exceptions.ignore(exception); // Expected. Field unavailable.
}
containerClass = containerClass.getSuperclass();
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy