/**
* Copyright (c) 2016 Codetrails GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andreas Sewe - initial API and implementation.
*/
package org.eclipse.recommenders.news.impl.poll;
import static org.eclipse.recommenders.news.api.poll.PollingResult.Status.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.recommenders.news.api.NewsItem;
import org.eclipse.recommenders.news.api.poll.INewsPollingService;
import org.eclipse.recommenders.news.api.poll.PollingPolicy;
import org.eclipse.recommenders.news.api.poll.PollingRequest;
import org.eclipse.recommenders.news.api.poll.PollingResult;
import org.eclipse.recommenders.news.api.poll.PollingResult.Status;
import com.google.common.annotations.VisibleForTesting;
public class DefaultNewsPollingService implements INewsPollingService {
private final IDownloadService downloadService;
private final IFeedItemStore feedItemStore;
public DefaultNewsPollingService() {
this.downloadService = new DefaultDownloadService();
this.feedItemStore = new DefaultFeedItemStore();
}
@VisibleForTesting
DefaultNewsPollingService(IDownloadService downloadService, IFeedItemStore feedItemStore) {
this.downloadService = downloadService;
this.feedItemStore = feedItemStore;
}
@Override
public Collection<PollingResult> poll(Collection<PollingRequest> requests, @Nullable IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, requests.size());
try {
Date now = new Date();
List<PollingResult> results = new ArrayList<>(requests.size());
for (PollingRequest request : requests) {
if (progress.isCanceled()) {
break;
}
PollingResult result = poll(request, now, progress.newChild(1));
results.add(result);
}
return results;
} finally {
if (monitor != null) {
monitor.done();
}
}
}
private PollingResult poll(PollingRequest request, Date pollingDate, SubMonitor monitor) {
URI feedUri = request.getFeedUri();
SubMonitor progress = SubMonitor.convert(monitor, feedUri.toString(), 1);
Date lastPolledDate;
try {
lastPolledDate = downloadService.getLastAttemptDate(feedUri);
} catch (IOException e) {
lastPolledDate = null;
}
PollingPolicy policy = request.getPollingPolicy();
if (policy.shouldPoll(lastPolledDate, pollingDate)) {
try {
return performDownload(feedUri, progress.newChild(1));
} catch (IOException e) {
try {
progress.setWorkRemaining(1);
return fallbackToLocalStore(feedUri, progress.newChild(1));
} catch (IOException f) {
progress.setWorkRemaining(1);
return fallbackToErrorResult(feedUri, progress.newChild(1));
}
}
} else {
try {
return fallbackToLocalStore(feedUri, progress.newChild(1));
} catch (IOException e) {
progress.setWorkRemaining(1);
return fallbackToErrorResult(feedUri, progress.newChild(1));
}
}
}
private PollingResult performDownload(URI feedUri, SubMonitor monitor) throws IOException {
SubMonitor progress = SubMonitor.convert(monitor, 2);
List<NewsItem> newItems;
List<NewsItem> allItems;
Status status;
try (InputStream stream = downloadService.download(feedUri, progress.newChild(1))) {
newItems = feedItemStore.udpate(feedUri, stream, progress.newChild(1));
allItems = feedItemStore.getNewsItems(feedUri);
status = DOWNLOADED;
return new PollingResult(feedUri, newItems, allItems, status);
}
}
private PollingResult fallbackToLocalStore(URI feedUri, SubMonitor monitor) throws IOException {
SubMonitor progress = SubMonitor.convert(monitor, 1);
List<NewsItem> newItems = Collections.emptyList();
List<NewsItem> allItems;
Status status;
InputStream in = downloadService.read(feedUri);
if (in != null) {
feedItemStore.udpate(feedUri, in, progress.newChild(1));
allItems = feedItemStore.getNewsItems(feedUri);
status = DOWNLOADED;
} else {
progress.worked(1);
allItems = Collections.emptyList();
status = NOT_DOWNLOADED;
}
return new PollingResult(feedUri, newItems, allItems, status);
}
private PollingResult fallbackToErrorResult(URI feedUri, SubMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, 1);
List<NewsItem> newItems = Collections.emptyList();
List<NewsItem> allItems = Collections.emptyList();
Status status = NOT_DOWNLOADED;
progress.worked(1);
return new PollingResult(feedUri, newItems, allItems, status);
}
}