tmf : Add pattern analysis behavior
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / tmf / analysis / xml / core / model / TmfXmlPatternSegmentBuilder.java
CommitLineData
2e1183f8
JCK
1/*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
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 ******************************************************************************/
9package org.eclipse.tracecompass.tmf.analysis.xml.core.model;
10
11import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
12
13import java.util.ArrayList;
14import java.util.HashMap;
15import java.util.List;
16import java.util.Map;
3a5f73a1 17import java.util.Map.Entry;
2e1183f8
JCK
18
19import org.eclipse.jdt.annotation.Nullable;
20import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
38e2a2e9 21import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternStateProvider;
2e1183f8
JCK
22import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
23import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
24import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
25import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
26import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
27import org.eclipse.tracecompass.tmf.analysis.xml.core.segment.TmfXmlPatternSegment;
28import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
29import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
30import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
31import org.w3c.dom.Element;
32import org.w3c.dom.NodeList;
33
34/**
35 * This class defines a pattern segment builder. It will use the XML description
36 * of the pattern segment to generate it at runtime.
37 *
38 * @author Jean-Christian Kouame
39 * @since 2.0
40 *
41 */
42public class TmfXmlPatternSegmentBuilder {
43
44 /**
45 * The string unknown
46 */
47 public static final String UNKNOWN_STRING = "unknown"; //$NON-NLS-1$
48 /**
49 * Prefix for the pattern segment name
50 */
51 public static final String PATTERN_SEGMENT_NAME_PREFIX = "seg_"; //$NON-NLS-1$
52 private final ITmfXmlModelFactory fModelFactory;
53 private final IXmlStateSystemContainer fContainer;
54 private final List<TmfXmlPatternSegmentField> fFields = new ArrayList<>();
55 private final TmfXmlPatternSegmentType fSegmentType;
56
57 /**
58 * @param modelFactory
59 * The factory used to create XML model elements
60 * @param node
61 * XML element of the pattern segment builder
62 * @param parent
63 * The state system container this pattern segment builder
64 * belongs to
65 */
66 public TmfXmlPatternSegmentBuilder(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer parent) {
67 fModelFactory = modelFactory;
68 fContainer = parent;
69
70 //Set the XML type of the segment
71 NodeList nodesSegmentType = node.getElementsByTagName(TmfXmlStrings.SEGMENT_TYPE);
72 Element element = (Element) nodesSegmentType.item(0);
73 if (element == null) {
74 throw new IllegalArgumentException();
75 }
76 fSegmentType = new TmfXmlPatternSegmentType(element);
77
78 //Set the XML content of the segment
79 NodeList nodesSegmentContent = node.getElementsByTagName(TmfXmlStrings.SEGMENT_CONTENT);
80 Element fContentElement = (Element) nodesSegmentContent.item(0);
81 if (fContentElement != null) {
82 NodeList nodesSegmentField = fContentElement.getElementsByTagName(TmfXmlStrings.SEGMENT_FIELD);
83 for (int i = 0; i < nodesSegmentField.getLength(); i++) {
84 fFields.add(new TmfXmlPatternSegmentField(checkNotNull((Element) nodesSegmentField.item(i))));
85 }
86 }
87 }
88
89 /**
90 * Generate a pattern segment
91 *
92 * @param event
93 * The active event
94 * @param start
95 * Start time of the pattern segment to generate
96 * @param end
97 * End time of the pattern segment to generate
0b563c20
JCK
98 * @param scenarioInfo
99 * The active scenario details. Or <code>null</code> if there is
100 * no scenario.
2e1183f8
JCK
101 * @return The pattern segment generated
102 */
0b563c20 103 public TmfXmlPatternSegment generatePatternSegment(ITmfEvent event, ITmfTimestamp start, ITmfTimestamp end, @Nullable TmfXmlScenarioInfo scenarioInfo) {
2e1183f8 104 int scale = event.getTimestamp().getScale();
16801c72
MK
105 long startValue = start.toNanos();
106 long endValue = end.toNanos();
0b563c20 107 String segmentName = getPatternSegmentName(event, scenarioInfo);
2e1183f8 108 Map<String, ITmfStateValue> fields = new HashMap<>();
0b563c20 109 setPatternSegmentContent(event, start, end, fields, scenarioInfo);
38e2a2e9
JCK
110 TmfXmlPatternSegment segment = new TmfXmlPatternSegment(startValue, endValue, scale, segmentName, fields);
111 if (fContainer instanceof XmlPatternStateProvider) {
112 ((XmlPatternStateProvider) fContainer).getListener().onNewSegment(segment);
113 }
114 return segment;
2e1183f8
JCK
115 }
116
117 /**
118 * Get the pattern segment name
119 *
120 * @param event
121 * The active event
0b563c20
JCK
122 * @param scenarioInfo
123 * The active scenario details. Or <code>null</code> if there is
124 * no scenario.
2e1183f8
JCK
125 * @return The name of the segment
126 */
0b563c20
JCK
127 private String getPatternSegmentName(ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) {
128 return fSegmentType.getName(event, scenarioInfo);
2e1183f8
JCK
129 }
130
131 /**
132 * Compute all the fields and their values for this pattern segment. The
133 * fields could be constant values or values queried from the state system.
134 *
135 * @param event
136 * The current event
137 * @param start
138 * The start timestamp of this segment
139 * @param end
140 * The end timestamp of this segment
141 * @param fields
142 * The map that will contained all the fields
0b563c20
JCK
143 * @param scenarioInfo
144 * The active scenario details. Or <code>null</code> if there is
145 * no scenario.
2e1183f8 146 */
0b563c20 147 private void setPatternSegmentContent(ITmfEvent event, ITmfTimestamp start, ITmfTimestamp end, Map<String, ITmfStateValue> fields, @Nullable TmfXmlScenarioInfo scenarioInfo) {
2e1183f8 148 for (TmfXmlPatternSegmentField field : fFields) {
0b563c20 149 fields.put(field.getName(), field.getValue(event, scenarioInfo));
2e1183f8 150 }
3a5f73a1
JCK
151 if (scenarioInfo != null) {
152 addStoredFieldsContent(event, fields, scenarioInfo);
153 }
154 }
155
156 /**
157 * Query the stored fields path and add them to the content of the pattern
158 * segment. This is specific to pattern analysis.
159 *
160 * @param event
161 * The active event
162 * @param fields
163 * The segment fields
164 * @param info
165 * The active scenario details
166 */
167 protected void addStoredFieldsContent(ITmfEvent event, Map<String, ITmfStateValue> fields, final TmfXmlScenarioInfo info) {
168 if (fContainer instanceof XmlPatternStateProvider) {
169 for (Entry<String, String> entry : ((XmlPatternStateProvider) fContainer).getStoredFields().entrySet()) {
170 ITmfStateValue value = ((XmlPatternStateProvider) fContainer).getHistoryBuilder().getStoredFieldValue(fContainer, entry.getValue(), info, event);
171 if (!value.isNull()) {
172 fields.put(entry.getValue(), value);
173 }
174 }
175 }
2e1183f8
JCK
176 }
177
178 private static ITmfStateValue getStateValueFromConstant(String constantValue, String type) {
179 switch (type) {
180 case TmfXmlStrings.TYPE_INT:
181 return TmfStateValue.newValueInt(Integer.parseInt(constantValue));
182 case TmfXmlStrings.TYPE_LONG:
183 return TmfStateValue.newValueLong(Long.parseLong(constantValue));
184 case TmfXmlStrings.TYPE_STRING:
185 return TmfStateValue.newValueString(constantValue);
186 case TmfXmlStrings.TYPE_NULL:
187 return TmfStateValue.nullValue();
188 default:
189 throw new IllegalArgumentException("Invalid type of field : " + type); //$NON-NLS-1$
190 }
191 }
192
0b563c20 193 private static void getNameFromXmlStateValue(ITmfEvent event, StringBuilder builder, ITmfXmlStateValue xmlStateValue, @Nullable TmfXmlScenarioInfo scenarioInfo) {
2e1183f8 194 try {
0b563c20 195 ITmfStateValue value = xmlStateValue.getValue(event, scenarioInfo);
2e1183f8
JCK
196 switch (value.getType()) {
197 case DOUBLE:
198 builder.append(value.unboxDouble());
199 break;
200 case INTEGER:
201 builder.append(value.unboxInt());
202 break;
203 case LONG:
204 builder.append(value.unboxLong());
205 break;
206 case NULL:
207 builder.append(UNKNOWN_STRING);
208 break;
209 case STRING:
210 builder.append(value.unboxStr());
211 break;
212 default:
213 throw new StateValueTypeException("Invalid type of state value"); //$NON-NLS-1$
214 }
215 } catch (AttributeNotFoundException e) {
216 Activator.logInfo("Impossible to get the state value", e); //$NON-NLS-1$
217 }
218 }
219
220 /**
221 * This class represents the segment fields described in the XML. The real
222 * value of the field will be set at runtime using the active event.
223 *
224 * @author Jean-Christian Kouame
225 *
226 */
227 private class TmfXmlPatternSegmentField {
228 private final String fName;
229 private final String fType;
230 private final @Nullable ITmfStateValue fStateValue;
231 private final @Nullable ITmfXmlStateValue fXmlStateValue;
232
233 /**
234 * Constructor
235 *
236 * @param element
237 * The pattern segment field node
238 */
239 public TmfXmlPatternSegmentField(Element element) {
240 // The name, the type and the value of each field could respectively
241 // be found from the attributes name, type and value. If the value
242 // attribute is not available, try to find it from the child state
243 // value.
244 fName = element.getAttribute(TmfXmlStrings.NAME);
245 fType = element.getAttribute(TmfXmlStrings.TYPE);
246 String constantValue = element.getAttribute(TmfXmlStrings.VALUE);
247 if (constantValue.isEmpty() && !fType.equals(TmfXmlStrings.TYPE_NULL)) {
248 fStateValue = null;
249 Element elementFieldStateValue = (Element) element.getElementsByTagName(TmfXmlStrings.STATE_VALUE).item(0);
250 if (elementFieldStateValue == null) {
251 throw new IllegalArgumentException("The value of the field " + fName + " is missing"); //$NON-NLS-1$ //$NON-NLS-2$
252 }
253 fXmlStateValue = fModelFactory.createStateValue(elementFieldStateValue, fContainer, new ArrayList<>());
254 } else {
255 fStateValue = getStateValueFromConstant(constantValue, fType);
256 fXmlStateValue = null;
257 }
258 }
259
260 /**
261 * Get the real value of the XML pattern segment field
262 *
263 * @param event
264 * The active event
265 * @return The state value representing the value of the XML pattern
266 * segment field
0b563c20
JCK
267 * @param scenarioInfo
268 * The active scenario details. Or <code>null</code> if there
269 * is no scenario.
2e1183f8 270 */
0b563c20 271 public ITmfStateValue getValue(ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) {
2e1183f8
JCK
272 if (fStateValue != null) {
273 return fStateValue;
274 }
275 try {
0b563c20 276 return checkNotNull(fXmlStateValue).getValue(event, scenarioInfo);
2e1183f8
JCK
277 } catch (AttributeNotFoundException e) {
278 Activator.logError("Failed to get the state value", e); //$NON-NLS-1$
279 }
280 throw new IllegalStateException("Failed to get the value for the segment field " + fName); //$NON-NLS-1$
281 }
282
283 /**
284 * Get the name of the XML pattern segment field
285 *
286 * @return The name
287 */
288 public String getName() {
289 return fName;
290 }
291 }
292
293 /**
294 * This class represents the segment type described in XML.
295 *
296 * @author Jean-Christian Kouame
297 *
298 */
299 private class TmfXmlPatternSegmentType {
300 private final String fSegmentNameAttribute;
301 private final @Nullable ITmfXmlStateValue fNameStateValue;
302
303 /**
304 * Constructor
305 *
306 * @param element
307 * The pattern segment type node
308 */
309 public TmfXmlPatternSegmentType(Element element) {
310 // Try to find the segment name from the name attribute. If
311 // attribute not available, try to find it from the child state value
312 fSegmentNameAttribute = element.getAttribute(TmfXmlStrings.SEGMENT_NAME);
313 if (!fSegmentNameAttribute.isEmpty()) {
314 fNameStateValue = null;
315 } else {
316 Element elementSegmentNameStateValue = (Element) element.getElementsByTagName(TmfXmlStrings.STATE_VALUE).item(0);
317 if (elementSegmentNameStateValue == null) {
318 throw new IllegalArgumentException("Failed to get the segment name. A state value is needed."); //$NON-NLS-1$
319 }
320 fNameStateValue = fModelFactory.createStateValue(elementSegmentNameStateValue, fContainer, new ArrayList<>());
321 }
322 }
323
324 /**
325 * Get the name of the segment
326 *
327 * @param event
328 * The active event
0b563c20
JCK
329 * @param scenarioInfo
330 * The active scenario details. Or <code>null</code> if there
331 * is no scenario.
2e1183f8
JCK
332 * @return The segment name
333 */
0b563c20 334 public String getName(ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) {
2e1183f8
JCK
335 StringBuilder name = new StringBuilder(PATTERN_SEGMENT_NAME_PREFIX);
336 if (fNameStateValue != null) {
0b563c20 337 getNameFromXmlStateValue(event, name, fNameStateValue, scenarioInfo);
2e1183f8
JCK
338 } else {
339 name.append(fSegmentNameAttribute);
340 }
341 return name.toString();
342 }
343 }
344}
This page took 0.039808 seconds and 5 git commands to generate.