Add abstraction level for services APIs

This commit is contained in:
Shinokuni 2019-08-09 12:44:07 +02:00
parent 985fcddb1e
commit 5df094ca30
6 changed files with 83 additions and 83 deletions

View File

@ -13,8 +13,8 @@ import com.readrops.app.utils.ItemMatcher;
import com.readrops.app.utils.ParsingResult; import com.readrops.app.utils.ParsingResult;
import com.readrops.app.utils.Utils; import com.readrops.app.utils.Utils;
import com.readrops.readropslibrary.services.nextcloudnews.NextNewsAPI; import com.readrops.readropslibrary.services.nextcloudnews.NextNewsAPI;
import com.readrops.readropslibrary.services.nextcloudnews.SyncData; import com.readrops.readropslibrary.services.nextcloudnews.NextNewsSyncData;
import com.readrops.readropslibrary.services.nextcloudnews.SyncResult; import com.readrops.readropslibrary.services.nextcloudnews.NextNewsSyncResult;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder;
@ -46,8 +46,8 @@ public class NextNewsRepository extends ARepository {
@Override @Override
public Single<Boolean> login(Account account, boolean insert) { public Single<Boolean> login(Account account, boolean insert) {
return Single.create(emitter -> { return Single.create(emitter -> {
NextNewsAPI newsAPI = new NextNewsAPI(); NextNewsAPI newsAPI = new NextNewsAPI(account.toCredentials());
NextNewsUser user = newsAPI.login(account.toCredentials()); NextNewsUser user = newsAPI.login();
if (user != null) { if (user != null) {
account.setDisplayedName(user.getDisplayName()); account.setDisplayedName(user.getDisplayName());
@ -65,7 +65,7 @@ public class NextNewsRepository extends ARepository {
public Observable<Feed> sync(List<Feed> feeds, Account account) { public Observable<Feed> sync(List<Feed> feeds, Account account) {
return Observable.create(emitter -> { return Observable.create(emitter -> {
try { try {
NextNewsAPI newsAPI = new NextNewsAPI(); NextNewsAPI newsAPI = new NextNewsAPI(account.toCredentials());
long lastModified = LocalDateTime.now().toDateTime().getMillis(); long lastModified = LocalDateTime.now().toDateTime().getMillis();
NextNewsAPI.SyncType syncType; NextNewsAPI.SyncType syncType;
@ -74,7 +74,7 @@ public class NextNewsRepository extends ARepository {
else else
syncType = NextNewsAPI.SyncType.INITIAL_SYNC; syncType = NextNewsAPI.SyncType.INITIAL_SYNC;
SyncData syncData = new SyncData(); NextNewsSyncData syncData = new NextNewsSyncData();
if (syncType == NextNewsAPI.SyncType.CLASSIC_SYNC) { if (syncType == NextNewsAPI.SyncType.CLASSIC_SYNC) {
syncData.setLastModified(account.getLastModified() / 1000L); syncData.setLastModified(account.getLastModified() / 1000L);
@ -83,7 +83,7 @@ public class NextNewsRepository extends ARepository {
} }
TimingLogger timings = new TimingLogger(TAG, "nextcloud news " + syncType.name().toLowerCase()); TimingLogger timings = new TimingLogger(TAG, "nextcloud news " + syncType.name().toLowerCase());
SyncResult syncResult = newsAPI.sync(account.toCredentials(), syncType, syncData); NextNewsSyncResult syncResult = newsAPI.sync(syncType, syncData);
timings.addSplit("server queries"); timings.addSplit("server queries");
if (!syncResult.isError()) { if (!syncResult.isError()) {
@ -117,13 +117,13 @@ public class NextNewsRepository extends ARepository {
public Single<List<FeedInsertionResult>> addFeeds(List<ParsingResult> results, Account account) { public Single<List<FeedInsertionResult>> addFeeds(List<ParsingResult> results, Account account) {
return Single.create(emitter -> { return Single.create(emitter -> {
List<FeedInsertionResult> feedInsertionResults = new ArrayList<>(); List<FeedInsertionResult> feedInsertionResults = new ArrayList<>();
NextNewsAPI newsAPI = new NextNewsAPI(); NextNewsAPI newsAPI = new NextNewsAPI(account.toCredentials());
for (ParsingResult result : results) { for (ParsingResult result : results) {
FeedInsertionResult insertionResult = new FeedInsertionResult(); FeedInsertionResult insertionResult = new FeedInsertionResult();
try { try {
NextNewsFeeds nextNewsFeeds = newsAPI.createFeed(account.toCredentials(), result.getUrl(), 0); NextNewsFeeds nextNewsFeeds = newsAPI.createFeed(result.getUrl(), 0);
if (nextNewsFeeds != null) { if (nextNewsFeeds != null) {
List<Feed> newFeeds = insertFeeds(nextNewsFeeds.getFeeds(), account); List<Feed> newFeeds = insertFeeds(nextNewsFeeds.getFeeds(), account);
@ -154,7 +154,7 @@ public class NextNewsRepository extends ARepository {
@Override @Override
public Completable updateFeed(Feed feed, Account account) { public Completable updateFeed(Feed feed, Account account) {
return Completable.create(emitter -> { return Completable.create(emitter -> {
NextNewsAPI api = new NextNewsAPI(); NextNewsAPI api = new NextNewsAPI(account.toCredentials());
Folder folder = feed.getFolderId() == null ? null : database.folderDao().select(feed.getFolderId()); Folder folder = feed.getFolderId() == null ? null : database.folderDao().select(feed.getFolderId());
@ -167,8 +167,7 @@ public class NextNewsRepository extends ARepository {
newsFeed = new NextNewsFeed(feed.getRemoteId(), 0); // 0 for no folder newsFeed = new NextNewsFeed(feed.getRemoteId(), 0); // 0 for no folder
try { try {
if (api.renameFeed(account.toCredentials(), newsRenameFeed) && if (api.renameFeed(newsRenameFeed) && api.changeFeedFolder(newsFeed)) {
api.changeFeedFolder(account.toCredentials(), newsFeed)) {
if (folder != null) if (folder != null)
database.feedDao().updateFeedFields(feed.getId(), feed.getName(), feed.getUrl(), folder.getId()); database.feedDao().updateFeedFields(feed.getId(), feed.getName(), feed.getUrl(), folder.getId());
else else
@ -186,10 +185,10 @@ public class NextNewsRepository extends ARepository {
@Override @Override
public Completable deleteFeed(Feed feed, Account account) { public Completable deleteFeed(Feed feed, Account account) {
return Completable.create(emitter -> { return Completable.create(emitter -> {
NextNewsAPI api = new NextNewsAPI(); NextNewsAPI api = new NextNewsAPI(account.toCredentials());
try { try {
if (api.deleteFeed(account.toCredentials(), feed.getRemoteId())) { if (api.deleteFeed(feed.getRemoteId())) {
database.feedDao().delete(feed.getId()); database.feedDao().delete(feed.getId());
emitter.onComplete(); emitter.onComplete();
} else } else
@ -205,10 +204,10 @@ public class NextNewsRepository extends ARepository {
@Override @Override
public Completable addFolder(Folder folder, Account account) { public Completable addFolder(Folder folder, Account account) {
return Completable.create(emitter -> { return Completable.create(emitter -> {
NextNewsAPI api = new NextNewsAPI(); NextNewsAPI api = new NextNewsAPI(account.toCredentials());
try { try {
NextNewsFolders folders = api.createFolder(account.toCredentials(), new NextNewsFolder(folder.getRemoteId(), folder.getName())); NextNewsFolders folders = api.createFolder(new NextNewsFolder(folder.getRemoteId(), folder.getName()));
if (folders != null) if (folders != null)
insertFolders(folders.getFolders(), account); insertFolders(folders.getFolders(), account);
@ -225,10 +224,10 @@ public class NextNewsRepository extends ARepository {
@Override @Override
public Completable updateFolder(Folder folder, Account account) { public Completable updateFolder(Folder folder, Account account) {
return Completable.create(emitter -> { return Completable.create(emitter -> {
NextNewsAPI api = new NextNewsAPI(); NextNewsAPI api = new NextNewsAPI(account.toCredentials());
try { try {
if (api.renameFolder(account.toCredentials(), new NextNewsFolder(folder.getRemoteId(), folder.getName()))) { if (api.renameFolder(new NextNewsFolder(folder.getRemoteId(), folder.getName()))) {
database.folderDao().update(folder); database.folderDao().update(folder);
emitter.onComplete(); emitter.onComplete();
} else } else
@ -245,10 +244,10 @@ public class NextNewsRepository extends ARepository {
@Override @Override
public Completable deleteFolder(Folder folder, Account account) { public Completable deleteFolder(Folder folder, Account account) {
return Completable.create(emitter -> { return Completable.create(emitter -> {
NextNewsAPI api = new NextNewsAPI(); NextNewsAPI api = new NextNewsAPI(account.toCredentials());
try { try {
if (api.deleteFolder(account.toCredentials(), new NextNewsFolder(folder.getRemoteId(), folder.getName()))) { if (api.deleteFolder(new NextNewsFolder(folder.getRemoteId(), folder.getName()))) {
database.folderDao().delete(folder); database.folderDao().delete(folder);
emitter.onComplete(); emitter.onComplete();
} else } else

View File

@ -0,0 +1,37 @@
package com.readrops.readropslibrary;
import androidx.annotation.NonNull;
import com.readrops.readropslibrary.services.nextcloudnews.Credentials;
import com.readrops.readropslibrary.utils.HttpManager;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Abstraction level for services APIs
* @param <T> an API service interface
*/
public abstract class API<T> {
protected T api;
public API(Credentials credentials, @NonNull Class<T> clazz, @NonNull String endPoint) {
api = createAPI(credentials, clazz, endPoint);
}
protected Retrofit getConfiguredRetrofitInstance(@NonNull HttpManager httpManager, @NonNull String endPoint) {
return new Retrofit.Builder()
.baseUrl(httpManager.getCredentials().getUrl() + endPoint)
.addConverterFactory(GsonConverterFactory.create())
.client(httpManager.getOkHttpClient())
.build();
}
private T createAPI(@NonNull Credentials credentials, @NonNull Class<T> clazz, @NonNull String endPoint) {
HttpManager httpManager = new HttpManager(credentials);
Retrofit retrofit = getConfiguredRetrofitInstance(httpManager, endPoint);
return retrofit.create(clazz);
}
}

View File

@ -5,7 +5,8 @@ import android.content.res.Resources;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.readrops.readropslibrary.services.NextNewsService; import com.readrops.readropslibrary.services.API;
import com.readrops.readropslibrary.services.Credentials;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder;
@ -15,7 +16,6 @@ import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItems;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsRenameFeed; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsRenameFeed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsUser; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsUser;
import com.readrops.readropslibrary.utils.ConflictException; import com.readrops.readropslibrary.utils.ConflictException;
import com.readrops.readropslibrary.utils.HttpManager;
import com.readrops.readropslibrary.utils.LibUtils; import com.readrops.readropslibrary.utils.LibUtils;
import com.readrops.readropslibrary.utils.UnknownFormatException; import com.readrops.readropslibrary.utils.UnknownFormatException;
@ -24,37 +24,16 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import retrofit2.Response; import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class NextNewsAPI { public class NextNewsAPI extends API<NextNewsService> {
private static final String TAG = NextNewsAPI.class.getSimpleName(); private static final String TAG = NextNewsAPI.class.getSimpleName();
private NextNewsService api; public NextNewsAPI(Credentials credentials) {
super(credentials, NextNewsService.class, NextNewsService.END_POINT);
public NextNewsAPI() {
} }
private Retrofit getConfiguredRetrofitInstance(@NonNull HttpManager httpManager) { public NextNewsUser login() throws IOException {
return new Retrofit.Builder()
.baseUrl(httpManager.getCredentials().getUrl() + NextNewsService.ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.client(httpManager.getOkHttpClient())
.build();
}
private NextNewsService createAPI(@NonNull Credentials credentials) {
HttpManager httpManager = new HttpManager(credentials);
Retrofit retrofit = getConfiguredRetrofitInstance(httpManager);
return retrofit.create(NextNewsService.class);
}
public NextNewsUser login(Credentials credentials) throws IOException {
api = createAPI(credentials);
Response<NextNewsUser> response = api.getUser().execute(); Response<NextNewsUser> response = api.getUser().execute();
if (!response.isSuccessful()) if (!response.isSuccessful())
@ -64,10 +43,8 @@ public class NextNewsAPI {
} }
public @Nullable public @Nullable
NextNewsFeeds createFeed(Credentials credentials, String url, int folderId) NextNewsFeeds createFeed(String url, int folderId)
throws IOException, UnknownFormatException { throws IOException, UnknownFormatException {
api = createAPI(credentials);
Response<NextNewsFeeds> response = api.createFeed(url, folderId).execute(); Response<NextNewsFeeds> response = api.createFeed(url, folderId).execute();
if (!response.isSuccessful()) { if (!response.isSuccessful()) {
@ -80,17 +57,15 @@ public class NextNewsAPI {
return response.body(); return response.body();
} }
public SyncResult sync(@NonNull Credentials credentials, @NonNull SyncType syncType, @Nullable SyncData data) throws IOException { public NextNewsSyncResult sync(@NonNull SyncType syncType, @Nullable NextNewsSyncData data) throws IOException {
api = createAPI(credentials); NextNewsSyncResult syncResult = new NextNewsSyncResult();
SyncResult syncResult = new SyncResult();
switch (syncType) { switch (syncType) {
case INITIAL_SYNC: case INITIAL_SYNC:
initialSync(syncResult); initialSync(syncResult);
break; break;
case CLASSIC_SYNC: case CLASSIC_SYNC:
if (data == null) if (data == null)
throw new NullPointerException("SyncData can't be null"); throw new NullPointerException("NextNewsSyncData can't be null");
classicSync(syncResult, data); classicSync(syncResult, data);
break; break;
@ -99,7 +74,7 @@ public class NextNewsAPI {
return syncResult; return syncResult;
} }
private void initialSync(SyncResult syncResult) throws IOException { private void initialSync(NextNewsSyncResult syncResult) throws IOException {
getFeedsAndFolders(syncResult); getFeedsAndFolders(syncResult);
Response<NextNewsItems> itemsResponse = api.getItems(3, false, -1).execute(); Response<NextNewsItems> itemsResponse = api.getItems(3, false, -1).execute();
@ -112,7 +87,7 @@ public class NextNewsAPI {
syncResult.setItems(itemList.getItems()); syncResult.setItems(itemList.getItems());
} }
private void classicSync(SyncResult syncResult, SyncData data) throws IOException { private void classicSync(NextNewsSyncResult syncResult, NextNewsSyncData data) throws IOException {
putModifiedItems(data, syncResult); putModifiedItems(data, syncResult);
getFeedsAndFolders(syncResult); getFeedsAndFolders(syncResult);
@ -126,7 +101,7 @@ public class NextNewsAPI {
syncResult.setItems(itemList.getItems()); syncResult.setItems(itemList.getItems());
} }
private void getFeedsAndFolders(SyncResult syncResult) throws IOException { private void getFeedsAndFolders(NextNewsSyncResult syncResult) throws IOException {
Response<NextNewsFeeds> feedResponse = api.getFeeds().execute(); Response<NextNewsFeeds> feedResponse = api.getFeeds().execute();
NextNewsFeeds feedList = feedResponse.body(); NextNewsFeeds feedList = feedResponse.body();
@ -147,7 +122,7 @@ public class NextNewsAPI {
} }
private void putModifiedItems(SyncData data, SyncResult syncResult) throws IOException { private void putModifiedItems(NextNewsSyncData data, NextNewsSyncResult syncResult) throws IOException {
if (data.getReadItems().size() == 0 && data.getUnreadItems().size() == 0) if (data.getReadItems().size() == 0 && data.getUnreadItems().size() == 0)
return; return;
@ -165,9 +140,7 @@ public class NextNewsAPI {
} }
public @Nullable public @Nullable
NextNewsFolders createFolder(Credentials credentials, NextNewsFolder folder) throws IOException, UnknownFormatException, ConflictException { NextNewsFolders createFolder(NextNewsFolder folder) throws IOException, UnknownFormatException, ConflictException {
api = createAPI(credentials);
Response<NextNewsFolders> foldersResponse = api.createFolder(folder).execute(); Response<NextNewsFolders> foldersResponse = api.createFolder(folder).execute();
if (foldersResponse.isSuccessful()) if (foldersResponse.isSuccessful())
@ -180,9 +153,7 @@ public class NextNewsAPI {
return null; return null;
} }
public boolean deleteFolder(Credentials credentials, NextNewsFolder folder) throws IOException { public boolean deleteFolder(NextNewsFolder folder) throws IOException {
api = createAPI(credentials);
Response response = api.deleteFolder(folder.getId()).execute(); Response response = api.deleteFolder(folder.getId()).execute();
if (response.isSuccessful()) if (response.isSuccessful())
@ -193,9 +164,7 @@ public class NextNewsAPI {
return false; return false;
} }
public boolean renameFolder(Credentials credentials, NextNewsFolder folder) throws IOException, UnknownFormatException, ConflictException { public boolean renameFolder(NextNewsFolder folder) throws IOException, UnknownFormatException, ConflictException {
api = createAPI(credentials);
Response response = api.renameFolder(folder.getId(), folder).execute(); Response response = api.renameFolder(folder.getId(), folder).execute();
if (response.isSuccessful()) if (response.isSuccessful())
@ -214,9 +183,7 @@ public class NextNewsAPI {
} }
} }
public boolean deleteFeed(Credentials credentials, int feedId) throws IOException { public boolean deleteFeed(int feedId) throws IOException {
api = createAPI(credentials);
Response response = api.deleteFeed(feedId).execute(); Response response = api.deleteFeed(feedId).execute();
if (response.isSuccessful()) if (response.isSuccessful())
@ -227,9 +194,7 @@ public class NextNewsAPI {
return false; return false;
} }
public boolean changeFeedFolder(Credentials credentials, NextNewsFeed feed) throws IOException { public boolean changeFeedFolder(NextNewsFeed feed) throws IOException {
api = createAPI(credentials);
Map<String, Integer> folderIdMap = new HashMap<>(); Map<String, Integer> folderIdMap = new HashMap<>();
folderIdMap.put("folderId", feed.getFolderId()); folderIdMap.put("folderId", feed.getFolderId());
@ -243,9 +208,7 @@ public class NextNewsAPI {
return false; return false;
} }
public boolean renameFeed(Credentials credentials, NextNewsRenameFeed feed) throws IOException { public boolean renameFeed(NextNewsRenameFeed feed) throws IOException {
api = createAPI(credentials);
Response response = api.renameFeed(feed.getId(), feed).execute(); Response response = api.renameFeed(feed.getId(), feed).execute();
if (response.isSuccessful()) if (response.isSuccessful())

View File

@ -1,4 +1,4 @@
package com.readrops.readropslibrary.services; package com.readrops.readropslibrary.services.nextcloudnews;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder; import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder;
@ -22,7 +22,7 @@ import retrofit2.http.Query;
public interface NextNewsService { public interface NextNewsService {
String ENDPOINT = "/index.php/apps/news/api/v1-2/"; String END_POINT = "/index.php/apps/news/api/v1-2/";
@GET("user") @GET("user")
Call<NextNewsUser> getUser(); Call<NextNewsUser> getUser();

View File

@ -3,7 +3,7 @@ package com.readrops.readropslibrary.services.nextcloudnews;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class SyncData { public class NextNewsSyncData {
private List<Integer> unreadItems; private List<Integer> unreadItems;
@ -15,7 +15,7 @@ public class SyncData {
private long lastModified; private long lastModified;
public SyncData() { public NextNewsSyncData() {
unreadItems = new ArrayList<>(); unreadItems = new ArrayList<>();
readItems = new ArrayList<>(); readItems = new ArrayList<>();
starredItems = new ArrayList<>(); starredItems = new ArrayList<>();

View File

@ -6,7 +6,7 @@ import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItem;
import java.util.List; import java.util.List;
public class SyncResult { public class NextNewsSyncResult {
private List<NextNewsFolder> folders; private List<NextNewsFolder> folders;
@ -16,7 +16,8 @@ public class SyncResult {
private boolean error; private boolean error;
public SyncResult() { public NextNewsSyncResult() {
// empty constructor
} }
public List<NextNewsFolder> getFolders() { public List<NextNewsFolder> getFolders() {