diff --git a/AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/SupposeBackground.java b/AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/SupposeBackground.java
new file mode 100644
index 0000000000..490f196ae4
--- /dev/null
+++ b/AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/SupposeBackground.java
@@ -0,0 +1,14 @@
+package org.androidannotations.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface SupposeBackground {
+
+ String[] serial() default {};
+
+}
diff --git a/AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/SupposeUiThread.java b/AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/SupposeUiThread.java
new file mode 100644
index 0000000000..f1a7dfae13
--- /dev/null
+++ b/AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/SupposeUiThread.java
@@ -0,0 +1,16 @@
+package org.androidannotations.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Ensures that method is called from the UI thread. If it is not, then
+ * {@link java.lang.IllegalStateException} will be thrown (by default).
+ * //TODO how to change default
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface SupposeUiThread {
+}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/sun/codemodel/JSuperWildcard.java b/AndroidAnnotations/androidannotations/src/main/java/com/sun/codemodel/JSuperWildcard.java
new file mode 100644
index 0000000000..fbff4716da
--- /dev/null
+++ b/AndroidAnnotations/androidannotations/src/main/java/com/sun/codemodel/JSuperWildcard.java
@@ -0,0 +1,69 @@
+package com.sun.codemodel;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class JSuperWildcard extends JClass {
+
+ private final JClass bound;
+
+ public JSuperWildcard(JClass bound) {
+ super(bound.owner());
+ this.bound = bound;
+ }
+
+ public String name() {
+ return "? super "+ bound.name();
+ }
+
+ public String fullName() {
+ return "? super "+ bound.fullName();
+ }
+
+ public JPackage _package() {
+ return null;
+ }
+
+ /**
+ * Returns the class bound of this variable.
+ *
+ *
+ * If no bound is given, this method returns {@link Object}.
+ */
+ public JClass _extends() {
+ if(bound !=null)
+ return bound;
+ else
+ return owner().ref(Object.class);
+ }
+
+ /**
+ * Returns the interface bounds of this variable.
+ */
+ public Iterator _implements() {
+ return bound._implements();
+ }
+
+ public boolean isInterface() {
+ return false;
+ }
+
+ public boolean isAbstract() {
+ return false;
+ }
+
+ protected JClass substituteParams(JTypeVar[] variables, List bindings) {
+ JClass nb = bound.substituteParams(variables,bindings);
+ if(nb== bound)
+ return this;
+ else
+ return nb.wildcard();
+ }
+
+ public void generate(JFormatter f) {
+ if(bound._extends()==null)
+ f.p("?"); // instead of "? extends Object"
+ else
+ f.p("? super").g(bound);
+ }
+}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java
index 1f9c9109cd..62124ded06 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java
@@ -89,6 +89,8 @@
import org.androidannotations.annotations.SeekBarTouchStart;
import org.androidannotations.annotations.SeekBarTouchStop;
import org.androidannotations.annotations.ServiceAction;
+import org.androidannotations.annotations.SupposeBackground;
+import org.androidannotations.annotations.SupposeUiThread;
import org.androidannotations.annotations.SystemService;
import org.androidannotations.annotations.TextChange;
import org.androidannotations.annotations.Touch;
@@ -193,6 +195,8 @@
import org.androidannotations.processing.ServiceActionProcessor;
import org.androidannotations.processing.SharedPrefProcessor;
import org.androidannotations.processing.SubscribeProcessor;
+import org.androidannotations.processing.SupposeBackgroundProcessor;
+import org.androidannotations.processing.SupposeUiThreadProcessor;
import org.androidannotations.processing.SystemServiceProcessor;
import org.androidannotations.processing.TextChangeProcessor;
import org.androidannotations.processing.TouchProcessor;
@@ -255,6 +259,7 @@
import org.androidannotations.validation.OptionsMenuValidator;
import org.androidannotations.validation.OrmLiteDaoValidator;
import org.androidannotations.validation.PrefValidator;
+import org.androidannotations.validation.SupposeValidator;
import org.androidannotations.validation.ProduceValidator;
import org.androidannotations.validation.ResValidator;
import org.androidannotations.validation.RestServiceValidator;
@@ -521,6 +526,8 @@ private ModelValidator buildModelValidator(IRClass rClass, AndroidSystemServices
modelValidator.register(new ProduceValidator(processingEnv));
modelValidator.register(new RunnableValidator(UiThread.class.getName(), processingEnv));
modelValidator.register(new RunnableValidator(Background.class.getName(), processingEnv));
+ modelValidator.register(new SupposeValidator(SupposeUiThread.class.getName(), processingEnv));
+ modelValidator.register(new SupposeValidator(SupposeBackground.class.getName(), processingEnv));
modelValidator.register(new InstanceStateValidator(processingEnv));
modelValidator.register(new OrmLiteDaoValidator(processingEnv, rClass));
modelValidator.register(new HttpsClientValidator(processingEnv, rClass));
@@ -543,7 +550,7 @@ private boolean traceActivated() {
private ProcessResult processAnnotations(AnnotationElements validatedModel, IRClass rClass, AndroidSystemServices androidSystemServices, AndroidManifest androidManifest) throws ProcessingException, Exception {
timeStats.start("Process Annotations");
ModelProcessor modelProcessor = buildModelProcessor(rClass, androidSystemServices, androidManifest, validatedModel);
- ProcessResult processResult = modelProcessor.process(validatedModel);
+ ProcessResult processResult = modelProcessor.process(processingEnv, validatedModel);
timeStats.stop("Process Annotations");
return processResult;
}
@@ -620,9 +627,11 @@ private ModelProcessor buildModelProcessor(IRClass rClass, AndroidSystemServices
}
modelProcessor.register(new SubscribeProcessor());
modelProcessor.register(new ProduceProcessor());
- modelProcessor.register(new UiThreadProcessor());
+ modelProcessor.register(new UiThreadProcessor());
+ modelProcessor.register(new SupposeUiThreadProcessor());
modelProcessor.register(new BackgroundProcessor());
- modelProcessor.register(new AfterInjectProcessor());
+ modelProcessor.register(new SupposeBackgroundProcessor());
+ modelProcessor.register(new AfterInjectProcessor());
modelProcessor.register(new InstanceStateProcessor(processingEnv));
modelProcessor.register(new HttpsClientProcessor(rClass));
modelProcessor.register(new OnActivityResultProcessor(processingEnv, rClass));
@@ -677,8 +686,10 @@ public Set getSupportedAnnotationTypes() {
Touch.class, //
ItemSelect.class, //
UiThread.class, //
+ SupposeUiThread.class,
Transactional.class, //
Background.class, //
+ SupposeBackground.class,
Extra.class, //
SystemService.class, //
SharedPref.class, //
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/api/BackgroundExecutor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/api/BackgroundExecutor.java
index 450708c701..4cee3e842c 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/api/BackgroundExecutor.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/api/BackgroundExecutor.java
@@ -16,6 +16,7 @@
package org.androidannotations.api;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
@@ -25,6 +26,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import android.os.Looper;
import android.util.Log;
public class BackgroundExecutor {
@@ -34,7 +36,32 @@ public class BackgroundExecutor {
public static Executor DEFAULT_EXECUTOR = Executors.newScheduledThreadPool(2 * Runtime.getRuntime().availableProcessors());
private static Executor executor = DEFAULT_EXECUTOR;
+ public static final WrongThreadListener DEFAULT_WRONG_THREAD_LISTENER = new WrongThreadListener() {
+ @Override
+ public void onUiExpected() {
+ throw new IllegalStateException("Method invocation is expected from the UI thread");
+ }
+
+ @Override
+ public void onBgExpected(String... expectedSerials) {
+ if (expectedSerials.length == 0) {
+ throw new IllegalStateException("Method invocation is expected from a background thread, but it was called from the UI thread");
+ }
+ throw new IllegalStateException("Method invocation is expected from one of serials " + Arrays.toString(expectedSerials) + ", but it was called from the UI thread");
+ }
+
+ @Override
+ public void onWrongBgSerial(String currentSerial, String... expectedSerials) {
+ if (currentSerial == null) {
+ currentSerial = "anonymous";
+ }
+ throw new IllegalStateException("Method invocation is expected from one of serials " + Arrays.toString(expectedSerials) + ", but it was called from " + currentSerial + " serial");
+ }
+ };
+ private static WrongThreadListener wrongThreadListener = DEFAULT_WRONG_THREAD_LISTENER;
+
private static final List tasks = new ArrayList();
+ private static final ThreadLocal currentSerial = new ThreadLocal();
/**
* Execute a runnable after the given delay.
@@ -181,9 +208,17 @@ public static void execute(Runnable runnable, String id, String serial) {
* @param executor
* the new executor
*/
- public static void setExecutor(Executor executor) {
- BackgroundExecutor.executor = executor;
- }
+ public static void setExecutor(Executor executor) {
+ BackgroundExecutor.executor = executor;
+ }
+
+ /**
+ * Change the WrongThreadListener.
+ * @param listener the new WrongThreadListener
+ */
+ public static void setWrongThreadListener(WrongThreadListener listener) {
+ BackgroundExecutor.wrongThreadListener = listener;
+ }
/**
* Cancel all tasks having the specified id.
@@ -219,6 +254,50 @@ public static synchronized void cancelAll(String id, boolean mayInterruptIfRunni
}
}
+ /**
+ * Checks if current thread is UI and notifies
+ * {@link BackgroundExecutor.WrongThreadListener#onUiExpected()} if it doesn't.
+ */
+ public static void checkUiThread() {
+ if (Looper.getMainLooper().getThread() != Thread.currentThread()) {
+ wrongThreadListener.onUiExpected();
+ }
+ }
+
+ /**
+ * Check if current thread is a background thread and, optionally, restrict it
+ * with passed serials. If no serials passed and current thread is UI, then
+ * {@link WrongThreadListener#onBgExpected(String...)} will be called.
+ * If current thread is not UI and serials list is empty, then method just returns.
+ * Otherwise, if method was called not during {@link Task} execution or the task has no
+ * serial, then {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called
+ * with null for the first parameter. If task has serial but passed serials don't contain that,
+ * then {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called with
+ * task's serial for the first parameter.
+ *
+ * @param serials (optional) list of allowed serials
+ */
+ public static void checkBgThread(String... serials) {
+ if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
+ wrongThreadListener.onBgExpected(serials);
+ return;
+ }
+ if (serials.length == 0) {
+ return;
+ }
+ String current = currentSerial.get();
+ if (current == null) {
+ wrongThreadListener.onWrongBgSerial(null, serials);
+ return;
+ }
+ for (String serial : serials) {
+ if (serial.equals(current)) {
+ return;
+ }
+ }
+ wrongThreadListener.onWrongBgSerial(current, serials);
+ }
+
/**
* Indicates whether a task with the specified serial has been
* submitted to the executor.
@@ -299,6 +378,7 @@ public void run() {
}
try {
+ currentSerial.set(serial);
execute();
} finally {
/* handle next tasks */
@@ -313,6 +393,7 @@ private void postExecute() {
/* nothing to do */
return;
}
+ currentSerial.set(null);
synchronized (BackgroundExecutor.class) {
/* execution complete */
tasks.remove(this);
@@ -333,4 +414,14 @@ private void postExecute() {
}
+ /**
+ * A callback interface to be notified when current thread, in which method has been invoked,
+ * is wrong.
+ * @see #setWrongThreadListener(WrongThreadListener)
+ */
+ public static interface WrongThreadListener {
+ void onUiExpected();
+ void onBgExpected(String... expectedSerials);
+ void onWrongBgSerial(String currentSerial, String... expectedSerials);
+ }
}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java
index ac63fb71d3..f9b9f14fc0 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java
@@ -37,6 +37,7 @@
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.WildcardType;
@@ -59,6 +60,7 @@
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JStatement;
+import com.sun.codemodel.JSuperWildcard;
import com.sun.codemodel.JType;
import com.sun.codemodel.JTypeVar;
import com.sun.codemodel.JVar;
@@ -86,15 +88,18 @@ public JClass typeMirrorToJClass(TypeMirror type, EBeanHolder holder) {
return declaredClass;
} else if (type instanceof WildcardType) {
- // TODO : At his time (01/2013), it is not possible to handle the
- // super bound because code model does not offer a way to model
- // statement like " ? super X"
- // (see http://java.net/jira/browse/CODEMODEL-11)
WildcardType wildcardType = (WildcardType) type;
- TypeMirror extendsBound = wildcardType.getExtendsBound();
+ TypeMirror bound = wildcardType.getExtendsBound();
+ if (bound == null) {
+ bound = wildcardType.getSuperBound();
+ if (bound == null) {
+ throw new IllegalArgumentException("There are should be 'extends' or 'super' in the wildcard");
+ }
+ return superWildcard(typeMirrorToJClass(bound, holder));
+ }
- return typeMirrorToJClass(extendsBound, holder).wildcard();
+ return typeMirrorToJClass(bound, holder).wildcard();
} else if (type instanceof ArrayType) {
ArrayType arrayType = (ArrayType) type;
@@ -106,7 +111,11 @@ public JClass typeMirrorToJClass(TypeMirror type, EBeanHolder holder) {
}
}
- public static class Parameter {
+ private JClass superWildcard(final JClass bound) {
+ return new JSuperWildcard(bound);
+ }
+
+ public static class Parameter {
public final String name;
public final JClass jClass;
@@ -118,16 +127,19 @@ public Parameter(String name, JClass jClass) {
public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, EBeanHolder holder) {
+ TypeMirror gen = holder.beans().getOriginatingElements().getClassOriginatingElements(holder.generatedClass.fullName())[0].asType();
+ ExecutableType generalisedElement = (ExecutableType) holder.beans().getProcessingEnv().getTypeUtils().asMemberOf((DeclaredType) gen, executableElement);
+
String methodName = executableElement.getSimpleName().toString();
- JClass returnType = typeMirrorToJClass(executableElement.getReturnType(), holder);
+ JClass returnType = typeMirrorToJClass(generalisedElement.getReturnType(), holder);
List parameters = new ArrayList();
- for (VariableElement parameter : executableElement.getParameters()) {
- String parameterName = parameter.getSimpleName().toString();
- JClass parameterClass = typeMirrorToJClass(parameter.asType(), holder);
- parameters.add(new Parameter(parameterName, parameterClass));
- }
+ for (int i = 0; i < executableElement.getParameters().size(); i++) {
+ String parameterName = executableElement.getParameters().get(i).getSimpleName().toString();
+ JClass parameterClass = typeMirrorToJClass(generalisedElement.getParameterTypes().get(i), holder);
+ parameters.add(new Parameter(parameterName, parameterClass));
+ }
JMethod existingMethod = findAlreadyGeneratedMethod(holder.generatedClass, methodName, parameters);
@@ -139,12 +151,13 @@ public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, EBea
method.annotate(Override.class);
List methodParameters = new ArrayList();
- for (VariableElement parameter : executableElement.getParameters()) {
- String parameterName = parameter.getSimpleName().toString();
- JClass parameterClass = typeMirrorToJClass(parameter.asType(), holder);
- JVar param = method.param(JMod.FINAL, parameterClass, parameterName);
- methodParameters.add(param);
- }
+ for (int i = 0; i < executableElement.getParameters().size(); i++) {
+ String parameterName = executableElement.getParameters().get(i).getSimpleName().toString();
+ JClass parameterClass = typeMirrorToJClass(generalisedElement.getParameterTypes().get(i), holder);
+
+ JVar param = method.param(JMod.FINAL, parameterClass, parameterName);
+ methodParameters.add(param);
+ }
for (TypeMirror superThrownType : executableElement.getThrownTypes()) {
JClass thrownType = typeMirrorToJClass(superThrownType, holder);
@@ -156,7 +169,7 @@ public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, EBea
return method;
}
- private JMethod findAlreadyGeneratedMethod(JDefinedClass definedClass, String methodName, List parameters) {
+ private JMethod findAlreadyGeneratedMethod(JDefinedClass definedClass, String methodName, List parameters) {
method: for (JMethod method : definedClass.methods()) {
if (method.name().equals(methodName) && method.params().size() == parameters.size()) {
int i = 0;
@@ -477,4 +490,5 @@ private JFieldVar addIntentBuilderFragmentConstructor(EBeanHolder holder, JClass
constructorBody.assign(holder.intentField, _new(holder.classes().INTENT).arg(contextField).arg(holder.generatedClass.dotclass()));
return fragmentField;
}
+
}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/BeanProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/BeanProcessor.java
index c148b0ce77..de4000ad77 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/BeanProcessor.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/BeanProcessor.java
@@ -63,6 +63,10 @@ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) {
String fieldName = element.getSimpleName().toString();
String typeQualifiedName = elementType.toString();
+ int genericIndex = typeQualifiedName.indexOf("<");
+ if (genericIndex >= 0) {
+ typeQualifiedName = typeQualifiedName.substring(0, genericIndex);
+ }
JClass injectedClass = holder.refClass(typeQualifiedName + GENERATION_SUFFIX);
@@ -77,7 +81,7 @@ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) {
body = body._if(beanField.eq(_null()))._then();
}
- JInvocation getInstance = injectedClass.staticInvoke(GET_INSTANCE_METHOD_NAME).arg(holder.contextRef);
+ JInvocation getInstance = injectedClass.erasure().staticInvoke(GET_INSTANCE_METHOD_NAME).arg(holder.contextRef);
body.assign(beanField, getInstance);
}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanHolder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanHolder.java
index 7ca53b6c71..caacd5d762 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanHolder.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanHolder.java
@@ -217,4 +217,8 @@ public void wrapInitWithNotifier() {
resetPreviousNotifier(initBlock, previousNotifier);
}
+ public EBeansHolder beans() {
+ return eBeansHolder;
+ }
+
}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanProcessor.java
index 899a24500b..85ae9c49ef 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanProcessor.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeanProcessor.java
@@ -28,6 +28,7 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.util.ElementFilter;
import org.androidannotations.annotations.EBean;
@@ -57,15 +58,25 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
TypeElement typeElement = (TypeElement) element;
- String eBeanQualifiedName = typeElement.getQualifiedName().toString();
+ StringBuilder eBeanQualifiedName = new StringBuilder(typeElement.getQualifiedName());
String generatedBeanQualifiedName = eBeanQualifiedName + GENERATION_SUFFIX;
JDefinedClass generatedClass = codeModel._class(PUBLIC | FINAL, generatedBeanQualifiedName, ClassType.CLASS);
+ if (!typeElement.getTypeParameters().isEmpty()) {
+ eBeanQualifiedName.append("<");
+ for (TypeParameterElement typeParam : typeElement.getTypeParameters()) {
+ generatedClass.generify(typeParam.getSimpleName().toString());
+ eBeanQualifiedName.append(typeParam.getSimpleName()).append(", ");
+ }
+ int l = eBeanQualifiedName.length();
+ eBeanQualifiedName.replace(l - 2, l, ">");
+ }
+
EBeanHolder holder = eBeansHolder.create(element, EBean.class, generatedClass);
- JClass eBeanClass = codeModel.directClass(eBeanQualifiedName);
+ JClass eBeanClass = codeModel.directClass(eBeanQualifiedName.toString());
holder.generatedClass._extends(eBeanClass);
@@ -94,6 +105,10 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
holder.initActivityRef = helper.castContextToActivity(holder, holder.initIfActivityBody);
}
+ EBean eBeanAnnotation = element.getAnnotation(EBean.class);
+ EBean.Scope eBeanScope = eBeanAnnotation.scope();
+ boolean hasSingletonScope = eBeanScope == EBean.Scope.Singleton;
+
{
// Constructor
@@ -113,13 +128,11 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
constructorBody.assign(contextField, constructorContextParam);
- constructorBody.invoke(init);
+ if (!hasSingletonScope) {
+ constructorBody.invoke(init);
+ }
}
- EBean eBeanAnnotation = element.getAnnotation(EBean.class);
- EBean.Scope eBeanScope = eBeanAnnotation.scope();
- boolean hasSingletonScope = eBeanScope == EBean.Scope.Singleton;
-
{
// Factory method
@@ -141,6 +154,7 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
._then();
JVar previousNotifier = holder.replacePreviousNotifierWithNull(creationBlock);
creationBlock.assign(instanceField, _new(holder.generatedClass).arg(factoryMethodContextParam.invoke("getApplicationContext")));
+ creationBlock.invoke(instanceField, init);
holder.resetPreviousNotifier(creationBlock, previousNotifier);
factoryMethodBody._return(instanceField);
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeansHolder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeansHolder.java
index e0d2a2f35e..83c4161678 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeansHolder.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeansHolder.java
@@ -25,6 +25,7 @@
import java.util.Map;
import java.util.Set;
+import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import org.androidannotations.helper.CanonicalNameConstants;
@@ -36,7 +37,11 @@
public class EBeansHolder {
- public class Classes {
+ public ProcessingEnvironment getProcessingEnv() {
+ return processingEnv;
+ }
+
+ public class Classes {
/*
* Java
@@ -170,7 +175,10 @@ public class Classes {
private final OriginatingElements originatingElements = new OriginatingElements();
- public EBeansHolder(JCodeModel codeModel) {
+ private final ProcessingEnvironment processingEnv;
+
+ public EBeansHolder(ProcessingEnvironment processingEnv, JCodeModel codeModel) {
+ this.processingEnv = processingEnv;
this.codeModel = codeModel;
classes = new Classes();
refClass(CanonicalNameConstants.STRING);
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/ModelProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/ModelProcessor.java
index 9aad843c6a..5efa7ecd4f 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/ModelProcessor.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/ModelProcessor.java
@@ -19,6 +19,7 @@
import java.util.List;
import java.util.Set;
+import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
@@ -60,11 +61,11 @@ public void register(GeneratingElementProcessor processor) {
typeProcessors.add(processor);
}
- public ProcessResult process(AnnotationElements validatedModel) throws ProcessingException, Exception {
+ public ProcessResult process(ProcessingEnvironment processingEnv, AnnotationElements validatedModel) throws ProcessingException, Exception {
JCodeModel codeModel = new JCodeModel();
- EBeansHolder eBeansHolder = new EBeansHolder(codeModel);
+ EBeansHolder eBeansHolder = new EBeansHolder(processingEnv, codeModel);
for (GeneratingElementProcessor processor : typeProcessors) {
String annotationName = processor.getTarget();
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/SupposeBackgroundProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/SupposeBackgroundProcessor.java
new file mode 100644
index 0000000000..5d6de6df87
--- /dev/null
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/SupposeBackgroundProcessor.java
@@ -0,0 +1,51 @@
+package org.androidannotations.processing;
+
+import com.sun.codemodel.JClass;
+import com.sun.codemodel.JClassAlreadyExistsException;
+import com.sun.codemodel.JCodeModel;
+import com.sun.codemodel.JInvocation;
+import com.sun.codemodel.JMethod;
+
+import org.androidannotations.annotations.SupposeBackground;
+import org.androidannotations.api.BackgroundExecutor;
+import org.androidannotations.helper.APTCodeModelHelper;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+
+import static com.sun.codemodel.JExpr.lit;
+
+public class SupposeBackgroundProcessor implements DecoratingElementProcessor {
+
+ private static final String METHOD_CHECK_BG_THREAD = "checkBgThread";
+
+ private final APTCodeModelHelper helper = new APTCodeModelHelper();
+
+ @Override
+ public String getTarget() {
+ return SupposeBackground.class.getName();
+ }
+
+ @Override
+ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) throws JClassAlreadyExistsException {
+
+ ExecutableElement executableElement = (ExecutableElement) element;
+
+ holder.generateApiClass(element, BackgroundExecutor.class);
+
+ JMethod delegatingMethod = helper.overrideAnnotatedMethod(executableElement, holder);
+ helper.removeBody(delegatingMethod);
+
+ JClass bgExecutor = holder.refClass(BackgroundExecutor.class);
+
+ SupposeBackground annotation = element.getAnnotation(SupposeBackground.class);
+ String[] serial = annotation.serial();
+ JInvocation invocation = bgExecutor.staticInvoke(METHOD_CHECK_BG_THREAD);
+ for (String s : serial) {
+ invocation.arg(lit(s));
+ }
+
+ delegatingMethod.body().add(invocation);
+ helper.callSuperMethod(delegatingMethod, holder, delegatingMethod.body());
+ }
+}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/SupposeUiThreadProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/SupposeUiThreadProcessor.java
new file mode 100644
index 0000000000..d89ddc9dd6
--- /dev/null
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/SupposeUiThreadProcessor.java
@@ -0,0 +1,41 @@
+package org.androidannotations.processing;
+
+import com.sun.codemodel.JClass;
+import com.sun.codemodel.JClassAlreadyExistsException;
+import com.sun.codemodel.JCodeModel;
+import com.sun.codemodel.JMethod;
+
+import org.androidannotations.annotations.SupposeUiThread;
+import org.androidannotations.api.BackgroundExecutor;
+import org.androidannotations.helper.APTCodeModelHelper;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+
+public class SupposeUiThreadProcessor implements DecoratingElementProcessor {
+
+ private static final String METHOD_CHECK_UI_THREAD = "checkUiThread";
+
+ private final APTCodeModelHelper helper = new APTCodeModelHelper();
+
+ @Override
+ public String getTarget() {
+ return SupposeUiThread.class.getName();
+ }
+
+ @Override
+ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) throws JClassAlreadyExistsException {
+
+ ExecutableElement executableElement = (ExecutableElement) element;
+
+ holder.generateApiClass(element, BackgroundExecutor.class);
+
+ JMethod delegatingMethod = helper.overrideAnnotatedMethod(executableElement, holder);
+ helper.removeBody(delegatingMethod);
+
+ JClass bgExecutor = holder.refClass(BackgroundExecutor.class);
+
+ delegatingMethod.body().staticInvoke(bgExecutor, METHOD_CHECK_UI_THREAD);
+ helper.callSuperMethod(delegatingMethod, holder, delegatingMethod.body());
+ }
+}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/validation/SupposeValidator.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/validation/SupposeValidator.java
new file mode 100644
index 0000000000..a0de0eadd5
--- /dev/null
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/validation/SupposeValidator.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2010-2013 eBusiness Information, Excilys Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed To in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.androidannotations.validation;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+
+import org.androidannotations.helper.TargetAnnotationHelper;
+import org.androidannotations.helper.ValidatorHelper;
+import org.androidannotations.model.AnnotationElements;
+
+public class SupposeValidator implements ElementValidator {
+
+ private ValidatorHelper validatorHelper;
+ private String annotationName;
+
+ public SupposeValidator(String annotationName, ProcessingEnvironment processingEnv) {
+ this.annotationName = annotationName;
+ TargetAnnotationHelper annotationHelper = new TargetAnnotationHelper(processingEnv, getTarget());
+ validatorHelper = new ValidatorHelper(annotationHelper);
+ }
+
+ @Override
+ public String getTarget() {
+ return annotationName;
+ }
+
+ @Override
+ public boolean validate(Element element, AnnotationElements validatedElements) {
+
+ IsValid valid = new IsValid();
+
+ validatorHelper.enclosingElementHasEnhancedComponentAnnotation(element, validatedElements, valid);
+
+ validatorHelper.isNotPrivate(element, valid);
+
+ return valid.isValid();
+ }
+
+}
diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithBackgroundMethod.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithBackgroundMethod.java
index bf48890dd8..12d0b2719e 100644
--- a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithBackgroundMethod.java
+++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithBackgroundMethod.java
@@ -17,9 +17,12 @@
import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.EActivity;
+import org.androidannotations.annotations.SupposeUiThread;
import android.app.Activity;
+import java.util.List;
+
@EActivity
public class ActivityWithBackgroundMethod extends Activity {
@@ -28,4 +31,9 @@ public void executingOnBackground() {
}
+ @SupposeUiThread
+ void executingOnBackground(List super Activity> arg) {
+
+ }
+
}