ITmfStateValue[] expectedValues = { TmfStateValue.newValueLong(1l), TmfStateValue.newValueLong(5l), TmfStateValue.newValueLong(1l) };
XmlUtilsTest.verifyStackStateIntervals("testStateValueModify", ss, quark, expectedStarts, expectedValues);
}
+
+ /**
+ * Test the mapping groups. This test verifies that, when needed, the mapped
+ * value is used. In this test, the mapping group is used on the 'entry'
+ * event.
+ *
+ * @throws StateSystemDisposedException
+ * Exceptions thrown during state system verification
+ * @throws AttributeNotFoundException
+ * Exceptions thrown during state system verification
+ */
+ @Test
+ public void testStateValueMapping() throws AttributeNotFoundException, StateSystemDisposedException {
+ XmlStateSystemModule module = fModule;
+ assertNotNull(module);
+
+ ITmfStateSystem ss = module.getStateSystem();
+ assertNotNull(ss);
+
+ int quark = ss.getQuarkAbsolute("mapped");
+
+ final int[] expectedStarts = { 1, 3, 5, 7, 7 };
+ ITmfStateValue[] expectedValues = { TmfStateValue.newValueString("TRUE"), TmfStateValue.newValueString("FALSE"), TmfStateValue.newValueString("TRUE"), TmfStateValue.newValueString("FALSE") };
+ XmlUtilsTest.verifyStateIntervals("testMappingGroups", ss, quark, expectedStarts, expectedValues);
+
+ }
}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * 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.tmf.analysis.xml.core.tests.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternAnalysis;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.segment.TmfXmlPatternSegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.common.TmfXmlTestFiles;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.module.XmlUtilsTest;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs.PatternSegmentFactoryStub;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test the XML pattern segment
+ *
+ * @author Jean-Christian Kouame
+ */
+public class XmlSegmentTest {
+
+ private static final @NonNull String TEST_TRACE = "test_traces/testTrace5.xml";
+
+ ITmfTrace fTrace;
+ XmlPatternAnalysis fModule;
+
+ /**
+ * Initializes the trace and the module for the tests
+ *
+ * @throws TmfAnalysisException
+ * Any exception thrown during module initialization
+ */
+ @Before
+ public void setUp() throws TmfAnalysisException {
+ ITmfTrace trace = XmlUtilsTest.initializeTrace(TEST_TRACE);
+ @NonNull XmlPatternAnalysis module = XmlUtilsTest.initializePatternModule(TmfXmlTestFiles.CONSUMING_FSM_TEST);
+
+ module.setTrace(trace);
+
+ module.schedule();
+ module.waitForCompletion();
+
+ fTrace = trace;
+ fModule = module;
+ }
+
+ /**
+ * Dispose the module and the trace
+ */
+ @After
+ public void cleanUp() {
+ fTrace.dispose();
+ fModule.dispose();
+ }
+
+ /**
+ * Test segment generated using a mapping group
+ */
+ @Test
+ public void testMappingGroup() {
+ XmlPatternAnalysis module = fModule;
+ assertNotNull(module);
+
+ @Nullable ISegmentStore<@NonNull ISegment> ss = module.getSegmentStore();
+ assertNotNull(ss);
+ assertEquals("Segment store size", 1, ss.size());
+ Object segment = ss.toArray()[0];
+ assertTrue(segment instanceof TmfXmlPatternSegment);
+ XmlUtilsTest.testPatternSegmentData(PatternSegmentFactoryStub.TEST_3, (TmfXmlPatternSegment)segment);
+ }
+}
+
******************************************************************************/
package org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs;
+import java.util.Collections;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
* end event for pattern segment TEST_2
*/
public static final @NonNull ITmfEvent TEST_2_END_EVENT = new TmfEvent(null, ITmfContext.UNKNOWN_RANK, TmfTimestamp.fromNanos(10), null, null);
+ private static final String PATTERN_SEGMENT_PREFIX = "seg_";
/**
* The pattern segment TEST_2
*/
- public static final @NonNull TmfXmlPatternSegment TEST_2 = new TmfXmlPatternSegment(TEST_2_START_EVENT.getTimestamp().getValue(), TEST_2_END_EVENT.getTimestamp().getValue(), ITmfTimestamp.NANOSECOND_SCALE, "seg_test2", TEST_2_CONTENT);
+ public static final @NonNull TmfXmlPatternSegment TEST_2 = new TmfXmlPatternSegment(TEST_2_START_EVENT.getTimestamp().getValue(), TEST_2_END_EVENT.getTimestamp().getValue(), ITmfTimestamp.NANOSECOND_SCALE, PATTERN_SEGMENT_PREFIX + "test2", TEST_2_CONTENT);
+
+ /**
+ * The pattern segment TEST_3
+ */
+ public static final @NonNull TmfXmlPatternSegment TEST_3 = new TmfXmlPatternSegment(TEST_2_START_EVENT.getTimestamp().getValue(), TEST_2_START_EVENT.getTimestamp().getValue(), ITmfTimestamp.NANOSECOND_SCALE, PATTERN_SEGMENT_PREFIX + "open", Collections.EMPTY_MAP);
}
<trace>
<event timestamp="1" name="entry" source="0">
<field name="cpu" type="int" value="0" />
+<field name="op" type="string" value="op1" />
</event>
<event timestamp="3" name="exit" source="0">
<field name="cpu" type="int" value="0" />
<field name="curState" type="string" value="GOOD" />
+<field name="op" type="string" value="op1" />
</event>
<event timestamp="5" name="entry" source="0">
<field name="cpu" type="int" value="0" />
+<field name="op" type="string" value="op1" />
</event>
<event timestamp="7" name="exit" source="0">
<field name="cpu" type="int" value="0" />
<field name="curState" type="string" value="BAD" />
+<field name="op" type="string" value="op1" />
</event>
</trace>
\ No newline at end of file
* http://www.eclipse.org/legal/epl-v10.html
*************************************************************************** -->
<pattern version="0" id="syscall.analysis">
+ <mappingGroup id="group">
+ <entry>
+ <stateValue type="int" value="1" />
+ <stateValue type="string" value="open" />
+ </entry>
+ </mappingGroup>
<patternHandler>
<action id="increment_counter_consuming">
<stateChange>
</state>
<final id="end"/>
</fsm>
+
+ <action id="segment_create">
+ <segment>
+ <segType>
+ <segName>
+ <stateValue mappingGroup="group" type="int" value="1"/>
+ </segName>
+ </segType>
+ </segment>
+ </action>
+
+ <fsm id="mapping" multiple="false">
+ <state id="start">
+ <transition event="entry" target="end" action="segment_create" />
+ </state>
+ <final id="end"/>
+ </fsm>
</patternHandler>
</pattern>
</tmfxml>
\ No newline at end of file
<stateProvider id="test.xml.attributes" version="1">
+ <mappingGroup id="operation">
+ <entry>
+ <stateValue type="string" value="read only" />
+ <stateValue type="string" value="op1" />
+ </entry>
+ </mappingGroup>
<!-- Test to see that state values are updated or modified depending on the requested state change -->
<eventHandler eventName="entry">
<stateChange>
<stateAttribute type="constant" value="stack"/>
<stateValue stack="push" type="eventField" value="timestamp" />
</stateChange>
+ <stateChange>
+ <if>
+ <condition>
+ <field name="op"/>
+ <stateValue mappingGroup="operation" type="string" value="read only"/>
+ </condition>
+ </if>
+ <then>
+ <stateAttribute type="constant" value="mapped" />
+ <stateValue type="string" value="TRUE" />
+ </then>
+ <else>
+ <stateAttribute type="constant" value="mapped" />
+ <stateValue type="string" value="FALSE" />
+ </else>
+ </stateChange>
</eventHandler>
<eventHandler eventName="exit">
<stateChange>
<stateValue stack="pop" type="long"/>
</then>
</stateChange>
+ <stateChange>
+ <if>
+ <condition>
+ <field name="op"/>
+ <stateValue type="string" value="read only"/>
+ </condition>
+ </if>
+ <then>
+ <stateAttribute type="constant" value="mapped" />
+ <stateValue type="string" value="TRUE" />
+ </then>
+ <else>
+ <stateAttribute type="constant" value="mapped" />
+ <stateValue type="string" value="FALSE" />
+ </else>
+ </stateChange>
</eventHandler>
</stateProvider>
</tmfxml>
\ No newline at end of file
* @return The new {@link TmfXmlPatternSegmentBuilder}
*/
TmfXmlPatternSegmentBuilder createPatternSegmentBuilder(Element node, IXmlStateSystemContainer container);
+
+ /**
+ * Create a new pattern map entry
+ *
+ * @param node
+ * The XML map entry element
+ * @param container
+ * The state system container this state value handler belongs to
+ * @return The new {@link TmfXmlMapEntry}
+ */
+ TmfXmlMapEntry createMapEntry(Element node, IXmlStateSystemContainer container);
}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 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.Collections;
+
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * This Class implements a map entry tree for mapping group in the XML-defined state system. A
+ * map entry is composed of two state values. The first value is a key to get the
+ * second state value.
+ *
+ * @author Jean-Christian Kouame
+ */
+public class TmfXmlMapEntry {
+ ITmfXmlStateValue fKey;
+ ITmfXmlStateValue fValue;
+
+ /**
+ * Constructor
+ *
+ * @param modelFactory
+ * The model factory
+ * @param node
+ * The XML element representing this {@link TmfXmlMapEntry}
+ * @param container
+ * The state system container this {@link TmfXmlMapEntry}
+ * belongs to
+ */
+ public TmfXmlMapEntry(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container) {
+ NodeList nodesSV = node.getElementsByTagName(TmfXmlStrings.STATE_VALUE);
+ if (nodesSV.getLength() != 2) {
+ throw new IllegalStateException("A map entry is composed of exactly 2 statevalues. Actual value is : " + nodesSV.getLength()); //$NON-NLS-1$
+ }
+ fKey = modelFactory.createStateValue((Element) NonNullUtils.checkNotNull(nodesSV.item(0)), container, Collections.EMPTY_LIST);
+ fValue = modelFactory.createStateValue((Element) NonNullUtils.checkNotNull(nodesSV.item(1)), container, Collections.EMPTY_LIST);
+ }
+
+ /**
+ * Get the value for this entry.
+ *
+ * @return The value
+ */
+ public ITmfXmlStateValue getValue() {
+ return fValue;
+ }
+
+ /**
+ * Get the key for this value
+ *
+ * @return The key
+ */
+ public ITmfXmlStateValue getKey() {
+ return fKey;
+ }
+}
package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model;
import java.util.List;
+import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
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.pattern.stateprovider.XmlPatternStateProvider;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.XmlStateProvider;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
private final IXmlStateSystemContainer fContainer;
+ private final String fMappingGroup;
+
/**
* Different behaviors of an attribute that is to be stacked
*/
*/
String stack = node.getAttribute(TmfXmlStrings.ATTRIBUTE_STACK);
fStackType = ValueTypeStack.getTypeFromString(stack);
+
+ fMappingGroup = node.getAttribute(TmfXmlStrings.MAPPING_GROUP);
}
/**
@Override
public ITmfStateValue getValue(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) throws AttributeNotFoundException {
- return fStateValue.getValue(event, scenarioInfo);
+ return getMappedValue(event, scenarioInfo, fStateValue.getValue(event, scenarioInfo));
+ }
+
+ private ITmfStateValue getMappedValue(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo, ITmfStateValue value) {
+ try {
+ Set<TmfXmlMapEntry> group = null;
+ if (fContainer instanceof XmlPatternStateProvider) {
+ group = ((XmlPatternStateProvider) fContainer).getMappingGroup(fMappingGroup);
+ } else if (fContainer instanceof XmlStateProvider) {
+ group = ((XmlStateProvider) fContainer).getMappingGroup(fMappingGroup);
+ }
+ if (group != null) {
+ for (TmfXmlMapEntry entry : group) {
+ if (entry.getKey().getValue(event, scenarioInfo).equals(value)) {
+ return entry.getValue().getValue(event, scenarioInfo);
+ }
+ }
+ }
+ return value;
+ } catch (AttributeNotFoundException e) {
+ Activator.logError("Unable to map the state value"); //$NON-NLS-1$
+ // FIXME maybe we should return the raw state value instead of a
+ // null state value
+ return TmfStateValue.nullValue();
+ }
}
/**
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlCondition;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlEventHandler;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlFsm;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlMapEntry;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlLocation;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlPatternEventHandler;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlPatternSegmentBuilder;
public TmfXmlPatternSegmentBuilder createPatternSegmentBuilder(Element node, IXmlStateSystemContainer container) {
return new TmfXmlPatternSegmentBuilder(this, node, container);
}
+
+ @Override
+ public @NonNull TmfXmlMapEntry createMapEntry(@NonNull Element node, @NonNull IXmlStateSystemContainer container) {
+ return new TmfXmlMapEntry(this, node, container);
+ }
}
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlCondition;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlEventHandler;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlFsm;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlMapEntry;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlLocation;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlPatternEventHandler;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlPatternSegmentBuilder;
public TmfXmlPatternSegmentBuilder createPatternSegmentBuilder(Element node, IXmlStateSystemContainer container) {
return new TmfXmlPatternSegmentBuilder(this, node, container);
}
+
+ @Override
+ public @NonNull TmfXmlMapEntry createMapEntry(@NonNull Element node, @NonNull IXmlStateSystemContainer container) {
+ return new TmfXmlMapEntry(this, node, container);
+ }
}
<xs:anyAttribute />
</xs:complexType>
+ <xs:complexType name="mappingGroup">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="entry" type="mapEntry" />
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="mapEntry">
+ <xs:annotation>
+ <xs:documentation>Define a handler for a state value. The second state value defined in the handler will be used instead of the first state one whenever it will be met.</xs:documentation></xs:annotation>
+ <xs:sequence maxOccurs="1" minOccurs="1">
+ <xs:element maxOccurs="2" minOccurs="2" name="stateValue" type="stateValue" />
+ </xs:sequence>
+ </xs:complexType>
+
</xs:schema>
<xs:element maxOccurs="unbounded" minOccurs="0" name="location" type="location" >
<xs:annotation>
<xs:documentation>Declares shortcuts to frequently used attribute/data locations. For instance, if a path to an often-used attribute is CPUs/{event.some_field}/Threads/Status, it may be a good idea to put this path in a location and then use the location name in the event handlers.</xs:documentation></xs:annotation></xs:element>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="mappingGroup" type="mappingGroup" >
+ <xs:annotation>
+ <xs:documentation>Define a mapping group for state values.</xs:documentation></xs:annotation></xs:element>
<xs:element maxOccurs="1" minOccurs="1" name="patternHandler" type="patternHandler" >
<xs:annotation>
<xs:documentation>Describes the pattern behavior. It defines all the entities; i.e., all the transitions, actions and state machines that describe the pattern.</xs:documentation></xs:annotation></xs:element>
<xs:element maxOccurs="unbounded" minOccurs="0" name="location" type="location" >
<xs:annotation>
<xs:documentation>Declare shortcuts to frequently used attribute/data locations. For instance, if a path to an often-used attribute is CPUs/{event.some_field}/Threads/Status, it may be a good idea to put this path in a location and then use the location name in the event handlers.</xs:documentation></xs:annotation></xs:element>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="mappingGroup" type="mappingGroup" >
+ <xs:annotation>
+ <xs:documentation>Define a mapping for a state value. A handler describe a state value V that will be use instead of a state value S.</xs:documentation></xs:annotation></xs:element>
</xs:choice>
<xs:element maxOccurs="unbounded" minOccurs="1" name="eventHandler" type="eventHandler" >
<xs:annotation>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
+ <xs:attribute name="mappingGroup" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Indicate which mapping group to use for this state value.</xs:documentation></xs:annotation></xs:attribute>
<xs:attribute name="value" type="xs:string" >
<xs:annotation>
<xs:documentation>Indicate what the value is. A value should be specified only if the type is int, long, string or event_field. See the documentation on types for information on what to put for value.</xs:documentation></xs:annotation></xs:attribute>
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.model.ITmfXmlModelFactory;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlMapEntry;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlLocation;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlPatternEventHandler;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlScenarioHistoryBuilder;
/** List of all Locations */
private final @NonNull Set<@NonNull TmfXmlLocation> fLocations;
+ private final @NonNull Map<@NonNull String, @NonNull Set<@NonNull TmfXmlMapEntry>> fMappingGroups;
+
/** Map for stored values */
private final @NonNull Map<@NonNull String, @NonNull String> fStoredFields = new HashMap<>();
Element doc = XmlUtils.getElementInFile(pathString, TmfXmlStrings.PATTERN, fStateId);
if (doc == null) {
fLocations = new HashSet<>();
+ fMappingGroups = new HashMap<>();
Activator.logError("Failed to find a pattern in " + pathString); //$NON-NLS-1$
return;
}
}
fLocations = Collections.unmodifiableSet(locations);
+ /* parser for the mapping groups */
+ final @NonNull Map<@NonNull String, @NonNull Set<@NonNull TmfXmlMapEntry>> mapGroups = new HashMap<>();
+ NodeList mapNodes = doc.getElementsByTagName(TmfXmlStrings.MAPPING_GROUP);
+ for (int i = 0; i < mapNodes.getLength(); i++) {
+ Element map = (Element) mapNodes.item(i);
+ String id = map.getAttribute(TmfXmlStrings.ID);
+
+ Set<@NonNull TmfXmlMapEntry> entrySet = mapGroups.get(id);
+ if (entrySet == null) {
+ entrySet = new HashSet<>();
+ mapGroups.put(id, entrySet);
+ }
+
+ NodeList entryNodes = map.getElementsByTagName(TmfXmlStrings.ENTRY);
+ for (int j = 0; j < entryNodes.getLength(); j++) {
+ Element entryElement = (Element) entryNodes.item(j);
+ if (entryElement == null) {
+ continue;
+ }
+ TmfXmlMapEntry entry = modelFactory.createMapEntry(entryElement, this);
+ entrySet.add(entry);
+ }
+ }
+ fMappingGroups = Collections.unmodifiableMap(mapGroups);
+
/* parser for the event handlers */
NodeList nodes = doc.getElementsByTagName(TmfXmlStrings.PATTERN_HANDLER);
fHandler = modelFactory.createPatternEventHandler(NonNullUtils.checkNotNull((Element) nodes.item(0)), this);
public @NonNull TmfXmlScenarioHistoryBuilder getHistoryBuilder() {
return fHistoryBuilder;
}
+
+ /**
+ * Get the list of state value handlers defined in this top level element
+ *
+ * @param id
+ * The mapping group id
+ * @return The set of {@link TmfXmlMapEntry}
+ */
+ public @Nullable Set<@NonNull TmfXmlMapEntry> getMappingGroup(@NonNull String id) {
+ return fMappingGroups.get(id);
+ }
}
\ No newline at end of file
String ALIAS = "alias";
String ABANDON = "abandon";
String CONSUMING = "consuming";
+ String MAPPING_GROUP = "mappingGroup";
+ String ENTRY = "entry";
}
\ No newline at end of file
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.ITmfXmlModelFactory;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlEventHandler;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlLocation;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlMapEntry;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.readwrite.TmfXmlReadWriteModelFactory;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
/** Map for defined values */
private final Map<String, String> fDefinedValues = new HashMap<>();
+ private final @NonNull Map<@NonNull String, @NonNull Set<@NonNull TmfXmlMapEntry>> fMappingGroups;
+
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
Element doc = XmlUtils.getElementInFile(fFilePath.makeAbsolute().toOSString(), TmfXmlStrings.STATE_PROVIDER, fStateId);
if (doc == null) {
fLocations = new HashSet<>();
+ fMappingGroups = new HashMap<>();
return;
}
}
fLocations = Collections.unmodifiableSet(locations);
+ /* parser for the mapping groups */
+ final @NonNull Map<@NonNull String, @NonNull Set<@NonNull TmfXmlMapEntry>> mapGroups = new HashMap<>();
+ NodeList mapNodes = doc.getElementsByTagName(TmfXmlStrings.MAPPING_GROUP);
+ for (int i = 0; i < mapNodes.getLength(); i++) {
+ Element map = (Element) mapNodes.item(i);
+ String id = map.getAttribute(TmfXmlStrings.ID);
+
+ Set<@NonNull TmfXmlMapEntry> entrySet = mapGroups.get(id);
+ if (entrySet == null) {
+ entrySet = new HashSet<>();
+ mapGroups.put(id, entrySet);
+ }
+
+ NodeList entryNodes = map.getElementsByTagName(TmfXmlStrings.ENTRY);
+ for (int j = 0; j < entryNodes.getLength(); j++) {
+ Element entryElement = (Element) entryNodes.item(j);
+ if (entryElement == null) {
+ continue;
+ }
+ TmfXmlMapEntry entry = modelFactory.createMapEntry(entryElement, this);
+ entrySet.add(entry);
+ }
+ }
+ fMappingGroups = Collections.unmodifiableMap(mapGroups);
+
/* parser for the event handlers */
childElements = XmlUtils.getChildElements(doc, TmfXmlStrings.EVENT_HANDLER);
for (Element element : childElements) {
return attribute;
}
+ /**
+ * Get the list of state value handlers defined in this top level element
+ *
+ * @param id
+ * The mapping group id
+ * @return The set of {@link TmfXmlMapEntry}
+ */
+ public @Nullable Set<@NonNull TmfXmlMapEntry> getMappingGroup(@NonNull String id) {
+ return fMappingGroups.get(id);
+ }
}
\ No newline at end of file