Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-notes.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2021-04-28 20:36:58 +0300
committerStefan Niedermann <info@niedermann.it>2021-04-28 20:36:58 +0300
commit4b416116d5017d8e571135bedc0409a75a87e9f5 (patch)
treea092196f723695c07326e4a730bdfe3b29a849b7 /app/src
parent1c3b9a0d629901d2d1c47000dae11347b06c57c9 (diff)
#1167 Use retrofit also for capabilities endpoint
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java26
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java68
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/SSOClient.java39
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/ApiProvider.java38
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java99
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_0_2.java70
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_1_0.java34
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/OcsAPI.java4
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java27
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/shared/model/SyncResultStatus.java7
10 files changed, 286 insertions, 126 deletions
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java
index b053227e..ecf9dfcf 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java
@@ -1,19 +1,24 @@
package it.niedermann.owncloud.notes.persistence;
import android.content.Context;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.gson.JsonParseException;
+import com.nextcloud.android.sso.api.NextcloudAPI;
+import com.nextcloud.android.sso.api.ParsedResponse;
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
import java.io.IOException;
+import java.util.Map;
-import it.niedermann.owncloud.notes.persistence.sync.ApiProvider;
+import it.niedermann.owncloud.notes.persistence.sync.OcsAPI;
import it.niedermann.owncloud.notes.shared.model.Capabilities;
+import retrofit2.NextcloudRetrofitApiBuilder;
import retrofit2.Response;
import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;
@@ -21,14 +26,23 @@ import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;
@WorkerThread
public class CapabilitiesClient {
- protected static final String HEADER_KEY_ETAG = "ETag";
+ private static final String TAG = CapabilitiesClient.class.getSimpleName();
+
+ private static final String API_ENDPOINT_OCS = "/ocs/v2.php/cloud/";
+ private static final String HEADER_KEY_ETAG = "ETag";
public static Capabilities getCapabilities(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @Nullable String lastETag) throws NextcloudHttpRequestFailedException, IOException {
- final ApiProvider provider = new ApiProvider(context, ssoAccount);
- final Response<Capabilities> response = provider.getOcsAPI().getCapabilities(lastETag).execute();
+ final NextcloudAPI nextcloudAPI = SSOClient.getNextcloudAPI(context.getApplicationContext(), ssoAccount);
+ final OcsAPI ocsAPI = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_OCS).create(OcsAPI.class);
+ final Response<ParsedResponse<Capabilities>> response = ocsAPI.getCapabilities(lastETag).execute();
try {
- final Capabilities capabilities = response.body();
- capabilities.setETag(response.headers().get(HEADER_KEY_ETAG));
+ final Capabilities capabilities = response.body().getResponse();
+ final Map<String, String> headers = response.body().getHeaders();
+ if (headers != null) {
+ capabilities.setETag(headers.get(HEADER_KEY_ETAG));
+ } else {
+ Log.w(TAG, "Response headers of capabilities are null");
+ }
return capabilities;
} catch (JsonParseException e) {
if (e.getCause() instanceof NextcloudHttpRequestFailedException && ((NextcloudHttpRequestFailedException) e.getCause()).getStatusCode() == HTTP_UNAVAILABLE) {
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java
index b3af4ab7..79e844ae 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java
@@ -6,6 +6,8 @@ import android.util.Log;
import androidx.annotation.NonNull;
import com.nextcloud.android.sso.AccountImporter;
+import com.nextcloud.android.sso.api.NextcloudAPI;
+import com.nextcloud.android.sso.api.ParsedResponse;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
import com.nextcloud.android.sso.exceptions.TokenMismatchException;
@@ -23,7 +25,7 @@ import java.util.Set;
import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.persistence.entity.Note;
-import it.niedermann.owncloud.notes.persistence.sync.ApiProvider;
+import it.niedermann.owncloud.notes.persistence.sync.NotesAPI;
import it.niedermann.owncloud.notes.shared.model.DBStatus;
import it.niedermann.owncloud.notes.shared.model.ISyncCallback;
import it.niedermann.owncloud.notes.shared.model.SyncResultStatus;
@@ -49,7 +51,7 @@ abstract class NotesServerSyncTask extends Thread {
@NonNull
private final Context context;
@NonNull
- private ApiProvider notesClient;
+ private NotesAPI notesAPI;
@NonNull
private final NotesRepository repo;
@NonNull
@@ -78,18 +80,21 @@ abstract class NotesServerSyncTask extends Thread {
@Override
public void run() {
onPreExecute();
- notesClient = new ApiProvider(context, ssoAccount);
- new Thread(() -> {
- Log.i(TAG, "STARTING SYNCHRONIZATION");
- final SyncResultStatus status = new SyncResultStatus();
- status.pushSuccessful = pushLocalChanges();
- if (!onlyLocalChanges) {
- status.pullSuccessful = pullRemoteChanges();
- }
- Log.i(TAG, "SYNCHRONIZATION FINISHED");
- onPostExecute(status);
- }).start();
+ final NextcloudAPI nextcloudAPI = SSOClient.getNextcloudAPI(context.getApplicationContext(), ssoAccount);
+ notesAPI = new NotesAPI(nextcloudAPI, localAccount.getPreferredApiVersion());
+
+ Log.i(TAG, "STARTING SYNCHRONIZATION");
+
+ final SyncResultStatus status = new SyncResultStatus();
+ status.pushSuccessful = pushLocalChanges();
+ if (!onlyLocalChanges) {
+ status.pullSuccessful = pullRemoteChanges();
+ }
+
+ Log.i(TAG, "SYNCHRONIZATION FINISHED");
+
+ onPostExecute(status);
}
abstract void onPreExecute();
@@ -113,13 +118,13 @@ abstract class NotesServerSyncTask extends Thread {
Log.v(TAG, " ...create/edit");
if (note.getRemoteId() != null) {
Log.v(TAG, " ...Note has remoteId → try to edit");
- final Response<Note> editResponse = notesClient.getNotesAPI().editNote(note, note.getRemoteId()).execute();
+ final Response<Note> editResponse = notesAPI.editNote(note, note.getRemoteId()).execute();
if (editResponse.isSuccessful()) {
remoteNote = editResponse.body();
} else {
if (editResponse.code() == HTTP_NOT_FOUND) {
Log.v(TAG, " ...Note does no longer exist on server → recreate");
- final Response<Note> createResponse = notesClient.getNotesAPI().createNote(note).execute();
+ final Response<Note> createResponse = notesAPI.createNote(note).execute();
if (createResponse.isSuccessful()) {
remoteNote = createResponse.body();
} else {
@@ -131,7 +136,7 @@ abstract class NotesServerSyncTask extends Thread {
}
} else {
Log.v(TAG, " ...Note does not have a remoteId yet → create");
- final Response<Note> createResponse = notesClient.getNotesAPI().createNote(note).execute();
+ final Response<Note> createResponse = notesAPI.createNote(note).execute();
if (createResponse.isSuccessful()) {
remoteNote = createResponse.body();
repo.updateRemoteId(note.getId(), remoteNote.getRemoteId());
@@ -147,7 +152,7 @@ abstract class NotesServerSyncTask extends Thread {
Log.v(TAG, " ...delete (only local, since it has never been synchronized)");
} else {
Log.v(TAG, " ...delete (from server and local)");
- final Response<Note> deleteResponse = notesClient.getNotesAPI().deleteNote(note.getRemoteId()).execute();
+ final Response<Note> deleteResponse = notesAPI.deleteNote(note.getRemoteId()).execute();
if (!deleteResponse.isSuccessful()) {
if (deleteResponse.code() == HTTP_NOT_FOUND) {
Log.v(TAG, " ...delete (note has already been deleted remotely)");
@@ -197,9 +202,9 @@ abstract class NotesServerSyncTask extends Thread {
localAccount.setModified(accountFromDatabase.getModified());
localAccount.setETag(accountFromDatabase.getETag());
- final Response<List<Note>> fetchResponse = notesClient.getNotesAPI().getNotes(localAccount.getModified().getTimeInMillis() / 1_000, localAccount.getETag()).execute();
+ final Response<ParsedResponse<List<Note>>> fetchResponse = notesAPI.getNotes(localAccount.getModified().getTimeInMillis() / 1_000, localAccount.getETag()).execute();
if (fetchResponse.isSuccessful()) {
- final List<Note> remoteNotes = fetchResponse.body();
+ final List<Note> remoteNotes = fetchResponse.body().getResponse();
final Set<Long> remoteIDs = new HashSet<>();
// pull remote changes: update or create each remote note
for (Note remoteNote : remoteNotes) {
@@ -231,14 +236,14 @@ abstract class NotesServerSyncTask extends Thread {
}
// update ETag and Last-Modified in order to reduce size of next response
- localAccount.setETag(fetchResponse.headers().get(HEADER_KEY_ETAG));
+ localAccount.setETag(fetchResponse.body().getHeaders().get(HEADER_KEY_ETAG));
final Calendar lastModified = Calendar.getInstance();
lastModified.setTimeInMillis(0);
- final String lastModifiedHeader = fetchResponse.headers().get(HEADER_KEY_LAST_MODIFIED);
+ final String lastModifiedHeader = fetchResponse.body().getHeaders().get(HEADER_KEY_LAST_MODIFIED);
if (lastModifiedHeader != null)
lastModified.setTimeInMillis(Date.parse(lastModifiedHeader));
- Log.d(TAG, "ETag: " + fetchResponse.headers().get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")");
+ Log.d(TAG, "ETag: " + fetchResponse.body().getHeaders().get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")");
localAccount.setModified(lastModified);
@@ -247,7 +252,7 @@ abstract class NotesServerSyncTask extends Thread {
String supportedApiVersions = null;
- final String supportedApiVersionsHeader = fetchResponse.headers().get(HEADER_KEY_X_NOTES_API_VERSIONS);
+ final String supportedApiVersionsHeader = fetchResponse.body().getHeaders().get(HEADER_KEY_X_NOTES_API_VERSIONS);
if (supportedApiVersionsHeader != null) {
supportedApiVersions = "[" + Objects.requireNonNull(supportedApiVersionsHeader) + "]";
}
@@ -260,16 +265,17 @@ abstract class NotesServerSyncTask extends Thread {
}
return true;
} else {
- throw new Exception(fetchResponse.errorBody().string());
- }
- } catch (NextcloudHttpRequestFailedException e) {
- Log.d(TAG, "Server returned HTTP Status Code " + e.getStatusCode() + " - " + e.getMessage());
- if (e.getStatusCode() == HTTP_NOT_MODIFIED) {
- return true;
- } else {
- exceptions.add(e);
+ exceptions.add(new Exception(fetchResponse.errorBody().string()));
return false;
}
+// } catch (NextcloudHttpRequestFailedException e) {
+// Log.d(TAG, "Server returned HTTP Status Code " + e.getStatusCode() + " - " + e.getMessage());
+// if (e.getStatusCode() == HTTP_NOT_MODIFIED) {
+// return true;
+// } else {
+// exceptions.add(e);
+// return false;
+// }
} catch (Exception e) {
if (e instanceof TokenMismatchException) {
SSOClient.invalidateAPICache(ssoAccount);
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/SSOClient.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/SSOClient.java
index 9f28cfff..d110c8a0 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/SSOClient.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/SSOClient.java
@@ -1,40 +1,25 @@
package it.niedermann.owncloud.notes.persistence;
import android.content.Context;
-import android.graphics.Color;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
-import com.bumptech.glide.load.HttpException;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializer;
-import com.nextcloud.android.sso.aidl.NextcloudRequest;
import com.nextcloud.android.sso.api.NextcloudAPI;
-import com.nextcloud.android.sso.api.Response;
-import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.lang.reflect.Type;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
-import it.niedermann.android.util.ColorUtil;
import it.niedermann.owncloud.notes.persistence.sync.CapabilitiesDeserializer;
import it.niedermann.owncloud.notes.shared.model.Capabilities;
-import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;
-
@SuppressWarnings("WeakerAccess")
@WorkerThread
public class SSOClient {
@@ -43,7 +28,7 @@ public class SSOClient {
private static final Map<String, NextcloudAPI> mNextcloudAPIs = new HashMap<>();
- public static NextcloudAPI getNextcloudAPI(Context appContext, SingleSignOnAccount ssoAccount) {
+ public static synchronized NextcloudAPI getNextcloudAPI(@NonNull Context appContext, @NonNull SingleSignOnAccount ssoAccount) {
if (mNextcloudAPIs.containsKey(ssoAccount.name)) {
return mNextcloudAPIs.get(ssoAccount.name);
} else {
@@ -58,18 +43,18 @@ public class SSOClient {
return calendar;
})
.registerTypeAdapter(Capabilities.class, new CapabilitiesDeserializer())
- .create(),
- new NextcloudAPI.ApiConnectedListener() {
- @Override
- public void onConnected() {
- Log.i(TAG, "SSO API connected for " + ssoAccount);
- }
+ .create(), new NextcloudAPI.ApiConnectedListener() {
+ @Override
+ public void onConnected() {
+ Log.i(TAG, "SSO API connected for " + ssoAccount);
+ }
- @Override
- public void onError(Exception ex) {
- ex.printStackTrace();
- }
- });
+ @Override
+ public void onError(Exception ex) {
+ ex.printStackTrace();
+ SSOClient.invalidateAPICache(ssoAccount);
+ }
+ });
mNextcloudAPIs.put(ssoAccount.name, nextcloudAPI);
return nextcloudAPI;
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/ApiProvider.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/ApiProvider.java
deleted file mode 100644
index 538afd89..00000000
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/ApiProvider.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package it.niedermann.owncloud.notes.persistence.sync;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-
-import com.google.gson.GsonBuilder;
-import com.nextcloud.android.sso.api.NextcloudAPI;
-import com.nextcloud.android.sso.model.SingleSignOnAccount;
-
-import it.niedermann.owncloud.notes.persistence.SSOClient;
-import retrofit2.NextcloudRetrofitApiBuilder;
-
-/**
- * Created by david on 26.05.17.
- */
-public class ApiProvider {
-
- private static final String API_ENDPOINT_OCS = "/ocs/v2.php/cloud/";
- private static final String API_ENDPOINT_NOTES = "/index.php/apps/notes/api/v1/";
-
- private final OcsAPI ocsAPI;
- private final NotesAPI notesAPI;
-
- public ApiProvider(@NonNull Context appContext, @NonNull SingleSignOnAccount ssoAccount) {
- final NextcloudAPI nextcloudAPI = SSOClient.getNextcloudAPI(appContext, ssoAccount);
- ocsAPI = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_OCS).create(OcsAPI.class);
- notesAPI = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_NOTES).create(NotesAPI.class);
- }
-
- public NotesAPI getNotesAPI() {
- return notesAPI;
- }
-
- public OcsAPI getOcsAPI() {
- return ocsAPI;
- }
-}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java
index 92130664..29f3119c 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java
@@ -1,34 +1,97 @@
package it.niedermann.owncloud.notes.persistence.sync;
-import java.util.Calendar;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.nextcloud.android.sso.api.NextcloudAPI;
+import com.nextcloud.android.sso.api.ParsedResponse;
+
import java.util.List;
import it.niedermann.owncloud.notes.persistence.entity.Note;
+import it.niedermann.owncloud.notes.shared.model.ApiVersion;
import retrofit2.Call;
-import retrofit2.http.Body;
-import retrofit2.http.DELETE;
-import retrofit2.http.GET;
-import retrofit2.http.POST;
-import retrofit2.http.PUT;
-import retrofit2.http.Path;
-import retrofit2.http.Query;
+import retrofit2.NextcloudRetrofitApiBuilder;
/**
- * @link <a href="https://deck.readthedocs.io/en/latest/API/">Deck REST API</a>
+ * Compatibility layer to support multiple API versions
*/
-public interface NotesAPI {
+public class NotesAPI {
+
+ private static final String TAG = NotesAPI.class.getSimpleName();
+
+ private static final String API_ENDPOINT_NOTES_1_0 = "/index.php/apps/notes/api/v1/";
+ private static final String API_ENDPOINT_NOTES_0_2 = "/index.php/apps/notes/api/v0.2/";
+
+ @NonNull
+ private final ApiVersion usedApiVersion;
+ private final NotesAPI_0_2 notesAPI_0_2;
+ private final NotesAPI_1_0 notesAPI_1_0;
- @GET("notes")
- Call<List<Note>> getNotes(@Query(value = "pruneBefore") long lastModified, @Query("If-None-Match") String lastETag);
+ public NotesAPI(@NonNull NextcloudAPI nextcloudAPI, @Nullable ApiVersion preferredApiVersion) {
+ if (preferredApiVersion == null) {
+ Log.i(TAG, "Using " + ApiVersion.API_VERSION_0_2 + ", preferredApiVersion is null");
+ usedApiVersion = ApiVersion.API_VERSION_0_2;
+ notesAPI_0_2 = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_NOTES_0_2).create(NotesAPI_0_2.class);
+ notesAPI_1_0 = null;
+ } else if (ApiVersion.API_VERSION_1_0.equals(preferredApiVersion)) {
+ Log.i(TAG, "Using " + ApiVersion.API_VERSION_1_0);
+ usedApiVersion = ApiVersion.API_VERSION_1_0;
+ notesAPI_0_2 = null;
+ notesAPI_1_0 = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_NOTES_1_0).create(NotesAPI_1_0.class);
+ } else if (ApiVersion.API_VERSION_0_2.equals(preferredApiVersion)) {
+ Log.i(TAG, "Using " + ApiVersion.API_VERSION_0_2);
+ usedApiVersion = ApiVersion.API_VERSION_0_2;
+ notesAPI_0_2 = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_NOTES_0_2).create(NotesAPI_0_2.class);
+ notesAPI_1_0 = null;
+ } else {
+ Log.w(TAG, "Unsupported API version " + preferredApiVersion + " - try using " + ApiVersion.API_VERSION_0_2);
+ usedApiVersion = ApiVersion.API_VERSION_0_2;
+ notesAPI_0_2 = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_NOTES_0_2).create(NotesAPI_0_2.class);
+ notesAPI_1_0 = null;
+ }
+ }
- @POST("notes")
- Call<Note> createNote(@Body Note note);
+ public Call<ParsedResponse<List<Note>>> getNotes(long lastModified, String lastETag) {
+ if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) {
+ return notesAPI_1_0.getNotes(lastModified, lastETag);
+ } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) {
+ return notesAPI_0_2.getNotes(lastModified, lastETag);
+ } else {
+ throw new UnsupportedOperationException("Used API version " + usedApiVersion + " does not support getNotes().");
+ }
+ }
- @PUT("notes/{remoteId}")
- Call<Note> editNote(@Body Note note, @Path("remoteId") long remoteId);
+ public Call<Note> createNote(Note note) {
+ if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) {
+ return notesAPI_1_0.createNote(note);
+ } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) {
+ return notesAPI_0_2.createNote(note);
+ } else {
+ throw new UnsupportedOperationException("Used API version " + usedApiVersion + " does not support createNote().");
+ }
+ }
- @DELETE("notes/{remoteId}")
- Call<Note> deleteNote(@Path("remoteId") long noteId);
+ public Call<Note> editNote(Note note, long remoteId) {
+ if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) {
+ return notesAPI_1_0.editNote(note, remoteId);
+ } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) {
+ return notesAPI_0_2.editNote(note, remoteId);
+ } else {
+ throw new UnsupportedOperationException("Used API version " + usedApiVersion + " does not support editNote().");
+ }
+ }
+ public Call<Note> deleteNote(long noteId) {
+ if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) {
+ return notesAPI_1_0.deleteNote(noteId);
+ } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) {
+ return notesAPI_0_2.deleteNote(noteId);
+ } else {
+ throw new UnsupportedOperationException("Used API version " + usedApiVersion + " does not support createNote().");
+ }
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_0_2.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_0_2.java
new file mode 100644
index 00000000..9a77f8c4
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_0_2.java
@@ -0,0 +1,70 @@
+package it.niedermann.owncloud.notes.persistence.sync;
+
+
+import com.google.gson.annotations.Expose;
+import com.nextcloud.android.sso.api.ParsedResponse;
+
+import java.util.Calendar;
+import java.util.List;
+
+import it.niedermann.owncloud.notes.persistence.entity.Note;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.DELETE;
+import retrofit2.http.GET;
+import retrofit2.http.POST;
+import retrofit2.http.PUT;
+import retrofit2.http.Path;
+import retrofit2.http.Query;
+
+/**
+ * @link <a href="https://github.com/nextcloud/notes/wiki/API-0.2">Notes API v0.2</a>
+ */
+public interface NotesAPI_0_2 {
+
+ @GET("notes")
+ Call<ParsedResponse<List<Note>>> getNotes(@Query(value = "pruneBefore") long lastModified, @Query("If-None-Match") String lastETag);
+
+ default Call<Note> createNote(@Body Note note) {
+ return createNote(new Note_0_2(note));
+ }
+
+ @POST("notes")
+ Call<Note> createNote(@Body Note_0_2 note);
+
+ @PUT("notes/{remoteId}")
+ Call<Note> editNote(@Body Note note, @Path("remoteId") long remoteId);
+
+ @DELETE("notes/{remoteId}")
+ Call<Note> deleteNote(@Path("remoteId") long noteId);
+
+ class Note_0_2 {
+ @Expose
+ public final long id;
+ @Expose
+ public final String title;
+ @Expose
+ public final String category;
+ @Expose
+ public final Calendar modified;
+ @Expose
+ public final String content;
+ @Expose
+ public final boolean favorite;
+ @Expose
+ public final String eTag;
+
+ private Note_0_2(Note note) {
+ if (note == null) {
+ throw new IllegalArgumentException(Note.class.getSimpleName() + " can not be converted to " + Note_0_2.class.getSimpleName() + " because it is null.");
+ }
+ this.id = note.getRemoteId();
+ this.title = note.getTitle();
+ this.category = note.getCategory();
+ this.modified = note.getModified();
+ this.content = note.getContent();
+ this.favorite = note.getFavorite();
+ this.eTag = note.getETag();
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_1_0.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_1_0.java
new file mode 100644
index 00000000..1c738ca7
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI_1_0.java
@@ -0,0 +1,34 @@
+package it.niedermann.owncloud.notes.persistence.sync;
+
+
+import com.nextcloud.android.sso.api.ParsedResponse;
+
+import java.util.List;
+
+import it.niedermann.owncloud.notes.persistence.entity.Note;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.DELETE;
+import retrofit2.http.GET;
+import retrofit2.http.POST;
+import retrofit2.http.PUT;
+import retrofit2.http.Path;
+import retrofit2.http.Query;
+
+/**
+ * @link <a href="https://github.com/nextcloud/notes/blob/master/docs/api/README.md">Notes API v1</a>
+ */
+public interface NotesAPI_1_0 {
+
+ @GET("notes")
+ Call<ParsedResponse<List<Note>>> getNotes(@Query(value = "pruneBefore") long lastModified, @Query("If-None-Match") String lastETag);
+
+ @POST("notes")
+ Call<Note> createNote(@Body Note note);
+
+ @PUT("notes/{remoteId}")
+ Call<Note> editNote(@Body Note note, @Path("remoteId") long remoteId);
+
+ @DELETE("notes/{remoteId}")
+ Call<Note> deleteNote(@Path("remoteId") long noteId);
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/OcsAPI.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/OcsAPI.java
index 17bc3c4f..8923d50f 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/OcsAPI.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/OcsAPI.java
@@ -1,6 +1,8 @@
package it.niedermann.owncloud.notes.persistence.sync;
+import com.nextcloud.android.sso.api.ParsedResponse;
+
import it.niedermann.owncloud.notes.shared.model.Capabilities;
import retrofit2.Call;
import retrofit2.http.GET;
@@ -12,5 +14,5 @@ import retrofit2.http.Query;
public interface OcsAPI {
@GET("capabilities?format=json")
- Call<Capabilities> getCapabilities(@Query("If-None-Match") String eTag);
+ Call<ParsedResponse<Capabilities>> getCapabilities(@Query("If-None-Match") String eTag);
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java
index 761d0dc3..94c5408d 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java
@@ -3,6 +3,7 @@ package it.niedermann.owncloud.notes.shared.model;
import androidx.annotation.NonNull;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -10,14 +11,17 @@ import java.util.regex.Pattern;
public class ApiVersion implements Comparable<ApiVersion> {
private static final Pattern NUMBER_EXTRACTION_PATTERN = Pattern.compile("[0-9]+");
+ public static final ApiVersion API_VERSION_0_2 = new ApiVersion(0, 2);
+ public static final ApiVersion API_VERSION_1_0 = new ApiVersion(1, 0);
+
public static final ApiVersion[] SUPPORTED_API_VERSIONS = new ApiVersion[]{
- new ApiVersion(1, 0),
- new ApiVersion(0, 2)
+ API_VERSION_1_0,
+ API_VERSION_0_2
};
private String originalVersion = "?";
- private int major;
- private int minor;
+ private final int major;
+ private final int minor;
public ApiVersion(String originalVersion, int major, int minor) {
this(major, minor);
@@ -70,7 +74,7 @@ public class ApiVersion implements Comparable<ApiVersion> {
* 1 if the compared major version is <strong>lower</strong> than the current major version
*/
@Override
- public int compareTo(ApiVersion compare) {
+ public int compareTo(@NonNull ApiVersion compare) {
if (compare.getMajor() > getMajor()) {
return -1;
} else if (compare.getMajor() < getMajor()) {
@@ -79,6 +83,19 @@ public class ApiVersion implements Comparable<ApiVersion> {
return 0;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ApiVersion that = (ApiVersion) o;
+ return compareTo(that) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(major, minor);
+ }
+
@NonNull
@Override
public String toString() {
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/SyncResultStatus.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/SyncResultStatus.java
index 2031568b..41ba850a 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/SyncResultStatus.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/SyncResultStatus.java
@@ -3,4 +3,11 @@ package it.niedermann.owncloud.notes.shared.model;
public class SyncResultStatus {
public boolean pullSuccessful = true;
public boolean pushSuccessful = true;
+
+ public static final SyncResultStatus FAILED = new SyncResultStatus();
+
+ static {
+ FAILED.pullSuccessful = false;
+ FAILED.pushSuccessful = false;
+ }
}