tmf.xml: Move all .core and .ui packages to internal
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / internal / tmf / analysis / xml / core / model / TmfXmlPatternSegmentBuilder.java
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 ******************************************************************************/
9 package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model;
10
11 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18
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;
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 */
40 public class TmfXmlPatternSegmentBuilder {
41
42 /**
43 * The string unknown
44 */
45 public static final String UNKNOWN_STRING = "unknown"; //$NON-NLS-1$
46 /**
47 * Prefix for the pattern segment name
48 */
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;
54
55 /**
56 * @param modelFactory
57 * The factory used to create XML model elements
58 * @param node
59 * XML element of the pattern segment builder
60 * @param parent
61 * The state system container this pattern segment builder
62 * belongs to
63 */
64 public TmfXmlPatternSegmentBuilder(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer parent) {
65 fModelFactory = modelFactory;
66 fContainer = parent;
67
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();
73 }
74 fSegmentType = new TmfXmlPatternSegmentType(element);
75
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))));
83 }
84 }
85 }
86
87 /**
88 * Generate a pattern segment
89 *
90 * @param event
91 * The active event
92 * @param start
93 * Start time of the pattern segment to generate
94 * @param end
95 * End time of the pattern segment to generate
96 * @param scenarioInfo
97 * The active scenario details. Or <code>null</code> if there is
98 * no scenario.
99 * @return The pattern segment generated
100 */
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);
111 }
112 return segment;
113 }
114
115 /**
116 * Get the pattern segment name
117 *
118 * @param event
119 * The active event
120 * @param scenarioInfo
121 * The active scenario details. Or <code>null</code> if there is
122 * no scenario.
123 * @return The name of the segment
124 */
125 private String getPatternSegmentName(ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) {
126 return fSegmentType.getName(event, scenarioInfo);
127 }
128
129 /**
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.
132 *
133 * @param event
134 * The current event
135 * @param start
136 * The start timestamp of this segment
137 * @param end
138 * The end timestamp of this segment
139 * @param fields
140 * The map that will contained all the fields
141 * @param scenarioInfo
142 * The active scenario details. Or <code>null</code> if there is
143 * no scenario.
144 */
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));
148 }
149 if (scenarioInfo != null) {
150 addStoredFieldsContent(event, fields, scenarioInfo);
151 }
152 }
153
154 /**
155 * Query the stored fields path and add them to the content of the pattern
156 * segment. This is specific to pattern analysis.
157 *
158 * @param event
159 * The active event
160 * @param fields
161 * The segment fields
162 * @param info
163 * The active scenario details
164 */
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);
171 }
172 }
173 }
174 }
175
176 private static ITmfStateValue getStateValueFromConstant(String constantValue, String type) {
177 switch (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();
186 default:
187 throw new IllegalArgumentException("Invalid type of field : " + type); //$NON-NLS-1$
188 }
189 }
190
191 private static void getNameFromXmlStateValue(ITmfEvent event, StringBuilder builder, ITmfXmlStateValue xmlStateValue, @Nullable TmfXmlScenarioInfo scenarioInfo) {
192 try {
193 ITmfStateValue value = xmlStateValue.getValue(event, scenarioInfo);
194 switch (value.getType()) {
195 case DOUBLE:
196 builder.append(value.unboxDouble());
197 break;
198 case INTEGER:
199 builder.append(value.unboxInt());
200 break;
201 case LONG:
202 builder.append(value.unboxLong());
203 break;
204 case NULL:
205 builder.append(UNKNOWN_STRING);
206 break;
207 case STRING:
208 builder.append(value.unboxStr());
209 break;
210 default:
211 throw new StateValueTypeException("Invalid type of state value"); //$NON-NLS-1$
212 }
213 } catch (AttributeNotFoundException e) {
214 Activator.logInfo("Impossible to get the state value", e); //$NON-NLS-1$
215 }
216 }
217
218 /**
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.
221 *
222 * @author Jean-Christian Kouame
223 *
224 */
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;
230
231 /**
232 * Constructor
233 *
234 * @param element
235 * The pattern segment field node
236 */
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
241 // value.
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)) {
246 fStateValue = 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$
250 }
251 fXmlStateValue = fModelFactory.createStateValue(elementFieldStateValue, fContainer, new ArrayList<>());
252 } else {
253 fStateValue = getStateValueFromConstant(constantValue, fType);
254 fXmlStateValue = null;
255 }
256 }
257
258 /**
259 * Get the real value of the XML pattern segment field
260 *
261 * @param event
262 * The active event
263 * @return The state value representing the value of the XML pattern
264 * segment field
265 * @param scenarioInfo
266 * The active scenario details. Or <code>null</code> if there
267 * is no scenario.
268 */
269 public ITmfStateValue getValue(ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) {
270 if (fStateValue != null) {
271 return fStateValue;
272 }
273 try {
274 return checkNotNull(fXmlStateValue).getValue(event, scenarioInfo);
275 } catch (AttributeNotFoundException e) {
276 Activator.logError("Failed to get the state value", e); //$NON-NLS-1$
277 }
278 throw new IllegalStateException("Failed to get the value for the segment field " + fName); //$NON-NLS-1$
279 }
280
281 /**
282 * Get the name of the XML pattern segment field
283 *
284 * @return The name
285 */
286 public String getName() {
287 return fName;
288 }
289 }
290
291 /**
292 * This class represents the segment type described in XML.
293 *
294 * @author Jean-Christian Kouame
295 *
296 */
297 private class TmfXmlPatternSegmentType {
298 private final String fSegmentNameAttribute;
299 private final @Nullable ITmfXmlStateValue fNameStateValue;
300
301 /**
302 * Constructor
303 *
304 * @param element
305 * The pattern segment type node
306 */
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;
313 } else {
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$
317 }
318 fNameStateValue = fModelFactory.createStateValue(elementSegmentNameStateValue, fContainer, new ArrayList<>());
319 }
320 }
321
322 /**
323 * Get the name of the segment
324 *
325 * @param event
326 * The active event
327 * @param scenarioInfo
328 * The active scenario details. Or <code>null</code> if there
329 * is no scenario.
330 * @return The segment name
331 */
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);
336 } else {
337 name.append(fSegmentNameAttribute);
338 }
339 return name.toString().intern();
340 }
341 }
342 }
This page took 0.038516 seconds and 5 git commands to generate.