Skip to content

Commit ecb8911

Browse files
committed
Added new interfaces and tests
1 parent a3c7200 commit ecb8911

11 files changed

Lines changed: 223 additions & 51 deletions

File tree

‎AndroidAnnotations/androidannotations-api/pom.xml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
<groupId>org.springframework.android</groupId>
3030
<artifactId>spring-android-rest-template</artifactId>
3131
<version>1.0.0.RELEASE</version>
32-
<scope>test</scope>
3332
</dependency>
3433
</dependencies>
3534

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.androidannotations.api.rest;
2+
3+
/**
4+
* A @Rest interface implementing this interface will automatically have the
5+
* implementations of this method generated.
6+
*/
7+
public interface RestClientErrorHandling {
8+
/**
9+
* Sets the error handler called when a rest error occurs.
10+
*
11+
* @param handler
12+
*/
13+
void setRestErrorHandler(RestErrorHandler handler);
14+
}

AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/api/rest/EnhancedRestClient.java renamed to AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/api/rest/RestClientHeaders.java

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,54 +15,58 @@
1515
*/
1616
package org.androidannotations.api.rest;
1717

18-
import org.springframework.web.client.RestTemplate;
18+
import org.springframework.http.HttpAuthentication;
1919

2020
/**
2121
* A @Rest interface implementing this interface will automatically have the
2222
* implementations of these methods generated.
2323
*/
24-
public interface EnhancedRestClient {
24+
public interface RestClientHeaders {
2525

2626
/**
27-
* Gets the root URL for the rest service.
27+
* Gets a cookie by name.
2828
*
29-
* @return String
29+
* @param name
30+
* @return the cookie value.
3031
*/
31-
String getRootUrl();
32+
String getCookie(String name);
3233

3334
/**
34-
* Sets the root URL for the rest service.
35+
* Sets a cookie by name.
3536
*
36-
* @param rootUrl
37+
* @param name
38+
* @param value
3739
*/
38-
void setRootUrl(String rootUrl);
40+
void setCookie(String name, String value);
3941

4042
/**
41-
* Gets the rest template used by the rest service implementation.
43+
* Gets a header by name.
4244
*
43-
* @return RestTemplate
45+
* @param name
46+
* @return the header value.
4447
*/
45-
RestTemplate getRestTemplate();
48+
String getHeader(String name);
4649

4750
/**
48-
* Sets the rest template used by the rest service implementation.
51+
* Sets a header by name.
4952
*
50-
* @param rt
53+
* @param name
54+
* @param value
5155
*/
52-
void setRestTemplate(RestTemplate rt);
56+
void setHeader(String name, String value);
5357

5458
/**
55-
* Sets the error handler called when a rest error occurs.
59+
* Sets the authentication object.
5660
*
57-
* @param handler
61+
* @param auth
5862
*/
59-
void setRestErrorHandler(RestErrorHandler handler);
63+
void setAuthentication(HttpAuthentication auth);
6064

61-
String getCookie(String c);
62-
63-
void setHeader(String h, String v);
64-
65-
String getHeader(String h);
66-
67-
void setCookie(String c, String v);
65+
/**
66+
* Sets the basic authentication user/password.
67+
*
68+
* @param user
69+
* @param password
70+
*/
71+
void setHttpBasicAuth(String user, String password);
6872
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.androidannotations.api.rest;
2+
3+
/**
4+
* A @Rest interface implementing this interface will automatically have the
5+
* implementations of these methods generated.
6+
*/
7+
public interface RestClientRootUrl {
8+
/**
9+
* Gets the root URL for the rest service.
10+
*
11+
* @return String
12+
*/
13+
String getRootUrl();
14+
15+
/**
16+
* Sets the root URL for the rest service.
17+
*
18+
* @param rootUrl
19+
*/
20+
void setRootUrl(String rootUrl);
21+
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.androidannotations.api.rest;
2+
3+
import org.springframework.web.client.RestTemplate;
4+
5+
/**
6+
* A @Rest interface implementing this interface will automatically have the
7+
* implementations of these methods generated.
8+
*/
9+
public interface RestClientSupport {
10+
/**
11+
* Gets the rest template used by the rest service implementation.
12+
*
13+
* @return RestTemplate
14+
*/
15+
RestTemplate getRestTemplate();
16+
17+
/**
18+
* Sets the rest template used by the rest service implementation.
19+
*
20+
* @param rt
21+
*/
22+
void setRestTemplate(RestTemplate rt);
23+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@
6868
import org.androidannotations.annotations.sharedpreferences.DefaultLong;
6969
import org.androidannotations.annotations.sharedpreferences.DefaultString;
7070
import org.androidannotations.annotations.sharedpreferences.SharedPref;
71-
import org.androidannotations.api.rest.EnhancedRestClient;
71+
import org.androidannotations.api.rest.RestClientErrorHandling;
72+
import org.androidannotations.api.rest.RestClientHeaders;
73+
import org.androidannotations.api.rest.RestClientRootUrl;
74+
import org.androidannotations.api.rest.RestClientSupport;
7275
import org.androidannotations.api.sharedpreferences.SharedPreferencesHelper;
7376
import org.androidannotations.model.AndroidSystemServices;
7477
import org.androidannotations.model.AnnotationElements;
@@ -77,6 +80,8 @@
7780

7881
public class ValidatorHelper {
7982

83+
private static final List<String> VALID_REST_INTERFACES = asList(RestClientHeaders.class.getName(), RestClientErrorHandling.class.getName(), RestClientRootUrl.class.getName(), RestClientSupport.class.getName());
84+
8085
private static final List<String> ANDROID_FRAGMENT_QUALIFIED_NAMES = asList(CanonicalNameConstants.FRAGMENT, CanonicalNameConstants.SUPPORT_V4_FRAGMENT);
8186

8287
private static final String METHOD_NAME_SET_ROOT_URL = "setRootUrl";
@@ -134,13 +139,19 @@ public void isTopLevel(TypeElement element, IsValid valid) {
134139

135140
public void doesNotExtendInvalidInterfaces(TypeElement element, IsValid valid) {
136141
if (element.getInterfaces().size() > 0) {
137-
if (element.getInterfaces().size() == 1 && element.getInterfaces().get(0).toString().equals(EnhancedRestClient.class.getName())) {
138-
// It's allowed to extend the EnhancedRestClient interface
139-
return;
142+
boolean isValid = true;
143+
144+
for (TypeMirror iface : element.getInterfaces()) {
145+
if (!VALID_REST_INTERFACES.contains(iface.toString())) {
146+
isValid = false;
147+
break;
148+
}
140149
}
141150

142-
valid.invalidate();
143-
annotationHelper.printAnnotationError(element, "%s interfaces can only extend EnhancedRestInterface");
151+
if (!isValid) {
152+
valid.invalidate();
153+
annotationHelper.printAnnotationError(element, "%s interfaces can only extend the following interfaces: " + VALID_REST_INTERFACES);
154+
}
144155
}
145156
}
146157

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/rest/MethodProcessor.java‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,19 @@ private void insertRestCallInBody(JBlock body, JExpression restCall, MethodProce
214214
}
215215
}
216216

217+
/**
218+
* Adds the try/catch around the rest execution code.
219+
*
220+
* If an exception is caught, it will first check if the handler is set. If
221+
* the handler is set, it will call the handler and return null (or nothing
222+
* if void). If the handler isn't set, it will re-throw the exception so
223+
* that it behaves as it did previous to this feature.
224+
*
225+
* @param body
226+
* @param restCall
227+
* @param methodHolder
228+
* @param methodReturnVoid
229+
*/
217230
private void insertRestTryCatchBlock(JBlock body, JExpression restCall, MethodProcessorHolder methodHolder, boolean methodReturnVoid) {
218231
RestImplementationHolder holder = restImplementationsHolder.getEnclosingHolder(methodHolder.getElement());
219232

@@ -233,12 +246,15 @@ private void insertRestTryCatchBlock(JBlock body, JExpression restCall, MethodPr
233246

234247
JBlock thenBlock = con._then();
235248

249+
// call the handler method if it was set.
236250
thenBlock.add(holder.restErrorHandlerField.invoke("onRestClientExceptionThrown").arg(excParam));
237251

252+
// return null if exception was caught and handled.
238253
if (!methodReturnVoid) {
239254
thenBlock._return(JExpr._null());
240255
}
241256

257+
// re-throw the exception if handler wasn't set.
242258
con._else()._throw(excParam);
243259
}
244260

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/rest/RestProcessor.java‎

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@
3434
import javax.lang.model.element.VariableElement;
3535
import javax.lang.model.type.DeclaredType;
3636
import javax.lang.model.type.TypeKind;
37+
import javax.lang.model.type.TypeMirror;
3738
import javax.lang.model.util.ElementFilter;
3839

3940
import org.androidannotations.annotations.rest.Rest;
40-
import org.androidannotations.api.rest.EnhancedRestClient;
4141
import org.androidannotations.api.rest.RestErrorHandler;
4242
import org.androidannotations.helper.AnnotationHelper;
4343
import org.androidannotations.helper.ModelConstants;
@@ -165,48 +165,59 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
165165
implementSetErrorHandler(holder, codeModel, eBeansHolder, methods);
166166
}
167167

168+
/**
169+
* Gets all of the methods of the class and includes the methods of any
170+
* implemented interfaces.
171+
*
172+
* @param typeElement
173+
* @return full list of methods.
174+
*/
168175
private List<ExecutableElement> getMethods(TypeElement typeElement) {
169176
List<? extends Element> enclosedElements = typeElement.getEnclosedElements();
170177
List<ExecutableElement> methods = new ArrayList<ExecutableElement>(ElementFilter.methodsIn(enclosedElements));
171178

172-
if (!typeElement.getInterfaces().isEmpty() && typeElement.getInterfaces().get(0).toString().equals(EnhancedRestClient.class.getName())) {
173-
DeclaredType dt = (DeclaredType) typeElement.getInterfaces().get(0);
179+
// Add methods of the interfaces. These will be valid as they have gone
180+
// through the validator.
181+
for (TypeMirror iface : typeElement.getInterfaces()) {
182+
DeclaredType dt = (DeclaredType) iface;
174183
methods.addAll(ElementFilter.methodsIn(dt.asElement().getEnclosedElements()));
175184
}
176185

177186
return methods;
178187
}
179188

180-
private void implementMapGetMethod(RestImplementationHolder holder, EBeansHolder eBeansHolder, List<ExecutableElement> methods, JFieldVar field, String methodName) {
181-
JMethod getCookieMethod = implementMethod(holder, null, eBeansHolder, methods, methodName, STRING, STRING);
182-
183-
if (getCookieMethod != null) {
184-
JInvocation cookieValue = JExpr.invoke(field, "get").arg(getCookieMethod.params().get(0));
185-
getCookieMethod.body()._return(cookieValue);
186-
}
187-
}
188-
189-
private void implementMapPutMethod(RestImplementationHolder holder, EBeansHolder eBeansHolder, JCodeModel codeModel, List<ExecutableElement> methods, JFieldVar field, String methodName) {
190-
JMethod putMapMethod = implementMethod(holder, codeModel, eBeansHolder, methods, methodName, TypeKind.VOID.toString(), STRING, STRING);
191-
192-
if (putMapMethod != null) {
193-
putMapMethod.body().invoke(field, "put").arg(putMapMethod.params().get(0)).arg(putMapMethod.params().get(1));
194-
}
195-
}
196-
189+
/**
190+
* Gets a method by name, return type and parameter types.
191+
*
192+
* Note: Maybe this method should be in a util class somewhere if it could
193+
* be reused by other processors.
194+
*
195+
* @param methods
196+
* @param methodName
197+
* @param returnType
198+
* @param parameterTypes
199+
* @return the ExecutableElement method object.
200+
*/
197201
private ExecutableElement getMethod(List<ExecutableElement> methods, String methodName, String returnType, String... parameterTypes) {
198202
for (ExecutableElement method : methods) {
199203
List<? extends VariableElement> parameters = method.getParameters();
204+
205+
// Get the method return type or "VOID" if none.
200206
String methodReturnType = method.getReturnType().getKind() == TypeKind.VOID ? TypeKind.VOID.toString() : method.getReturnType().toString();
201207

202208
if (parameters.size() == parameterTypes.length && methodReturnType.equals(returnType)) {
203209
if (methodName == null || method.getSimpleName().toString().equals(methodName)) {
210+
// At this point, method name, return type and number of
211+
// parameters are correct. Now we need to validate the
212+
// parameter types.
204213
boolean validMethod = true;
205214

206215
for (int i = 0; i < parameters.size(); i++) {
207216
VariableElement param = parameters.get(i);
208217

209218
if (!param.asType().toString().equals(parameterTypes[i])) {
219+
// Parameter type does not match, this is not the
220+
// correct method.
210221
validMethod = false;
211222
break;
212223
}
@@ -222,15 +233,37 @@ private ExecutableElement getMethod(List<ExecutableElement> methods, String meth
222233
return null;
223234
}
224235

236+
/**
237+
* Implements a method based on its name, return type and parameter types.
238+
* It will return the JMethod object to be given the full implementation.
239+
*
240+
* Note: Maybe this method should be in a util class somewhere if it could
241+
* be reused by other processors.
242+
*
243+
* @param holder
244+
* @param codeModel
245+
* @param eBeansHolder
246+
* @param methods
247+
* @param methodName
248+
* @param returnType
249+
* @param parameterTypes
250+
* @return The JMethod object created.
251+
*/
225252
private JMethod implementMethod(RestImplementationHolder holder, JCodeModel codeModel, EBeansHolder eBeansHolder, List<ExecutableElement> methods, String methodName, String returnType, String... parameterTypes) {
253+
// First get the ExecutableElement method object from the util function.
226254
ExecutableElement method = getMethod(methods, methodName, returnType, parameterTypes);
227255
JMethod jmethod = null;
228256

229257
if (method != null) {
258+
// Get the return type or VOID if none.
230259
JType jcReturnType = returnType.equals(TypeKind.VOID.toString()) ? codeModel.VOID : eBeansHolder.refClass(returnType);
260+
261+
// Create the implementation and annotate it with the Override
262+
// annotation.
231263
jmethod = holder.restImplementationClass.method(JMod.PUBLIC, jcReturnType, method.getSimpleName().toString());
232264
jmethod.annotate(Override.class);
233265

266+
// Create the parameters.
234267
for (int i = 0; i < method.getParameters().size(); i++) {
235268
VariableElement param = method.getParameters().get(i);
236269
jmethod.param(eBeansHolder.refClass(parameterTypes[i]), param.getSimpleName().toString());
@@ -240,6 +273,23 @@ private JMethod implementMethod(RestImplementationHolder holder, JCodeModel code
240273
return jmethod;
241274
}
242275

276+
private void implementMapGetMethod(RestImplementationHolder holder, EBeansHolder eBeansHolder, List<ExecutableElement> methods, JFieldVar field, String methodName) {
277+
JMethod getCookieMethod = implementMethod(holder, null, eBeansHolder, methods, methodName, STRING, STRING);
278+
279+
if (getCookieMethod != null) {
280+
JInvocation cookieValue = JExpr.invoke(field, "get").arg(getCookieMethod.params().get(0));
281+
getCookieMethod.body()._return(cookieValue);
282+
}
283+
}
284+
285+
private void implementMapPutMethod(RestImplementationHolder holder, EBeansHolder eBeansHolder, JCodeModel codeModel, List<ExecutableElement> methods, JFieldVar field, String methodName) {
286+
JMethod putMapMethod = implementMethod(holder, codeModel, eBeansHolder, methods, methodName, TypeKind.VOID.toString(), STRING, STRING);
287+
288+
if (putMapMethod != null) {
289+
putMapMethod.body().invoke(field, "put").arg(putMapMethod.params().get(0)).arg(putMapMethod.params().get(1));
290+
}
291+
}
292+
243293
private void implementSetAuthentication(RestImplementationHolder holder, JCodeModel codeModel, EBeansHolder eBeansHolder, List<ExecutableElement> methods) {
244294
JMethod setAuthMethod = implementMethod(holder, codeModel, eBeansHolder, methods, "setAuthentication", TypeKind.VOID.toString(), "org.springframework.http.HttpAuthentication");
245295

0 commit comments

Comments
 (0)