1 /*******************************************************************************
2 * Copyright (c) 2011, 2013 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 *******************************************************************************/
16 package org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Arrays
;
20 import java
.util
.List
;
21 import java
.util
.Map
.Entry
;
23 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.ArrayDeclaration
;
24 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.ArrayDefinition
;
25 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.Definition
;
26 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.EnumDefinition
;
27 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.FloatDefinition
;
28 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
29 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDefinition
;
30 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDeclaration
;
31 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDefinition
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDefinition
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDefinition
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDefinition
;
35 import org
.eclipse
.linuxtools
.internal
.tmf
.core
.Messages
;
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
);
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
;
107 ArrayDeclaration arrayDecl
= arrayDef
.getDeclaration();
109 if (arrayDef
.isString()) {
110 /* This is an array of UTF-8 bytes, a.k.a. a String! */
111 field
= new CTFStringField(fieldName
, fieldDef
.toString());
113 } else if (arrayDecl
.getElementType() instanceof IntegerDeclaration
) {
114 /* This is a an array of CTF Integers */
115 List
<Long
> values
= new ArrayList
<Long
>(arrayDecl
.getLength());
116 for (int i
= 0; i
< arrayDecl
.getLength(); i
++) {
117 values
.add(((IntegerDefinition
) arrayDef
.getElem(i
)).getValue());
119 field
= new CTFIntegerArrayField(fieldName
, values
, ((IntegerDeclaration
) arrayDecl
.getElementType()).getBase());
121 /* Add other types of arrays here */
123 } else if (fieldDef
instanceof SequenceDefinition
) {
124 SequenceDefinition seqDef
= (SequenceDefinition
) fieldDef
;
125 SequenceDeclaration seqDecl
= seqDef
.getDeclaration();
127 if (seqDef
.getLength() == 0) {
128 /* Some sequences have length = 0. Simply use an empty string */
129 field
= new CTFStringField(fieldName
, ""); //$NON-NLS-1$
130 } else if (seqDef
.isString()) {
131 /* Interpret this sequence as a String */
132 field
= new CTFStringField(fieldName
, seqDef
.toString());
133 } else if (seqDecl
.getElementType() instanceof IntegerDeclaration
) {
134 /* Sequence of integers => CTFIntegerArrayField */
135 List
<Long
> values
= new ArrayList
<Long
>(seqDef
.getLength());
136 for (int i
= 0; i
< seqDef
.getLength(); i
++) {
137 values
.add(((IntegerDefinition
) seqDef
.getElem(i
)).getValue());
139 field
= new CTFIntegerArrayField(fieldName
, values
, ((IntegerDeclaration
) seqDecl
.getElementType()).getBase());
141 /* Add other Sequence types here */
143 } else if (fieldDef
instanceof StructDefinition
) {
144 StructDefinition strDef
= (StructDefinition
) fieldDef
;
146 String curFieldName
= null;
147 Definition curFieldDef
;
148 CtfTmfEventField curField
;
149 List
<ITmfEventField
> list
= new ArrayList
<ITmfEventField
>();
150 /* Recursively parse the fields */
151 for (Entry
<String
, Definition
> entry
: strDef
.getDefinitions().entrySet()) {
152 curFieldName
= entry
.getKey();
153 curFieldDef
= entry
.getValue();
154 curField
= CtfTmfEventField
.parseField(curFieldDef
, curFieldName
);
157 field
= new CTFStructField(fieldName
, list
.toArray(new CtfTmfEventField
[list
.size()]));
159 } else if (fieldDef
instanceof VariantDefinition
) {
160 VariantDefinition varDef
= (VariantDefinition
) fieldDef
;
162 String curFieldName
= varDef
.getCurrentFieldName();
163 Definition curFieldDef
= varDef
.getDefinitions().get(curFieldName
);
164 if (curFieldDef
!= null) {
165 field
= CtfTmfEventField
.parseField(curFieldDef
, curFieldName
);
167 /* A safe-guard, but curFieldDef should never be null */
168 field
= new CTFStringField(curFieldName
, ""); //$NON-NLS-1$
172 /* Safe-guard, to avoid null exceptions later, field is expected not to be null */
173 field
= new CTFStringField(fieldName
, Messages
.TmfEventField_UnsupportedType
+ fieldDef
.getClass().toString());
179 public String
toString() {
180 return getName() + '=' + getValue().toString();
184 * Print a numeric value as a string in a given base
187 * The value to print as string
189 * The base for this value
190 * @return formatted number string
193 protected final static String
formatNumber(long value
, int base
) {
195 /* Format the number correctly according to the integer's base */
198 s
= "0b" + Long
.toBinaryString(value
); //$NON-NLS-1$
201 s
= "0" + Long
.toOctalString(value
); //$NON-NLS-1$
204 s
= Long
.toString(value
);
207 s
= "0x" + Long
.toHexString(value
); //$NON-NLS-1$
210 /* Non-standard base, we'll just print it as a decimal number */
211 s
= Long
.toString(value
);
220 * The CTF field implementation for integer fields.
224 final class CTFIntegerField
extends CtfTmfEventField
{
226 private final int base
;
229 * A CTF "IntegerDefinition" can be an integer of any byte size, so in the
230 * Java parser this is interpreted as a long.
233 * The integer value of this field
235 * The name of this field
237 CTFIntegerField(String name
, long longValue
, int base
) {
238 super(name
, longValue
, null);
243 public Long
getValue() {
244 return (Long
) super.getValue();
248 public String
getFormattedValue() {
249 return formatNumber(getValue(), base
);
253 * Custom-format the integer values depending on their base.
256 public String
toString() {
257 return getName() + '=' + formatNumber(getValue(), base
);
262 * The CTF field implementation for string fields
266 final class CTFStringField
extends CtfTmfEventField
{
269 * Constructor for CTFStringField.
272 * The string value of this field
274 * The name of this field
276 CTFStringField(String name
, String strValue
) {
277 super(name
, strValue
, null);
281 public String
getValue() {
282 return (String
) super.getValue();
287 * CTF field implementation for arrays of integers.
291 final class CTFIntegerArrayField
extends CtfTmfEventField
{
293 private final int base
;
294 private String formattedValue
= null;
297 * Constructor for CTFIntegerArrayField.
300 * The array of integers (as longs) that compose this field's
303 * The name of this field
305 CTFIntegerArrayField(String name
, List
<Long
> longValues
, int base
) {
306 super(name
, longValues
, null);
311 public List
<Long
> getValue() {
312 return (List
<Long
>) super.getValue();
316 public String
getFormattedValue() {
317 if (formattedValue
== null) {
318 List
<String
> strings
= new ArrayList
<String
>();
319 for (Long value
: getValue()) {
320 strings
.add(formatNumber(value
, base
));
322 formattedValue
= strings
.toString();
324 return formattedValue
;
328 * Custom-format the integer values depending on their base.
331 public String
toString() {
332 return getName() + '=' + getFormattedValue();
337 * CTF field implementation for floats.
341 final class CTFFloatField
extends CtfTmfEventField
{
344 * Constructor for CTFFloatField.
347 * The float value (actually a double) of this field
349 * The name of this field
351 protected CTFFloatField(String name
, double value
) {
352 super(name
, value
, null);
356 public Double
getValue() {
357 return (Double
) super.getValue();
362 * The CTF field implementation for Enum fields
364 * @author Bernd Hufmann
366 final class CTFEnumField
extends CtfTmfEventField
{
369 * Constructor for CTFEnumField.
372 * The Enum value consisting of a pair of Enum value name and its long value
374 * The name of this field
376 CTFEnumField(String name
, CtfEnumPair enumValue
) {
377 super(name
, new CtfEnumPair(enumValue
.getFirst(),
378 enumValue
.getSecond().longValue()), null);
382 public CtfEnumPair
getValue() {
383 return (CtfEnumPair
) super.getValue();
388 * The CTF field implementation for struct fields with sub-types
392 final class CTFStructField
extends CtfTmfEventField
{
395 * Constructor for CTFStringField.
398 * The string value of this field
400 * The name of this field
402 CTFStructField(String name
, CtfTmfEventField
[] fields
) {
403 super(name
, fields
, fields
);
407 public CtfTmfEventField
[] getValue() {
408 return (CtfTmfEventField
[]) super.getValue();
412 public String
toString() {
413 return getName() + '=' + Arrays
.toString(getValue());
417 /* Implement other possible fields types here... */