Skip to content
This repository was archived by the owner on Dec 17, 2020. It is now read-only.

Commit e02cd50

Browse files
committed
Added automatic casting to the AnnotationsProcessor
1 parent c1e14a0 commit e02cd50

File tree

8 files changed

+73
-88
lines changed

8 files changed

+73
-88
lines changed

annotations-processor/src/main/java/org/neotech/library/retainabletasks/AnnotationsProcessor.java

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.lang.annotation.Annotation;
1212
import java.util.HashMap;
1313
import java.util.LinkedHashSet;
14+
import java.util.List;
1415
import java.util.Map;
1516
import java.util.Set;
1617

@@ -21,8 +22,15 @@
2122
import javax.annotation.processing.RoundEnvironment;
2223
import javax.lang.model.SourceVersion;
2324
import javax.lang.model.element.Element;
25+
import javax.lang.model.element.ElementKind;
26+
import javax.lang.model.element.ExecutableElement;
2427
import javax.lang.model.element.Modifier;
2528
import javax.lang.model.element.TypeElement;
29+
import javax.lang.model.element.VariableElement;
30+
import javax.lang.model.type.DeclaredType;
31+
import javax.lang.model.type.TypeKind;
32+
import javax.lang.model.type.TypeMirror;
33+
import javax.lang.model.util.Types;
2634
import javax.tools.Diagnostic;
2735

2836
public final class AnnotationsProcessor extends AbstractProcessor {
@@ -171,7 +179,12 @@ private JavaFile createJavaFile(TypeElement forTypeElement, TaskBindingContainer
171179
if(onlyCallOnReAttach){
172180
getListenerForMethod.beginControlFlow("if(isReAttach)");
173181
}
174-
getListenerForMethod.addStatement("target.$L(task)", methods.getElementForAttach().getSimpleName());
182+
final List<? extends VariableElement> parameters = ((ExecutableElement) methods.getElementForAttach()).getParameters();
183+
if(parameters.size() == 0) {
184+
getListenerForMethod.addStatement("target.$L()", methods.getElementForAttach().getSimpleName());
185+
} else {
186+
getListenerForMethod.addStatement("target.$L(task)", methods.getElementForAttach().getSimpleName());
187+
}
175188
if(onlyCallOnReAttach){
176189
getListenerForMethod.endControlFlow();
177190
}
@@ -186,7 +199,6 @@ private JavaFile createJavaFile(TypeElement forTypeElement, TaskBindingContainer
186199
getListenerForMethod.addStatement("return null");
187200
getListenerForMethod.endControlFlow();
188201

189-
190202
// Create an implementation of TaskAttachBinding interface.
191203
final TypeSpec generatedClass = TypeSpec.classBuilder(bindingClassName)
192204
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
@@ -210,16 +222,34 @@ private MethodSpec createTaskCallbackMethod(String methodName, @Nullable Element
210222
.addParameter(CLASS_TASK, "task");
211223

212224
if(methodToCall != null) {
213-
onPreExecuteMethod.addStatement("target.$L(task)", methodToCall.getSimpleName());
225+
// There is a method known that should be called, check the parameters.
226+
final List<? extends VariableElement> parameters = ((ExecutableElement) methodToCall).getParameters();
227+
if(parameters.size() == 0){
228+
// Zero parameters, just call the method.
229+
onPreExecuteMethod.addStatement("target.$L()", methodToCall.getSimpleName());
230+
} else if(parameters.size() == 1){
231+
// One parameter, check it and call the method.
232+
final VariableElement parameter = parameters.get(0);
233+
final TypeMirror taskType = processingEnv.getTypeUtils().erasure(processingEnv.getElementUtils().getTypeElement(CLASS_TASK.reflectionName()).asType());
234+
235+
if(!processingEnv.getTypeUtils().isAssignable(parameter.asType(), taskType)){
236+
// Parameter not an instance of Task
237+
error(parameter, "Type of parameter '%s' is not an instance of '%s'!", parameter.getSimpleName(), taskType);
238+
} else {
239+
// Check if the class to cast too is accessible.
240+
final Element requiredElement = processingEnv.getTypeUtils().asElement(parameter.asType());
241+
if (!requiredElement.getModifiers().contains(Modifier.PUBLIC) && !requiredElement.getModifiers().contains(Modifier.PROTECTED)) {
242+
error(parameter, "Type of parameter '%s' is not public or protected accessible! This prevents Android-Retainable-Tasks from casting '%s' to '%s'.\nTo fix this either the type of the parameter or make the class accessible by adding the public or protected modifier!", parameter.getSimpleName(), taskType, parameter.asType().toString());
243+
}
244+
onPreExecuteMethod.addStatement("target.$L(($T) task)", methodToCall.getSimpleName(), parameter.asType());
245+
}
246+
}
214247
} else {
215248
onPreExecuteMethod.addComment("No annotated method found for $L", methodName);
216249
}
217250
return onPreExecuteMethod.build();
218251
}
219252

220-
221-
222-
223253
private void error(Element element, String message, Object... args) {
224254
printMessage(Diagnostic.Kind.ERROR, element, message, args);
225255
}

demo/src/main/java/org/neotech/app/retainabletasksdemo/activity/DemoActivityAnnotations.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
/**
2121
* Created by Rolf Smit on 29-May-17.
2222
*/
23-
24-
public class DemoActivityAnnotations extends TaskActivityCompat implements View.OnClickListener, OnAlertDialogClickListener {
23+
public final class DemoActivityAnnotations extends TaskActivityCompat implements View.OnClickListener, OnAlertDialogClickListener {
2524

2625
private static final String TASK_PROGRESS = "progress-dialog";
2726
private static final String DIALOG_PROGRESS = "progress-dialog";
@@ -34,7 +33,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
3433
setContentView(R.layout.activity_demo_annotations);
3534
findViewById(R.id.button_progress_task).setOnClickListener(this);
3635

37-
3836
if(savedInstanceState == null) {
3937
// After starting this activity directly start the task.
4038
getTaskManager().execute(new SimpleTask(TASK_PROGRESS));
@@ -73,7 +71,6 @@ public void onFinish(Task<?, ?> task){
7371
}
7472
}
7573

76-
7774
@Override
7875
public void onDialogFragmentClick(DialogFragment fragment, int which) {
7976
getTaskManager().cancel(TASK_PROGRESS);

demo/src/main/java/org/neotech/app/retainabletasksdemo/activity/DemoActivityBasic.java

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import android.support.annotation.NonNull;
55
import android.support.design.widget.Snackbar;
66
import android.support.v4.app.DialogFragment;
7-
import android.util.Log;
87
import android.view.View;
98
import android.widget.Button;
109
import android.widget.Toast;
@@ -16,17 +15,14 @@
1615
import org.neotech.app.retainabletasksdemo.tasks.SimpleTask;
1716
import org.neotech.app.retainabletasksdemo.tasks.TaskWithoutCallback;
1817
import org.neotech.library.retainabletasks.Task;
19-
import org.neotech.library.retainabletasks.TaskAttach;
2018
import org.neotech.library.retainabletasks.TaskExecutor;
21-
import org.neotech.library.retainabletasks.TaskPostExecute;
22-
import org.neotech.library.retainabletasks.TaskPreExecute;
23-
import org.neotech.library.retainabletasks.TaskProgress;
2419
import org.neotech.library.retainabletasks.providers.TaskActivityCompat;
2520

26-
public class DemoActivityBasic extends TaskActivityCompat implements View.OnClickListener, Task.AdvancedCallback, OnAlertDialogClickListener {
21+
public final class DemoActivityBasic extends TaskActivityCompat implements View.OnClickListener, Task.AdvancedCallback, OnAlertDialogClickListener {
2722

2823
private static final String TASK_RETAIN_UI_STATE = "retain-ui-state";
2924
private static final String TASK_PROGRESS = "progress-dialog";
25+
3026
private static final String DIALOG_PROGRESS = "progress-dialog";
3127

3228
private ProgressDialog progressDialog;
@@ -47,15 +43,15 @@ protected void onCreate(Bundle savedInstanceState) {
4743
@Override
4844
public Task.Callback onPreAttach(@NonNull Task<?, ?> task) {
4945
if(task.getTag().equals(TASK_RETAIN_UI_STATE)){
50-
/*
51-
the onPreAttach method will only be called if the task did not deliver its result
52-
and thus is still available/referenced by the TaskManger.
53-
54-
At this point the UI can be restored to the "task is running" state.
46+
/**
47+
* the onPreAttach method will only be called if the task did not deliver its result
48+
* and thus is still available/referenced by the TaskManger.
49+
*
50+
* At this point the UI can be restored to the "task is running" state.
5551
*/
5652
if (!task.isResultDelivered()) { //This call isn't necessary.
5753
retainUserInterfaceButton.setEnabled(false);
58-
retainUserInterfaceButton.setText(String.valueOf(task.getLastKnownProgress()));
54+
retainUserInterfaceButton.setText("" + task.getLastKnownProgress());
5955
}
6056
} else if(task.getTag().equals(TASK_PROGRESS)){
6157
progressDialog = ProgressDialog.getExistingInstance(getSupportFragmentManager(), DIALOG_PROGRESS);
@@ -67,18 +63,18 @@ public Task.Callback onPreAttach(@NonNull Task<?, ?> task) {
6763
public void onClick(View v) {
6864
final int id = v.getId();
6965
if(id == R.id.button_progress_task) {
70-
if (getTaskManager().isActive(TASK_PROGRESS)) {
66+
if (getTaskManager().isRunning(TASK_PROGRESS)) {
7167
Toast.makeText(this, R.string.toast_task_already_running, Toast.LENGTH_SHORT).show();
7268
}
7369
SimpleTask task = new SimpleTask(TASK_PROGRESS);
74-
getTaskManager().execute(task);
70+
getTaskManager().execute(task, this);
7571

7672
} else if(id == R.id.button_no_ui_task){
7773
TaskWithoutCallback task = new TaskWithoutCallback(this);
7874
TaskExecutor.execute(task);
7975
} else if(id == R.id.button_retain_ui_state_task){
8076
CountDownTask task = new CountDownTask(TASK_RETAIN_UI_STATE, 10);
81-
getTaskManager().execute(task);
77+
getTaskManager().execute(task, this);
8278
retainUserInterfaceButton.setEnabled(false);
8379
}
8480
}
@@ -90,48 +86,14 @@ public void onPreExecute(Task<?, ?> task) {
9086
}
9187
}
9288

93-
94-
//TaskAttach
95-
96-
//TaskPostExecute
97-
//TaskPreExecute
98-
//TaskProgressUpdate
99-
100-
@TaskAttach(TASK_RETAIN_UI_STATE)
101-
public void onAttach(Task<?, ?> task) {
102-
retainUserInterfaceButton.setEnabled(false);
103-
if (task.getLastKnownProgress() != null){
104-
retainUserInterfaceButton.setText(String.valueOf(task.getLastKnownProgress()));
105-
}
106-
}
107-
108-
@TaskPreExecute(TASK_RETAIN_UI_STATE)
109-
public void onPreExecuteAnnotated(Task<?, ?> task){
110-
Log.d("Test", "onPreExecuteAnnotated(" + task + ")");
111-
retainUserInterfaceButton.setEnabled(false);
112-
}
113-
114-
@TaskPostExecute(TASK_RETAIN_UI_STATE)
115-
public void onPostExecuteAnnotated(Task<?, ?> task){
116-
Log.d("Test", "onPostExecuteAnnotated(" + task + ")");
117-
retainUserInterfaceButton.setEnabled(true);
118-
retainUserInterfaceButton.setText(R.string.task_retain_ui_state);
119-
}
120-
121-
@TaskProgress(TASK_RETAIN_UI_STATE)
122-
public void onProgressUpdateAnnotated(Task<?, ?> task, Object progress){
123-
Log.d("Test", "onProgressUpdateAnnotated(" + task + ")");
124-
retainUserInterfaceButton.setText(String.valueOf(progress));
125-
}
126-
12789
@Override
12890
public void onPostExecute(Task<?, ?> task) {
12991
if(task.getTag().equals(TASK_PROGRESS)) {
13092
progressDialog.dismiss();
13193
Snackbar.make(findViewById(android.R.id.content), getString(R.string.toast_task_finished, getString(R.string.task_progress_dialog)), Snackbar.LENGTH_LONG).show();
13294
} else if(task.getTag().equals(TASK_RETAIN_UI_STATE)){
133-
//retainUserInterfaceButton.setEnabled(true);
134-
//retainUserInterfaceButton.setText(R.string.task_retain_ui_state);
95+
retainUserInterfaceButton.setEnabled(true);
96+
retainUserInterfaceButton.setText(R.string.task_retain_ui_state);
13597
}
13698
}
13799

@@ -148,12 +110,12 @@ public void onProgressUpdate(Task<?, ?> task, Object progress) {
148110
if(task.getTag().equals(TASK_PROGRESS)) {
149111
progressDialog.setProgress((int) progress);
150112
} else if(task.getTag().equals(TASK_RETAIN_UI_STATE)){
151-
retainUserInterfaceButton.setText(String.valueOf(progress));
113+
retainUserInterfaceButton.setText("" + (int) progress);
152114
}
153115
}
154116

155117
@Override
156118
public void onDialogFragmentClick(DialogFragment fragment, int which) {
157119
getTaskManager().cancel(TASK_PROGRESS);
158120
}
159-
}
121+
}

demo/src/main/java/org/neotech/app/retainabletasksdemo/activity/DemoActivityFragments.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import java.util.HashMap;
2121

22-
public class DemoActivityFragments extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
22+
public final class DemoActivityFragments extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
2323

2424
private static final String[] FRAGMENT_TAGS = new String[]{"Fragment 1", "Fragment 2", "Fragment 3"};
2525

demo/src/main/java/org/neotech/app/retainabletasksdemo/activity/DemoActivityLegacy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/**
1717
* Created by Rolf on 4-3-2016.
1818
*/
19-
public class DemoActivityLegacy extends TaskActivity implements View.OnClickListener, Task.AdvancedCallback {
19+
public final class DemoActivityLegacy extends TaskActivity implements View.OnClickListener, Task.AdvancedCallback {
2020

2121
private static final String TASK_COUNT_DOWN = "count-down";
2222
private Button button;

demo/src/main/java/org/neotech/app/retainabletasksdemo/activity/DemoActivitySerial.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
/**
1515
* Created by Rolf on 17-3-2016.
1616
*/
17-
public class DemoActivitySerial extends TaskActivityCompat implements View.OnClickListener, Task.AdvancedCallback {
17+
public final class DemoActivitySerial extends TaskActivityCompat implements View.OnClickListener, Task.AdvancedCallback {
1818

1919
private static final String TASK_SERIAL_1 = "serial-1";
2020
private static final String TASK_SERIAL_2 = "serial-2";

demo/src/main/java/org/neotech/app/retainabletasksdemo/activity/Main.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.neotech.app.retainabletasksdemo.ExtendedHtml;
2222
import org.neotech.app.retainabletasksdemo.R;
2323
import org.neotech.library.retainabletasks.Task;
24+
import org.neotech.library.retainabletasks.TaskAttach;
25+
import org.neotech.library.retainabletasks.TaskPostExecute;
2426
import org.neotech.library.retainabletasks.providers.TaskActivityCompat;
2527

2628
import java.util.ArrayList;
@@ -29,7 +31,7 @@
2931
/**
3032
* Created by Rolf on 16-3-2016.
3133
*/
32-
public class Main extends TaskActivityCompat implements Task.Callback {
34+
public final class Main extends TaskActivityCompat {
3335

3436
private ViewSwitcher vSwitcher;
3537
private ListView list;
@@ -43,7 +45,7 @@ protected void onCreate(Bundle savedInstanceState) {
4345
list = (ListView) findViewById(android.R.id.list);
4446

4547
if(!getTaskManager().isActive("list-loader")) {
46-
getTaskManager().execute(new UselessLoadingTask("list-loader", this), this);
48+
getTaskManager().execute(new UselessLoadingTask("list-loader", getApplicationContext()));
4749
}
4850
}
4951

@@ -69,28 +71,23 @@ public void setListShown(boolean shown){
6971
}
7072
}
7173

72-
@Override
73-
public Task.Callback onPreAttach(@NonNull Task<?, ?> task) {
74+
// This is quite fancy, we can just omit the Task parameter if we wan't to.
75+
@TaskAttach("list-loader")
76+
public void onAttach() {
7477
setListShown(false);
75-
return this;
76-
}
77-
78-
@Override
79-
public void onPreExecute(Task<?, ?> task) {
80-
8178
}
8279

83-
@Override
84-
public void onPostExecute(Task<?, ?> raw) {
85-
UselessLoadingTask task = (UselessLoadingTask) raw;
80+
// Even fancier the generated code automatically handles subtypes of Task.
81+
@TaskPostExecute("list-loader")
82+
public void onPostExecute(UselessLoadingTask task) {
8683
list.setAdapter(new DemoAdapter(task.getResult()));
8784
setListShown(true);
8885
}
8986

9087
/**
9188
* Task just to demonstrate the principe of starting a task before the UI is ready.
9289
*/
93-
private static class UselessLoadingTask extends Task<Void, ArrayList<Demo>> {
90+
protected static class UselessLoadingTask extends Task<Void, ArrayList<Demo>> {
9491

9592
private final Context context;
9693

library/src/main/java/org/neotech/library/retainabletasks/TaskManager.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,31 +96,30 @@ public interface TaskAttachListener {
9696
/**
9797
* Start the given task on the default Executor
9898
* ({@link TaskExecutor#getDefaultExecutor()}). The Task life-cycle events will be delivered to
99-
* the given {@link Task.Callback} listener.
99+
* the given {@link Task.Callback} listener. If you need annotation support please use
100+
* {@link #execute(Task, Executor)} instead which supports annotation based Task life-cycle
101+
* callbacks.
100102
*
101103
* @param task The Task to execute.
102104
* @param callback The Callback listener to deliver the Task events to.
103105
* @see TaskExecutor#setDefaultExecutor(Executor)
104-
* @deprecated This method has been deprecated, please use {@link #execute(Task)} instead which
105-
* supports annotation based Task life-cycle callbacks.
106106
*/
107107
@MainThread
108-
@Deprecated
109108
public abstract <Progress, Result> void execute(@NonNull Task<Progress, Result> task, @NonNull Task.Callback callback);
110109

111110
/**
112111
* Start the given task on {@link Executor}
113112
* ({@link TaskExecutor#setDefaultExecutor(Executor)}). The Task life-cycle events will be
114-
* delivered to the given {@link Task.Callback} listener.
113+
* delivered to the given {@link Task.Callback} listener. If you need annotation support please
114+
* use {@link #execute(Task, Executor)} instead which supports annotation based Task life-cycle
115+
* callbacks.
115116
*
116117
* @param task The Task to execute.
117118
* @param callback The Callback listener to deliver the Task events to.
118119
* @param executor The Executor to execute the given Task with.
119-
* @deprecated This method has been deprecated, please use {@link #execute(Task, Executor)}
120-
* instead which supports annotation based Task life-cycle callbacks.
120+
* @deprecated This method has been deprecated,
121121
*/
122122
@MainThread
123-
@Deprecated
124123
public abstract <Progress, Result> void execute(@NonNull Task<Progress, Result> task, @NonNull Task.Callback callback, @NonNull Executor executor);
125124

126125
/**

0 commit comments

Comments
 (0)