/*
* Copyright (C) 2015 Actor LLC. <https://actor.im>
*/
package im.actor.runtime.generic.storage;
import com.google.j2objc.annotations.AutoreleasePool;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import im.actor.runtime.actors.Actor;
import im.actor.runtime.bser.Bser;
import im.actor.runtime.bser.BserCreator;
import im.actor.runtime.bser.BserObject;
import im.actor.runtime.storage.ListEngineDisplayLoadCallback;
import im.actor.runtime.storage.ListEngineItem;
import im.actor.runtime.storage.ListEngineRecord;
import im.actor.runtime.storage.ListStorageDisplayEx;
// Disabling Bounds checks for speeding up calculations
/*-[
#define J2OBJC_DISABLE_ARRAY_BOUND_CHECKS 1
]-*/
class AsyncStorageActor<T extends BserObject & ListEngineItem> extends Actor {
private final ListStorageDisplayEx storage;
private final BserCreator<T> creator;
public AsyncStorageActor(ListStorageDisplayEx storage, BserCreator<T> creator) {
this.storage = storage;
this.creator = creator;
}
@AutoreleasePool
public void addOrUpdate(List<T> items) {
if (items.size() == 1) {
T item = items.get(0);
storage.updateOrAdd(new ListEngineRecord(item.getEngineId(), item.getEngineSort(),
item.getEngineSearch(), item.toByteArray()));
} else if (items.size() > 0) {
List<ListEngineRecord> updated = new ArrayList<>();
for (T i : items) {
updated.add(new ListEngineRecord(i.getEngineId(), i.getEngineSort(),
i.getEngineSearch(), i.toByteArray()));
}
storage.updateOrAdd(updated);
}
}
@AutoreleasePool
public void replace(List<T> items) {
List<ListEngineRecord> updated = new ArrayList<>();
for (T i : items) {
updated.add(new ListEngineRecord(i.getEngineId(), i.getEngineSort(),
i.getEngineSearch(), i.toByteArray()));
}
storage.clear();
storage.updateOrAdd(updated);
}
@AutoreleasePool
public void remove(long[] keys) {
if (keys.length == 1) {
storage.delete(keys[0]);
} else if (keys.length > 0) {
storage.delete(keys);
}
}
@AutoreleasePool
public void clear() {
storage.clear();
}
@AutoreleasePool
public void loadItem(long key, LoadItemCallback<T> callback) {
ListEngineRecord record = storage.loadItem(key);
if (record != null) {
try {
T res = Bser.parse(creator.createInstance(), record.getData());
callback.onLoaded(res);
} catch (IOException e) {
e.printStackTrace();
callback.onLoaded(null);
}
} else {
callback.onLoaded(null);
}
}
@AutoreleasePool
public void loadHead(LoadItemCallback<T> callback) {
List<ListEngineRecord> records = storage.loadForward(null, 1);
if (records.size() != 1) {
callback.onLoaded(null);
return;
}
ListEngineRecord record = records.get(0);
try {
callback.onLoaded(Bser.parse(creator.createInstance(), record.getData()));
} catch (IOException e) {
e.printStackTrace();
callback.onLoaded(null);
}
}
@AutoreleasePool
public void loadCount(LoadCountCallback callback) {
callback.onLoaded(storage.getCount());
}
@AutoreleasePool
public void loadForward(String query, Long topSortKey, int limit, ListEngineDisplayLoadCallback<T> callback) {
ArrayList<T> res;
if (query == null) {
res = convertList(storage.loadForward(topSortKey, limit));
} else {
res = convertList(storage.loadForward(query, topSortKey, limit));
}
callCallback(callback, res);
}
@AutoreleasePool
public void loadBackward(String query, Long topSortKey, int limit, ListEngineDisplayLoadCallback<T> callback) {
ArrayList<T> res;
if (query == null) {
res = convertList(storage.loadBackward(topSortKey, limit));
} else {
res = convertList(storage.loadBackward(query, topSortKey, limit));
}
callCallback(callback, res);
}
@AutoreleasePool
public void loadCenter(Long centerSortKey, int limit, ListEngineDisplayLoadCallback<T> callback) {
ArrayList<T> res;
res = convertList(storage.loadCenter(centerSortKey, limit));
callCallback(callback, res);
}
@AutoreleasePool
private void callCallback(ListEngineDisplayLoadCallback<T> callback, List<T> res) {
if (res.size() == 0) {
callback.onLoaded(res, 0, 0);
} else {
long topSort, bottomSort;
topSort = bottomSort = res.get(0).getEngineSort();
for (T t : res) {
long sort = t.getEngineSort();
if (topSort < sort) {
topSort = sort;
}
if (bottomSort > sort) {
bottomSort = sort;
}
}
callback.onLoaded(res, topSort, bottomSort);
}
}
private ArrayList<T> convertList(List<ListEngineRecord> records) {
ArrayList<T> res = new ArrayList<T>();
for (ListEngineRecord record : records) {
try {
T loaded = Bser.parse(creator.createInstance(), record.getData());
res.add(loaded);
} catch (IOException e) {
e.printStackTrace();
}
}
return res;
}
@Override
@AutoreleasePool
public void onReceive(Object message) {
if (message instanceof AddOrUpdate) {
addOrUpdate(((AddOrUpdate) message).getItems());
} else if (message instanceof Remove) {
remove(((Remove) message).getKeys());
} else if (message instanceof Clear) {
clear();
} else if (message instanceof Replace) {
replace(((Replace) message).getItems());
} else if (message instanceof LoadItem) {
loadItem(((LoadItem) message).getKey(), ((LoadItem) message).getCallback());
} else if (message instanceof LoadCount) {
loadCount(((LoadCount) message).getCallback());
} else if (message instanceof LoadHead) {
loadHead(((LoadHead) message).getCallback());
} else if (message instanceof LoadForward) {
loadForward(((LoadForward) message).getQuery(), ((LoadForward) message).getTopSortKey(),
((LoadForward) message).getLimit(), ((LoadForward) message).getCallback());
} else if (message instanceof LoadBackward) {
loadBackward(((LoadBackward) message).getQuery(), ((LoadBackward) message).getTopSortKey(),
((LoadBackward) message).getLimit(), ((LoadBackward) message).getCallback());
} else if (message instanceof LoadCenter) {
loadCenter(((LoadCenter) message).getCenterSortKey(),
((LoadCenter) message).getLimit(), ((LoadCenter) message).getCallback());
} else {
super.onReceive(message);
}
}
public static class AddOrUpdate<T extends BserObject & ListEngineItem> {
private List<T> items;
public AddOrUpdate(List<T> items) {
this.items = items;
}
public List<T> getItems() {
return items;
}
}
public static class Replace<T extends BserObject & ListEngineItem> {
private List<T> items;
public Replace(List<T> items) {
this.items = items;
}
public List<T> getItems() {
return items;
}
}
public static class Remove {
private long[] keys;
public Remove(long[] keys) {
this.keys = keys;
}
public long[] getKeys() {
return keys;
}
}
public static class Clear {
}
public static class LoadItem<T extends BserObject & ListEngineItem> {
private long key;
private LoadItemCallback<T> callback;
public LoadItem(long key, LoadItemCallback<T> callback) {
this.key = key;
this.callback = callback;
}
public long getKey() {
return key;
}
public LoadItemCallback<T> getCallback() {
return callback;
}
}
public static class LoadCount {
private LoadCountCallback callback;
public LoadCount(LoadCountCallback callback) {
this.callback = callback;
}
public LoadCountCallback getCallback() {
return callback;
}
}
public static class LoadHead<T extends BserObject & ListEngineItem> {
private LoadItemCallback<T> callback;
public LoadHead(LoadItemCallback<T> callback) {
this.callback = callback;
}
public LoadItemCallback<T> getCallback() {
return callback;
}
}
public static class LoadForward<T extends BserObject & ListEngineItem> {
private String query;
private Long topSortKey;
private int limit;
private ListEngineDisplayLoadCallback<T> callback;
public LoadForward(String query, Long topSortKey, int limit, ListEngineDisplayLoadCallback<T> callback) {
this.query = query;
this.topSortKey = topSortKey;
this.limit = limit;
this.callback = callback;
}
public String getQuery() {
return query;
}
public Long getTopSortKey() {
return topSortKey;
}
public int getLimit() {
return limit;
}
public ListEngineDisplayLoadCallback<T> getCallback() {
return callback;
}
}
public static class LoadBackward<T extends BserObject & ListEngineItem> {
private String query;
private Long topSortKey;
private int limit;
private ListEngineDisplayLoadCallback<T> callback;
public LoadBackward(String query, Long topSortKey, int limit, ListEngineDisplayLoadCallback<T> callback) {
this.query = query;
this.topSortKey = topSortKey;
this.limit = limit;
this.callback = callback;
}
public String getQuery() {
return query;
}
public Long getTopSortKey() {
return topSortKey;
}
public int getLimit() {
return limit;
}
public ListEngineDisplayLoadCallback<T> getCallback() {
return callback;
}
}
public static class LoadCenter<T extends BserObject & ListEngineItem> {
private Long centerSortKey;
private int limit;
private ListEngineDisplayLoadCallback<T> callback;
public LoadCenter(Long centerSortKey, int limit, ListEngineDisplayLoadCallback<T> callback) {
this.centerSortKey = centerSortKey;
this.limit = limit;
this.callback = callback;
}
public Long getCenterSortKey() {
return centerSortKey;
}
public int getLimit() {
return limit;
}
public ListEngineDisplayLoadCallback<T> getCallback() {
return callback;
}
}
public interface LoadItemCallback<T extends BserObject & ListEngineItem> {
void onLoaded(T item);
}
public interface LoadCountCallback {
void onLoaded(int count);
}
}