/*******************************************************************************
* Copyright (c) 2015, 2017 Pivotal Software, 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 Software, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.dash.views;
import java.util.Collection;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.widgets.Display;
import org.springframework.ide.eclipse.boot.dash.livexp.MultiSelection;
import org.springframework.ide.eclipse.boot.dash.model.BootDashElement;
import org.springframework.ide.eclipse.boot.dash.model.BootDashModel.ElementStateListener;
import org.springframework.ide.eclipse.boot.dash.model.BootDashViewModel;
import org.springframework.ide.eclipse.boot.dash.model.RunState;
import org.springframework.ide.eclipse.boot.dash.model.UserInteractions;
import org.springsource.ide.eclipse.commons.frameworks.core.util.JobUtil;
/**
* An action who's intended effect is to transition a BootDashElement to a
* given goal state.
*
* @author Kris De Volder
*/
public abstract class RunStateAction extends AbstractBootDashElementsAction {
private static final boolean DEBUG = false; //(""+Platform.getLocation()).contains("kdvolder");
private static void debug(String string) {
if (DEBUG) {
System.out.println(string);
}
}
private static final ISchedulingRule SCEDULING_RULE = JobUtil.lightRule("RunStateAction.RULE");
protected final RunState goalState;
private ElementStateListener stateListener = null;
private BootDashViewModel model;
protected void configureJob(Job job) {
job.setRule(SCEDULING_RULE);
}
public RunStateAction(
BootDashViewModel model,
MultiSelection<BootDashElement> selection,
UserInteractions ui,
RunState goalState) {
super(selection, ui);
debug("Create RunStateAction "+goalState);
this.model = model;
this.goalState = goalState;
model.addElementStateListener(stateListener = new ElementStateListener() {
public void stateChanged(BootDashElement e) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
updateEnablement();
}
});
}
});
}
@Override
public void updateEnablement() {
Collection<BootDashElement> selecteds = getSelectedElements();
setEnabled(appliesTo(selecteds));
}
@Override
public void updateVisibility() {
/**
* TODO: Evaluate possibility of adding new API on BootDashModel and/or
* BootDashElement to check whether element supports run states.
* Currently run state == null means element doesn't support run states
*/
boolean visible = !getSelectedElements().isEmpty();
for (BootDashElement e : getSelectedElements()) {
if (e.getRunState() == null) {
visible = false;
break;
}
}
setVisible(visible);
}
private boolean appliesTo(Collection<BootDashElement> selection) {
for (BootDashElement e : selection) {
if (!appliesTo(e)) {
return false;
}
}
return !selection.isEmpty();
}
private boolean appliesTo(BootDashElement e) {
return goalStateAppliesTo(e) && currentStateAcceptable(e.getRunState()) && appliesToElement(e);
}
/**
* Subclass can override when action should only apply to
* certain boot dash elements
*/
protected boolean appliesToElement(BootDashElement e) {
return true;
}
/**
* Subclass can override when action should only apply to
* processes in a specific runState.
*/
protected boolean currentStateAcceptable(RunState runState) {
return true;
}
protected boolean goalStateAppliesTo(BootDashElement e) {
return e.supportedGoalStates().contains(goalState);
}
@Override
public String toString() {
return "RunStateAction("+goalState+")";
}
/**
* Subclass must override to define what 'work' this action does when it triggered.
*/
protected abstract Job createJob();
public final void run() {
Job job = createJob();
if (job!=null) {
configureJob(job);
job.schedule();
}
}
@Override
public void dispose() {
debug("DISPOSE RunStateAction "+goalState);
super.dispose();
if (stateListener!=null) {
//Avoid leaking model listeners
model.removeElementStateListener(stateListener);
stateListener = null;
}
}
public RunState getGoalState() {
return goalState;
}
}