tmf: Split the state system in a separate plugin
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.analysis.xml.core / src / org / eclipse / linuxtools / tmf / analysis / xml / core / model / TmfXmlStateAttribute.java
1 /*******************************************************************************
2 * Copyright (c) 2014 Ecole Polytechnique de Montreal
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 * Florian Wininger - Initial API and implementation
11 ******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.analysis.xml.core.model;
14
15 import java.util.LinkedList;
16 import java.util.List;
17
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.eclipse.linuxtools.internal.tmf.analysis.xml.core.Activator;
20 import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
21 import org.eclipse.linuxtools.statesystem.core.ITmfStateSystemBuilder;
22 import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
23 import org.eclipse.linuxtools.statesystem.core.exceptions.StateValueTypeException;
24 import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue;
25 import org.eclipse.linuxtools.statesystem.core.statevalue.TmfStateValue;
26 import org.eclipse.linuxtools.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
27 import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils;
28 import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
29 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
30 import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
31 import org.w3c.dom.Element;
32
33 /**
34 * This Class implements a single attribute value in the XML-defined state
35 * system.
36 *
37 * <pre>
38 * Examples:
39 * <stateAttribute type="constant" value="Threads" />
40 * <stateAttribute type="query" />
41 * <stateAttribute type="constant" value="CPUs" />
42 * <stateAttribute type="eventField" value="cpu" />
43 * <stateAttribute type="constant" value="Current_thread" />
44 * </attribute>
45 * </pre>
46 *
47 * @author Florian Wininger
48 */
49 public abstract class TmfXmlStateAttribute implements ITmfXmlStateAttribute {
50
51 private enum StateAttributeType {
52 NONE,
53 CONSTANT,
54 EVENTFIELD,
55 QUERY,
56 LOCATION,
57 SELF
58 }
59
60 /** Type of attribute */
61 private final StateAttributeType fType;
62
63 /** Attribute's name */
64 private final String fName;
65
66 /** List of attributes for a query */
67 private final List<ITmfXmlStateAttribute> fQueryList = new LinkedList<>();
68
69 private final IXmlStateSystemContainer fContainer;
70
71 /**
72 * Constructor
73 *
74 * @param modelFactory
75 * The factory used to create XML model elements
76 * @param attribute
77 * XML element of the attribute
78 * @param container
79 * The state system container this state attribute belongs to
80 */
81 protected TmfXmlStateAttribute(ITmfXmlModelFactory modelFactory, Element attribute, IXmlStateSystemContainer container) {
82 fContainer = container;
83
84 switch (attribute.getAttribute(TmfXmlStrings.TYPE)) {
85 case TmfXmlStrings.TYPE_CONSTANT:
86 fType = StateAttributeType.CONSTANT;
87 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
88 break;
89 case TmfXmlStrings.EVENT_FIELD:
90 fType = StateAttributeType.EVENTFIELD;
91 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
92 break;
93 case TmfXmlStrings.TYPE_LOCATION:
94 fType = StateAttributeType.LOCATION;
95 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
96 break;
97 case TmfXmlStrings.TYPE_QUERY:
98 List<Element> childElements = XmlUtils.getChildElements(attribute);
99 for (Element subAttributeNode : childElements) {
100 ITmfXmlStateAttribute subAttribute = modelFactory.createStateAttribute(subAttributeNode, fContainer);
101 fQueryList.add(subAttribute);
102 }
103 fType = StateAttributeType.QUERY;
104 fName = null;
105 break;
106 case TmfXmlStrings.NULL:
107 fType = StateAttributeType.NONE;
108 fName = null;
109 break;
110 case TmfXmlStrings.TYPE_SELF:
111 fType = StateAttributeType.SELF;
112 fName = null;
113 break;
114 default:
115 throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$
116 }
117 }
118
119 /**
120 * This method gets the quark for this state attribute in the State System.
121 *
122 * Unless this attribute is a location, in which case the quark must exist,
123 * the quark will be added to the state system if the state system is in
124 * builder mode.
125 *
126 * @param startQuark
127 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
128 * search the full attribute tree
129 * @return the quark described by attribute or
130 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
131 * found
132 */
133 @Override
134 public int getAttributeQuark(int startQuark) {
135 return getAttributeQuark(null, startQuark);
136 }
137
138 /**
139 * Basic quark-retrieving method. Pass an attribute in parameter as an array
140 * of strings, the matching quark will be returned. If the attribute does
141 * not exist, it will add the quark to the state system if the context
142 * allows it.
143 *
144 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
145 *
146 * @param path
147 * Full path to the attribute
148 * @return The quark for this attribute
149 * @throws AttributeNotFoundException
150 * The attribute does not exist and cannot be added
151 */
152 protected abstract int getQuarkAbsoluteAndAdd(String... path) throws AttributeNotFoundException;
153
154 /**
155 * Quark-retrieving method, but the attribute is queried starting from the
156 * startNodeQuark. If the attribute does not exist, it will add it to the
157 * state system if the context allows it.
158 *
159 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
160 *
161 * @param startNodeQuark
162 * The quark of the attribute from which 'path' originates.
163 * @param path
164 * Relative path to the attribute
165 * @return The quark for this attribute
166 * @throws AttributeNotFoundException
167 * The attribute does not exist and cannot be added
168 */
169 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark, String... path) throws AttributeNotFoundException;
170
171 /**
172 * Get the state system associated with this attribute's container
173 *
174 * @return The state system associated with this state attribute
175 */
176 protected ITmfStateSystem getStateSystem() {
177 return fContainer.getStateSystem();
178 }
179
180 /**
181 * This method gets the quark for this state attribute in the State System.
182 *
183 * Unless this attribute is a location, in which case the quark must exist,
184 * the quark will be added to the state system if the state system is in
185 * builder mode.
186 *
187 * @param event
188 * The current event being handled, or <code>null</code> if no
189 * event available in the context
190 * @param startQuark
191 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
192 * search the full attribute tree
193 * @return the quark described by attribute or
194 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
195 * found
196 */
197 @Override
198 public int getAttributeQuark(@Nullable ITmfEvent event, int startQuark) {
199 ITmfStateSystem ss = getStateSystem();
200
201 try {
202 switch (fType) {
203 case CONSTANT: {
204 int quark;
205 if (startQuark == IXmlStateSystemContainer.ROOT_QUARK) {
206 quark = getQuarkAbsoluteAndAdd(fName);
207 } else {
208 quark = getQuarkRelativeAndAdd(startQuark, fName);
209 }
210 return quark;
211 }
212 case EVENTFIELD: {
213 int quark = IXmlStateSystemContainer.ERROR_QUARK;
214 if (event == null) {
215 Activator.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
216 return quark;
217 }
218 /* special case if field is CPU which is not in the field */
219 if (fName.equals(TmfXmlStrings.CPU)) {
220 quark = getQuarkRelativeAndAdd(startQuark, event.getSource());
221 } else {
222 final ITmfEventField content = event.getContent();
223 /* stop if the event field doesn't exist */
224 if (content.getField(fName) == null) {
225 return IXmlStateSystemContainer.ERROR_QUARK;
226 }
227
228 Object field = content.getField(fName).getValue();
229
230 if (field instanceof String) {
231 String fieldString = (String) field;
232 quark = getQuarkRelativeAndAdd(startQuark, fieldString);
233 } else if (field instanceof Long) {
234 Long fieldLong = (Long) field;
235 quark = getQuarkRelativeAndAdd(startQuark, fieldLong.toString());
236 } else if (field instanceof Integer) {
237 Integer fieldInterger = (Integer) field;
238 quark = getQuarkRelativeAndAdd(startQuark, fieldInterger.toString());
239 }
240 }
241 return quark;
242 }
243 case QUERY: {
244 int quark;
245 ITmfStateValue value = TmfStateValue.nullValue();
246 int quarkQuery = IXmlStateSystemContainer.ROOT_QUARK;
247
248 for (ITmfXmlStateAttribute attrib : fQueryList) {
249 quarkQuery = attrib.getAttributeQuark(event, quarkQuery);
250 if (quarkQuery == IXmlStateSystemContainer.ERROR_QUARK) {
251 break;
252 }
253 }
254
255 // the query may fail: for example CurrentThread if there
256 // has not been a sched_switch event
257 if (quarkQuery != IXmlStateSystemContainer.ERROR_QUARK) {
258 value = ss.queryOngoingState(quarkQuery);
259 }
260
261 switch (value.getType()) {
262 case INTEGER: {
263 int result = value.unboxInt();
264 quark = getQuarkRelativeAndAdd(startQuark, String.valueOf(result));
265 break;
266 }
267 case LONG: {
268 long result = value.unboxLong();
269 quark = getQuarkRelativeAndAdd(startQuark, String.valueOf(result));
270 break;
271 }
272 case STRING: {
273 String result = value.unboxStr();
274 quark = getQuarkRelativeAndAdd(startQuark, result);
275 break;
276 }
277 case DOUBLE:
278 case NULL:
279 default:
280 quark = IXmlStateSystemContainer.ERROR_QUARK; // error
281 break;
282 }
283 return quark;
284 }
285 case LOCATION: {
286 int quark = startQuark;
287 String idLocation = fName;
288
289 /* TODO: Add a fContainer.getLocation(id) method */
290 for (TmfXmlLocation location : fContainer.getLocations()) {
291 if (location.getId().equals(idLocation)) {
292 quark = location.getLocationQuark(event, quark);
293 if (quark == IXmlStateSystemContainer.ERROR_QUARK) {
294 break;
295 }
296 }
297 }
298 return quark;
299 }
300 case SELF:
301 return startQuark;
302 case NONE:
303 default:
304 return startQuark;
305 }
306 } catch (AttributeNotFoundException ae) {
307 /*
308 * This can be happen before the creation of the node for a query in
309 * the state system. Example : current thread before a sched_switch
310 */
311 return IXmlStateSystemContainer.ERROR_QUARK;
312 } catch (StateValueTypeException e) {
313 /*
314 * This would happen if we were trying to push/pop attributes not of
315 * type integer. Which, once again, should never happen.
316 */
317 Activator.logError("StateValueTypeException", e); //$NON-NLS-1$
318 return IXmlStateSystemContainer.ERROR_QUARK;
319 }
320 }
321
322 }
This page took 0.039023 seconds and 5 git commands to generate.