Skip to content
This repository has been archived by the owner on Jun 21, 2022. It is now read-only.

Param support added #63

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions app/src/main/assets/barricade/jokes/path/failure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
2 changes: 2 additions & 0 deletions app/src/main/assets/barricade/jokes/random/failure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
6 changes: 6 additions & 0 deletions app/src/main/assets/barricade/jokes/random/success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"icon_url" : "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id" : "gX6RQU9EQxC4oZd6kVeiSw",
"url" : "http://api.chucknorris.io/jokes/gX6RQU9EQxC4oZd6kVeiSw",
"value" : "When Chuck Norris was a kid, he made his mom eat her vegetables"
}
6 changes: 6 additions & 0 deletions app/src/main/assets/barricade/jokes/success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"icon_url" : "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id" : "gX6RQU9EQxC4oZd6kVeiSw",
"url" : "http://api.chucknorris.io/jokes/gX6RQU9EQxC4oZd6kVeiSw",
"value" : "When Chuck Norris was a kid, he made his mom eat her vegetables"
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
public class BarricadeSampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
new Barricade.Builder(this, BarricadeConfig.getInstance()).enableShakeToStart(this).install();
Barricade barricade =new Barricade.Builder(this, BarricadeConfig.getInstance()).install();
barricade.enableShakeListener(this);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
package com.mutualmobile.barricade.sample.api;

import com.mutualmobile.barricade.annotation.Barricade;
import com.mutualmobile.barricade.annotation.Params;
import com.mutualmobile.barricade.annotation.QueryParams;
import com.mutualmobile.barricade.annotation.Response;
import com.mutualmobile.barricade.annotation.UrlPath;
import com.mutualmobile.barricade.sample.api.model.Joke;

import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;

public interface ChuckNorrisApiService {

@GET("/jokes/random") @Barricade(endpoint = "random", responses = {
@GET("/jokes/random") @Barricade(endpoint = "jokes/random", responses = {
@Response(fileName = "success.json",isDefault = true),
@Response(fileName = "failure.json", statusCode = 401)
}) Call<Joke> getRandomJoke();


/*Example of of using barricade with query params*/
@GET("/jokes/random")
@Barricade(endpoint = "jokes/random",
queryParams = {
@QueryParams( params = {@Params(name = "path",value = "success")} ,
response = @Response(fileName = "success.json",isDefault = true)),
@QueryParams( params = {@Params(name = "path",value = "failure")} ,
response = @Response(fileName = "failure.json", statusCode = 401))
},
responses = {
@Response(fileName = "success.json",isDefault = true),
@Response(fileName = "failure.json", statusCode = 401)
}) Call<Joke> getRandomJoke(@Query("path")String test);

/*Using barricade with url path param */
@GET("/jokes/{path}")
@Barricade(endpoint = "jokes/",
path = {@UrlPath(path = "path", responses = { @Response(fileName = "success.json") }) })
Call<Joke> getRandomJokePath(@Path("path") String test);

@GET("/jokes/categories") Call<List<String>> getJokeCategories();
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,27 @@ public class ChuckNorrisApiServiceTest {

@Test public void canFetchRandomJokeFromBarricade() throws IOException {
barricade.setEnabled(true);
Response<Joke> response = getApiService().getRandomJoke().execute();
Response<Joke> response = getApiService().getRandomJoke("success").execute();

assertThat(response.isSuccessful()).isTrue();
assertThat(response.code()).isEqualTo(200);
assertThat(response.body()).isNotNull();

Joke joke = response.body();
assertThat(joke.id).isNotNull();
assertThat(joke.id).isNotEmpty();
assertThat(joke.id).isEqualTo("gX6RQU9EQxC4oZd6kVeiSw");
assertThat(joke.value).isNotNull();
assertThat(joke.value).isNotEmpty();
assertThat(joke.value).isEqualTo("When Chuck Norris was a kid, he made his mom eat her vegetables");
assertThat(joke.iconUrl).isNotNull();
assertThat(joke.iconUrl).isNotEmpty();
assertThat(joke.iconUrl).isEqualTo("https://assets.chucknorris.host/img/avatar/chuck-norris.png");
}

@Test public void canFetchRandomJokeFromBarricadeWithPathUrl() throws IOException {
barricade.setEnabled(true);
Response<Joke> response = getApiService().getRandomJokePath("path").execute();

assertThat(response.isSuccessful()).isTrue();
assertThat(response.code()).isEqualTo(200);
Expand All @@ -71,7 +91,7 @@ public class ChuckNorrisApiServiceTest {
}

@Test public void canSetBarricadeResponseAtRunTime() throws IOException {
barricade.setEnabled(true).setResponse(BarricadeConfig.Endpoints.RANDOM, BarricadeConfig.Responses.Random.FAILURE);
barricade.setEnabled(true).setResponse(BarricadeConfig.Endpoints.JOKESRANDOM, BarricadeConfig.Responses.Jokesrandom.FAILURE);
Response<Joke> response = getApiService().getRandomJoke().execute();
assertThat(response.isSuccessful()).isFalse();
assertThat(response.code()).isEqualTo(401);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ public interface IBarricadeConfig {
HashMap<String, BarricadeResponseSet> getConfigs();

BarricadeResponse getResponseForEndpoint(String endpoint);
BarricadeResponse getResponseForParams(String endpoint,String params);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.HashMap;

import static java.lang.annotation.RetentionPolicy.CLASS;

Expand All @@ -12,6 +13,8 @@
*/
@Documented @Retention(CLASS) @Target(ElementType.METHOD) public @interface Barricade {
String endpoint() default "";

UrlPath[] path() default {};
QueryParams[] queryParams() default {};
RequestJson[] requestJson() default {};
Response[] responses() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mutualmobile.barricade.annotation;

/**
* Annotation to declare a params of API.
*/
public @interface Params {
String name();
String value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mutualmobile.barricade.annotation;

/**
* Annotations to declare query parameters and response for corresponding query params
*/
public @interface QueryParams {
Params[] params();
Response response();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mutualmobile.barricade.annotation;

/**
* Annotations for Post Request body and corresponding response
*/
public @interface RequestJson {
String body();
Response response();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.mutualmobile.barricade.annotation;

/**
* Support for dynamic url path
* @path will appended after endpoint.
* for eg. if your retrofit url is user/{path}/class
* you barricade code will be endpoint = user , UrlPath{ path= {expected value}/class}
*/
public @interface UrlPath {
String path();
Response[] responses();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
public class BarricadeResponse {
public int statusCode;
public String responseFileName;
public String filePath;
public String contentType;

public BarricadeResponse(int statusCode, String responseFileName, String contentType) {
public BarricadeResponse(int statusCode, String responseFileName, String contentType,String filePath) {
this.statusCode = statusCode;
this.responseFileName = responseFileName;
this.contentType = contentType;
this.filePath = filePath;
}

public BarricadeResponse(Response response) {
public BarricadeResponse(Response response,String filePath) {
this.statusCode = response.statusCode();
this.responseFileName = response.fileName();
this.contentType = response.type();
this.filePath = filePath;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mutualmobile.barricade.response;

import com.mutualmobile.barricade.annotation.QueryParams;
import java.util.List;

/**
Expand All @@ -15,4 +16,4 @@ public BarricadeResponseSet(List<BarricadeResponse> responses, int defaultIndex)
this.defaultIndex = defaultIndex;
this.originalDefaultIndex = defaultIndex;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import com.google.auto.service.AutoService;
import com.mutualmobile.barricade.annotation.Barricade;
import com.mutualmobile.barricade.annotation.Params;
import com.mutualmobile.barricade.annotation.QueryParams;
import com.mutualmobile.barricade.annotation.RequestJson;
import com.mutualmobile.barricade.annotation.Response;
import com.mutualmobile.barricade.annotation.UrlPath;
import com.mutualmobile.barricade.response.BarricadeResponse;
import com.mutualmobile.barricade.response.BarricadeResponseSet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
Expand All @@ -29,59 +34,100 @@
*/
@AutoService(Processor.class) public class BarricadeProcessor extends AbstractProcessor {

private Messager messager;

@Override public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
messager = processingEnvironment.getMessager();
}

@Override public Set<String> getSupportedAnnotationTypes() {
return singleton(Barricade.class.getCanonicalName());
}

@Override public SourceVersion getSupportedSourceVersion() {
return latestSupported();
}

@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
try {
HashMap<String, BarricadeResponseSet> configs = new HashMap<>();
// Iterate over all @Barricade annotated elements
for (Element annotatedElement : roundEnvironment.getElementsAnnotatedWith(Barricade.class)) {
Barricade barricade = annotatedElement.getAnnotation(Barricade.class);
messager.printMessage(NOTE, "[Barricade] Processing endpoint: " + barricade.endpoint());

List<BarricadeResponse> responses = new ArrayList<>(barricade.responses().length);
int defaultIndex = 0;

for (int i = 0; i < barricade.responses().length; i++) {
Response option = barricade.responses()[i];
responses.add(new BarricadeResponse(option));
if (option.isDefault()) {
defaultIndex = i;
}
}
configs.put(barricade.endpoint(), new BarricadeResponseSet(responses, defaultIndex));
}

// This method is called multiple times, but we want to generate code only once
if (!configs.isEmpty()) {
generateCode(configs);
}
} catch (Exception e) {
messager.printMessage(ERROR, "Couldn't process class:" + e.getMessage());
}

return true;
}

private void generateCode(HashMap<String, BarricadeResponseSet> configs) throws IOException {
if (configs.isEmpty()) {
messager.printMessage(ERROR, "Couldn't find any endpoints to barricade");
} else {
CodeGenerator.generateClass(processingEnv, configs, messager);
}
}
private Messager messager;

@Override public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
messager = processingEnvironment.getMessager();
}

@Override public Set<String> getSupportedAnnotationTypes() {
return singleton(Barricade.class.getCanonicalName());
}

@Override public SourceVersion getSupportedSourceVersion() {
return latestSupported();
}

@Override public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
try {
HashMap<String, BarricadeResponseSet> configs = new HashMap<>();
HashMap<String, Map<String, BarricadeResponse>> paramConfig = new HashMap<>();
// Iterate over all @Barricade annotated elements
for (Element annotatedElement : roundEnvironment.getElementsAnnotatedWith(Barricade.class)) {
Barricade barricade = annotatedElement.getAnnotation(Barricade.class);
messager.printMessage(NOTE, "[Barricade] Processing Start for endpoint: " + barricade.endpoint());
if (barricade.queryParams().length > 0) {
Map<String, BarricadeResponse> responseMap = mapQueryParams(barricade);
paramConfig.put(barricade.endpoint(), responseMap);
} else if (barricade.requestJson().length > 0) {
Map<String, BarricadeResponse> responseMap = mapRequestJson(barricade);
paramConfig.put(barricade.endpoint(), responseMap);
} else if (barricade.path().length > 0) {
for (int i = 0; i < barricade.path().length; i++) {
UrlPath urlPath = barricade.path()[i];
String endPoint = barricade.endpoint() + urlPath.path();
configs.putAll(mapEndPoints(endPoint, urlPath.responses()));
}
} else {
configs.putAll(mapEndPoints(barricade.endpoint(), barricade.responses()));
}
}

// This method is called multiple times, but we want to generate code only once
if (!configs.isEmpty()||!paramConfig.isEmpty()) {
generateCode(paramConfig,configs);
}
} catch (Exception e) {
messager.printMessage(ERROR, "Couldn't process class:" + e.getMessage());
}

return true;
}

private Map<String, BarricadeResponseSet> mapEndPoints(String endPoint, Response[] responses){
Map<String, BarricadeResponseSet> responseMap = new HashMap();
List<BarricadeResponse> responseList = new ArrayList(responses.length);
int defaultIndex = 0;

for (int i = 0; i < responses.length; i++) {
Response option = responses[i];
responseList.add(new BarricadeResponse(option,endPoint));
if (option.isDefault()) {
defaultIndex = i;
}
}
responseMap.put(endPoint, new BarricadeResponseSet(responseList, defaultIndex));
return responseMap;
}


private Map<String, BarricadeResponse> mapQueryParams(Barricade barricade){
Map<String, BarricadeResponse> responseMap = new HashMap<>(barricade.queryParams().length);
for (QueryParams queryParams : barricade.queryParams()) {
StringBuilder query = new StringBuilder();
for (Params params : queryParams.params()) {
query.append(params.name()).append("=").append(params.value()).append("&");
}
responseMap.put(query.toString(), new BarricadeResponse(queryParams.response(),barricade.endpoint()));
}
return responseMap;
}

private Map<String, BarricadeResponse> mapRequestJson(Barricade barricade){
Map<String, BarricadeResponse> responseMap = new HashMap<>(barricade.queryParams().length);
for (RequestJson postJson : barricade.requestJson()) {
String query = postJson.body();
responseMap.put(query, new BarricadeResponse(postJson.response(),barricade.endpoint()));
}
return responseMap;
}

private void generateCode(HashMap<String, Map<String,BarricadeResponse>> paramConfigs,HashMap<String, BarricadeResponseSet> configs) throws IOException {
if (configs.isEmpty()&& paramConfigs.isEmpty()) {
messager.printMessage(ERROR, "Couldn't find any endpoints");
} else {
CodeGenerator.generateClass(processingEnv,paramConfigs,configs, messager);
}
}
}
Loading