4f0f38c5df6bfb2fc8e9806ca55739d04d3b6c7f
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.tmf.ctf.core / src / org / eclipse / tracecompass / tmf / ctf / core / event / CtfTmfEventField.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 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 * François Doray - Add generic array field type
16 *******************************************************************************/
17
18 package org.eclipse.tracecompass.tmf.ctf.core.event;
19
20 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
21
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.eclipse.tracecompass.ctf.core.event.types.AbstractArrayDefinition;
28 import org.eclipse.tracecompass.ctf.core.event.types.CompoundDeclaration;
29 import org.eclipse.tracecompass.ctf.core.event.types.Definition;
30 import org.eclipse.tracecompass.ctf.core.event.types.EnumDefinition;
31 import org.eclipse.tracecompass.ctf.core.event.types.FloatDefinition;
32 import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
33 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
34 import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
35 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
36 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
37 import org.eclipse.tracecompass.ctf.core.event.types.StringDefinition;
38 import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
39 import org.eclipse.tracecompass.internal.ctf.core.event.types.ByteArrayDefinition;
40 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
41 import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
42 import org.eclipse.tracecompass.tmf.ctf.core.CtfEnumPair;
43
44 /**
45 * The CTF implementation of the TMF event field model
46 *
47 * @version 2.0
48 * @author Matthew Khouzam
49 * @author Alexandre Montplaisir
50 */
51 public abstract class CtfTmfEventField extends TmfEventField {
52
53 /**
54 * Value that can be used in the {@link #getField(String...)} for variants.
55 * Using this field value means that the selected field will be returned
56 * whatever the selected choice for the event
57 *
58 * @since 2.1
59 */
60 public static final @NonNull String FIELD_VARIANT_SELECTED = "Any"; //$NON-NLS-1$
61
62 // ------------------------------------------------------------------------
63 // Constructor
64 // ------------------------------------------------------------------------
65
66 /**
67 * Standard constructor. Only to be used internally, call parseField() to
68 * generate a new field object.
69 *
70 * @param name
71 * The name of this field
72 * @param value
73 * The value of this field. Its type should match the field type.
74 * @param fields
75 * The children fields. Useful for composite fields
76 */
77 protected CtfTmfEventField(@NonNull String name, Object value, ITmfEventField[] fields) {
78 super(/* Strip the underscore from the field name if there is one */
79 name.startsWith("_") ? name.substring(1) : name, //$NON-NLS-1$
80 value,
81 fields);
82 }
83
84 // ------------------------------------------------------------------------
85 // Operations
86 // ------------------------------------------------------------------------
87
88 /**
89 * Factory method to instantiate CtfTmfEventField objects.
90 *
91 * @param fieldDef
92 * The CTF Definition of this event field
93 * @param fieldName
94 * String The name to assign to this field
95 * @return The resulting CtfTmfEventField object
96 * @deprecated use {@link CtfTmfEventField#parseField(IDefinition, String)}
97 */
98 @Deprecated
99 public static CtfTmfEventField parseField(Definition fieldDef,
100 @NonNull String fieldName) {
101 return parseField((IDefinition) fieldDef, fieldName);
102 }
103
104 /**
105 * Factory method to instantiate CtfTmfEventField objects.
106 *
107 * @param fieldDef
108 * The CTF Definition of this event field
109 * @param fieldName
110 * String The name to assign to this field
111 * @return The resulting CtfTmfEventField object
112 */
113 public static @NonNull CtfTmfEventField parseField(IDefinition fieldDef,
114 @NonNull String fieldName) {
115 CtfTmfEventField field = null;
116
117 /* Determine the Definition type */
118 if (fieldDef instanceof IntegerDefinition) {
119 IntegerDefinition intDef = (IntegerDefinition) fieldDef;
120 int base = intDef.getDeclaration().getBase();
121 field = new CTFIntegerField(fieldName, intDef.getValue(), base, intDef.getDeclaration().isSigned());
122
123 } else if (fieldDef instanceof EnumDefinition) {
124 EnumDefinition enumDef = (EnumDefinition) fieldDef;
125 field = new CTFEnumField(fieldName, new CtfEnumPair(enumDef.getValue(), enumDef.getIntegerValue()));
126
127 } else if (fieldDef instanceof StringDefinition) {
128 field = new CTFStringField(fieldName, ((StringDefinition) fieldDef).getValue());
129
130 } else if (fieldDef instanceof FloatDefinition) {
131 FloatDefinition floatDef = (FloatDefinition) fieldDef;
132 field = new CTFFloatField(fieldName, floatDef.getValue());
133
134 } else if (fieldDef instanceof AbstractArrayDefinition) {
135 AbstractArrayDefinition arrayDef = (AbstractArrayDefinition) fieldDef;
136 IDeclaration decl = arrayDef.getDeclaration();
137 if (!(decl instanceof CompoundDeclaration)) {
138 throw new IllegalArgumentException("Array definitions should only come from sequence or array declarations"); //$NON-NLS-1$
139 }
140 CompoundDeclaration arrDecl = (CompoundDeclaration) decl;
141 IDeclaration elemType = null;
142 elemType = arrDecl.getElementType();
143 if (elemType instanceof IntegerDeclaration) {
144 /*
145 * Array of integers => CTFIntegerArrayField, unless it's a
146 * CTFStringField
147 */
148 IntegerDeclaration elemIntType = (IntegerDeclaration) elemType;
149 /* Are the integers characters and encoded? */
150 if (elemIntType.isCharacter()) {
151 /* it's a CTFStringField */
152 field = new CTFStringField(fieldName, arrayDef.toString());
153 } else if (arrayDef instanceof ByteArrayDefinition) { // unsigned byte array
154 ByteArrayDefinition byteArrayDefinition = (ByteArrayDefinition) arrayDef;
155 /* it's a CTFIntegerArrayField */
156 int size = arrayDef.getLength();
157 long[] values = new long[size];
158 for (int i = 0; i < size; i++) {
159 values[i] = Byte.toUnsignedLong(byteArrayDefinition.getByte(i));
160 }
161 field = new CTFIntegerArrayField(fieldName, values,
162 elemIntType.getBase(),
163 elemIntType.isSigned());
164
165 } else {
166 /* it's a CTFIntegerArrayField */
167 int size = arrayDef.getLength();
168 long[] values = new long[size];
169 for (int i = 0; i < size; i++) {
170 IDefinition elem = arrayDef.getDefinitions().get(i);
171 if (elem == null) {
172 break;
173 }
174 values[i] = ((IntegerDefinition) elem).getValue();
175 }
176 field = new CTFIntegerArrayField(fieldName, values,
177 elemIntType.getBase(),
178 elemIntType.isSigned());
179 }
180 } else {
181 /* Arrays of elements of any other type */
182 CtfTmfEventField[] elements = new CtfTmfEventField[arrayDef.getLength()];
183 /* Parse the elements of the array. */
184 int i = 0;
185 List<Definition> definitions = arrayDef.getDefinitions();
186 for (IDefinition definition : definitions) {
187 CtfTmfEventField curField = CtfTmfEventField.parseField(
188 definition, fieldName + '[' + i + ']');
189 elements[i] = curField;
190 i++;
191 }
192
193 field = new CTFArrayField(fieldName, elements);
194 }
195 } else if (fieldDef instanceof ICompositeDefinition) {
196 ICompositeDefinition strDef = (ICompositeDefinition) fieldDef;
197
198 List<ITmfEventField> list = new ArrayList<>();
199 /* Recursively parse the fields */
200 for (String fn : strDef.getFieldNames()) {
201 list.add(CtfTmfEventField.parseField((IDefinition) strDef.getDefinition(fn), fn));
202 }
203 field = new CTFStructField(fieldName, list.toArray(new CtfTmfEventField[list.size()]));
204
205 } else if (fieldDef instanceof VariantDefinition) {
206 VariantDefinition varDef = (VariantDefinition) fieldDef;
207
208 String curFieldName = checkNotNull(varDef.getCurrentFieldName());
209 IDefinition curFieldDef = varDef.getCurrentField();
210 if (curFieldDef != null) {
211 CtfTmfEventField subField = CtfTmfEventField.parseField(curFieldDef, curFieldName);
212 field = new CTFVariantField(fieldName, subField);
213 } else {
214 /* A safe-guard, but curFieldDef should never be null */
215 field = new CTFStringField(curFieldName, ""); //$NON-NLS-1$
216 }
217
218 } else {
219 /*
220 * Safe-guard, to avoid null exceptions later, field is expected not
221 * to be null
222 */
223 field = new CTFStringField(fieldName, Messages.CtfTmfEventField_UnsupportedType + fieldDef.getClass().toString());
224 }
225 return field;
226 }
227
228 @Override
229 public String toString() {
230 return getName() + '=' + getFormattedValue();
231 }
232
233 }
234
235 /**
236 * The CTF field implementation for integer fields.
237 *
238 * @author alexmont
239 */
240 final class CTFIntegerField extends CtfTmfEventField {
241
242 private final int fBase;
243 private final boolean fSigned;
244
245 /**
246 * A CTF "IntegerDefinition" can be an integer of any byte size, so in the
247 * Java parser this is interpreted as a long.
248 *
249 * @param name
250 * The name of this field
251 * @param longValue
252 * The integer value of this field
253 * @param signed
254 * Is the value signed or not
255 */
256 CTFIntegerField(@NonNull String name, long longValue, int base, boolean signed) {
257 super(name, Long.valueOf(longValue), null);
258 fSigned = signed;
259 fBase = base;
260 }
261
262 @Override
263 public Long getValue() {
264 return (Long) super.getValue();
265 }
266
267 @Override
268 public String getFormattedValue() {
269 return IntegerDefinition.formatNumber(getValue(), fBase, fSigned);
270 }
271
272 }
273
274 /**
275 * The CTF field implementation for string fields
276 *
277 * @author alexmont
278 */
279 final class CTFStringField extends CtfTmfEventField {
280
281 /**
282 * Constructor for CTFStringField.
283 *
284 * @param strValue
285 * The string value of this field
286 * @param name
287 * The name of this field
288 */
289 CTFStringField(@NonNull String name, String strValue) {
290 super(name, strValue, null);
291 }
292
293 @Override
294 public String getValue() {
295 return (String) super.getValue();
296 }
297 }
298
299 /**
300 * CTF field implementation for arrays of integers.
301 *
302 * @author alexmont
303 */
304 final class CTFIntegerArrayField extends CtfTmfEventField {
305
306 private final int fBase;
307 private final boolean fSigned;
308 private String fFormattedValue = null;
309
310 /**
311 * Constructor for CTFIntegerArrayField.
312 *
313 * @param name
314 * The name of this field
315 * @param longValues
316 * The array of integers (as longs) that compose this field's
317 * value
318 * @param signed
319 * Are the values in the array signed or not
320 */
321 CTFIntegerArrayField(@NonNull String name, long[] longValues, int base, boolean signed) {
322 super(name, longValues, null);
323 fBase = base;
324 fSigned = signed;
325 }
326
327 @Override
328 public long[] getValue() {
329 return (long[]) super.getValue();
330 }
331
332 @Override
333 public synchronized String getFormattedValue() {
334 if (fFormattedValue == null) {
335 List<String> strings = new ArrayList<>();
336 for (long value : getValue()) {
337 strings.add(IntegerDefinition.formatNumber(value, fBase, fSigned));
338 }
339 fFormattedValue = strings.toString();
340 }
341 return fFormattedValue;
342 }
343
344 }
345
346 /**
347 * CTF field implementation for arrays of arbitrary types.
348 *
349 * @author fdoray
350 */
351 final class CTFArrayField extends CtfTmfEventField {
352
353 private String fFormattedValue = null;
354
355 /**
356 * Constructor for CTFArrayField.
357 *
358 * @param name
359 * The name of this field
360 * @param elements
361 * The array elements of this field
362 */
363 CTFArrayField(@NonNull String name, CtfTmfEventField[] elements) {
364 super(name, elements, elements);
365 }
366
367 @Override
368 public CtfTmfEventField[] getValue() {
369 return (CtfTmfEventField[]) super.getValue();
370 }
371
372 @Override
373 public synchronized String getFormattedValue() {
374 if (fFormattedValue == null) {
375 List<String> strings = new ArrayList<>();
376 for (CtfTmfEventField element : getValue()) {
377 strings.add(element.getFormattedValue());
378 }
379 fFormattedValue = strings.toString();
380 }
381 return fFormattedValue;
382 }
383 }
384
385 /**
386 * CTF field implementation for floats.
387 *
388 * @author emathko
389 */
390 final class CTFFloatField extends CtfTmfEventField {
391
392 /**
393 * Constructor for CTFFloatField.
394 *
395 * @param value
396 * The float value (actually a double) of this field
397 * @param name
398 * The name of this field
399 */
400 protected CTFFloatField(@NonNull String name, double value) {
401 super(name, value, null);
402 }
403
404 @Override
405 public Double getValue() {
406 return (Double) super.getValue();
407 }
408 }
409
410 /**
411 * The CTF field implementation for Enum fields
412 *
413 * @author Bernd Hufmann
414 */
415 final class CTFEnumField extends CtfTmfEventField {
416
417 /**
418 * Constructor for CTFEnumField.
419 *
420 * @param enumValue
421 * The Enum value consisting of a pair of Enum value name and its
422 * long value
423 * @param name
424 * The name of this field
425 */
426 CTFEnumField(@NonNull String name, CtfEnumPair enumValue) {
427 super(name, new CtfEnumPair(enumValue.getFirst(),
428 enumValue.getSecond()), null);
429 }
430
431 @Override
432 public CtfEnumPair getValue() {
433 return (CtfEnumPair) super.getValue();
434 }
435 }
436
437 /**
438 * The CTF field implementation for struct fields with sub-fields
439 *
440 * @author gbastien
441 */
442 final class CTFStructField extends CtfTmfEventField {
443
444 /**
445 * Constructor for CTFStructField.
446 *
447 * @param fields
448 * The children of this field
449 * @param name
450 * The name of this field
451 */
452 CTFStructField(@NonNull String name, CtfTmfEventField[] fields) {
453 super(name, fields, fields);
454 }
455
456 @Override
457 public CtfTmfEventField[] getValue() {
458 return (CtfTmfEventField[]) super.getValue();
459 }
460
461 @Override
462 public String getFormattedValue() {
463 return Arrays.toString(getValue());
464 }
465
466 }
467
468 /**
469 * The CTF field implementation for variant fields its child
470 *
471 * @author gbastien
472 */
473 final class CTFVariantField extends CtfTmfEventField {
474
475 /**
476 * Constructor for CTFVariantField.
477 *
478 * @param field
479 * The field selected for this variant
480 * @param name
481 * The name of this field
482 */
483 CTFVariantField(@NonNull String name, CtfTmfEventField field) {
484 super(name, field, new CtfTmfEventField[] { field });
485 }
486
487 @Override
488 public CtfTmfEventField getValue() {
489 return (CtfTmfEventField) super.getValue();
490 }
491
492 @Override
493 public ITmfEventField getField(final String... path) {
494 /*
495 * We use the == to make sure that this constant was used, otherwise, it
496 * could conflict with a field with the same name
497 */
498 if (path.length == 1 && path[0] == FIELD_VARIANT_SELECTED) {
499 return getFields().stream().findFirst().orElse(null);
500 }
501 return super.getField(path);
502 }
503
504 }
505
506 /* Implement other possible fields types here... */
This page took 0.040046 seconds and 4 git commands to generate.