/******************************************************************************* * Copyright (c) 2017 Pivotal, Inc. * 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: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash.livexp; import java.time.Duration; import javax.inject.Provider; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression; /** * LiveExpression that continually refreshes itself at regular intervals with a background job. * <p> * The expression, when created, starts out in a 'sleeping' state. It will not start refreshing/computing * its value until methods like 'refreshOnce', 'refreshFor' or 'refreshForever' are called. * * @author Kris De Volder */ public abstract class PollingLiveExp<T> extends LiveExpression<T> { private static final Provider<Boolean> STOP_REFRESHING = () -> false; private Job refreshJob = createRefreshJob(); /** * Time in ms to 'sleep' between refreshes. */ private long sleepBetweenRefreshes = 500; private Provider<Boolean> continueRefreshing = STOP_REFRESHING; /** * Override the default 'sleepBetweenRefreshes' value. */ public PollingLiveExp<T> sleepBetweenRefreshes(Duration duration) { this.sleepBetweenRefreshes = duration.toMillis(); return this; } private Job createRefreshJob() { Job job = new Job("Refresh PollingLiveExp") { @Override protected IStatus run(IProgressMonitor monitor) { refresh(); if (continueRefreshing.get()) { this.schedule(sleepBetweenRefreshes); } return Status.OK_STATUS; } }; job.setSystem(true); return job; } @Override public void refresh() { if (continueRefreshing.get()) { super.refresh(); } } @Override public void dispose() { refreshJob = null; continueRefreshing = STOP_REFRESHING; super.dispose(); } /** * Start refreshing now, and continue until given duration expires. */ public void refreshFor(Duration duration) { Job job = refreshJob; if (job!=null) { long stopRefrestingAfter = System.currentTimeMillis() + duration.toMillis(); this.continueRefreshing = () -> System.currentTimeMillis() <= stopRefrestingAfter; job.schedule(); } } /** * Start refreshing now, and continue forever (or until this expression is disposed). */ public PollingLiveExp<T> refreshForever() { Job job = refreshJob; if (job!=null) { continueRefreshing = () -> true; job.schedule(); } return this; } public PollingLiveExp<T> refreshOnce() { Job job = refreshJob; if (job!=null) { continueRefreshing = new Provider<Boolean>() { boolean firstTime = true; @Override public Boolean get() { try { return firstTime; } finally { firstTime = false; } } }; job.schedule(); } return this; } /** * Lambda-friendly way of creating a PollingLiveExp instance. */ public static <T> PollingLiveExp<T> create(Provider<T> computer) { return new PollingLiveExp<T>() { @Override protected T compute() { return computer.get(); } }; } }