1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 ******************************************************************************/
9 package org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.model
;
11 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
13 import java
.util
.ArrayList
;
14 import java
.util
.HashMap
;
15 import java
.util
.List
;
17 import java
.util
.Map
.Entry
;
19 import org
.eclipse
.jdt
.annotation
.Nullable
;
20 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.Activator
;
21 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
22 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.pattern
.stateprovider
.XmlPatternStateProvider
;
23 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.segment
.TmfXmlPatternSegment
;
24 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
31 import org
.w3c
.dom
.Element
;
32 import org
.w3c
.dom
.NodeList
;
35 * This class defines a pattern segment builder. It will use the XML description
36 * of the pattern segment to generate it at runtime.
38 * @author Jean-Christian Kouame
40 public class TmfXmlPatternSegmentBuilder
{
45 public static final String UNKNOWN_STRING
= "unknown"; //$NON-NLS-1$
47 * Prefix for the pattern segment name
49 public static final String PATTERN_SEGMENT_NAME_PREFIX
= "seg_"; //$NON-NLS-1$
50 private final ITmfXmlModelFactory fModelFactory
;
51 private final IXmlStateSystemContainer fContainer
;
52 private final List
<TmfXmlPatternSegmentField
> fFields
= new ArrayList
<>();
53 private final TmfXmlPatternSegmentType fSegmentType
;
57 * The factory used to create XML model elements
59 * XML element of the pattern segment builder
61 * The state system container this pattern segment builder
64 public TmfXmlPatternSegmentBuilder(ITmfXmlModelFactory modelFactory
, Element node
, IXmlStateSystemContainer parent
) {
65 fModelFactory
= modelFactory
;
68 //Set the XML type of the segment
69 NodeList nodesSegmentType
= node
.getElementsByTagName(TmfXmlStrings
.SEGMENT_TYPE
);
70 Element element
= (Element
) nodesSegmentType
.item(0);
71 if (element
== null) {
72 throw new IllegalArgumentException();
74 fSegmentType
= new TmfXmlPatternSegmentType(element
);
76 //Set the XML content of the segment
77 NodeList nodesSegmentContent
= node
.getElementsByTagName(TmfXmlStrings
.SEGMENT_CONTENT
);
78 Element fContentElement
= (Element
) nodesSegmentContent
.item(0);
79 if (fContentElement
!= null) {
80 NodeList nodesSegmentField
= fContentElement
.getElementsByTagName(TmfXmlStrings
.SEGMENT_FIELD
);
81 for (int i
= 0; i
< nodesSegmentField
.getLength(); i
++) {
82 fFields
.add(new TmfXmlPatternSegmentField(checkNotNull((Element
) nodesSegmentField
.item(i
))));
88 * Generate a pattern segment
93 * Start time of the pattern segment to generate
95 * End time of the pattern segment to generate
97 * The active scenario details. Or <code>null</code> if there is
99 * @return The pattern segment generated
101 public TmfXmlPatternSegment
generatePatternSegment(ITmfEvent event
, ITmfTimestamp start
, ITmfTimestamp end
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
102 int scale
= event
.getTimestamp().getScale();
103 long startValue
= start
.toNanos();
104 long endValue
= end
.toNanos();
105 String segmentName
= getPatternSegmentName(event
, scenarioInfo
);
106 Map
<String
, ITmfStateValue
> fields
= new HashMap
<>();
107 setPatternSegmentContent(event
, start
, end
, fields
, scenarioInfo
);
108 TmfXmlPatternSegment segment
= new TmfXmlPatternSegment(startValue
, endValue
, scale
, segmentName
, fields
);
109 if (fContainer
instanceof XmlPatternStateProvider
) {
110 ((XmlPatternStateProvider
) fContainer
).getListener().onNewSegment(segment
);
116 * Get the pattern segment name
120 * @param scenarioInfo
121 * The active scenario details. Or <code>null</code> if there is
123 * @return The name of the segment
125 private String
getPatternSegmentName(ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
126 return fSegmentType
.getName(event
, scenarioInfo
);
130 * Compute all the fields and their values for this pattern segment. The
131 * fields could be constant values or values queried from the state system.
136 * The start timestamp of this segment
138 * The end timestamp of this segment
140 * The map that will contained all the fields
141 * @param scenarioInfo
142 * The active scenario details. Or <code>null</code> if there is
145 private void setPatternSegmentContent(ITmfEvent event
, ITmfTimestamp start
, ITmfTimestamp end
, Map
<String
, ITmfStateValue
> fields
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
146 for (TmfXmlPatternSegmentField field
: fFields
) {
147 fields
.put(field
.getName().intern(), field
.getValue(event
, scenarioInfo
));
149 if (scenarioInfo
!= null) {
150 addStoredFieldsContent(event
, fields
, scenarioInfo
);
155 * Query the stored fields path and add them to the content of the pattern
156 * segment. This is specific to pattern analysis.
163 * The active scenario details
165 protected void addStoredFieldsContent(ITmfEvent event
, Map
<String
, ITmfStateValue
> fields
, final TmfXmlScenarioInfo info
) {
166 if (fContainer
instanceof XmlPatternStateProvider
) {
167 for (Entry
<String
, String
> entry
: ((XmlPatternStateProvider
) fContainer
).getStoredFields().entrySet()) {
168 ITmfStateValue value
= ((XmlPatternStateProvider
) fContainer
).getHistoryBuilder().getStoredFieldValue(fContainer
, entry
.getValue(), info
, event
);
169 if (!value
.isNull()) {
170 fields
.put(entry
.getValue().intern(), value
);
176 private static ITmfStateValue
getStateValueFromConstant(String constantValue
, String type
) {
178 case TmfXmlStrings
.TYPE_INT
:
179 return TmfStateValue
.newValueInt(Integer
.parseInt(constantValue
));
180 case TmfXmlStrings
.TYPE_LONG
:
181 return TmfStateValue
.newValueLong(Long
.parseLong(constantValue
));
182 case TmfXmlStrings
.TYPE_STRING
:
183 return TmfStateValue
.newValueString(constantValue
);
184 case TmfXmlStrings
.TYPE_NULL
:
185 return TmfStateValue
.nullValue();
187 throw new IllegalArgumentException("Invalid type of field : " + type
); //$NON-NLS-1$
191 private static void getNameFromXmlStateValue(ITmfEvent event
, StringBuilder builder
, ITmfXmlStateValue xmlStateValue
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
193 ITmfStateValue value
= xmlStateValue
.getValue(event
, scenarioInfo
);
194 switch (value
.getType()) {
196 builder
.append(value
.unboxDouble());
199 builder
.append(value
.unboxInt());
202 builder
.append(value
.unboxLong());
205 builder
.append(UNKNOWN_STRING
);
208 builder
.append(value
.unboxStr());
211 throw new StateValueTypeException("Invalid type of state value"); //$NON-NLS-1$
213 } catch (AttributeNotFoundException e
) {
214 Activator
.logInfo("Impossible to get the state value", e
); //$NON-NLS-1$
219 * This class represents the segment fields described in the XML. The real
220 * value of the field will be set at runtime using the active event.
222 * @author Jean-Christian Kouame
225 private class TmfXmlPatternSegmentField
{
226 private final String fName
;
227 private final String fType
;
228 private final @Nullable ITmfStateValue fStateValue
;
229 private final @Nullable ITmfXmlStateValue fXmlStateValue
;
235 * The pattern segment field node
237 public TmfXmlPatternSegmentField(Element element
) {
238 // The name, the type and the value of each field could respectively
239 // be found from the attributes name, type and value. If the value
240 // attribute is not available, try to find it from the child state
242 fName
= element
.getAttribute(TmfXmlStrings
.NAME
);
243 fType
= element
.getAttribute(TmfXmlStrings
.TYPE
);
244 String constantValue
= element
.getAttribute(TmfXmlStrings
.VALUE
);
245 if (constantValue
.isEmpty() && !fType
.equals(TmfXmlStrings
.TYPE_NULL
)) {
247 Element elementFieldStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
248 if (elementFieldStateValue
== null) {
249 throw new IllegalArgumentException("The value of the field " + fName
+ " is missing"); //$NON-NLS-1$ //$NON-NLS-2$
251 fXmlStateValue
= fModelFactory
.createStateValue(elementFieldStateValue
, fContainer
, new ArrayList
<>());
253 fStateValue
= getStateValueFromConstant(constantValue
, fType
);
254 fXmlStateValue
= null;
259 * Get the real value of the XML pattern segment field
263 * @return The state value representing the value of the XML pattern
265 * @param scenarioInfo
266 * The active scenario details. Or <code>null</code> if there
269 public ITmfStateValue
getValue(ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
270 if (fStateValue
!= null) {
274 return checkNotNull(fXmlStateValue
).getValue(event
, scenarioInfo
);
275 } catch (AttributeNotFoundException e
) {
276 Activator
.logError("Failed to get the state value", e
); //$NON-NLS-1$
278 throw new IllegalStateException("Failed to get the value for the segment field " + fName
); //$NON-NLS-1$
282 * Get the name of the XML pattern segment field
286 public String
getName() {
292 * This class represents the segment type described in XML.
294 * @author Jean-Christian Kouame
297 private class TmfXmlPatternSegmentType
{
298 private final String fSegmentNameAttribute
;
299 private final @Nullable ITmfXmlStateValue fNameStateValue
;
305 * The pattern segment type node
307 public TmfXmlPatternSegmentType(Element element
) {
308 // Try to find the segment name from the name attribute. If
309 // attribute not available, try to find it from the child state value
310 fSegmentNameAttribute
= element
.getAttribute(TmfXmlStrings
.SEGMENT_NAME
);
311 if (!fSegmentNameAttribute
.isEmpty()) {
312 fNameStateValue
= null;
314 Element elementSegmentNameStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
315 if (elementSegmentNameStateValue
== null) {
316 throw new IllegalArgumentException("Failed to get the segment name. A state value is needed."); //$NON-NLS-1$
318 fNameStateValue
= fModelFactory
.createStateValue(elementSegmentNameStateValue
, fContainer
, new ArrayList
<>());
323 * Get the name of the segment
327 * @param scenarioInfo
328 * The active scenario details. Or <code>null</code> if there
330 * @return The segment name
332 public String
getName(ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
333 StringBuilder name
= new StringBuilder(PATTERN_SEGMENT_NAME_PREFIX
);
334 if (fNameStateValue
!= null) {
335 getNameFromXmlStateValue(event
, name
, fNameStateValue
, scenarioInfo
);
337 name
.append(fSegmentNameAttribute
);
339 return name
.toString().intern();