blob: a60942f4528f4ac93bc122cd53186122392c2358 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2018 EfficiOS Inc., Alexandre Montplaisir
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.tmf.ui.project.model;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.tracecompass.tmf.core.analysis.ondemand.IOnDemandAnalysis;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
/**
* Project model element for individual on-demand analyses that apply to the
* related trace.
*
* @author Alexandre Montplaisir
* @since 2.0
*/
@NonNullByDefault
public abstract class TmfOnDemandAnalysisElement extends TmfProjectModelElement
implements ITmfStyledProjectModelElement {
/**
* Checking if the analysis can run may take some time (running external
* scripts, etc.) so we do this outside of the UI thread. The executor will
* reserve one thread to check all on-demand analyses sequentially.
*/
private static final ExecutorService EXECUTOR = checkNotNull(Executors.newFixedThreadPool(1));
/**
* Worker thread sent to the executor
*/
private static class AnalysisChecker implements Runnable {
private final TmfOnDemandAnalysisElement fElem;
public AnalysisChecker(TmfOnDemandAnalysisElement elem) {
fElem = elem;
}
@Override
public void run() {
ITmfTrace trace = fElem.getParent().getParent().getTrace();
if (trace != null) {
fElem.fCanRun = fElem.getAnalysis().canExecute(trace);
fElem.refresh();
}
}
}
/**
* Styler to strike-out the analysis when it is not available
*/
private static final Styler STRIKED_OUT_STYLER = new Styler() {
@Override
public void applyStyles(@Nullable TextStyle textStyle) {
if (textStyle != null) {
textStyle.strikeout = true;
}
}
};
private final IOnDemandAnalysis fAnalysis;
private volatile boolean fKnowIfCanRun = false;
private volatile boolean fCanRun = false;
/**
* Constructor
*
* @param analysisName
* Name of the element
* @param resource
* Workspace resource
* @param parent
* Parent element, should be the "on-demand analyses" one
* @param analysis
* The actual analysis represented by this element
*/
protected TmfOnDemandAnalysisElement(String analysisName, IResource resource,
TmfOnDemandAnalysesElement parent, IOnDemandAnalysis analysis) {
super(analysisName, resource, parent);
fAnalysis = analysis;
}
@Override
public TmfOnDemandAnalysesElement getParent() {
return checkNotNull((TmfOnDemandAnalysesElement) super.getParent());
}
@Override
public abstract Image getIcon();
@Override
protected synchronized void refreshChildren() {
/* No children, but determine if we can run or not. */
if (!fKnowIfCanRun) {
fKnowIfCanRun = true;
EXECUTOR.execute(new AnalysisChecker(this));
}
}
@Override
public @Nullable Styler getStyler() {
if (!fCanRun) {
return STRIKED_OUT_STYLER;
}
return null;
}
/**
* Get the analysis represented by this model element
*
* @return The real analysis
*/
public IOnDemandAnalysis getAnalysis() {
return fAnalysis;
}
/**
* Return if the analysis can be run or not. Determines if we should enable
* the run actions.
*
* @return If this analysis can run
*/
public boolean canRun() {
return fCanRun;
}
}