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

com.microsoft.azure.PagedList Maven / Gradle / Ivy

Go to download

This package contains the basic runtime for AutoRest generated Azure Java clients.

The newest version!
/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

package com.microsoft.azure;

import com.microsoft.rest.RestException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

/**
 * Defines a list response from a paging operation. The pages are
 * lazy initialized when an instance of this class is iterated.
 *
 * @param  the element type.
 */
public abstract class PagedList implements List {
    /** The actual items in the list. */
    private List items;
    /** Stores the latest page fetched. */
    private Page currentPage;
    /** Cached page right after the current one. */
    private Page cachedPage;

    /**
     * Creates an instance of Pagedlist.
     */
    public PagedList() {
        items = new ArrayList<>();
    }

    /**
     * Creates an instance of PagedList from a {@link Page} response.
     *
     * @param page the {@link Page} object.
     */
    public PagedList(Page page) {
        this();
        if (page == null) {
            return;
        }
        List retrievedItems = page.items();
        if (retrievedItems != null) {
            items.addAll(retrievedItems);
        }
        currentPage = page;
        cachePage(page.nextPageLink());
    }

    private void cachePage(String nextPageLink) {
        try {
            while (nextPageLink != null && nextPageLink != "") {
                cachedPage = nextPage(nextPageLink);
                if (cachedPage == null) {
                    break;
                }
                nextPageLink = cachedPage.nextPageLink();
                if (hasNextPage()) {
                    // a legit, non-empty page has been fetched, otherwise keep fetching
                    break;
                }
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Override this method to load the next page of items from a next page link.
     *
     * @param nextPageLink the link to get the next page of items.
     * @return the {@link Page} object storing a page of items and a link to the next page.
     * @throws RestException thrown if an error is raised from Azure.
     * @throws IOException thrown if there's any failure in deserialization.
     */
    public abstract Page nextPage(String nextPageLink) throws RestException, IOException;

    /**
     * If there are more pages available.
     *
     * @return true if there are more pages to load. False otherwise.
     */
    public boolean hasNextPage() {
        return this.cachedPage != null && this.cachedPage.items() != null && !this.cachedPage.items().isEmpty();
    }

    /**
     * Loads a page from next page link.
     * The exceptions are wrapped into Java Runtime exceptions.
     */
    public void loadNextPage() {
        this.currentPage = cachedPage;
        cachedPage = null;
        this.items.addAll(currentPage.items());
        cachePage(currentPage.nextPageLink());
    }

    /**
     * Keep loading the next page from the next page link until all items are loaded.
     */
    public void loadAll() {
        while (hasNextPage()) {
            loadNextPage();
        }
    }

    /**
     * Gets the latest page fetched.
     *
     * @return the latest page.
     */
    public Page currentPage() {
        return currentPage;
    }

    /**
     * Sets the current page.
     *
     * @param currentPage the current page.
     */
    protected void setCurrentPage(Page currentPage) {
        this.currentPage = currentPage;
        List retrievedItems = currentPage.items();
        if (retrievedItems != null) {
            items.addAll(retrievedItems);
        }
        cachePage(currentPage.nextPageLink());
    }

    /**
     * The implementation of {@link ListIterator} for PagedList.
     */
    private class ListItr implements ListIterator {
        /**
         * index of next element to return.
         */
        private int nextIndex;
        /**
         * index of last element returned; -1 if no such action happened.
         */
        private int lastRetIndex = -1;

        /**
         * Creates an instance of the ListIterator.
         *
         * @param index the position in the list to start.
         */
        ListItr(int index) {
            this.nextIndex = index;
        }

        @Override
        public boolean hasNext() {
            return this.nextIndex != items.size() || hasNextPage();
        }

        @Override
        public E next() {
            if (this.nextIndex >= items.size()) {
                if (!hasNextPage()) {
                    throw new NoSuchElementException();
                } else {
                    loadNextPage();
                }
                // Recurse until we load a page with non-zero items.
                return next();
            } else {
                try {
                    E nextItem = items.get(this.nextIndex);
                    this.lastRetIndex = this.nextIndex;
                    this.nextIndex = this.nextIndex + 1;
                    return nextItem;
                } catch (IndexOutOfBoundsException ex) {
                    // The nextIndex got invalid means a different instance of iterator
                    // removed item from this index.
                    throw new ConcurrentModificationException();
                }
            }
        }

        @Override
        public void remove() {
            if (this.lastRetIndex < 0) {
                throw new IllegalStateException();
            } else {
                try {
                    items.remove(this.lastRetIndex);
                    this.nextIndex = this.lastRetIndex;
                    this.lastRetIndex = -1;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
        }

        @Override
        public boolean hasPrevious() {
            return this.nextIndex != 0;
        }

        @Override
        public E previous() {
            int i = this.nextIndex - 1;
            if (i < 0) {
                throw new NoSuchElementException();
            } else if (i >= items.size()) {
                    throw new ConcurrentModificationException();
            } else {
                try {
                    this.nextIndex = i;
                    this.lastRetIndex = i;
                    return items.get(this.lastRetIndex);
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
        }

        @Override
        public int nextIndex() {
            return this.nextIndex;
        }

        @Override
        public int previousIndex() {
            return this.nextIndex - 1;
        }

        @Override
        public void set(E e) {
            if (this.lastRetIndex < 0) {
                throw new IllegalStateException();
            } else {
                try {
                    items.set(this.lastRetIndex, e);
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
        }

        @Override
        public void add(E e) {
            try {
                items.add(this.nextIndex, e);
                this.nextIndex = this.nextIndex + 1;
                this.lastRetIndex = -1;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

    @Override
    public int size() {
        loadAll();
        return items.size();
    }

    @Override
    public boolean isEmpty() {
        return items.isEmpty() && !hasNextPage();
    }

    @Override
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    @Override
    public Iterator iterator() {
        return new ListItr(0);
    }

    @Override
    public Object[] toArray() {
        loadAll();
        return items.toArray();
    }

    @Override
    public  T[] toArray(T[] a) {
        loadAll();
        return items.toArray(a);
    }

    @Override
    public boolean add(E e) {
        return items.add(e);
    }

    @Override
    public boolean remove(Object o) {
        return items.remove(o);
    }

    @Override
    public boolean containsAll(Collection c) {
        for (Object e : c) {
            if (!contains(e)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean addAll(Collection c) {
        return items.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection c) {
        return items.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection c) {
        return items.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection c) {
        return items.retainAll(c);
    }

    @Override
    public void clear() {
        items.clear();
    }

    @Override
    public E get(int index) {
        while (index >= items.size() && hasNextPage()) {
            loadNextPage();
        }
        return items.get(index);
    }

    @Override
    public E set(int index, E element) {
        return items.set(index, element);
    }

    @Override
    public void add(int index, E element) {
        items.add(index, element);
    }

    @Override
    public E remove(int index) {
        return items.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            for (E item : this) {
                if (item == null) {
                    return index;
                }
                ++index;
            }
        } else {
            for (E item : this) {
                if (item == o) {
                    return index;
                }
                ++index;
            }
        }
        return -1;
    }

    @Override
    public int lastIndexOf(Object o) {
        loadAll();
        return items.lastIndexOf(o);
    }

    @Override
    public ListIterator listIterator() {
        return new ListItr(0);
    }

    @Override
    public ListIterator listIterator(int index) {
        while (index >= items.size() && hasNextPage()) {
            loadNextPage();
        }
        return new ListItr(index);
    }

    @Override
    public List subList(int fromIndex, int toIndex) {
        while ((fromIndex >= items.size()
                || toIndex >= items.size())
                && hasNextPage()) {
            loadNextPage();
        }
        return items.subList(fromIndex, toIndex);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy