package com.thebluealliance.androidclient.datafeed.maps;
import com.thebluealliance.androidclient.database.writers.BaseDbWriter;
import java.util.Date;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Response;
import rx.Observable;
import rx.functions.Func1;
/**
* A class that extracts the body from a Retrofit {@link Response} and calls an action (for use
* in writing to the db), if desired
*/
@Singleton
public class RetrofitResponseMap {
@Inject
public RetrofitResponseMap() {
}
/**
* Just returns the body from the response
*/
public synchronized <T> Observable<T> getResponseBody(Observable<Response<T>> response) {
return response.map(Response::body);
}
/**
* If the response is successful, call the provided db writer without cleaning previous info
*/
public synchronized <T> Observable<T> getAndWriteResponseBody(
Observable<Response<T>> response,
BaseDbWriter<T> writer) {
return getAndWriteResponseBody(response, writer, null, null, null);
}
/**
* If the response is successful (HTTP code between [200...300)), then call the provided
* db writer (which should write to the db) on the body
*/
public synchronized <T> Observable<T> getAndWriteResponseBody(
Observable<Response<T>> response,
BaseDbWriter<T> writer,
String dbTable,
String sqlWhere,
String[] whereArgs) {
return response.map(response1 -> {
T data = response1.body();
if (shouldWriteData(response1)) {
writer.call(dbTable, sqlWhere, whereArgs, data, getLastModifiedTimestamp(response1));
}
return data;
});
}
/**
* Map the response value before a write, does not clean db before
*/
public synchronized <T, W> Observable<T> getAndWriteMappedResponseBody(
Observable<Response<T>> response,
Func1<T, W> writerMap,
BaseDbWriter<W> writer) {
return getAndWriteMappedResponseBody(response, writerMap, writer, null, null, null);
}
/**
* Same as {@link #getAndWriteResponseBody(Observable, BaseDbWriter)} except this method allows for
* a map to be passed before write. The map does not affect the return value
*/
public synchronized <T, W> Observable<T> getAndWriteMappedResponseBody(
Observable<Response<T>> response,
Func1<T, W> writerMap,
BaseDbWriter<W> writer,
String dbTable,
String sqlWhere,
String[] whereArgs) {
return response.map(response1 -> {
T data = response1.body();
if (shouldWriteData(response1)) {
writer.call(dbTable, sqlWhere, whereArgs, writerMap.call(data),
getLastModifiedTimestamp(response1));
}
return data;
});
}
/**
* Return the mapped value also, without cleaning before
*/
public synchronized <T, W> Observable<W> mapAndWriteResponseBody(
Observable<Response<T>> response,
Func1<T, W> map,
BaseDbWriter<W> writer) {
return mapAndWriteResponseBody(response, map, writer, null, null, null);
}
/**
* Same as {@link #getAndWriteResponseBody(Observable, BaseDbWriter)} except this method allows for
* the response to be mapped, both for the return value and for the write
*/
public synchronized <T, W> Observable<W> mapAndWriteResponseBody(
Observable<Response<T>> response,
Func1<T, W> map,
BaseDbWriter<W> writer,
String dbTable,
String sqlWhere,
String[] whereArgs) {
return response.map(response1 -> {
W data = map.call(response1.body());
if (shouldWriteData(response1)) {
writer.call(dbTable, sqlWhere, whereArgs, data, getLastModifiedTimestamp(response1));
}
return data;
});
}
private static synchronized boolean shouldWriteData(Response response) {
okhttp3.Response cacheResponse = response.raw().cacheResponse();
return cacheResponse == null || cacheResponse.code() == 504;
}
private static synchronized Long getLastModifiedTimestamp(Response response) {
Date modifiedDate = response.headers().getDate("Last-Modified");
return modifiedDate != null ? modifiedDate.getTime() : 0;
}
}