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
.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
;
18 import org
.eclipse
.jdt
.annotation
.Nullable
;
19 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.Activator
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
24 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
25 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.segment
.TmfXmlPatternSegment
;
26 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
29 import org
.w3c
.dom
.Element
;
30 import org
.w3c
.dom
.NodeList
;
33 * This class defines a pattern segment builder. It will use the XML description
34 * of the pattern segment to generate it at runtime.
36 * @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
96 * @return The pattern segment generated
98 public TmfXmlPatternSegment
generatePatternSegment(ITmfEvent event
, ITmfTimestamp start
, ITmfTimestamp end
) {
99 int scale
= event
.getTimestamp().getScale();
100 long startValue
= start
.normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
101 long endValue
= end
.normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
102 String segmentName
= getPatternSegmentName(event
);
103 Map
<String
, ITmfStateValue
> fields
= new HashMap
<>();
104 setPatternSegmentContent(event
, start
, end
, fields
);
105 return new TmfXmlPatternSegment(startValue
, endValue
, scale
, segmentName
, fields
);
109 * Get the pattern segment name
113 * @return The name of the segment
115 private String
getPatternSegmentName(ITmfEvent event
) {
116 return fSegmentType
.getName(event
);
120 * Compute all the fields and their values for this pattern segment. The
121 * fields could be constant values or values queried from the state system.
126 * The start timestamp of this segment
128 * The end timestamp of this segment
130 * The map that will contained all the fields
132 private void setPatternSegmentContent(ITmfEvent event
, ITmfTimestamp start
, ITmfTimestamp end
, Map
<String
, ITmfStateValue
> fields
) {
133 for (TmfXmlPatternSegmentField field
: fFields
) {
134 fields
.put(field
.getName(), field
.getValue(event
));
138 private static ITmfStateValue
getStateValueFromConstant(String constantValue
, String type
) {
140 case TmfXmlStrings
.TYPE_INT
:
141 return TmfStateValue
.newValueInt(Integer
.parseInt(constantValue
));
142 case TmfXmlStrings
.TYPE_LONG
:
143 return TmfStateValue
.newValueLong(Long
.parseLong(constantValue
));
144 case TmfXmlStrings
.TYPE_STRING
:
145 return TmfStateValue
.newValueString(constantValue
);
146 case TmfXmlStrings
.TYPE_NULL
:
147 return TmfStateValue
.nullValue();
149 throw new IllegalArgumentException("Invalid type of field : " + type
); //$NON-NLS-1$
153 private static void getNameFromXmlStateValue(ITmfEvent event
, StringBuilder builder
, ITmfXmlStateValue xmlStateValue
) {
155 ITmfStateValue value
= xmlStateValue
.getValue(event
);
156 switch (value
.getType()) {
158 builder
.append(value
.unboxDouble());
161 builder
.append(value
.unboxInt());
164 builder
.append(value
.unboxLong());
167 builder
.append(UNKNOWN_STRING
);
170 builder
.append(value
.unboxStr());
173 throw new StateValueTypeException("Invalid type of state value"); //$NON-NLS-1$
175 } catch (AttributeNotFoundException e
) {
176 Activator
.logInfo("Impossible to get the state value", e
); //$NON-NLS-1$
181 * This class represents the segment fields described in the XML. The real
182 * value of the field will be set at runtime using the active event.
184 * @author Jean-Christian Kouame
187 private class TmfXmlPatternSegmentField
{
188 private final String fName
;
189 private final String fType
;
190 private final @Nullable ITmfStateValue fStateValue
;
191 private final @Nullable ITmfXmlStateValue fXmlStateValue
;
197 * The pattern segment field node
199 public TmfXmlPatternSegmentField(Element element
) {
200 // The name, the type and the value of each field could respectively
201 // be found from the attributes name, type and value. If the value
202 // attribute is not available, try to find it from the child state
204 fName
= element
.getAttribute(TmfXmlStrings
.NAME
);
205 fType
= element
.getAttribute(TmfXmlStrings
.TYPE
);
206 String constantValue
= element
.getAttribute(TmfXmlStrings
.VALUE
);
207 if (constantValue
.isEmpty() && !fType
.equals(TmfXmlStrings
.TYPE_NULL
)) {
209 Element elementFieldStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
210 if (elementFieldStateValue
== null) {
211 throw new IllegalArgumentException("The value of the field " + fName
+ " is missing"); //$NON-NLS-1$ //$NON-NLS-2$
213 fXmlStateValue
= fModelFactory
.createStateValue(elementFieldStateValue
, fContainer
, new ArrayList
<>());
215 fStateValue
= getStateValueFromConstant(constantValue
, fType
);
216 fXmlStateValue
= null;
221 * Get the real value of the XML pattern segment field
225 * @return The state value representing the value of the XML pattern
228 public ITmfStateValue
getValue(ITmfEvent event
) {
229 if (fStateValue
!= null) {
233 return checkNotNull(fXmlStateValue
).getValue(event
);
234 } catch (AttributeNotFoundException e
) {
235 Activator
.logError("Failed to get the state value", e
); //$NON-NLS-1$
237 throw new IllegalStateException("Failed to get the value for the segment field " + fName
); //$NON-NLS-1$
241 * Get the name of the XML pattern segment field
245 public String
getName() {
251 * This class represents the segment type described in XML.
253 * @author Jean-Christian Kouame
256 private class TmfXmlPatternSegmentType
{
257 private final String fSegmentNameAttribute
;
258 private final @Nullable ITmfXmlStateValue fNameStateValue
;
264 * The pattern segment type node
266 public TmfXmlPatternSegmentType(Element element
) {
267 // Try to find the segment name from the name attribute. If
268 // attribute not available, try to find it from the child state value
269 fSegmentNameAttribute
= element
.getAttribute(TmfXmlStrings
.SEGMENT_NAME
);
270 if (!fSegmentNameAttribute
.isEmpty()) {
271 fNameStateValue
= null;
273 Element elementSegmentNameStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
274 if (elementSegmentNameStateValue
== null) {
275 throw new IllegalArgumentException("Failed to get the segment name. A state value is needed."); //$NON-NLS-1$
277 fNameStateValue
= fModelFactory
.createStateValue(elementSegmentNameStateValue
, fContainer
, new ArrayList
<>());
282 * Get the name of the segment
286 * @return The segment name
288 public String
getName(ITmfEvent event
) {
289 StringBuilder name
= new StringBuilder(PATTERN_SEGMENT_NAME_PREFIX
);
290 if (fNameStateValue
!= null) {
291 getNameFromXmlStateValue(event
, name
, fNameStateValue
);
293 name
.append(fSegmentNameAttribute
);
295 return name
.toString();