--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.provisional.tmf.core.views.timegraph2.statesystem;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.views.timegraph2.ColorDefinition;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.views.timegraph2.TimeGraphModelRender;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.views.timegraph2.TimeGraphModelRenderProvider;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.views.timegraph2.TimeGraphStateInterval;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.views.timegraph2.TimeGraphStateInterval.LineThickness;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.views.timegraph2.TimeGraphTreeRender;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+public abstract class StateSystemModelRenderProvider extends TimeGraphModelRenderProvider {
+
+ /**
+ * The context of a tree render. Should contain all the information to
+ * generate the corresponding tree render, according to all configuration
+ * options like sorting, filtering etc. specified by the user.
+ */
+ protected static final class TreeRenderContext {
+
+ public final ITmfStateSystem ss;
+ public final SortingMode sortingMode;
+ public final Set<FilterMode> filterModes;
+ public final long renderTimeRangeStart;
+ public final long renderTimeRangeEnd;
+ public final List<ITmfStateInterval> fullQueryAtRangeStart;
+
+ public TreeRenderContext(ITmfStateSystem ss,
+ SortingMode sortingMode,
+ Set<FilterMode> filterModes,
+ long renderTimeRangeStart,
+ long renderTimeRangeEnd,
+ List<ITmfStateInterval> fullQueryAtRangeStart) {
+ this.ss = ss;
+ this.sortingMode = sortingMode;
+ this.filterModes = filterModes;
+ this.renderTimeRangeStart = renderTimeRangeStart;
+ this.renderTimeRangeEnd = renderTimeRangeEnd;
+ this.fullQueryAtRangeStart = fullQueryAtRangeStart;
+ }
+ }
+
+ /**
+ * The context of a single state interval. Should contain all the
+ * information required to generate the state interval in the render (name,
+ * color, etc.)
+ */
+ protected static final class StateIntervalContext {
+
+ public final ITmfStateSystem ss;
+ public final StateSystemTimeGraphTreeElement baseTreeElement;
+ public final ITmfStateInterval sourceInterval;
+ public final List<ITmfStateInterval> fullQueryAtIntervalStart;
+
+ public StateIntervalContext(ITmfStateSystem ss,
+ StateSystemTimeGraphTreeElement baseTreeElement,
+ ITmfStateInterval sourceInterval,
+ List<ITmfStateInterval> fullQueryAtIntervalStart) {
+ this.ss = ss;
+ this.baseTreeElement = baseTreeElement;
+ this.sourceInterval = sourceInterval;
+ this.fullQueryAtIntervalStart = fullQueryAtIntervalStart;
+ }
+ }
+
+ private final String fStateSystemModuleId;
+ private final Function<TreeRenderContext, TimeGraphTreeRender> fTreeRenderFunction;
+ private final Function<StateIntervalContext, TimeGraphStateInterval> fIntervalMappingFunction;
+
+// private final Map<ITmfStateSystem, TimeGraphTreeRender> fLastTreeRenders = new WeakHashMap<>();
+
+ /**
+ * @param stateSystemModuleId
+ * @param stateNameMappingFunction
+ * @param colorMappingFunction
+ * @param lineThicknessMappingFunction
+ * @param propertyMappingFunction
+ * @param baseQuarkPattern
+ */
+ protected StateSystemModelRenderProvider(
+ @Nullable List<SortingMode> sortingModes,
+ @Nullable List<FilterMode> filterModes,
+ String stateSystemModuleId,
+ Function<TreeRenderContext, TimeGraphTreeRender> treeRenderFunction,
+ Function<StateIntervalContext, String> stateNameMappingFunction,
+ Function<StateIntervalContext, ColorDefinition> colorMappingFunction,
+ Function<StateIntervalContext, LineThickness> lineThicknessMappingFunction,
+ Function<StateIntervalContext, @Nullable Supplier<Map<String, String>>> propertyMappingFunction) {
+
+ super(sortingModes, filterModes);
+
+ fStateSystemModuleId = stateSystemModuleId;
+ fTreeRenderFunction = treeRenderFunction;
+
+ fIntervalMappingFunction = ssCtx -> {
+ return new TimeGraphStateInterval(
+ ssCtx.sourceInterval.getStartTime(),
+ ssCtx.sourceInterval.getEndTime(),
+ ssCtx.baseTreeElement,
+ stateNameMappingFunction.apply(ssCtx),
+ colorMappingFunction.apply(ssCtx),
+ lineThicknessMappingFunction.apply(ssCtx),
+ propertyMappingFunction.apply(ssCtx));
+ };
+ }
+
+ private synchronized TimeGraphTreeRender getTreeRender(final ITmfStateSystem ss) {
+ TimeGraphTreeRender lastRender = null;
+// TimeGraphTreeRender lastRender = fLastTreeRenders.get(ss);
+// if (lastRender != null && lastRender.getAllTreeElements().size() == ss.getNbAttributes()) {
+// /* The last render is still valid, we can re-use it */
+// return lastRender;
+// }
+
+ /* First generate the tree render context */
+ long start = getConfiguredTimeRangeStart();
+ long end = getConfiguredTimeRangeEnd();
+ List<ITmfStateInterval> fullStateAtStart;
+ try {
+ fullStateAtStart = ss.queryFullState(start);
+ } catch (StateSystemDisposedException e) {
+ return new TimeGraphTreeRender(Collections.EMPTY_LIST);
+ }
+
+ TreeRenderContext treeContext = new TreeRenderContext(ss,
+ getCurrentSortingMode(),
+ getActiveFilterModes(),
+ start,
+ end,
+ fullStateAtStart);
+
+ /* Generate a new tree render */
+ lastRender = fTreeRenderFunction.apply(treeContext);
+
+// fLastTreeRenders.put(ss, lastRender);
+ return lastRender;
+ }
+
+ @Override
+ public @NonNull TimeGraphModelRender getRender(ITmfTrace trace, long rangeStart, long rangeEnd,
+ long resolution, @Nullable IProgressMonitor monitor) {
+ // FIXME Potentially costly to query this every time, cache it?
+ final ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(trace, fStateSystemModuleId);
+ if (ss == null) {
+ /* This trace does not provide the expected state system */
+ return TimeGraphModelRender.EMPTY_RENDER;
+ }
+ TimeGraphTreeRender treeRender = getTreeRender(ss);
+
+ /* Prepare the state intervals */
+ /*
+ * FIXME Inefficient series of queryHistoryRange() calls, replace with a
+ * 2D query once those become available.
+ */
+ List<List<TimeGraphStateInterval>> stateIntervals = treeRender.getAllTreeElements().stream()
+ .map(treeElem -> (StateSystemTimeGraphTreeElement) treeElem) // FIXME, generic type?
+ .map(treeElem -> {
+ List<ITmfStateInterval> intervals;
+ try {
+ intervals = StateSystemUtils.queryHistoryRange(ss, treeElem.getSourceQuark(), rangeStart, rangeEnd, resolution, monitor);
+ } catch (AttributeNotFoundException | StateSystemDisposedException e) {
+ intervals = Collections.emptyList();
+ }
+ return intervals.stream()
+ .map(interval -> {
+ List<ITmfStateInterval> fullState;
+ try {
+ fullState = ss.queryFullState(interval.getStartTime());
+ } catch (StateSystemDisposedException e) {
+ fullState = Collections.emptyList();
+ }
+ return new StateIntervalContext(ss, treeElem, interval, fullState);
+ })
+ .map(fIntervalMappingFunction)
+ .collect(Collectors.toList());
+ })
+ .collect(Collectors.toList());
+
+ /* TODO Prepare the drawn events */
+
+ /* TODO Prepare the arrows series */
+
+ TimeGraphModelRender render = new TimeGraphModelRender(
+ rangeStart, rangeEnd,
+ treeRender,
+ stateIntervals,
+ Collections.EMPTY_LIST,
+ Collections.EMPTY_LIST);
+ return render;
+ }
+
+}