Skip to content
This repository was archived by the owner on Jun 21, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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