use of org.matrix.androidsdk.rest.model.TokensChunkEvents in project matrix-android-sdk by matrix-org.
the class DataRetriever method backPaginate.
/**
* Trigger a back pagination for a dedicated room from Token.
*
* @param store the store to use
* @param roomId the room Id
* @param token the start token.
* @param limit the maximum number of messages to retrieve
* @param roomEventFilter the filter to use
* @param callback the callback
*/
public void backPaginate(final IMXStore store, final String roomId, final String token, final int limit, final RoomEventFilter roomEventFilter, final ApiCallback<TokensChunkEvents> callback) {
// reach the marker end
if (TextUtils.equals(token, Event.PAGINATE_BACK_TOKEN_END)) {
// nothing more to provide
final android.os.Handler handler = new android.os.Handler(Looper.getMainLooper());
// call the callback with a delay
// to reproduce the same behaviour as a network request.
// except for the initial request.
Runnable r = new Runnable() {
@Override
public void run() {
handler.postDelayed(new Runnable() {
public void run() {
callback.onSuccess(new TokensChunkEvents());
}
}, 0);
}
};
handler.post(r);
return;
}
Log.d(LOG_TAG, "## backPaginate() : starts for roomId " + roomId);
TokensChunkEvents storageResponse = store.getEarlierMessages(roomId, token, limit);
putPendingToken(mPendingBackwardRequestTokenByRoomId, roomId, token);
if (storageResponse != null) {
final android.os.Handler handler = new android.os.Handler(Looper.getMainLooper());
final TokensChunkEvents fStorageResponse = storageResponse;
Log.d(LOG_TAG, "## backPaginate() : some data has been retrieved into the local storage (" + fStorageResponse.chunk.size() + " events)");
// call the callback with a delay
// to reproduce the same behaviour as a network request.
// except for the initial request.
Runnable r = new Runnable() {
@Override
public void run() {
handler.postDelayed(new Runnable() {
public void run() {
String expectedToken = getPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
Log.d(LOG_TAG, "## backPaginate() : local store roomId " + roomId + " token " + token + " vs " + expectedToken);
if (TextUtils.equals(expectedToken, token)) {
clearPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
callback.onSuccess(fStorageResponse);
}
}
}, 0);
}
};
Thread t = new Thread(r);
t.start();
} else {
Log.d(LOG_TAG, "## backPaginate() : trigger a remote request");
mRestClient.getRoomMessagesFrom(roomId, token, EventTimeline.Direction.BACKWARDS, limit, roomEventFilter, new SimpleApiCallback<TokensChunkEvents>(callback) {
@Override
public void onSuccess(TokensChunkEvents tokensChunkEvents) {
String expectedToken = getPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
Log.d(LOG_TAG, "## backPaginate() succeeds : roomId " + roomId + " token " + token + " vs " + expectedToken);
if (TextUtils.equals(expectedToken, token)) {
clearPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
// Watch for the one event overlap
Event oldestEvent = store.getOldestEvent(roomId);
if (tokensChunkEvents.chunk.size() != 0) {
tokensChunkEvents.chunk.get(0).mToken = tokensChunkEvents.start;
// there is no more data on server side
if (null == tokensChunkEvents.end) {
tokensChunkEvents.end = Event.PAGINATE_BACK_TOKEN_END;
}
tokensChunkEvents.chunk.get(tokensChunkEvents.chunk.size() - 1).mToken = tokensChunkEvents.end;
Event firstReturnedEvent = tokensChunkEvents.chunk.get(0);
if ((oldestEvent != null) && (firstReturnedEvent != null) && TextUtils.equals(oldestEvent.eventId, firstReturnedEvent.eventId)) {
tokensChunkEvents.chunk.remove(0);
}
store.storeRoomEvents(roomId, tokensChunkEvents, EventTimeline.Direction.BACKWARDS);
}
Log.d(LOG_TAG, "## backPaginate() succeed : roomId " + roomId + " token " + token + " got " + tokensChunkEvents.chunk.size());
callback.onSuccess(tokensChunkEvents);
}
}
private void logErrorMessage(String expectedToken, String errorMessage) {
Log.e(LOG_TAG, "## backPaginate() failed : roomId " + roomId + " token " + token + " expected " + expectedToken + " with " + errorMessage);
}
@Override
public void onNetworkError(Exception e) {
String expectedToken = getPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
logErrorMessage(expectedToken, e.getMessage());
// dispatch only if it is expected
if (TextUtils.equals(token, expectedToken)) {
clearPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
callback.onNetworkError(e);
}
}
@Override
public void onMatrixError(MatrixError e) {
String expectedToken = getPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
logErrorMessage(expectedToken, e.getMessage());
// dispatch only if it is expected
if (TextUtils.equals(token, expectedToken)) {
clearPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
callback.onMatrixError(e);
}
}
@Override
public void onUnexpectedError(Exception e) {
String expectedToken = getPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
logErrorMessage(expectedToken, e.getMessage());
// dispatch only if it is expected
if (TextUtils.equals(token, expectedToken)) {
clearPendingToken(mPendingBackwardRequestTokenByRoomId, roomId);
callback.onUnexpectedError(e);
}
}
});
}
}
use of org.matrix.androidsdk.rest.model.TokensChunkEvents in project matrix-android-sdk by matrix-org.
the class MXMemoryStore method getEarlierMessages.
@Override
public TokensChunkEvents getEarlierMessages(final String roomId, final String fromToken, final int limit) {
// For older requests (providing a token), returning null for now
if (null != roomId) {
List<Event> eventsList;
synchronized (mRoomEventsLock) {
LinkedHashMap<String, Event> events = mRoomEvents.get(roomId);
if ((events == null) || (events.size() == 0)) {
return null;
}
// reach the end of the stored items
if (TextUtils.equals(mRoomTokens.get(roomId), fromToken)) {
return null;
}
// check if the token is known in the sublist
eventsList = new ArrayList<>(events.values());
}
List<Event> subEventsList = new ArrayList<>();
// search from the latest to the oldest events
Collections.reverse(eventsList);
TokensChunkEvents response = new TokensChunkEvents();
// start the latest event and there is enough events to provide to the caller ?
if ((null == fromToken) && (eventsList.size() <= limit)) {
subEventsList = eventsList;
} else {
int index = 0;
if (null != fromToken) {
// search if token is one of the stored events
for (; (index < eventsList.size()) && (!TextUtils.equals(fromToken, eventsList.get(index).mToken)); index++) ;
index++;
}
// found it ?
if (index < eventsList.size()) {
for (; index < eventsList.size(); index++) {
Event event = eventsList.get(index);
subEventsList.add(event);
// loop until to find an event with a token
if ((subEventsList.size() >= limit) && (event.mToken != null)) {
break;
}
}
}
}
// unknown token
if (subEventsList.size() == 0) {
return null;
}
response.chunk = subEventsList;
Event firstEvent = subEventsList.get(0);
Event lastEvent = subEventsList.get(subEventsList.size() - 1);
response.start = firstEvent.mToken;
// unknown last event token, use the latest known one
if ((null == lastEvent.mToken) && !TextUtils.isEmpty(mRoomTokens.get(roomId))) {
lastEvent.mToken = mRoomTokens.get(roomId);
}
response.end = lastEvent.mToken;
return response;
}
return null;
}
Aggregations