net.sf.andromedaioc.annotation.processor.OnEventAnnotationProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of andromeda-ioc Show documentation
Show all versions of andromeda-ioc Show documentation
Inversion of Control Framework for Android
The newest version!
package net.sf.andromedaioc.annotation.processor;
import android.app.Activity;
import android.view.*;
import net.sf.andromedaioc.annotation.Inject;
import net.sf.andromedaioc.annotation.Property;
import net.sf.andromedaioc.annotation.Resource;
import net.sf.andromedaioc.annotation.android.AndromedaView;
import net.sf.andromedaioc.annotation.android.EventSource;
import net.sf.andromedaioc.annotation.android.OnEvent;
import net.sf.andromedaioc.context.AndromedaContext;
import net.sf.andromedaioc.exception.IllegalReturnTypeException;
import net.sf.andromedaioc.exception.OnEventProcessingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
/**
* Process OnEvent annotation
*
* @author Alexey Mitrov
*/
public class OnEventAnnotationProcessor implements AnnotationProcessor {
public void process(final Object target, final Activity activity, AnnotatedElement annotated, final AndromedaContext andromedaContext) throws Exception {
OnEvent onEvent = annotated.getAnnotation(OnEvent.class);
int targetId = onEvent.target();
EventSource eventSource = onEvent.source();
View view = activity.findViewById(targetId);
final Method onEventMethod = (Method) annotated;
validateOnEventMethod(onEventMethod, eventSource);
onEventMethod.setAccessible(true);
if(eventSource.equals(EventSource.ON_CLICK)) {
view.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
Object[] parameters = collectParameters(onEventMethod, activity, andromedaContext, null);
onEventMethod.invoke(target, parameters);
} catch (Exception e) {
throw new OnEventProcessingException(String.format("Error processing onEvent for method %s. Reason: %s", onEventMethod, e.getMessage()), e);
}
}
});
} else if(eventSource.equals(EventSource.ON_LONG_CLICK)) {
view.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
try {
Object[] parameters = collectParameters(onEventMethod, activity, andromedaContext, null);
Object result = onEventMethod.invoke(target, parameters);
return (Boolean) result;
} catch (Exception e) {
throw new OnEventProcessingException(String.format("Error processing onEvent for method %s. Reason: %s", onEventMethod, e.getMessage()), e);
}
}
});
} else if(eventSource.equals(EventSource.ON_TOUCH)) {
view.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
try {
Object[] parameters = collectParameters(onEventMethod, activity, andromedaContext, new Object[]{event});
Object result = onEventMethod.invoke(target, parameters);
return (Boolean) result;
} catch (Exception e) {
throw new OnEventProcessingException(String.format("Error processing onEvent for method %s. Reason: %s", onEventMethod, e.getMessage()), e);
}
}
});
} else if(eventSource.equals(EventSource.ON_KEY)) {
view.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
try {
Object[] parameters = collectParameters(onEventMethod, activity, andromedaContext, new Object[]{keyCode, event});
Object result = onEventMethod.invoke(target, parameters);
return (Boolean) result;
} catch (Exception e) {
throw new OnEventProcessingException(String.format("Error processing onEvent for method %s. Reason: %s", onEventMethod, e.getMessage()), e);
}
}
});
} else if(eventSource.equals(EventSource.ON_FOCUS_CHANGE)) {
view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
try {
Object[] parameters = collectParameters(onEventMethod, activity, andromedaContext, new Object[]{hasFocus});
onEventMethod.invoke(target, parameters);
} catch (Exception e) {
throw new OnEventProcessingException(String.format("Error processing onEvent for method %s. Reason: %s", onEventMethod, e.getMessage()), e);
}
}
});
} else if(eventSource.equals(EventSource.ON_CREATE_CONTEXT_MENU)) {
view.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
try {
Object[] parameters = collectParameters(onEventMethod, activity, andromedaContext, new Object[]{menu, menuInfo});
onEventMethod.invoke(target, parameters);
} catch (Exception e) {
throw new OnEventProcessingException(String.format("Error processing onEvent for method %s. Reason: %s", onEventMethod, e.getMessage()), e);
}
}
});
}
}
private void validateOnEventMethod(Method onEventMethod, EventSource eventSource) {
if(eventSource.getReturnType() != null && !eventSource.getReturnType().equals(onEventMethod.getReturnType())) {
throw new IllegalReturnTypeException(String.format("Illegal return type of method %s. The return type for %s event source should be %s", onEventMethod.getName(), eventSource.name(), eventSource.getReturnType().getName()));
}
}
private Object[] collectParameters(Method onEventMethod, Activity activity, AndromedaContext andromedaContext, Object[] additionalParameters) {
Annotation[][] parametersAnnotations = onEventMethod.getParameterAnnotations();
Class>[] parameterTypes = onEventMethod.getParameterTypes();
Object[] parameters = new Object[parameterTypes.length];
for(int i = 0; i < parameterTypes.length; i++) {
if(parametersAnnotations[i].length > 0) {
for(Annotation parameterAnnotation : parametersAnnotations[i]) {
if(Inject.class.equals(parameterAnnotation.annotationType())) {
Inject inject = (Inject) parameterAnnotation;
if(inject.id() != null && inject.id().length() > 0) {
parameters[i] = andromedaContext.getBean(inject.id());
} else {
parameters[i] = andromedaContext.getBean(parameterTypes[i]);
}
} else if(Resource.class.equals(parameterAnnotation.annotationType())) {
Resource resource = (Resource) parameterAnnotation;
parameters[i] = andromedaContext.getResourceProvider().getAndroidResource(resource.id());
} else if(Property.class.equals(parameterAnnotation.annotationType())) {
Property property = (Property) parameterAnnotation;
parameters[i] = andromedaContext.getResourceProvider().getProperty(property.name());
} else if(AndromedaView.class.equals(parameterAnnotation.annotationType())) {
AndromedaView andromedaView = (AndromedaView) parameterAnnotation;
parameters[i] = activity.findViewById(andromedaView.id());
}
}
} else {
Object additionalParameter = searchInAdditionalParameters(parameterTypes[i], additionalParameters);
parameters[i] = additionalParameter == null ? andromedaContext.getBean(parameterTypes[i]) : additionalParameter;
}
}
return parameters;
}
private Object searchInAdditionalParameters(Class> type, Object[] additionalParameters) {
if(additionalParameters == null || additionalParameters.length <= 0) {
return null;
} else {
for(Object parameter : additionalParameters) {
if(parameter != null && type.equals(parameter.getClass())) {
return parameter;
}
}
return null;
}
}
public boolean canProcessService() {
return false;
}
}