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

com.qmetric.feed.consumer.AvailableFeedEntriesFinder Maven / Gradle / Ivy

Go to download

Java library for consuming HAL+JSON feeds (https://github.com/qmetric/hal-feed-server)

There is a newer version: 3.18
Show newest version
package com.qmetric.feed.consumer;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.qmetric.feed.consumer.store.FeedTracker;
import com.theoryinpractise.halbuilder.DefaultRepresentationFactory;
import com.theoryinpractise.halbuilder.api.Link;
import com.theoryinpractise.halbuilder.api.ReadableRepresentation;
import com.theoryinpractise.halbuilder.api.RepresentationFactory;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.List;

import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Iterables.concat;

class AvailableFeedEntriesFinder
{
    private static final Logger log = LoggerFactory.getLogger(AvailableFeedEntriesFinder.class);

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");

    private static final String ENTRY_ID = "_id";

    private final FeedEndpoint endpoint;

    private final FeedTracker feedTracker;

    private final Optional earliestEntryLimit;

    private final RepresentationFactory representationFactory;

    private final FeedEndpointFactory feedEndpointFactory;

    AvailableFeedEntriesFinder(final FeedEndpoint endpoint, final FeedEndpointFactory feedEndpointFactory, final FeedTracker feedTracker, final Optional earliestEntryLimit)
    {
        this.endpoint = endpoint;
        this.feedTracker = feedTracker;
        this.earliestEntryLimit = earliestEntryLimit;
        this.representationFactory = new DefaultRepresentationFactory();
        this.feedEndpointFactory = feedEndpointFactory;
    }

    public void trackNewEntries()
    {
        trackAll(newEntries());
    }

    private void trackAll(final List newEntries)
    {
        for (final EntryId entry : newEntries)
        {
            feedTracker.track(entry);
        }
    }

    private List newEntries()
    {
        return from(concat(ImmutableList.copyOf(new UnconsumedPageIterator()))) //
                .toList() //
                .reverse();
    }

    private EntryId idOf(final ReadableRepresentation entry)
    {
        return EntryId.of((String) entry.getValue(ENTRY_ID));
    }

    private class UnconsumedPageIterator implements Iterator>
    {
        private static final String NEXT_LINK_RELATION = "next";

        private static final String PUBLISHED = "_published";

        private Optional currentPage;

        UnconsumedPageIterator()
        {
            currentPage = Optional.of(representationFactory.readRepresentation(endpoint.get()));
        }

        @Override public boolean hasNext()
        {
            return currentPage.isPresent();
        }

        @Override public void remove()
        {
            throw new UnsupportedOperationException();
        }

        @Override public List next()
        {
            log.info("Reading feed-page {}", currentPage.get().getResourceLink().getHref());

            final List allFromPage = currentPageEntries();

            final List newEntries = newEntries(allFromPage);

            flipToNextPage(allFromPage, newEntries);

            return from(newEntries).transform(new Function()
            {
                @Override public EntryId apply(final ReadableRepresentation input)
                {
                    return idOf(input);
                }
            }).toList();
        }

        private List currentPageEntries()
        {
            return currentPage.get().getResourcesByRel("entries");
        }

        private void flipToNextPage(final List allFromPage, final List unconsumedFromPage)
        {
            log.debug("Found {} unconsumed entries out of {}", unconsumedFromPage.size(), allFromPage.size());

            this.currentPage = allFromPage.size() == unconsumedFromPage.size() ? getNextPage() : Optional.absent();

            log.debug("Next page: {}", currentPage);
        }

        private Optional getNextPage()
        {
            return nextLink(currentPage.get()).transform(new Function()
            {
                @Override public ReadableRepresentation apply(final Link link)
                {
                    return representationFactory.readRepresentation(feedEndpointFactory.create(link.getHref()).get());
                }
            });
        }

        private Optional nextLink(final ReadableRepresentation readableRepresentation)
        {
            return Optional.fromNullable(readableRepresentation.getLinkByRel(NEXT_LINK_RELATION));
        }

        private List newEntries(final List entries)
        {
            return from(entries).filter(new Predicate()
            {
                @Override
                public boolean apply(final ReadableRepresentation input)
                {
                    return hasConsumablePublishedDate(input) && isNotTracked(input);
                }

                private boolean isNotTracked(final ReadableRepresentation entry)
                {
                    return !feedTracker.isTracked(idOf(entry));
                }

                private boolean hasConsumablePublishedDate(final ReadableRepresentation entry)
                {
                    return !earliestEntryLimit.isPresent() || earliestEntryLimit.get().date.isBefore(publishedDate(entry));
                }

                private DateTime publishedDate(final ReadableRepresentation entry)
                {
                    return DATE_FORMATTER.parseDateTime((String) entry.getValue(PUBLISHED));
                }
            }).toList();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy