Commit | Line | Data |
---|---|---|
0f7276b6 GB |
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.internal.tmf.analysis.xml.core.stateprovider.model; | |
14 | ||
15 | import java.util.ArrayList; | |
16 | import java.util.List; | |
17 | ||
18 | import org.eclipse.linuxtools.internal.tmf.analysis.xml.core.Activator; | |
19 | import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils; | |
20 | import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; | |
21 | import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.XmlStateProvider; | |
22 | import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; | |
23 | import org.eclipse.linuxtools.tmf.core.event.ITmfEventField; | |
24 | import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; | |
25 | import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException; | |
26 | import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder; | |
27 | import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue; | |
28 | import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue; | |
29 | import org.w3c.dom.Element; | |
30 | ||
31 | /** | |
32 | * This Class implements a single attribute value | |
33 | * | |
34 | * <pre> | |
35 | * Examples: | |
36 | * <stateAttribute type="constant" value="Threads" /> | |
37 | * <stateAttribute type="query" /> | |
38 | * <stateAttribute type="constant" value="CPUs" /> | |
39 | * <stateAttribute type="eventField" value="cpu" /> | |
40 | * <stateAttribute type="constant" value="Current_thread" /> | |
41 | * </attribute> | |
42 | * </pre> | |
43 | * | |
44 | * @author Florian Wininger | |
45 | */ | |
46 | public class TmfXmlStateAttribute { | |
47 | ||
48 | private enum StateAttributeType { | |
49 | NONE, | |
50 | CONSTANT, | |
51 | EVENTFIELD, | |
52 | QUERY, | |
53 | LOCATION | |
54 | } | |
55 | ||
56 | /** Type of attribute */ | |
57 | private final StateAttributeType fType; | |
58 | ||
59 | /** Attribute's name */ | |
60 | private final String fName; | |
61 | ||
62 | /** List of attributes for a query */ | |
63 | private final List<TmfXmlStateAttribute> fQueryList = new ArrayList<>(); | |
64 | ||
65 | private final XmlStateProvider fProvider; | |
66 | ||
67 | /** | |
68 | * Constructor | |
69 | * | |
70 | * @param attribute | |
71 | * XML element of the attribute | |
72 | * @param provider | |
73 | * The state provider this state attribute belongs to | |
74 | */ | |
75 | public TmfXmlStateAttribute(Element attribute, XmlStateProvider provider) { | |
76 | fProvider = provider; | |
77 | ||
78 | switch (attribute.getAttribute(TmfXmlStrings.TYPE)) { | |
79 | case TmfXmlStrings.TYPE_CONSTANT: | |
80 | fType = StateAttributeType.CONSTANT; | |
81 | fName = fProvider.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE)); | |
82 | break; | |
83 | case TmfXmlStrings.EVENT_FIELD: | |
84 | fType = StateAttributeType.EVENTFIELD; | |
85 | fName = fProvider.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE)); | |
86 | break; | |
87 | case TmfXmlStrings.TYPE_LOCATION: | |
88 | fType = StateAttributeType.LOCATION; | |
89 | fName = fProvider.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE)); | |
90 | break; | |
91 | case TmfXmlStrings.TYPE_QUERY: | |
92 | List<Element> childElements = XmlUtils.getChildElements(attribute); | |
93 | for (Element subAttributeNode : childElements) { | |
94 | TmfXmlStateAttribute subAttribute = new TmfXmlStateAttribute(subAttributeNode, fProvider); | |
95 | fQueryList.add(subAttribute); | |
96 | } | |
97 | fType = StateAttributeType.QUERY; | |
98 | fName = null; | |
99 | break; | |
100 | case TmfXmlStrings.NULL: | |
101 | fType = StateAttributeType.NONE; | |
102 | fName = null; | |
103 | break; | |
104 | default: | |
105 | throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$ | |
106 | } | |
107 | } | |
108 | ||
109 | /** | |
110 | * This method gets the quark for this state attribute in the State System. | |
111 | * The method use the ss.getQuarkRelativeAndAdd method in the State System. | |
112 | * | |
113 | * Unless this attribute is a location, in which case the quark must exist, | |
114 | * the quark will be added to the state system. | |
115 | * | |
116 | * @param event | |
117 | * The current event being handled | |
118 | * @param startQuark | |
119 | * root quark, use {@link XmlStateProvider#ROOT_QUARK} to search | |
120 | * the full attribute tree | |
121 | * @return the quark described by attribute or | |
122 | * {@link XmlStateProvider#ERROR_QUARK} if quark cannot be found | |
123 | */ | |
124 | public int getAttributeQuark(ITmfEvent event, int startQuark) { | |
125 | final ITmfEventField content = event.getContent(); | |
126 | ||
127 | ITmfStateSystemBuilder ss = fProvider.getAssignedStateSystem(); | |
128 | ||
129 | try { | |
130 | switch (fType) { | |
131 | case CONSTANT: { | |
132 | int quark; | |
133 | if (startQuark == XmlStateProvider.ROOT_QUARK) { | |
134 | quark = ss.getQuarkAbsoluteAndAdd(fName); | |
135 | } else { | |
136 | quark = ss.getQuarkRelativeAndAdd(startQuark, fName); | |
137 | } | |
138 | return quark; | |
139 | } | |
140 | case EVENTFIELD: { | |
141 | int quark = XmlStateProvider.ERROR_QUARK; | |
142 | /* special case if field is CPU which is not in the field */ | |
143 | if (fName.equals(TmfXmlStrings.CPU)) { | |
144 | quark = ss.getQuarkRelativeAndAdd(startQuark, event.getSource()); | |
145 | } else { | |
146 | /* stop if the event field doesn't exist */ | |
147 | if (content.getField(fName) == null) { | |
148 | return XmlStateProvider.ERROR_QUARK; | |
149 | } | |
150 | ||
151 | Object field = content.getField(fName).getValue(); | |
152 | ||
153 | if (field instanceof String) { | |
154 | String fieldString = (String) field; | |
155 | quark = ss.getQuarkRelativeAndAdd(startQuark, fieldString); | |
156 | } else if (field instanceof Long) { | |
157 | Long fieldLong = (Long) field; | |
158 | quark = ss.getQuarkRelativeAndAdd(startQuark, fieldLong.toString()); | |
159 | } else if (field instanceof Integer) { | |
160 | Integer fieldInterger = (Integer) field; | |
161 | quark = ss.getQuarkRelativeAndAdd(startQuark, fieldInterger.toString()); | |
162 | } | |
163 | } | |
164 | return quark; | |
165 | } | |
166 | case QUERY: { | |
167 | int quark; | |
168 | ITmfStateValue value = TmfStateValue.nullValue(); | |
169 | int quarkQuery = XmlStateProvider.ROOT_QUARK; | |
170 | ||
171 | for (TmfXmlStateAttribute attrib : fQueryList) { | |
172 | quarkQuery = attrib.getAttributeQuark(event, quarkQuery); | |
173 | if (quarkQuery == XmlStateProvider.ERROR_QUARK) { | |
174 | break; | |
175 | } | |
176 | } | |
177 | ||
178 | // the query may fail: for example CurrentThread if there | |
179 | // has not been a sched_switch event | |
180 | if (quarkQuery != XmlStateProvider.ERROR_QUARK) { | |
181 | value = ss.queryOngoingState(quarkQuery); | |
182 | } | |
183 | ||
184 | switch (value.getType()) { | |
185 | case INTEGER: { | |
186 | int result = value.unboxInt(); | |
187 | quark = ss.getQuarkRelativeAndAdd(startQuark, String.valueOf(result)); | |
188 | break; | |
189 | } | |
190 | case LONG: { | |
191 | long result = value.unboxLong(); | |
192 | quark = ss.getQuarkRelativeAndAdd(startQuark, String.valueOf(result)); | |
193 | break; | |
194 | } | |
195 | case STRING: { | |
196 | String result = value.unboxStr(); | |
197 | quark = ss.getQuarkRelativeAndAdd(startQuark, result); | |
198 | break; | |
199 | } | |
200 | case DOUBLE: | |
201 | case NULL: | |
202 | default: | |
203 | quark = XmlStateProvider.ERROR_QUARK; // error | |
204 | break; | |
205 | } | |
206 | return quark; | |
207 | } | |
208 | case LOCATION: { | |
209 | int quark = startQuark; | |
210 | String idLocation = fName; | |
211 | ||
212 | /* TODO: Add a fProvider.getLocation(id) method */ | |
213 | for (TmfXmlLocation location : fProvider.getLocations()) { | |
214 | if (location.getId().equals(idLocation)) { | |
215 | quark = location.getLocationQuark(event, quark); | |
216 | if (quark == XmlStateProvider.ERROR_QUARK) { | |
217 | break; | |
218 | } | |
219 | } | |
220 | } | |
221 | return quark; | |
222 | } | |
223 | case NONE: | |
224 | default: | |
225 | return startQuark; | |
226 | } | |
227 | } catch (AttributeNotFoundException ae) { | |
228 | /* | |
229 | * This can be happen before the creation of the node for a query in | |
230 | * the state system. Example : current thread before a sched_switch | |
231 | */ | |
232 | return XmlStateProvider.ERROR_QUARK; | |
233 | } catch (StateValueTypeException e) { | |
234 | /* | |
235 | * This would happen if we were trying to push/pop attributes not of | |
236 | * type integer. Which, once again, should never happen. | |
237 | */ | |
238 | Activator.logError("StateValueTypeException", e); //$NON-NLS-1$ | |
239 | return XmlStateProvider.ERROR_QUARK; | |
240 | } | |
241 | } | |
242 | ||
243 | } |