1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 Ericsson, École Polytechnique de Montréal
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
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 *******************************************************************************/
18 package org
.eclipse
.tracecompass
.tmf
.ctf
.core
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Arrays
;
22 import java
.util
.Collection
;
23 import java
.util
.List
;
25 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.CompoundDeclaration
;
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
.ICompositeDefinition
;
30 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDeclaration
;
31 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDefinition
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDefinition
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDefinition
;
35 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDefinition
;
36 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.types
.ArrayDefinition
;
37 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.types
.ByteArrayDefinition
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEventField
;
42 * The CTF implementation of the TMF event field model
45 * @author Matthew Khouzam
46 * @author Alexandre Montplaisir
48 public abstract class CtfTmfEventField
extends TmfEventField
{
50 // ------------------------------------------------------------------------
52 // ------------------------------------------------------------------------
55 * Standard constructor. Only to be used internally, call parseField() to
56 * generate a new field object.
59 * The name of this field
61 * The value of this field. Its type should match the field type.
63 * The children fields. Useful for composite fields
66 protected CtfTmfEventField(String name
, Object value
, ITmfEventField
[] fields
) {
67 super(/* Strip the underscore from the field name if there is one */
68 name
.startsWith("_") ? name
.substring(1) : name
, //$NON-NLS-1$
73 // ------------------------------------------------------------------------
75 // ------------------------------------------------------------------------
78 * Factory method to instantiate CtfTmfEventField objects.
81 * The CTF Definition of this event field
83 * String The name to assign to this field
84 * @return The resulting CtfTmfEventField object
85 * @deprecated use {@link CtfTmfEventField#parseField(IDefinition, String)}
88 public static CtfTmfEventField
parseField(Definition fieldDef
,
90 return parseField((IDefinition
) fieldDef
, fieldName
);
94 * Factory method to instantiate CtfTmfEventField objects.
97 * The CTF Definition of this event field
99 * String The name to assign to this field
100 * @return The resulting CtfTmfEventField object
103 public static CtfTmfEventField
parseField(IDefinition fieldDef
,
105 CtfTmfEventField field
= null;
107 /* Determine the Definition type */
108 if (fieldDef
instanceof IntegerDefinition
) {
109 IntegerDefinition intDef
= (IntegerDefinition
) fieldDef
;
110 int base
= intDef
.getDeclaration().getBase();
111 field
= new CTFIntegerField(fieldName
, intDef
.getValue(), base
, intDef
.getDeclaration().isSigned());
113 } else if (fieldDef
instanceof EnumDefinition
) {
114 EnumDefinition enumDef
= (EnumDefinition
) fieldDef
;
115 field
= new CTFEnumField(fieldName
, new CtfEnumPair(enumDef
.getValue(), enumDef
.getIntegerValue()));
117 } else if (fieldDef
instanceof StringDefinition
) {
118 field
= new CTFStringField(fieldName
, ((StringDefinition
) fieldDef
).getValue());
120 } else if (fieldDef
instanceof FloatDefinition
) {
121 FloatDefinition floatDef
= (FloatDefinition
) fieldDef
;
122 field
= new CTFFloatField(fieldName
, floatDef
.getValue());
124 } else if (fieldDef
instanceof ArrayDefinition
) {
125 ArrayDefinition arrayDef
= (ArrayDefinition
) fieldDef
;
126 IDeclaration decl
= arrayDef
.getDeclaration();
127 if (!(decl
instanceof CompoundDeclaration
)) {
128 throw new IllegalArgumentException("Array definitions should only come from sequence or array declarations"); //$NON-NLS-1$
130 CompoundDeclaration arrDecl
= (CompoundDeclaration
) decl
;
131 IDeclaration elemType
= null;
132 Collection
<Definition
> definitions
= arrayDef
.getDefinitions();
133 elemType
= arrDecl
.getElementType();
134 if (elemType
instanceof IntegerDeclaration
) {
135 /* Array of integers => CTFIntegerArrayField, unless it's a CTFStringField */
136 IntegerDeclaration elemIntType
= (IntegerDeclaration
) elemType
;
137 /* Are the integers characters and encoded? */
138 if (elemIntType
.isCharacter()) {
139 /* it's a CTFStringField */
140 field
= new CTFStringField(fieldName
, arrayDef
.toString());
142 /* it's a CTFIntegerArrayField */
143 long[] values
= new long[arrayDef
.getLength()];
144 for (int i
= 0; i
< arrayDef
.getLength(); i
++) {
145 IDefinition elem
= arrayDef
.getDefinitions().get(i
);
149 values
[i
] = ((IntegerDefinition
) elem
).getValue();
151 field
= new CTFIntegerArrayField(fieldName
, values
,
152 elemIntType
.getBase(),
153 elemIntType
.isSigned());
156 /* Arrays of elements of any other type */
157 CtfTmfEventField
[] elements
= new CtfTmfEventField
[arrayDef
.getLength()];
158 /* Parse the elements of the array. */
160 for (IDefinition definition
: definitions
) {
161 CtfTmfEventField curField
= CtfTmfEventField
.parseField(
162 definition
, fieldName
+ '[' + i
+ ']');
163 elements
[i
] = curField
;
167 field
= new CTFArrayField(fieldName
, elements
);
169 } else if (fieldDef
instanceof ByteArrayDefinition
) {
170 /* This is an array of ascii bytes, a.k.a. a String! */
171 field
= new CTFStringField(fieldName
, fieldDef
.toString());
173 } else if (fieldDef
instanceof ICompositeDefinition
) {
174 ICompositeDefinition strDef
= (ICompositeDefinition
) fieldDef
;
176 List
<ITmfEventField
> list
= new ArrayList
<>();
177 /* Recursively parse the fields */
178 for (String curFieldName
: strDef
.getFieldNames()) {
179 list
.add(CtfTmfEventField
.parseField(strDef
.getDefinition(curFieldName
), curFieldName
));
181 field
= new CTFStructField(fieldName
, list
.toArray(new CtfTmfEventField
[list
.size()]));
183 } else if (fieldDef
instanceof VariantDefinition
) {
184 VariantDefinition varDef
= (VariantDefinition
) fieldDef
;
186 String curFieldName
= varDef
.getCurrentFieldName();
187 IDefinition curFieldDef
= varDef
.getCurrentField();
188 if (curFieldDef
!= null) {
189 CtfTmfEventField subField
= CtfTmfEventField
.parseField(curFieldDef
, curFieldName
);
190 field
= new CTFVariantField(fieldName
, subField
);
192 /* A safe-guard, but curFieldDef should never be null */
193 field
= new CTFStringField(curFieldName
, ""); //$NON-NLS-1$
198 * Safe-guard, to avoid null exceptions later, field is expected not
201 field
= new CTFStringField(fieldName
, Messages
.CtfTmfEventField_UnsupportedType
+ fieldDef
.getClass().toString());
207 public String
toString() {
208 return getName() + '=' + getFormattedValue();
214 * The CTF field implementation for integer fields.
218 final class CTFIntegerField
extends CtfTmfEventField
{
220 private final int fBase
;
221 private final boolean fSigned
;
224 * A CTF "IntegerDefinition" can be an integer of any byte size, so in the
225 * Java parser this is interpreted as a long.
228 * The name of this field
230 * The integer value of this field
232 * Is the value signed or not
234 CTFIntegerField(String name
, long longValue
, int base
, boolean signed
) {
235 super(name
, longValue
, null);
241 public Long
getValue() {
242 return (Long
) super.getValue();
246 public String
getFormattedValue() {
247 return IntegerDefinition
.formatNumber(getValue(), fBase
, fSigned
);
253 * The CTF field implementation for string fields
257 final class CTFStringField
extends CtfTmfEventField
{
260 * Constructor for CTFStringField.
263 * The string value of this field
265 * The name of this field
267 CTFStringField(String name
, String strValue
) {
268 super(name
, strValue
, null);
272 public String
getValue() {
273 return (String
) super.getValue();
278 * CTF field implementation for arrays of integers.
282 final class CTFIntegerArrayField
extends CtfTmfEventField
{
284 private final int fBase
;
285 private final boolean fSigned
;
286 private String fFormattedValue
= null;
289 * Constructor for CTFIntegerArrayField.
292 * The name of this field
294 * The array of integers (as longs) that compose this field's
297 * Are the values in the array signed or not
299 CTFIntegerArrayField(String name
, long[] longValues
, int base
, boolean signed
) {
300 super(name
, longValues
, null);
306 public long[] getValue() {
307 return (long[]) super.getValue();
311 public synchronized String
getFormattedValue() {
312 if (fFormattedValue
== null) {
313 List
<String
> strings
= new ArrayList
<>();
314 for (long value
: getValue()) {
315 strings
.add(IntegerDefinition
.formatNumber(value
, fBase
, fSigned
));
317 fFormattedValue
= strings
.toString();
319 return fFormattedValue
;
325 * CTF field implementation for arrays of arbitrary types.
329 final class CTFArrayField
extends CtfTmfEventField
{
331 private String fFormattedValue
= null;
334 * Constructor for CTFArrayField.
337 * The name of this field
339 * The array elements of this field
341 CTFArrayField(String name
, CtfTmfEventField
[] elements
) {
342 super(name
, elements
, elements
);
346 public CtfTmfEventField
[] getValue() {
347 return (CtfTmfEventField
[]) super.getValue();
351 public synchronized String
getFormattedValue() {
352 if (fFormattedValue
== null) {
353 List
<String
> strings
= new ArrayList
<>();
354 for (CtfTmfEventField element
: getValue()) {
355 strings
.add(element
.getFormattedValue());
357 fFormattedValue
= strings
.toString();
359 return fFormattedValue
;
364 * CTF field implementation for floats.
368 final class CTFFloatField
extends CtfTmfEventField
{
371 * Constructor for CTFFloatField.
374 * The float value (actually a double) of this field
376 * The name of this field
378 protected CTFFloatField(String name
, double value
) {
379 super(name
, value
, null);
383 public Double
getValue() {
384 return (Double
) super.getValue();
389 * The CTF field implementation for Enum fields
391 * @author Bernd Hufmann
393 final class CTFEnumField
extends CtfTmfEventField
{
396 * Constructor for CTFEnumField.
399 * The Enum value consisting of a pair of Enum value name and its
402 * The name of this field
404 CTFEnumField(String name
, CtfEnumPair enumValue
) {
405 super(name
, new CtfEnumPair(enumValue
.getFirst(),
406 enumValue
.getSecond()), null);
410 public CtfEnumPair
getValue() {
411 return (CtfEnumPair
) super.getValue();
416 * The CTF field implementation for struct fields with sub-fields
420 final class CTFStructField
extends CtfTmfEventField
{
423 * Constructor for CTFStructField.
426 * The children of this field
428 * The name of this field
430 CTFStructField(String name
, CtfTmfEventField
[] fields
) {
431 super(name
, fields
, fields
);
435 public CtfTmfEventField
[] getValue() {
436 return (CtfTmfEventField
[]) super.getValue();
440 public String
getFormattedValue() {
441 return Arrays
.toString(getValue());
447 * The CTF field implementation for variant fields its child
451 final class CTFVariantField
extends CtfTmfEventField
{
454 * Constructor for CTFVariantField.
457 * The field selected for this variant
459 * The name of this field
461 CTFVariantField(String name
, CtfTmfEventField field
) {
462 super(name
, field
, new CtfTmfEventField
[] { field
});
466 public CtfTmfEventField
getValue() {
467 return (CtfTmfEventField
) super.getValue();
472 /* Implement other possible fields types here... */