42f40755892d9ca883275ef50fbbba90b9ac0e8a
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / tmf / analysis / xml / core / model / readwrite / TmfXmlReadWriteStateValue.java
1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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 * Contributors:
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.analysis.xml.core.model.readwrite;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
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.ITmfStateSystem;
21 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
22 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
23 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
24 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
25 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
26 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
27 import org.eclipse.tracecompass.tmf.analysis.xml.core.model.ITmfXmlModelFactory;
28 import org.eclipse.tracecompass.tmf.analysis.xml.core.model.ITmfXmlStateAttribute;
29 import org.eclipse.tracecompass.tmf.analysis.xml.core.model.TmfXmlStateValue;
30 import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
31 import org.eclipse.tracecompass.tmf.analysis.xml.core.module.XmlUtils;
32 import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
33 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
34 import org.w3c.dom.Element;
35
36 /**
37 * Implements a state value in a read write mode. See {@link TmfXmlStateValue}
38 * for the syntax of the state value.
39 *
40 * In read/write mode, a state value can be considered as an assignation where
41 * the state value is assigned to the quark represented by the state attributes
42 *
43 * @author Geneviève Bastien
44 */
45 public class TmfXmlReadWriteStateValue extends TmfXmlStateValue {
46
47 private static final String ILLEGAL_STATE_EXCEPTION_MESSAGE = "The state system hasn't been initialized yet"; //$NON-NLS-1$
48
49 /**
50 * Constructor where the path to the value is a list of state attributes
51 *
52 * @param modelFactory
53 * The factory used to create XML model elements
54 * @param node
55 * The state value XML element
56 * @param container
57 * The state system container this state value belongs to
58 * @param attributes
59 * The attributes representing the path to this value
60 */
61 public TmfXmlReadWriteStateValue(TmfXmlReadWriteModelFactory modelFactory, Element node, IXmlStateSystemContainer container, List<ITmfXmlStateAttribute> attributes) {
62 this(modelFactory, node, container, attributes, null);
63 }
64
65 /**
66 * Constructor where the path to the value is an event field
67 *
68 * @param modelFactory
69 * The factory used to create XML model elements
70 * @param node
71 * The state value XML element
72 * @param container
73 * The state system container this state value belongs to
74 * @param eventField
75 * The event field where to get the value
76 */
77 public TmfXmlReadWriteStateValue(TmfXmlReadWriteModelFactory modelFactory, Element node, IXmlStateSystemContainer container, String eventField) {
78 this(modelFactory, node, container, new ArrayList<ITmfXmlStateAttribute>(), eventField);
79 }
80
81 private TmfXmlReadWriteStateValue(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container, List<ITmfXmlStateAttribute> attributes, @Nullable String eventField) {
82 super(modelFactory, node, container, attributes, eventField);
83 }
84
85 @Override
86 protected @Nullable ITmfStateSystemBuilder getStateSystem() {
87 return (ITmfStateSystemBuilder) super.getStateSystem();
88 }
89
90 @Override
91 protected TmfXmlStateValueBase initializeStateValue(ITmfXmlModelFactory modelFactory, Element node) {
92 TmfXmlStateValueBase stateValueType = null;
93 /* Process the XML Element state value */
94 String type = node.getAttribute(TmfXmlStrings.TYPE);
95 String value = getSsContainer().getAttributeValue(node.getAttribute(TmfXmlStrings.VALUE));
96 if (value == null) {
97 throw new IllegalStateException();
98 }
99
100 switch (type) {
101 case TmfXmlStrings.TYPE_INT: {
102 /* Integer value */
103 ITmfStateValue stateValue = TmfStateValue.newValueInt(Integer.parseInt(value));
104 stateValueType = new TmfXmlStateValueTmf(stateValue);
105 break;
106 }
107 case TmfXmlStrings.TYPE_LONG: {
108 /* Long value */
109 ITmfStateValue stateValue = TmfStateValue.newValueLong(Long.parseLong(value));
110 stateValueType = new TmfXmlStateValueTmf(stateValue);
111 break;
112 }
113 case TmfXmlStrings.TYPE_STRING: {
114 /* String value */
115 ITmfStateValue stateValue = TmfStateValue.newValueString(value);
116 stateValueType = new TmfXmlStateValueTmf(stateValue);
117 break;
118 }
119 case TmfXmlStrings.TYPE_NULL: {
120 /* Null value */
121 ITmfStateValue stateValue = TmfStateValue.nullValue();
122 stateValueType = new TmfXmlStateValueTmf(stateValue);
123 break;
124 }
125 case TmfXmlStrings.EVENT_FIELD:
126 /* Event field */
127 stateValueType = new TmfXmlStateValueEventField(value);
128 break;
129 case TmfXmlStrings.TYPE_EVENT_NAME:
130 /* The value is the event name */
131 stateValueType = new TmfXmlStateValueEventName();
132 break;
133 case TmfXmlStrings.TYPE_DELETE:
134 /* Deletes the value of an attribute */
135 stateValueType = new TmfXmlStateValueDelete();
136 break;
137 case TmfXmlStrings.TYPE_QUERY:
138 /* Value is the result of a query */
139 List<@Nullable Element> children = XmlUtils.getChildElements(node);
140 List<ITmfXmlStateAttribute> childAttributes = new ArrayList<>();
141 for (Element child : children) {
142 if (child == null) {
143 continue;
144 }
145 ITmfXmlStateAttribute queryAttribute = modelFactory.createStateAttribute(child, getSsContainer());
146 childAttributes.add(queryAttribute);
147 }
148 stateValueType = new TmfXmlStateValueQuery(childAttributes);
149 break;
150 default:
151 throw new IllegalArgumentException(String.format("TmfXmlStateValue constructor: unexpected element %s for stateValue type", type)); //$NON-NLS-1$
152 }
153 return stateValueType;
154 }
155
156 // ----------------------------------------------------------
157 // Internal state value classes for the different types
158 // ----------------------------------------------------------
159
160 /**
161 * Base class for all state value. Contain default methods to handle event,
162 * process or increment the value
163 */
164 protected abstract class TmfXmlStateValueTypeReadWrite extends TmfXmlStateValueBase {
165
166 @Override
167 public final void handleEvent(ITmfEvent event, int quark, long timestamp) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
168 if (isIncrement()) {
169 incrementValue(event, quark, timestamp);
170 } else {
171 ITmfStateValue value = getValue(event);
172 processValue(quark, timestamp, value);
173 }
174 }
175
176 @Override
177 protected void processValue(int quark, long timestamp, ITmfStateValue value) throws AttributeNotFoundException, TimeRangeException, StateValueTypeException {
178 ITmfStateSystemBuilder ss = getStateSystem();
179 if (ss == null) {
180 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
181 }
182 switch (getStackType()) {
183 case POP:
184 ss.popAttribute(timestamp, quark);
185 break;
186 case PUSH:
187 ss.pushAttribute(timestamp, value, quark);
188 break;
189 case NULL:
190 case PEEK:
191 default:
192 ss.modifyAttribute(timestamp, value, quark);
193 break;
194 }
195 }
196
197 @Override
198 protected void incrementValue(ITmfEvent event, int quark, long timestamp) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
199 ITmfStateSystemBuilder ss = getStateSystem();
200 if (ss == null) {
201 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
202 }
203 ss.incrementAttribute(timestamp, quark);
204 }
205 }
206
207 private static @Nullable ITmfStateValue incrementByType(int quark, ITmfStateSystem ss, ITmfStateValue stateValue) throws AttributeNotFoundException {
208 ITmfStateValue value = null;
209 switch (stateValue.getType()) {
210 case LONG: {
211 long incrementLong = stateValue.unboxLong();
212 ITmfStateValue currentState = ss.queryOngoingState(quark);
213 long currentValue = (currentState.isNull() ? 0 : currentState.unboxLong());
214 value = TmfStateValue.newValueLong(incrementLong + currentValue);
215 return value;
216 }
217 case INTEGER: {
218 int increment = stateValue.unboxInt();
219 ITmfStateValue currentState = ss.queryOngoingState(quark);
220 int currentValue = (currentState.isNull() ? 0 : currentState.unboxInt());
221 value = TmfStateValue.newValueInt(increment + currentValue);
222 return value;
223 }
224 case DOUBLE:
225 case NULL:
226 case STRING:
227 default:
228 }
229 return value;
230 }
231
232 /* This state value uses a constant value, defined in the XML */
233 private class TmfXmlStateValueTmf extends TmfXmlStateValueTypeReadWrite {
234
235 private final ITmfStateValue fValue;
236
237 public TmfXmlStateValueTmf(ITmfStateValue value) {
238 fValue = value;
239 }
240
241 @Override
242 public ITmfStateValue getValue(@Nullable ITmfEvent event) {
243 return fValue;
244 }
245
246 @Override
247 public void incrementValue(ITmfEvent event, int quark, long timestamp) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
248 ITmfStateSystem ss = getStateSystem();
249 if (ss == null) {
250 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
251 }
252 ITmfStateValue value = incrementByType(quark, ss, fValue);
253 if (value != null) {
254 processValue(quark, timestamp, value);
255 } else {
256 Activator.logWarning("TmfXmlStateValue: The increment value is not a number type"); //$NON-NLS-1$
257 }
258 }
259
260 }
261
262 /* The state value uses the value of an event field */
263 private class TmfXmlStateValueEventField extends TmfXmlStateValueTypeReadWrite {
264
265 private final String fFieldName;
266
267 public TmfXmlStateValueEventField(String field) {
268 fFieldName = field;
269 }
270
271 @Override
272 public ITmfStateValue getValue(@Nullable ITmfEvent event) {
273 if (event == null) {
274 Activator.logWarning("XML State value: requested an event field, but event is null"); //$NON-NLS-1$
275 return TmfStateValue.nullValue();
276 }
277 return getEventFieldValue(event, fFieldName);
278 }
279
280 @Override
281 public void incrementValue(ITmfEvent event, int quark, long timestamp) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
282 ITmfStateSystem ss = getSsContainer().getStateSystem();
283 if (ss == null) {
284 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
285 }
286 ITmfStateValue incrementValue = getValue(event);
287 ITmfStateValue value = incrementByType(quark, ss, incrementValue);
288 if (value != null) {
289 processValue(quark, timestamp, value);
290 } else {
291 Activator.logWarning(String.format("TmfXmlStateValue: The event field increment %s is not a number type but a %s", fFieldName, incrementValue.getType())); //$NON-NLS-1$
292 }
293 }
294 }
295
296 /* The state value is the event name */
297 private class TmfXmlStateValueEventName extends TmfXmlStateValueTypeReadWrite {
298
299 @Override
300 public ITmfStateValue getValue(@Nullable ITmfEvent event) {
301 if (event == null) {
302 Activator.logWarning("XML State value: request event name, but event is null"); //$NON-NLS-1$
303 return TmfStateValue.nullValue();
304 }
305 return TmfStateValue.newValueString(event.getName());
306 }
307
308 }
309
310 /* The state value deletes an attribute */
311 private class TmfXmlStateValueDelete extends TmfXmlStateValueTypeReadWrite {
312
313 @Override
314 public ITmfStateValue getValue(@Nullable ITmfEvent event) throws AttributeNotFoundException {
315 return TmfStateValue.nullValue();
316 }
317
318 @Override
319 protected void processValue(int quark, long timestamp, ITmfStateValue value) throws TimeRangeException, AttributeNotFoundException {
320 ITmfStateSystem ss = getStateSystem();
321 if (!(ss instanceof ITmfStateSystemBuilder)) {
322 throw new IllegalStateException("incrementValue should never be called when not building the state system"); //$NON-NLS-1$
323 }
324 ITmfStateSystemBuilder builder = (ITmfStateSystemBuilder) ss;
325 builder.removeAttribute(timestamp, quark);
326 }
327
328 }
329
330 /* The state value uses the result of a query */
331 private class TmfXmlStateValueQuery extends TmfXmlStateValueTypeReadWrite {
332
333 private final List<ITmfXmlStateAttribute> fQueryValue;
334
335 public TmfXmlStateValueQuery(List<ITmfXmlStateAttribute> childAttributes) {
336 fQueryValue = childAttributes;
337 }
338
339 @Override
340 public ITmfStateValue getValue(@Nullable ITmfEvent event) throws AttributeNotFoundException {
341 /* Query the state system for the value */
342 ITmfStateValue value = TmfStateValue.nullValue();
343 int quarkQuery = IXmlStateSystemContainer.ROOT_QUARK;
344 ITmfStateSystem ss = getStateSystem();
345 if (ss == null) {
346 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
347 }
348
349 for (ITmfXmlStateAttribute attribute : fQueryValue) {
350 quarkQuery = attribute.getAttributeQuark(event, quarkQuery);
351 if (quarkQuery == IXmlStateSystemContainer.ERROR_QUARK) {
352 /* the query is not valid, we stop the state change */
353 break;
354 }
355 }
356 /*
357 * the query can fail : for example, if a value is requested but has
358 * not been set yet
359 */
360 if (quarkQuery != IXmlStateSystemContainer.ERROR_QUARK) {
361 value = ss.queryOngoingState(quarkQuery);
362 if (value == null) {
363 throw new IllegalStateException();
364 }
365 }
366 return value;
367 }
368
369 @Override
370 public void incrementValue(ITmfEvent event, int quark, long timestamp) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
371 ITmfStateSystem ss = getStateSystem();
372 if (ss == null) {
373 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
374 }
375
376 ITmfStateValue incrementValue = getValue(event);
377 ITmfStateValue value = incrementByType(quark, ss, incrementValue);
378 if (value != null) {
379 processValue(quark, timestamp, value);
380 } else {
381 Activator.logWarning("TmfXmlStateValue: The query result increment is not a number type"); //$NON-NLS-1$
382 }
383 }
384 }
385
386 }
This page took 0.049845 seconds and 4 git commands to generate.