All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.client.base.AbstractPage Maven / Gradle / Ivy

There is a newer version: 5.10.8
Show newest version
package org.yamcs.client.base;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.yamcs.api.Observer;
import org.yamcs.client.Page;

import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Message;

public abstract class AbstractPage implements Page {

    private static final String CONTINUATION_TOKEN = "continuationToken";
    private static final String NEXT = "next";

    private final RequestT originalRequest;
    private final String repeatableField;
    private final FieldDescriptor nextField;

    private CompletableFuture future;

    // Only set when the future resolves
    private ResponseT response;
    private List items;
    private String continuationToken;

    public AbstractPage(RequestT request, String repeatableField) {
        originalRequest = request;
        this.repeatableField = repeatableField;

        Descriptor requestDescriptor = request.getDescriptorForType();
        nextField = requestDescriptor.findFieldByName(NEXT);
        if (nextField == null) {
            throw new IllegalArgumentException(String.format(
                    "Paging requires the request message to have a field '%s'", NEXT));
        }

        future = new CompletableFuture<>();
        fetch(request, new ResponseObserver<>(future));
    }

    public CompletableFuture> future() {
        return future.thenApply(response -> {
            readResponse(response);
            return this;
        });
    }

    private void readResponse(ResponseT response) {
        this.response = response;
        Descriptor responseDescriptor = response.getDescriptorForType();
        FieldDescriptor continuationField = responseDescriptor.findFieldByName(CONTINUATION_TOKEN);
        if (continuationField == null) {
            throw new IllegalArgumentException(String.format(
                    "Paging requires the message to have a field '%s'", CONTINUATION_TOKEN));
        }

        if (response.hasField(continuationField)) {
            continuationToken = (String) response.getField(continuationField);
        }

        FieldDescriptor repeatableDescriptor = responseDescriptor.findFieldByName(repeatableField);
        items = mapRepeatableField(response.getField(repeatableDescriptor));
    }

    // Can be overriden to expose a page of non-protobuf messages
    @SuppressWarnings("unchecked")
    protected List mapRepeatableField(Object field) {
        return new ArrayList<>((List) field);
    }

    public ResponseT getResponse() {
        return response;
    }

    @Override
    public boolean hasNextPage() {
        return continuationToken != null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public CompletableFuture> getNextPage() {
        if (continuationToken == null) {
            return CompletableFuture.completedFuture(null);
        }

        Message.Builder newRequest = originalRequest.toBuilder();
        newRequest.setField(nextField, continuationToken);
        RequestT continuationRequest = (RequestT) newRequest.build();
        return new ContinuationPage(continuationRequest, repeatableField).future();
    }

    protected abstract void fetch(RequestT request, Observer observer);

    /**
     * Returns an iterator. This only iterates the current page.
     */
    @Override
    public Iterator iterator() {
        return items.iterator();
    }

    // Delegates the actual fetch to the subclass
    private class ContinuationPage extends AbstractPage {

        public ContinuationPage(RequestT request, String repeatableField) {
            super(request, repeatableField);
        }

        @Override
        protected void fetch(RequestT request, Observer observer) {
            AbstractPage.this.fetch(request, observer);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy