package net.rrm.ehour.update;
import com.google.common.base.Optional;
import org.apache.log4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class UpdateService {
private static final Logger LOGGER = Logger.getLogger(UpdateService.class);
private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
private String formattedVersion;
private Integer sanitizedVersion;
private LatestVersionFetcher latestVersionFetcher;
private Future<Optional<String>> latestVersionNumber;
@SuppressWarnings("UnusedDeclaration")
public UpdateService() {
}
public UpdateService(String formattedVersion, LatestVersionFetcher latestVersionFetcher) {
this.formattedVersion = formattedVersion;
Optional<Integer> sanitizedVersionNumber = VersionNumberSanitizer.sanitize(formattedVersion);
this.sanitizedVersion = sanitizedVersionNumber.or(0);
this.latestVersionFetcher = latestVersionFetcher;
}
@Scheduled(cron ="0 0 3 * * *")
public void scheduledFetchLatestVersion() {
fetchLatestVersion(new VersionFetcher(true));
}
public void initialFetchLatestVersion() {
fetchLatestVersion(new VersionFetcher(false));
}
private void fetchLatestVersion(VersionFetcher versionFetcher) {
synchronized (this) {
if (latestVersionNumber == null || latestVersionNumber.isDone()) {
latestVersionNumber = EXECUTOR.submit(versionFetcher);
}
}
}
public synchronized Optional<String> getLatestVersionNumber() {
if (isLatestVersionNumberValid()) {
try {
return latestVersionNumber.get();
} catch (Exception e) {
LOGGER.warn("Failed to retrieve the latest version number", e);
}
}
return Optional.absent();
}
private boolean isLatestVersionNumberValid() {
return latestVersionNumber.isDone() && !latestVersionNumber.isCancelled();
}
public boolean isLatestVersion() {
Optional<String> latest = getLatestVersionNumber();
return sanitizedVersion >= VersionNumberSanitizer.sanitize(latest.or("")).or(0);
}
class VersionFetcher implements Callable<Optional<String>> {
private final boolean isScheduled;
VersionFetcher(boolean isScheduled) {
this.isScheduled = isScheduled;
}
@Override
public Optional<String> call() throws Exception {
return latestVersionFetcher.getLatestVersionNumber(formattedVersion, isScheduled);
}
}
}