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
, 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 map that will contained all the fields
137 * @param scenarioInfo
138 * The active scenario details. Or <code>null</code> if there is
141 private void setPatternSegmentContent(ITmfEvent event
, Map
<String
, ITmfStateValue
> fields
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
142 for (TmfXmlPatternSegmentField field
: fFields
) {
143 fields
.put(field
.getName().intern(), field
.getValue(event
, scenarioInfo
));
145 if (scenarioInfo
!= null) {
146 addStoredFieldsContent(event
, fields
, scenarioInfo
);
151 * Query the stored fields path and add them to the content of the pattern
152 * segment. This is specific to pattern analysis.
159 * The active scenario details
161 protected void addStoredFieldsContent(ITmfEvent event
, Map
<String
, ITmfStateValue
> fields
, final TmfXmlScenarioInfo info
) {
162 if (fContainer
instanceof XmlPatternStateProvider
) {
163 for (Entry
<String
, String
> entry
: ((XmlPatternStateProvider
) fContainer
).getStoredFields().entrySet()) {
164 ITmfStateValue value
= ((XmlPatternStateProvider
) fContainer
).getHistoryBuilder().getStoredFieldValue(fContainer
, entry
.getValue(), info
, event
);
165 if (!value
.isNull()) {
166 fields
.put(entry
.getValue().intern(), value
);
172 private static ITmfStateValue
getStateValueFromConstant(String constantValue
, String type
) {
174 case TmfXmlStrings
.TYPE_INT
:
175 return TmfStateValue
.newValueInt(Integer
.parseInt(constantValue
));
176 case TmfXmlStrings
.TYPE_LONG
:
177 return TmfStateValue
.newValueLong(Long
.parseLong(constantValue
));
178 case TmfXmlStrings
.TYPE_STRING
:
179 return TmfStateValue
.newValueString(constantValue
);
180 case TmfXmlStrings
.TYPE_NULL
:
181 return TmfStateValue
.nullValue();
183 throw new IllegalArgumentException("Invalid type of field : " + type
); //$NON-NLS-1$
187 private static void getNameFromXmlStateValue(ITmfEvent event
, StringBuilder builder
, ITmfXmlStateValue xmlStateValue
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
189 ITmfStateValue value
= xmlStateValue
.getValue(event
, scenarioInfo
);
190 switch (value
.getType()) {
192 builder
.append(value
.unboxDouble());
195 builder
.append(value
.unboxInt());
198 builder
.append(value
.unboxLong());
201 builder
.append(UNKNOWN_STRING
);
204 builder
.append(value
.unboxStr());
208 throw new StateValueTypeException("Invalid type of state value"); //$NON-NLS-1$
210 } catch (AttributeNotFoundException e
) {
211 Activator
.logInfo("Impossible to get the state value", e
); //$NON-NLS-1$
216 * This class represents the segment fields described in the XML. The real
217 * value of the field will be set at runtime using the active event.
219 * @author Jean-Christian Kouame
222 private class TmfXmlPatternSegmentField
{
223 private final String fName
;
224 private final String fType
;
225 private final @Nullable ITmfStateValue fStateValue
;
226 private final @Nullable ITmfXmlStateValue fXmlStateValue
;
232 * The pattern segment field node
234 public TmfXmlPatternSegmentField(Element element
) {
235 // The name, the type and the value of each field could respectively
236 // be found from the attributes name, type and value. If the value
237 // attribute is not available, try to find it from the child state
239 fName
= element
.getAttribute(TmfXmlStrings
.NAME
);
240 fType
= element
.getAttribute(TmfXmlStrings
.TYPE
);
241 String constantValue
= element
.getAttribute(TmfXmlStrings
.VALUE
);
242 if (constantValue
.isEmpty() && !fType
.equals(TmfXmlStrings
.TYPE_NULL
)) {
244 Element elementFieldStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
245 if (elementFieldStateValue
== null) {
246 throw new IllegalArgumentException("The value of the field " + fName
+ " is missing"); //$NON-NLS-1$ //$NON-NLS-2$
248 fXmlStateValue
= fModelFactory
.createStateValue(elementFieldStateValue
, fContainer
, new ArrayList
<>());
250 fStateValue
= getStateValueFromConstant(constantValue
, fType
);
251 fXmlStateValue
= null;
256 * Get the real value of the XML pattern segment field
260 * @return The state value representing the value of the XML pattern
262 * @param scenarioInfo
263 * The active scenario details. Or <code>null</code> if there
266 public ITmfStateValue
getValue(ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
267 if (fStateValue
!= null) {
271 return checkNotNull(fXmlStateValue
).getValue(event
, scenarioInfo
);
272 } catch (AttributeNotFoundException e
) {
273 Activator
.logError("Failed to get the state value", e
); //$NON-NLS-1$
275 throw new IllegalStateException("Failed to get the value for the segment field " + fName
); //$NON-NLS-1$
279 * Get the name of the XML pattern segment field
283 public String
getName() {
289 * This class represents the segment type described in XML.
291 * @author Jean-Christian Kouame
294 private class TmfXmlPatternSegmentType
{
295 private final String fSegmentNameAttribute
;
296 private final @Nullable ITmfXmlStateValue fNameStateValue
;
302 * The pattern segment type node
304 public TmfXmlPatternSegmentType(Element element
) {
305 // Try to find the segment name from the name attribute. If
306 // attribute not available, try to find it from the child state value
307 fSegmentNameAttribute
= element
.getAttribute(TmfXmlStrings
.SEGMENT_NAME
);
308 if (!fSegmentNameAttribute
.isEmpty()) {
309 fNameStateValue
= null;
311 Element elementSegmentNameStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
312 if (elementSegmentNameStateValue
== null) {
313 throw new IllegalArgumentException("Failed to get the segment name. A state value is needed."); //$NON-NLS-1$
315 fNameStateValue
= fModelFactory
.createStateValue(elementSegmentNameStateValue
, fContainer
, new ArrayList
<>());
320 * Get the name of the segment
324 * @param scenarioInfo
325 * The active scenario details. Or <code>null</code> if there
327 * @return The segment name
329 public String
getName(ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
330 StringBuilder name
= new StringBuilder(PATTERN_SEGMENT_NAME_PREFIX
);
331 if (fNameStateValue
!= null) {
332 getNameFromXmlStateValue(event
, name
, fNameStateValue
, scenarioInfo
);
334 name
.append(fSegmentNameAttribute
);
336 return name
.toString().intern();