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
.internal
.tmf
.analysis
.xml
.core
.pattern
.stateprovider
.XmlPatternStateProvider
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
25 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
26 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.segment
.TmfXmlPatternSegment
;
27 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
30 import org
.w3c
.dom
.Element
;
31 import org
.w3c
.dom
.NodeList
;
34 * This class defines a pattern segment builder. It will use the XML description
35 * of the pattern segment to generate it at runtime.
37 * @author Jean-Christian Kouame
41 public class TmfXmlPatternSegmentBuilder
{
46 public static final String UNKNOWN_STRING
= "unknown"; //$NON-NLS-1$
48 * Prefix for the pattern segment name
50 public static final String PATTERN_SEGMENT_NAME_PREFIX
= "seg_"; //$NON-NLS-1$
51 private final ITmfXmlModelFactory fModelFactory
;
52 private final IXmlStateSystemContainer fContainer
;
53 private final List
<TmfXmlPatternSegmentField
> fFields
= new ArrayList
<>();
54 private final TmfXmlPatternSegmentType fSegmentType
;
58 * The factory used to create XML model elements
60 * XML element of the pattern segment builder
62 * The state system container this pattern segment builder
65 public TmfXmlPatternSegmentBuilder(ITmfXmlModelFactory modelFactory
, Element node
, IXmlStateSystemContainer parent
) {
66 fModelFactory
= modelFactory
;
69 //Set the XML type of the segment
70 NodeList nodesSegmentType
= node
.getElementsByTagName(TmfXmlStrings
.SEGMENT_TYPE
);
71 Element element
= (Element
) nodesSegmentType
.item(0);
72 if (element
== null) {
73 throw new IllegalArgumentException();
75 fSegmentType
= new TmfXmlPatternSegmentType(element
);
77 //Set the XML content of the segment
78 NodeList nodesSegmentContent
= node
.getElementsByTagName(TmfXmlStrings
.SEGMENT_CONTENT
);
79 Element fContentElement
= (Element
) nodesSegmentContent
.item(0);
80 if (fContentElement
!= null) {
81 NodeList nodesSegmentField
= fContentElement
.getElementsByTagName(TmfXmlStrings
.SEGMENT_FIELD
);
82 for (int i
= 0; i
< nodesSegmentField
.getLength(); i
++) {
83 fFields
.add(new TmfXmlPatternSegmentField(checkNotNull((Element
) nodesSegmentField
.item(i
))));
89 * Generate a pattern segment
94 * Start time of the pattern segment to generate
96 * End time of the pattern segment to generate
97 * @return The pattern segment generated
99 public TmfXmlPatternSegment
generatePatternSegment(ITmfEvent event
, ITmfTimestamp start
, ITmfTimestamp end
) {
100 int scale
= event
.getTimestamp().getScale();
101 long startValue
= start
.toNanos();
102 long endValue
= end
.toNanos();
103 String segmentName
= getPatternSegmentName(event
);
104 Map
<String
, ITmfStateValue
> fields
= new HashMap
<>();
105 setPatternSegmentContent(event
, start
, end
, fields
);
106 TmfXmlPatternSegment segment
= new TmfXmlPatternSegment(startValue
, endValue
, scale
, segmentName
, fields
);
107 if (fContainer
instanceof XmlPatternStateProvider
) {
108 ((XmlPatternStateProvider
) fContainer
).getListener().onNewSegment(segment
);
114 * Get the pattern segment name
118 * @return The name of the segment
120 private String
getPatternSegmentName(ITmfEvent event
) {
121 return fSegmentType
.getName(event
);
125 * Compute all the fields and their values for this pattern segment. The
126 * fields could be constant values or values queried from the state system.
131 * The start timestamp of this segment
133 * The end timestamp of this segment
135 * The map that will contained all the fields
137 private void setPatternSegmentContent(ITmfEvent event
, ITmfTimestamp start
, ITmfTimestamp end
, Map
<String
, ITmfStateValue
> fields
) {
138 for (TmfXmlPatternSegmentField field
: fFields
) {
139 fields
.put(field
.getName(), field
.getValue(event
));
143 private static ITmfStateValue
getStateValueFromConstant(String constantValue
, String type
) {
145 case TmfXmlStrings
.TYPE_INT
:
146 return TmfStateValue
.newValueInt(Integer
.parseInt(constantValue
));
147 case TmfXmlStrings
.TYPE_LONG
:
148 return TmfStateValue
.newValueLong(Long
.parseLong(constantValue
));
149 case TmfXmlStrings
.TYPE_STRING
:
150 return TmfStateValue
.newValueString(constantValue
);
151 case TmfXmlStrings
.TYPE_NULL
:
152 return TmfStateValue
.nullValue();
154 throw new IllegalArgumentException("Invalid type of field : " + type
); //$NON-NLS-1$
158 private static void getNameFromXmlStateValue(ITmfEvent event
, StringBuilder builder
, ITmfXmlStateValue xmlStateValue
) {
160 ITmfStateValue value
= xmlStateValue
.getValue(event
);
161 switch (value
.getType()) {
163 builder
.append(value
.unboxDouble());
166 builder
.append(value
.unboxInt());
169 builder
.append(value
.unboxLong());
172 builder
.append(UNKNOWN_STRING
);
175 builder
.append(value
.unboxStr());
178 throw new StateValueTypeException("Invalid type of state value"); //$NON-NLS-1$
180 } catch (AttributeNotFoundException e
) {
181 Activator
.logInfo("Impossible to get the state value", e
); //$NON-NLS-1$
186 * This class represents the segment fields described in the XML. The real
187 * value of the field will be set at runtime using the active event.
189 * @author Jean-Christian Kouame
192 private class TmfXmlPatternSegmentField
{
193 private final String fName
;
194 private final String fType
;
195 private final @Nullable ITmfStateValue fStateValue
;
196 private final @Nullable ITmfXmlStateValue fXmlStateValue
;
202 * The pattern segment field node
204 public TmfXmlPatternSegmentField(Element element
) {
205 // The name, the type and the value of each field could respectively
206 // be found from the attributes name, type and value. If the value
207 // attribute is not available, try to find it from the child state
209 fName
= element
.getAttribute(TmfXmlStrings
.NAME
);
210 fType
= element
.getAttribute(TmfXmlStrings
.TYPE
);
211 String constantValue
= element
.getAttribute(TmfXmlStrings
.VALUE
);
212 if (constantValue
.isEmpty() && !fType
.equals(TmfXmlStrings
.TYPE_NULL
)) {
214 Element elementFieldStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
215 if (elementFieldStateValue
== null) {
216 throw new IllegalArgumentException("The value of the field " + fName
+ " is missing"); //$NON-NLS-1$ //$NON-NLS-2$
218 fXmlStateValue
= fModelFactory
.createStateValue(elementFieldStateValue
, fContainer
, new ArrayList
<>());
220 fStateValue
= getStateValueFromConstant(constantValue
, fType
);
221 fXmlStateValue
= null;
226 * Get the real value of the XML pattern segment field
230 * @return The state value representing the value of the XML pattern
233 public ITmfStateValue
getValue(ITmfEvent event
) {
234 if (fStateValue
!= null) {
238 return checkNotNull(fXmlStateValue
).getValue(event
);
239 } catch (AttributeNotFoundException e
) {
240 Activator
.logError("Failed to get the state value", e
); //$NON-NLS-1$
242 throw new IllegalStateException("Failed to get the value for the segment field " + fName
); //$NON-NLS-1$
246 * Get the name of the XML pattern segment field
250 public String
getName() {
256 * This class represents the segment type described in XML.
258 * @author Jean-Christian Kouame
261 private class TmfXmlPatternSegmentType
{
262 private final String fSegmentNameAttribute
;
263 private final @Nullable ITmfXmlStateValue fNameStateValue
;
269 * The pattern segment type node
271 public TmfXmlPatternSegmentType(Element element
) {
272 // Try to find the segment name from the name attribute. If
273 // attribute not available, try to find it from the child state value
274 fSegmentNameAttribute
= element
.getAttribute(TmfXmlStrings
.SEGMENT_NAME
);
275 if (!fSegmentNameAttribute
.isEmpty()) {
276 fNameStateValue
= null;
278 Element elementSegmentNameStateValue
= (Element
) element
.getElementsByTagName(TmfXmlStrings
.STATE_VALUE
).item(0);
279 if (elementSegmentNameStateValue
== null) {
280 throw new IllegalArgumentException("Failed to get the segment name. A state value is needed."); //$NON-NLS-1$
282 fNameStateValue
= fModelFactory
.createStateValue(elementSegmentNameStateValue
, fContainer
, new ArrayList
<>());
287 * Get the name of the segment
291 * @return The segment name
293 public String
getName(ITmfEvent event
) {
294 StringBuilder name
= new StringBuilder(PATTERN_SEGMENT_NAME_PREFIX
);
295 if (fNameStateValue
!= null) {
296 getNameFromXmlStateValue(event
, name
, fNameStateValue
);
298 name
.append(fSegmentNameAttribute
);
300 return name
.toString();