Merge branch 'master' into lttng-luna
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / ctfadaptor / CtfTmfEventField.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2013 Ericsson, École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * 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 * Matthew Khouzam - Initial API and implementation
11 * Alexandre Montplaisir - Initial API and implementation, extend TmfEventField
12 * Bernd Hufmann - Add Enum field handling
13 * Geneviève Bastien - Add Struct and Variant field handling
14 * Jean-Christian Kouame - Correct handling of unsigned integer fields
15 *******************************************************************************/
16
17 package org.eclipse.linuxtools.tmf.core.ctfadaptor;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22 import java.util.Map.Entry;
23
24 import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
25 import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
26 import org.eclipse.linuxtools.ctf.core.event.types.Definition;
27 import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
28 import org.eclipse.linuxtools.ctf.core.event.types.FloatDefinition;
29 import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
30 import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
31 import org.eclipse.linuxtools.ctf.core.event.types.SequenceDeclaration;
32 import org.eclipse.linuxtools.ctf.core.event.types.SequenceDefinition;
33 import org.eclipse.linuxtools.ctf.core.event.types.StringDefinition;
34 import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
35 import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
36 import org.eclipse.linuxtools.internal.tmf.core.Messages;
37 import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
38 import org.eclipse.linuxtools.tmf.core.event.TmfEventField;
39
40 /**
41 * The CTF implementation of the TMF event field model
42 *
43 * @version 2.0
44 * @author Matthew Khouzam
45 * @author Alexandre Montplaisir
46 */
47 public abstract class CtfTmfEventField extends TmfEventField {
48
49 // ------------------------------------------------------------------------
50 // Constructor
51 // ------------------------------------------------------------------------
52
53 /**
54 * Standard constructor. Only to be used internally, call parseField() to
55 * generate a new field object.
56 *
57 * @param name
58 * The name of this field
59 * @param value
60 * The value of this field. Its type should match the field type.
61 * @param fields
62 * The children fields. Useful for composite fields
63 * @since 2.0
64 */
65 protected CtfTmfEventField(String name, Object value, ITmfEventField[] fields) {
66 super(/* Strip the underscore from the field name if there is one */
67 name.startsWith("_") ? name.substring(1) : name, //$NON-NLS-1$
68 value,
69 fields);
70 }
71
72 // ------------------------------------------------------------------------
73 // Operations
74 // ------------------------------------------------------------------------
75
76 /**
77 * Factory method to instantiate CtfTmfEventField objects.
78 *
79 * @param fieldDef
80 * The CTF Definition of this event field
81 * @param fieldName
82 * String The name to assign to this field
83 * @return The resulting CtfTmfEventField object
84 */
85 public static CtfTmfEventField parseField(Definition fieldDef,
86 String fieldName) {
87 CtfTmfEventField field = null;
88
89 /* Determine the Definition type */
90 if (fieldDef instanceof IntegerDefinition) {
91 IntegerDefinition intDef = (IntegerDefinition) fieldDef;
92 int base = intDef.getDeclaration().getBase();
93 field = new CTFIntegerField(fieldName, intDef.getValue(), base, intDef.getDeclaration().isSigned());
94
95 } else if (fieldDef instanceof EnumDefinition) {
96 EnumDefinition enumDef = (EnumDefinition) fieldDef;
97 field = new CTFEnumField(fieldName, new CtfEnumPair(enumDef.getValue(), enumDef.getIntegerValue()));
98
99 } else if (fieldDef instanceof StringDefinition) {
100 field = new CTFStringField(fieldName, ((StringDefinition) fieldDef).getValue());
101
102 } else if (fieldDef instanceof FloatDefinition) {
103 FloatDefinition floatDef = (FloatDefinition) fieldDef;
104 field = new CTFFloatField(fieldName, floatDef.getValue());
105
106 } else if (fieldDef instanceof ArrayDefinition) {
107 ArrayDefinition arrayDef = (ArrayDefinition) fieldDef;
108 ArrayDeclaration arrayDecl = arrayDef.getDeclaration();
109
110 if (arrayDef.isString()) {
111 /* This is an array of UTF-8 bytes, a.k.a. a String! */
112 field = new CTFStringField(fieldName, fieldDef.toString());
113
114 } else if (arrayDecl.getElementType() instanceof IntegerDeclaration) {
115 /* This is a an array of CTF Integers */
116 List<Long> values = new ArrayList<Long>(arrayDecl.getLength());
117 for (int i = 0; i < arrayDecl.getLength(); i++) {
118 values.add(((IntegerDefinition) arrayDef.getElem(i)).getValue());
119 }
120 long[] valuesArray = convertListToArray(values);
121 field = new CTFIntegerArrayField(fieldName, valuesArray,
122 ((IntegerDeclaration) arrayDecl.getElementType()).getBase(),
123 ((IntegerDeclaration) arrayDecl.getElementType()).isSigned());
124 }
125 /* Add other types of arrays here */
126
127 } else if (fieldDef instanceof SequenceDefinition) {
128 SequenceDefinition seqDef = (SequenceDefinition) fieldDef;
129 SequenceDeclaration seqDecl = seqDef.getDeclaration();
130
131 if (seqDef.getLength() == 0) {
132 /* Some sequences have length = 0. Simply use an empty string */
133 field = new CTFStringField(fieldName, ""); //$NON-NLS-1$
134 } else if (seqDef.isString()) {
135 /* Interpret this sequence as a String */
136 field = new CTFStringField(fieldName, seqDef.toString());
137 } else if (seqDecl.getElementType() instanceof IntegerDeclaration) {
138 /* Sequence of integers => CTFIntegerArrayField */
139 List<Long> values = new ArrayList<Long>(seqDef.getLength());
140 for (int i = 0; i < seqDef.getLength(); i++) {
141 values.add(((IntegerDefinition) seqDef.getElem(i)).getValue());
142 }
143 long[] valuesArray = convertListToArray(values);
144 field = new CTFIntegerArrayField(fieldName, valuesArray,
145 ((IntegerDeclaration) seqDecl.getElementType()).getBase(),
146 ((IntegerDeclaration) seqDecl.getElementType()).isSigned());
147 }
148 /* Add other Sequence types here */
149
150 } else if (fieldDef instanceof StructDefinition) {
151 StructDefinition strDef = (StructDefinition) fieldDef;
152
153 String curFieldName = null;
154 Definition curFieldDef;
155 CtfTmfEventField curField;
156 List<ITmfEventField> list = new ArrayList<ITmfEventField>();
157 /* Recursively parse the fields */
158 for (Entry<String, Definition> entry : strDef.getDefinitions().entrySet()) {
159 curFieldName = entry.getKey();
160 curFieldDef = entry.getValue();
161 curField = CtfTmfEventField.parseField(curFieldDef, curFieldName);
162 list.add(curField);
163 }
164 field = new CTFStructField(fieldName, list.toArray(new CtfTmfEventField[list.size()]));
165
166 } else if (fieldDef instanceof VariantDefinition) {
167 VariantDefinition varDef = (VariantDefinition) fieldDef;
168
169 String curFieldName = varDef.getCurrentFieldName();
170 Definition curFieldDef = varDef.getDefinitions().get(curFieldName);
171 if (curFieldDef != null) {
172 CtfTmfEventField subField = CtfTmfEventField.parseField(curFieldDef, curFieldName);
173 field = new CTFVariantField(fieldName, subField);
174 } else {
175 /* A safe-guard, but curFieldDef should never be null */
176 field = new CTFStringField(curFieldName, ""); //$NON-NLS-1$
177 }
178
179 } else {
180 /*
181 * Safe-guard, to avoid null exceptions later, field is expected not
182 * to be null
183 */
184 field = new CTFStringField(fieldName, Messages.TmfEventField_UnsupportedType + fieldDef.getClass().toString());
185 }
186 return field;
187 }
188
189 @Override
190 public String toString() {
191 return getName() + '=' + getFormattedValue();
192 }
193
194 /**
195 * We cannot use List.toArray(T[]) for primitives types, so do it manually.
196 */
197 private static long[] convertListToArray(List<Long> list) {
198 long[] array = new long[list.size()];
199 for (int i = 0; i < list.size(); i++) {
200 array[i] = list.get(i);
201 }
202 return array;
203 }
204
205 }
206
207 /**
208 * The CTF field implementation for integer fields.
209 *
210 * @author alexmont
211 */
212 final class CTFIntegerField extends CtfTmfEventField {
213
214 private final int base;
215 private final boolean signed;
216
217 /**
218 * A CTF "IntegerDefinition" can be an integer of any byte size, so in the
219 * Java parser this is interpreted as a long.
220 *
221 * @param name
222 * The name of this field
223 * @param longValue
224 * The integer value of this field
225 * @param signed
226 * Is the value signed or not
227 */
228 CTFIntegerField(String name, long longValue, int base, boolean signed) {
229 super(name, longValue, null);
230 this.signed = signed;
231 this.base = base;
232 }
233
234 @Override
235 public Long getValue() {
236 return (Long) super.getValue();
237 }
238
239 @Override
240 public String getFormattedValue() {
241 return IntegerDefinition.formatNumber(getValue(), base, signed);
242 }
243
244 }
245
246 /**
247 * The CTF field implementation for string fields
248 *
249 * @author alexmont
250 */
251 final class CTFStringField extends CtfTmfEventField {
252
253 /**
254 * Constructor for CTFStringField.
255 *
256 * @param strValue
257 * The string value of this field
258 * @param name
259 * The name of this field
260 */
261 CTFStringField(String name, String strValue) {
262 super(name, strValue, null);
263 }
264
265 @Override
266 public String getValue() {
267 return (String) super.getValue();
268 }
269 }
270
271 /**
272 * CTF field implementation for arrays of integers.
273 *
274 * @author alexmont
275 */
276 final class CTFIntegerArrayField extends CtfTmfEventField {
277
278 private final int base;
279 private final boolean signed;
280 private String formattedValue = null;
281
282 /**
283 * Constructor for CTFIntegerArrayField.
284 *
285 * @param name
286 * The name of this field
287 * @param longValues
288 * The array of integers (as longs) that compose this field's
289 * value
290 * @param signed
291 * Are the values in the array signed or not
292 */
293 CTFIntegerArrayField(String name, long[] longValues, int base, boolean signed) {
294 super(name, longValues, null);
295 this.base = base;
296 this.signed = signed;
297 }
298
299 @Override
300 public long[] getValue() {
301 return (long[]) super.getValue();
302 }
303
304 @Override
305 public String getFormattedValue() {
306 if (formattedValue == null) {
307 List<String> strings = new ArrayList<String>();
308 for (long value : getValue()) {
309 strings.add(IntegerDefinition.formatNumber(value, base, signed));
310 }
311 formattedValue = strings.toString();
312 }
313 return formattedValue;
314 }
315
316 }
317
318 /**
319 * CTF field implementation for floats.
320 *
321 * @author emathko
322 */
323 final class CTFFloatField extends CtfTmfEventField {
324
325 /**
326 * Constructor for CTFFloatField.
327 *
328 * @param value
329 * The float value (actually a double) of this field
330 * @param name
331 * The name of this field
332 */
333 protected CTFFloatField(String name, double value) {
334 super(name, value, null);
335 }
336
337 @Override
338 public Double getValue() {
339 return (Double) super.getValue();
340 }
341 }
342
343 /**
344 * The CTF field implementation for Enum fields
345 *
346 * @author Bernd Hufmann
347 */
348 final class CTFEnumField extends CtfTmfEventField {
349
350 /**
351 * Constructor for CTFEnumField.
352 *
353 * @param enumValue
354 * The Enum value consisting of a pair of Enum value name and its
355 * long value
356 * @param name
357 * The name of this field
358 */
359 CTFEnumField(String name, CtfEnumPair enumValue) {
360 super(name, new CtfEnumPair(enumValue.getFirst(),
361 enumValue.getSecond().longValue()), null);
362 }
363
364 @Override
365 public CtfEnumPair getValue() {
366 return (CtfEnumPair) super.getValue();
367 }
368 }
369
370 /**
371 * The CTF field implementation for struct fields with sub-fields
372 *
373 * @author gbastien
374 */
375 final class CTFStructField extends CtfTmfEventField {
376
377 /**
378 * Constructor for CTFStructField.
379 *
380 * @param fields
381 * The children of this field
382 * @param name
383 * The name of this field
384 */
385 CTFStructField(String name, CtfTmfEventField[] fields) {
386 super(name, fields, fields);
387 }
388
389 @Override
390 public CtfTmfEventField[] getValue() {
391 return (CtfTmfEventField[]) super.getValue();
392 }
393
394 @Override
395 public String getFormattedValue() {
396 return Arrays.toString(getValue());
397 }
398
399 }
400
401 /**
402 * The CTF field implementation for variant fields its child
403 *
404 * @author gbastien
405 */
406 final class CTFVariantField extends CtfTmfEventField {
407
408 /**
409 * Constructor for CTFVariantField.
410 *
411 * @param field
412 * The field selected for this variant
413 * @param name
414 * The name of this field
415 */
416 CTFVariantField(String name, CtfTmfEventField field) {
417 super(name, field, new CtfTmfEventField[] { field });
418 }
419
420 @Override
421 public CtfTmfEventField getValue() {
422 return (CtfTmfEventField) super.getValue();
423 }
424
425 }
426
427 /* Implement other possible fields types here... */
This page took 0.040098 seconds and 6 git commands to generate.