Commit | Line | Data |
---|---|---|
3a5f73a1 JCK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 Ecole Polytechnique de Montreal, 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.tmf.analysis.xml.core.model; | |
10 | ||
11 | import java.util.List; | |
12 | ||
13 | import org.eclipse.jdt.annotation.Nullable; | |
14 | import org.eclipse.tracecompass.common.core.NonNullUtils; | |
15 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator; | |
16 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternStateProvider; | |
17 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; | |
18 | import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer; | |
19 | import org.eclipse.tracecompass.tmf.analysis.xml.core.module.XmlUtils; | |
20 | import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; | |
21 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; | |
22 | import org.w3c.dom.Element; | |
23 | ||
24 | /** | |
25 | * This Class implements a timestamp condition tree in the XML-defined state | |
26 | * system. | |
27 | * | |
28 | * @author Jean-Christian Kouame | |
29 | * @since 2.0 | |
30 | */ | |
31 | public class TmfXmlTimestampCondition implements ITmfXmlCondition { | |
32 | ||
33 | private enum TimeRangeOperator { | |
34 | IN, | |
35 | OUT, | |
36 | OTHER | |
37 | } | |
38 | ||
39 | private enum ElapsedTimeOperator { | |
40 | LESS, | |
41 | EQUAL, | |
42 | MORE, | |
43 | NONE | |
44 | } | |
45 | ||
46 | private static final long US = 1000l; | |
47 | private final IXmlTimestampsCondition fTimestampsCondition; | |
48 | private final IXmlStateSystemContainer fParent; | |
49 | ||
50 | /** | |
51 | * Constructor | |
52 | * | |
53 | * @param modelFactory | |
54 | * The factory used to create XML model elements | |
55 | * @param node | |
56 | * The XML root of this timestamp condition | |
57 | * @param container | |
58 | * The state system container this timestamp condition belongs to | |
59 | */ | |
60 | public TmfXmlTimestampCondition(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container) { | |
61 | fParent = container; | |
62 | String type = node.getNodeName(); | |
63 | switch (type) { | |
64 | case TmfXmlStrings.TIME_RANGE: | |
65 | fTimestampsCondition = new TmfXmlTimeRangeCondition(modelFactory, node, fParent); | |
66 | break; | |
67 | case TmfXmlStrings.ELAPSED_TIME: | |
68 | fTimestampsCondition = new TmfXmlElapsedTimeCondition(modelFactory, node, fParent); | |
69 | break; | |
70 | default: | |
71 | throw new IllegalArgumentException("Invalid timestampsChecker declaration in XML : Type should be timeRange or elapsedTime"); //$NON-NLS-1$ | |
72 | } | |
73 | } | |
74 | ||
75 | /** | |
76 | * Normalize the value into a nanosecond time value | |
77 | * | |
78 | * @param timestamp | |
79 | * The timestamp value | |
80 | * @param unit | |
81 | * The initial unit of the timestamp | |
82 | * @return The value of the timestamp in nanoseconds | |
83 | */ | |
84 | public static long valueToNanoseconds(long timestamp, String unit) { | |
85 | switch (unit) { | |
86 | case TmfXmlStrings.NS: | |
87 | return timestamp; | |
88 | case TmfXmlStrings.US: | |
89 | return timestamp * US; | |
90 | case TmfXmlStrings.MS: | |
91 | return timestamp * US * US; | |
92 | case TmfXmlStrings.S: | |
93 | return timestamp * US * US * US; | |
94 | default: | |
95 | throw new IllegalArgumentException("The time unit is not yet supporting."); //$NON-NLS-1$ | |
96 | } | |
97 | } | |
98 | ||
99 | /** | |
100 | * Validate the event | |
101 | * | |
102 | * @param event | |
103 | * The current event | |
104 | * @param scenarioInfo | |
105 | * The active scenario details. The value should be null if there | |
106 | * is no scenario | |
107 | * @return True if the test succeed, false otherwise | |
108 | */ | |
109 | @Override | |
110 | public boolean test(ITmfEvent event,@Nullable TmfXmlScenarioInfo scenarioInfo) { | |
111 | return fTimestampsCondition.test(event, scenarioInfo); | |
112 | } | |
113 | ||
114 | private interface IXmlTimestampsCondition extends ITmfXmlCondition { | |
115 | } | |
116 | ||
117 | private class TmfXmlTimeRangeCondition implements IXmlTimestampsCondition { | |
118 | ||
119 | private final TimeRangeOperator fType; | |
120 | private final String fUnit; | |
121 | private final String fBegin; | |
122 | private final String fEnd; | |
123 | private final IXmlStateSystemContainer fContainer; | |
124 | ||
125 | /** | |
126 | * Constructor | |
127 | * | |
128 | * @param modelFactory | |
129 | * The factory used to create XML model elements | |
130 | * @param node | |
131 | * The XML root of this time range condition transition | |
132 | * @param container | |
133 | * The state system container this time range condition | |
134 | * belongs to | |
135 | */ | |
136 | public TmfXmlTimeRangeCondition(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container) { | |
137 | fContainer = container; | |
138 | String unit = node.getAttribute(TmfXmlStrings.UNIT); | |
139 | fUnit = unit; | |
140 | List<@Nullable Element> childElements = NonNullUtils.checkNotNull(XmlUtils.getChildElements(node)); | |
141 | if (childElements.size() != 1) { | |
142 | throw new IllegalArgumentException("Invalid timestampsChecker declaration in XML : Only one timing condition is allowed"); //$NON-NLS-1$ | |
143 | } | |
144 | final Element firstElement = NonNullUtils.checkNotNull(childElements.get(0)); | |
145 | String type = firstElement.getNodeName(); | |
146 | switch (type) { | |
147 | case TmfXmlStrings.IN: | |
148 | fType = TimeRangeOperator.IN; | |
149 | break; | |
150 | case TmfXmlStrings.OUT: | |
151 | fType = TimeRangeOperator.OUT; | |
152 | break; | |
153 | default: | |
154 | fType = TimeRangeOperator.OTHER; | |
155 | break; | |
156 | } | |
157 | ||
158 | final String begin = firstElement.getAttribute(TmfXmlStrings.BEGIN); | |
159 | final String end = firstElement.getAttribute(TmfXmlStrings.END); | |
160 | fBegin = begin; | |
161 | fEnd = end; | |
162 | } | |
163 | ||
164 | @Override | |
165 | public boolean test(ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) { | |
166 | ITmfStateSystem ss = fContainer.getStateSystem(); | |
167 | ||
168 | long begin; | |
169 | begin = valueToNanoseconds(Long.parseLong(fBegin), fUnit); | |
170 | ||
171 | long end; | |
172 | end = valueToNanoseconds(Long.parseLong(fEnd), fUnit); | |
173 | ||
174 | // swap the value if begin > end | |
175 | if (begin > end) { | |
176 | begin = begin ^ end; | |
177 | end = begin ^ end; | |
178 | begin = begin ^ end; | |
179 | } | |
180 | ||
181 | begin = Math.max(ss.getStartTime(), begin); | |
182 | end = Math.min(ss.getCurrentEndTime(), end); | |
183 | begin = Math.min(begin, end); | |
184 | ||
185 | long ts = event.getTimestamp().toNanos(); | |
186 | switch (fType) { | |
187 | case IN: | |
188 | return intersects(begin, end, ts); | |
189 | case OUT: | |
190 | return !intersects(begin, end, ts); | |
191 | case OTHER: | |
192 | default: | |
193 | return false; | |
194 | } | |
195 | } | |
196 | ||
197 | private boolean intersects(long begin, long end, long ts) { | |
198 | return ts >= begin && ts <= end; | |
199 | } | |
200 | ||
201 | } | |
202 | ||
203 | private class TmfXmlElapsedTimeCondition implements IXmlTimestampsCondition { | |
204 | ||
205 | private final IXmlStateSystemContainer fContainer; | |
206 | private final ElapsedTimeOperator fType; | |
207 | private final String fUnit; | |
208 | private final String fValue; | |
209 | private final String fReferenceState; | |
210 | ||
211 | /** | |
212 | * Constructor | |
213 | * | |
214 | * @param modelFactory | |
215 | * The factory used to create XML model elements | |
216 | * @param node | |
217 | * The XML root of this elapsed time condition | |
218 | * @param container | |
219 | * The state system container this elapsed time condition | |
220 | * belongs to | |
221 | */ | |
222 | public TmfXmlElapsedTimeCondition(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container) { | |
223 | fContainer = container; | |
224 | String unit = node.getAttribute(TmfXmlStrings.UNIT); | |
225 | fUnit = unit; | |
226 | List<@Nullable Element> childElements = XmlUtils.getChildElements(node); | |
227 | if (childElements.size() != 1) { | |
228 | throw new IllegalArgumentException("Invalid timestampsChecker declaration in XML : Only one timing condition is allowed"); //$NON-NLS-1$ | |
229 | } | |
230 | final Element firstElement = NonNullUtils.checkNotNull(childElements.get(0)); | |
231 | String type = firstElement.getNodeName(); | |
232 | switch (type) { | |
233 | case TmfXmlStrings.LESS: | |
234 | fType = ElapsedTimeOperator.LESS; | |
235 | break; | |
236 | case TmfXmlStrings.EQUAL: | |
237 | fType = ElapsedTimeOperator.EQUAL; | |
238 | break; | |
239 | case TmfXmlStrings.MORE: | |
240 | fType = ElapsedTimeOperator.MORE; | |
241 | break; | |
242 | default: | |
243 | fType = ElapsedTimeOperator.NONE; | |
244 | break; | |
245 | } | |
246 | final String reference = firstElement.getAttribute(TmfXmlStrings.SINCE); | |
247 | final String value = firstElement.getAttribute(TmfXmlStrings.VALUE); | |
248 | fReferenceState = reference; | |
249 | fValue = value; | |
250 | } | |
251 | ||
252 | @Override | |
253 | public boolean test(ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) { | |
254 | if (scenarioInfo == null) { | |
255 | Activator.logError("Elapse time conditions require scenarioInfos and scenarioInfos is null"); //$NON-NLS-1$ | |
256 | return false; | |
257 | } | |
258 | boolean success; | |
259 | long ts = event.getTimestamp().toNanos(); | |
260 | long referenceTimestamps = ((XmlPatternStateProvider) fContainer).getHistoryBuilder().getSpecificStateStartTime(fContainer, fReferenceState, scenarioInfo, event); | |
261 | if (ts < referenceTimestamps) { | |
262 | throw new IllegalArgumentException("Timestamp is inferior to reference time"); //$NON-NLS-1$ | |
263 | } | |
264 | switch (fType) { | |
265 | case LESS: | |
266 | success = (ts - referenceTimestamps) < valueToNanoseconds(Long.parseLong(fValue), fUnit); | |
267 | break; | |
268 | case EQUAL: | |
269 | success = (ts - referenceTimestamps) == valueToNanoseconds(Long.parseLong(fValue), fUnit); | |
270 | break; | |
271 | case MORE: | |
272 | success = (ts - referenceTimestamps) > valueToNanoseconds(Long.parseLong(fValue), fUnit); | |
273 | break; | |
274 | case NONE: | |
275 | default: | |
276 | success = false; | |
277 | break; | |
278 | } | |
279 | return success; | |
280 | } | |
281 | ||
282 | } | |
283 | } |