ParseApplication/ExternalLibs/Parse-SDK-Android/Parse/src/main/java/com/parse/OfflineObjectStore.java

135 lines
4.2 KiB
Java

/*
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.parse;
import java.util.Arrays;
import java.util.List;
import bolts.Continuation;
import bolts.Task;
/** package */ class OfflineObjectStore<T extends ParseObject> implements ParseObjectStore<T> {
private static ParseObjectSubclassingController getSubclassingController() {
return ParseCorePlugins.getInstance().getSubclassingController();
}
private static <T extends ParseObject> Task<T> migrate(
final ParseObjectStore<T> from, final ParseObjectStore<T> to) {
return from.getAsync().onSuccessTask(new Continuation<T, Task<T>>() {
@Override
public Task<T> then(Task<T> task) throws Exception {
final T object = task.getResult();
if (object == null) {
return task;
}
return Task.whenAll(Arrays.asList(
from.deleteAsync(),
to.setAsync(object)
)).continueWith(new Continuation<Void, T>() {
@Override
public T then(Task<Void> task) throws Exception {
return object;
}
});
}
});
}
private final String className;
private final String pinName;
private final ParseObjectStore<T> legacy;
public OfflineObjectStore(Class<T> clazz, String pinName, ParseObjectStore<T> legacy) {
this(getSubclassingController().getClassName(clazz), pinName, legacy);
}
public OfflineObjectStore(String className, String pinName, ParseObjectStore<T> legacy) {
this.className = className;
this.pinName = pinName;
this.legacy = legacy;
}
@Override
public Task<Void> setAsync(final T object) {
return ParseObject.unpinAllInBackground(pinName).continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> task) throws Exception {
return object.pinInBackground(pinName, false);
}
});
}
@Override
public Task<T> getAsync() {
// We need to set `ignoreACLs` since we can't use ACLs without the current user.
ParseQuery<T> query = ParseQuery.<T>getQuery(className)
.fromPin(pinName)
.ignoreACLs();
return query.findInBackground().onSuccessTask(new Continuation<List<T>, Task<T>>() {
@Override
public Task<T> then(Task<List<T>> task) throws Exception {
List<T> results = task.getResult();
if (results != null) {
if (results.size() == 1) {
return Task.forResult(results.get(0));
} else {
return ParseObject.unpinAllInBackground(pinName).cast();
}
}
return Task.forResult(null);
}
}).onSuccessTask(new Continuation<T, Task<T>>() {
@Override
public Task<T> then(Task<T> task) throws Exception {
T ldsObject = task.getResult();
if (ldsObject != null) {
return task;
}
return migrate(legacy, OfflineObjectStore.this).cast();
}
});
}
@Override
public Task<Boolean> existsAsync() {
// We need to set `ignoreACLs` since we can't use ACLs without the current user.
ParseQuery<T> query = ParseQuery.<T>getQuery(className)
.fromPin(pinName)
.ignoreACLs();
return query.countInBackground().onSuccessTask(new Continuation<Integer, Task<Boolean>>() {
@Override
public Task<Boolean> then(Task<Integer> task) throws Exception {
boolean exists = task.getResult() == 1;
if (exists) {
return Task.forResult(true);
}
return legacy.existsAsync();
}
});
}
@Override
public Task<Void> deleteAsync() {
final Task<Void> ldsTask = ParseObject.unpinAllInBackground(pinName);
return Task.whenAll(Arrays.asList(
legacy.deleteAsync(),
ldsTask
)).continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> task) throws Exception {
// We only really care about the result of unpinning.
return ldsTask;
}
});
}
}