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
.linuxtools
.tmf
.ctf
.core
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Arrays
;
22 import java
.util
.List
;
23 import java
.util
.Map
.Entry
;
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
.tmf
.core
.event
.ITmfEventField
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfEventField
;
40 * The CTF implementation of the TMF event field model
43 * @author Matthew Khouzam
44 * @author Alexandre Montplaisir
46 public abstract class CtfTmfEventField
extends TmfEventField
{
48 // ------------------------------------------------------------------------
50 // ------------------------------------------------------------------------
53 * Standard constructor. Only to be used internally, call parseField() to
54 * generate a new field object.
57 * The name of this field
59 * The value of this field. Its type should match the field type.
61 * The children fields. Useful for composite fields
64 protected CtfTmfEventField(String name
, Object value
, ITmfEventField
[] fields
) {
65 super(/* Strip the underscore from the field name if there is one */
66 name
.startsWith("_") ? name
.substring(1) : name
, //$NON-NLS-1$
71 // ------------------------------------------------------------------------
73 // ------------------------------------------------------------------------
76 * Factory method to instantiate CtfTmfEventField objects.
79 * The CTF Definition of this event field
81 * String The name to assign to this field
82 * @return The resulting CtfTmfEventField object
84 public static CtfTmfEventField
parseField(Definition fieldDef
,
86 CtfTmfEventField field
= null;
88 /* Determine the Definition type */
89 if (fieldDef
instanceof IntegerDefinition
) {
90 IntegerDefinition intDef
= (IntegerDefinition
) fieldDef
;
91 int base
= intDef
.getDeclaration().getBase();
92 field
= new CTFIntegerField(fieldName
, intDef
.getValue(), base
, intDef
.getDeclaration().isSigned());
94 } else if (fieldDef
instanceof EnumDefinition
) {
95 EnumDefinition enumDef
= (EnumDefinition
) fieldDef
;
96 field
= new CTFEnumField(fieldName
, new CtfEnumPair(enumDef
.getValue(), enumDef
.getIntegerValue()));
98 } else if (fieldDef
instanceof StringDefinition
) {
99 field
= new CTFStringField(fieldName
, ((StringDefinition
) fieldDef
).getValue());
101 } else if (fieldDef
instanceof FloatDefinition
) {
102 FloatDefinition floatDef
= (FloatDefinition
) fieldDef
;
103 field
= new CTFFloatField(fieldName
, floatDef
.getValue());
105 } else if (fieldDef
instanceof ArrayDefinition
) {
106 ArrayDefinition arrayDef
= (ArrayDefinition
) fieldDef
;
108 if (arrayDef
.getDeclaration().isString()) {
109 /* This is an array of UTF-8 bytes, a.k.a. a String! */
110 field
= new CTFStringField(fieldName
, fieldDef
.toString());
113 /* Arrays of elements of any other type */
114 Definition
[] definitions
= arrayDef
.getDefinitions();
115 CtfTmfEventField
[] elements
= new CtfTmfEventField
[definitions
.length
];
117 /* Parse the elements of the array. */
118 for (int i
= 0; i
< definitions
.length
; i
++) {
119 CtfTmfEventField curField
= CtfTmfEventField
.parseField(
120 definitions
[i
], fieldName
+ '[' + i
+ ']');
121 elements
[i
] = curField
;
124 field
= new CTFArrayField(fieldName
, elements
);
126 } else if (fieldDef
instanceof SequenceDefinition
) {
127 SequenceDefinition seqDef
= (SequenceDefinition
) fieldDef
;
128 SequenceDeclaration seqDecl
= seqDef
.getDeclaration();
130 if (seqDef
.getLength() == 0) {
131 /* Some sequences have length = 0. Simply use an empty string */
132 field
= new CTFStringField(fieldName
, ""); //$NON-NLS-1$
133 } else if (seqDef
.isString()) {
134 /* Interpret this sequence as a String */
135 field
= new CTFStringField(fieldName
, seqDef
.toString());
136 } else if (seqDecl
.getElementType() instanceof IntegerDeclaration
) {
137 /* Sequence of integers => CTFIntegerArrayField */
138 long[] values
= new long[seqDef
.getLength()];
139 for (int i
= 0; i
< seqDef
.getLength(); i
++) {
140 values
[i
] = ((IntegerDefinition
) seqDef
.getElem(i
)).getValue();
142 field
= new CTFIntegerArrayField(fieldName
, values
,
143 ((IntegerDeclaration
) seqDecl
.getElementType()).getBase(),
144 ((IntegerDeclaration
) seqDecl
.getElementType()).isSigned());
147 /* Add other Sequence types here */
149 } else if (fieldDef
instanceof StructDefinition
) {
150 StructDefinition strDef
= (StructDefinition
) fieldDef
;
152 String curFieldName
= null;
153 Definition curFieldDef
;
154 CtfTmfEventField curField
;
155 List
<ITmfEventField
> list
= new ArrayList
<>();
156 /* Recursively parse the fields */
157 for (Entry
<String
, Definition
> entry
: strDef
.getDefinitions().entrySet()) {
158 curFieldName
= entry
.getKey();
159 curFieldDef
= entry
.getValue();
160 curField
= CtfTmfEventField
.parseField(curFieldDef
, curFieldName
);
163 field
= new CTFStructField(fieldName
, list
.toArray(new CtfTmfEventField
[list
.size()]));
165 } else if (fieldDef
instanceof VariantDefinition
) {
166 VariantDefinition varDef
= (VariantDefinition
) fieldDef
;
168 String curFieldName
= varDef
.getCurrentFieldName();
169 Definition curFieldDef
= varDef
.getDefinitions().get(curFieldName
);
170 if (curFieldDef
!= null) {
171 CtfTmfEventField subField
= CtfTmfEventField
.parseField(curFieldDef
, curFieldName
);
172 field
= new CTFVariantField(fieldName
, subField
);
174 /* A safe-guard, but curFieldDef should never be null */
175 field
= new CTFStringField(curFieldName
, ""); //$NON-NLS-1$
180 * Safe-guard, to avoid null exceptions later, field is expected not
183 field
= new CTFStringField(fieldName
, Messages
.CtfTmfEventField_UnsupportedType
+ fieldDef
.getClass().toString());
189 public String
toString() {
190 return getName() + '=' + getFormattedValue();
196 * The CTF field implementation for integer fields.
200 final class CTFIntegerField
extends CtfTmfEventField
{
202 private final int fBase
;
203 private final boolean fSigned
;
206 * A CTF "IntegerDefinition" can be an integer of any byte size, so in the
207 * Java parser this is interpreted as a long.
210 * The name of this field
212 * The integer value of this field
214 * Is the value signed or not
216 CTFIntegerField(String name
, long longValue
, int base
, boolean signed
) {
217 super(name
, longValue
, null);
223 public Long
getValue() {
224 return (Long
) super.getValue();
228 public String
getFormattedValue() {
229 return IntegerDefinition
.formatNumber(getValue(), fBase
, fSigned
);
235 * The CTF field implementation for string fields
239 final class CTFStringField
extends CtfTmfEventField
{
242 * Constructor for CTFStringField.
245 * The string value of this field
247 * The name of this field
249 CTFStringField(String name
, String strValue
) {
250 super(name
, strValue
, null);
254 public String
getValue() {
255 return (String
) super.getValue();
260 * CTF field implementation for arrays of integers.
264 final class CTFIntegerArrayField
extends CtfTmfEventField
{
266 private final int fBase
;
267 private final boolean fSigned
;
268 private String fFormattedValue
= null;
271 * Constructor for CTFIntegerArrayField.
274 * The name of this field
276 * The array of integers (as longs) that compose this field's
279 * Are the values in the array signed or not
281 CTFIntegerArrayField(String name
, long[] longValues
, int base
, boolean signed
) {
282 super(name
, longValues
, null);
288 public long[] getValue() {
289 return (long[]) super.getValue();
293 public synchronized String
getFormattedValue() {
294 if (fFormattedValue
== null) {
295 List
<String
> strings
= new ArrayList
<>();
296 for (long value
: getValue()) {
297 strings
.add(IntegerDefinition
.formatNumber(value
, fBase
, fSigned
));
299 fFormattedValue
= strings
.toString();
301 return fFormattedValue
;
307 * CTF field implementation for arrays of arbitrary types.
311 final class CTFArrayField
extends CtfTmfEventField
{
313 private String fFormattedValue
= null;
316 * Constructor for CTFArrayField.
319 * The name of this field
321 * The array elements of this field
323 CTFArrayField(String name
, CtfTmfEventField
[] elements
) {
324 super(name
, elements
, elements
);
328 public CtfTmfEventField
[] getValue() {
329 return (CtfTmfEventField
[]) super.getValue();
333 public synchronized String
getFormattedValue() {
334 if (fFormattedValue
== null) {
335 List
<String
> strings
= new ArrayList
<>();
336 for (CtfTmfEventField element
: getValue()) {
337 strings
.add(element
.getFormattedValue());
339 fFormattedValue
= strings
.toString();
341 return fFormattedValue
;
346 * CTF field implementation for floats.
350 final class CTFFloatField
extends CtfTmfEventField
{
353 * Constructor for CTFFloatField.
356 * The float value (actually a double) of this field
358 * The name of this field
360 protected CTFFloatField(String name
, double value
) {
361 super(name
, value
, null);
365 public Double
getValue() {
366 return (Double
) super.getValue();
371 * The CTF field implementation for Enum fields
373 * @author Bernd Hufmann
375 final class CTFEnumField
extends CtfTmfEventField
{
378 * Constructor for CTFEnumField.
381 * The Enum value consisting of a pair of Enum value name and its
384 * The name of this field
386 CTFEnumField(String name
, CtfEnumPair enumValue
) {
387 super(name
, new CtfEnumPair(enumValue
.getFirst(),
388 enumValue
.getSecond()), null);
392 public CtfEnumPair
getValue() {
393 return (CtfEnumPair
) super.getValue();
398 * The CTF field implementation for struct fields with sub-fields
402 final class CTFStructField
extends CtfTmfEventField
{
405 * Constructor for CTFStructField.
408 * The children of this field
410 * The name of this field
412 CTFStructField(String name
, CtfTmfEventField
[] fields
) {
413 super(name
, fields
, fields
);
417 public CtfTmfEventField
[] getValue() {
418 return (CtfTmfEventField
[]) super.getValue();
422 public String
getFormattedValue() {
423 return Arrays
.toString(getValue());
429 * The CTF field implementation for variant fields its child
433 final class CTFVariantField
extends CtfTmfEventField
{
436 * Constructor for CTFVariantField.
439 * The field selected for this variant
441 * The name of this field
443 CTFVariantField(String name
, CtfTmfEventField field
) {
444 super(name
, field
, new CtfTmfEventField
[] { field
});
448 public CtfTmfEventField
getValue() {
449 return (CtfTmfEventField
) super.getValue();
454 /* Implement other possible fields types here... */