/*******************************************************************************
* Copyright (c) 2016 Ecole Polytechnique de Montreal, Ericsson
*
* 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.tmf.analysis.xml.core.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternStateProvider;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
import org.w3c.dom.Element;
/**
* This Class implements an action tree in the XML-defined state system.
* An action is a collection of {@link ITmfXmlAction} that are executed when necessary.
*
* @author Jean-Christian Kouame
*/
public class TmfXmlAction implements ITmfXmlAction {
private final IXmlStateSystemContainer fParent;
private final String fId;
private final List<ITmfXmlAction> fActionList = new ArrayList<>();
/**
* Constructor
*
* @param modelFactory
* The factory used to create XML model elements
* @param node
* The XML root of this action
* @param container
* The state system container this action belongs to
*/
public TmfXmlAction(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container) {
fParent = container;
fId = NonNullUtils.checkNotNull(node.getAttribute(TmfXmlStrings.ID));
List<@Nullable Element> childElements = XmlUtils.getChildElements(node);
for (Element child : childElements) {
final @NonNull Element nonNullChild = NonNullUtils.checkNotNull(child);
switch (nonNullChild.getNodeName()) {
case TmfXmlStrings.STATE_CHANGE:
fActionList.add(new StateChange(modelFactory, nonNullChild, fParent));
break;
case TmfXmlStrings.FSM_SCHEDULE_ACTION:
fActionList.add(new ScheduleNewScenario(modelFactory, nonNullChild, fParent));
break;
case TmfXmlStrings.SEGMENT:
fActionList.add(new GeneratePatternSegment(modelFactory, nonNullChild, fParent));
break;
case TmfXmlStrings.ACTION:
fActionList.add(new TmfXmlAction(modelFactory, nonNullChild, fParent));
break;
default:
Activator.logError("Invalid action type : " + nonNullChild.getNodeName()); //$NON-NLS-1$
}
}
}
/**
* Get the ID of this action
*
* @return The id of this action
*/
public String getId() {
return fId;
}
@Override
public void execute(@NonNull ITmfEvent event, TmfXmlScenarioInfo scenarioInfo) {
// the order of the actions is important, do not parallelize.
for (ITmfXmlAction action : fActionList) {
action.execute(event, scenarioInfo);
}
}
/**
* Private class for an action that will create a state change in the state
* system
*/
private class StateChange implements ITmfXmlAction {
private final TmfXmlStateChange fStateChange;
public StateChange(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer parent) {
fStateChange = modelFactory.createStateChange(node, parent);
}
@Override
public void execute(@NonNull ITmfEvent event, TmfXmlScenarioInfo scenarioInfo) {
try {
fStateChange.handleEvent(event, scenarioInfo);
} catch (StateValueTypeException | AttributeNotFoundException e) {
Activator.logError("Exception when executing action state change", e); //$NON-NLS-1$
}
}
}
/**
* Private class for an action that will instantiate and schedule a new instance of
* an fsm
*/
private static class ScheduleNewScenario implements ITmfXmlAction {
/**
* Constructor
*
* @param modelFactory
* The factory used to create XML model elements
* @param node
* The XML root of this action
* @param container
* The state system container this action belongs to
*/
public ScheduleNewScenario(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container) {
}
@Override
public void execute(ITmfEvent event, TmfXmlScenarioInfo scenarioInfo) {
// TODO This action needs to be implemented
throw new UnsupportedOperationException("Schedule an FSM is not yet supported"); //$NON-NLS-1$
}
}
/**
* Private class for an action that will generate pattern segment
*/
private static class GeneratePatternSegment implements ITmfXmlAction {
private final TmfXmlPatternSegmentBuilder fSegmentBuilder;
private final XmlPatternStateProvider fProvider;
public GeneratePatternSegment(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer parent) {
fProvider = ((XmlPatternStateProvider) parent);
fSegmentBuilder = modelFactory.createPatternSegmentBuilder(node, parent);
}
@Override
public void execute(ITmfEvent event, TmfXmlScenarioInfo scenarioInfo) {
long ts = fProvider.getHistoryBuilder().getStartTime(fProvider, scenarioInfo, event);
// FIXME Should the scale always be nanoseconds?
ITmfTimestamp start = TmfTimestamp.fromNanos(ts);
ITmfTimestamp end = event.getTimestamp();
fSegmentBuilder.generatePatternSegment(event, start, end, scenarioInfo);
}
}
}