package com.pluscubed.plustimer.model;
import android.content.Context;
import android.support.annotation.WorkerThread;
import com.couchbase.lite.CouchbaseLiteException;
import com.couchbase.lite.Document;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import rx.Completable;
import rx.Single;
import rx.schedulers.Schedulers;
@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.NONE,
fieldVisibility = JsonAutoDetect.Visibility.NONE,
getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE,
setterVisibility = JsonAutoDetect.Visibility.NONE
)
public abstract class CbObject {
private static final ObjectMapper sMapper = new ObjectMapper();
private static final Map<String, CbObject> sUpdatingObjects = new HashMap<>();
protected String mId;
protected CbObject() {
}
/**
* Create new CbObject
*
* @throws CouchbaseLiteException
* @throws IOException
*/
@WorkerThread
protected CbObject(Context context) throws CouchbaseLiteException, IOException {
connectCb(context);
}
@WorkerThread
protected CbObject(Context context, String id) throws CouchbaseLiteException, IOException {
mId = id;
CouchbaseInstance.get(context).getDatabase().getDocument(id);
updateCb(context);
}
static <T extends CbObject> T fromDocId(Context context, String docId, Class<T> type) throws CouchbaseLiteException, IOException {
if (sUpdatingObjects.containsKey(docId)) {
return (T) sUpdatingObjects.get(docId);
}
Document doc = CouchbaseInstance.get(context).getDatabase().getDocument(docId);
return fromDoc(doc, type);
}
static <T extends CbObject> T fromDoc(Document doc, Class<T> type) {
if (sUpdatingObjects.containsKey(doc.getId())) {
return (T) sUpdatingObjects.get(doc.getId());
}
Map<String, Object> userProperties = doc.getUserProperties();
userProperties.remove("type");
T cbObject = sMapper.convertValue(userProperties, type);
cbObject.mId = doc.getId();
return cbObject;
}
protected void connectCb(Context context) throws CouchbaseLiteException, IOException {
Document doc = CouchbaseInstance.get(context).getDatabase().createDocument();
mId = doc.getId();
updateCb(context);
}
protected void updateCb(Context context) {
if (mId == null) {
return;
}
sUpdatingObjects.put(mId, this);
Completable.fromCallable(() -> {
Document document = getDocument(context);
document.update(newRevision -> {
Map<String, Object> userProperties = newRevision.getUserProperties();
userProperties.putAll(toMap());
newRevision.setUserProperties(userProperties);
return true;
});
sUpdatingObjects.remove(mId);
return null;
}).subscribeOn(Schedulers.io())
.subscribe();
}
public Document getDocument(Context context) throws CouchbaseLiteException, IOException {
return CouchbaseInstance.get(context).getDatabase().getDocument(mId);
}
public Single<Document> getDocumentDeferred(Context context) {
return Single.defer(() -> Single.just(getDocument(context)));
}
public Map<String, Object> toMap() {
Map<String, Object> objectMap = sMapper.convertValue(this, Map.class);
objectMap.put("type", getType());
return objectMap;
}
protected abstract String getType();
}