code: Observable<ChatResult> getPreviousMessages(final String conversationId) {
  
          return persistenceController.getConversation(conversationId)
                  .map(conversation -> conversation != null ? conversation.getFirstLocalEventId() : null)
                  .flatMap(from -> {
  
                      final Long queryFrom;
  
                      if (from != null) {
  
                          if (from == 0) {
                              return Observable.fromCallable(() -> new ChatResult(true, null));
                          } else if (from > 0) {
                              queryFrom = from - 1;
                          } else {
                              queryFrom = null;
                          }
                      } else {
                          queryFrom = null;
                      }
  
                      return checkState().flatMap(client -> client.service().messaging().queryMessages(conversationId, queryFrom, messagesPerQuery))
                              .flatMap(result -> persistenceController.processMessageQueryResponse(conversationId, result))
                              .flatMap(result -> persistenceController.processOrphanedEvents(result, orphanedEventsToRemoveListener))
                              .flatMap((Func1<ComapiResult<MessagesQueryResponse>, Observable<ChatResult>>) result -> (result.isSuccessful() && result.getResult().getMessages().isEmpty() && result.getResult().getEarliestEventId() > 0) ?
                                      getPreviousMessages(conversationId) :
                                      Observable.fromCallable(() -> new ChatResult(result.isSuccessful(), result.isSuccessful() ? null : new ChatResult.Error(result))));
                  });
      }
docs: Gets next page of messages and saves them using {@link ChatStore} implementation.
  
  @param conversationId ID of a conversation in which participant is typing a message.
  @return Observable with the result.