f1d3a1ccb1ea36825e88b0080936db4e60895045
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ctf.core / src / org / eclipse / tracecompass / tmf / ctf / core / 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;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.List;
24
25 import org.eclipse.tracecompass.ctf.core.event.types.CompoundDeclaration;
26 import org.eclipse.tracecompass.ctf.core.event.types.Definition;
27 import org.eclipse.tracecompass.ctf.core.event.types.EnumDefinition;
28 import org.eclipse.tracecompass.ctf.core.event.types.FloatDefinition;
29 import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
30 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
31 import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
32 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
33 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
34 import org.eclipse.tracecompass.ctf.core.event.types.StringDefinition;
35 import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
36 import org.eclipse.tracecompass.internal.ctf.core.event.types.ArrayDefinition;
37 import org.eclipse.tracecompass.internal.ctf.core.event.types.ByteArrayDefinition;
38 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
39 import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
40
41 /**
42 * The CTF implementation of the TMF event field model
43 *
44 * @version 2.0
45 * @author Matthew Khouzam
46 * @author Alexandre Montplaisir
47 */
48 public abstract class CtfTmfEventField extends TmfEventField {
49
50 // ------------------------------------------------------------------------
51 // Constructor
52 // ------------------------------------------------------------------------
53
54 /**
55 * Standard constructor. Only to be used internally, call parseField() to
56 * generate a new field object.
57 *
58 * @param name
59 * The name of this field
60 * @param value
61 * The value of this field. Its type should match the field type.
62 * @param fields
63 * The children fields. Useful for composite fields
64 * @since 2.0
65 */
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$
69 value,
70 fields);
71 }
72
73 // ------------------------------------------------------------------------
74 // Operations
75 // ------------------------------------------------------------------------
76
77 /**
78 * Factory method to instantiate CtfTmfEventField objects.
79 *
80 * @param fieldDef
81 * The CTF Definition of this event field
82 * @param fieldName
83 * String The name to assign to this field
84 * @return The resulting CtfTmfEventField object
85 * @deprecated use {@link CtfTmfEventField#parseField(IDefinition, String)}
86 */
87 @Deprecated
88 public static CtfTmfEventField parseField(Definition fieldDef,
89 String fieldName) {
90 return parseField((IDefinition) fieldDef, fieldName);
91 }
92
93 /**
94 * Factory method to instantiate CtfTmfEventField objects.
95 *
96 * @param fieldDef
97 * The CTF Definition of this event field
98 * @param fieldName
99 * String The name to assign to this field
100 * @return The resulting CtfTmfEventField object
101 * @since 3.1
102 */
103 public static CtfTmfEventField parseField(IDefinition fieldDef,
104 String fieldName) {
105 CtfTmfEventField field = null;
106
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());
112
113 } else if (fieldDef instanceof EnumDefinition) {
114 EnumDefinition enumDef = (EnumDefinition) fieldDef;
115 field = new CTFEnumField(fieldName, new CtfEnumPair(enumDef.getValue(), enumDef.getIntegerValue()));
116
117 } else if (fieldDef instanceof StringDefinition) {
118 field = new CTFStringField(fieldName, ((StringDefinition) fieldDef).getValue());
119
120 } else if (fieldDef instanceof FloatDefinition) {
121 FloatDefinition floatDef = (FloatDefinition) fieldDef;
122 field = new CTFFloatField(fieldName, floatDef.getValue());
123
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$
129 }
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());
141 } else {
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);
146 if (elem == null) {
147 break;
148 }
149 values[i] = ((IntegerDefinition) elem).getValue();
150 }
151 field = new CTFIntegerArrayField(fieldName, values,
152 elemIntType.getBase(),
153 elemIntType.isSigned());
154 }
155 } else {
156 /* Arrays of elements of any other type */
157 CtfTmfEventField[] elements = new CtfTmfEventField[arrayDef.getLength()];
158 /* Parse the elements of the array. */
159 int i = 0;
160 for (IDefinition definition : definitions) {
161 CtfTmfEventField curField = CtfTmfEventField.parseField(
162 definition, fieldName + '[' + i + ']');
163 elements[i] = curField;
164 i++;
165 }
166
167 field = new CTFArrayField(fieldName, elements);
168 }
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());
172
173 } else if (fieldDef instanceof ICompositeDefinition) {
174 ICompositeDefinition strDef = (ICompositeDefinition) fieldDef;
175
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));
180 }
181 field = new CTFStructField(fieldName, list.toArray(new CtfTmfEventField[list.size()]));
182
183 } else if (fieldDef instanceof VariantDefinition) {
184 VariantDefinition varDef = (VariantDefinition) fieldDef;
185
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);
191 } else {
192 /* A safe-guard, but curFieldDef should never be null */
193 field = new CTFStringField(curFieldName, ""); //$NON-NLS-1$
194 }
195
196 } else {
197 /*
198 * Safe-guard, to avoid null exceptions later, field is expected not
199 * to be null
200 */
201 field = new CTFStringField(fieldName, Messages.CtfTmfEventField_UnsupportedType + fieldDef.getClass().toString());
202 }
203 return field;
204 }
205
206 @Override
207 public String toString() {
208 return getName() + '=' + getFormattedValue();
209 }
210
211 }
212
213 /**
214 * The CTF field implementation for integer fields.
215 *
216 * @author alexmont
217 */
218 final class CTFIntegerField extends CtfTmfEventField {
219
220 private final int fBase;
221 private final boolean fSigned;
222
223 /**
224 * A CTF "IntegerDefinition" can be an integer of any byte size, so in the
225 * Java parser this is interpreted as a long.
226 *
227 * @param name
228 * The name of this field
229 * @param longValue
230 * The integer value of this field
231 * @param signed
232 * Is the value signed or not
233 */
234 CTFIntegerField(String name, long longValue, int base, boolean signed) {
235 super(name, longValue, null);
236 fSigned = signed;
237 fBase = base;
238 }
239
240 @Override
241 public Long getValue() {
242 return (Long) super.getValue();
243 }
244
245 @Override
246 public String getFormattedValue() {
247 return IntegerDefinition.formatNumber(getValue(), fBase, fSigned);
248 }
249
250 }
251
252 /**
253 * The CTF field implementation for string fields
254 *
255 * @author alexmont
256 */
257 final class CTFStringField extends CtfTmfEventField {
258
259 /**
260 * Constructor for CTFStringField.
261 *
262 * @param strValue
263 * The string value of this field
264 * @param name
265 * The name of this field
266 */
267 CTFStringField(String name, String strValue) {
268 super(name, strValue, null);
269 }
270
271 @Override
272 public String getValue() {
273 return (String) super.getValue();
274 }
275 }
276
277 /**
278 * CTF field implementation for arrays of integers.
279 *
280 * @author alexmont
281 */
282 final class CTFIntegerArrayField extends CtfTmfEventField {
283
284 private final int fBase;
285 private final boolean fSigned;
286 private String fFormattedValue = null;
287
288 /**
289 * Constructor for CTFIntegerArrayField.
290 *
291 * @param name
292 * The name of this field
293 * @param longValues
294 * The array of integers (as longs) that compose this field's
295 * value
296 * @param signed
297 * Are the values in the array signed or not
298 */
299 CTFIntegerArrayField(String name, long[] longValues, int base, boolean signed) {
300 super(name, longValues, null);
301 fBase = base;
302 fSigned = signed;
303 }
304
305 @Override
306 public long[] getValue() {
307 return (long[]) super.getValue();
308 }
309
310 @Override
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));
316 }
317 fFormattedValue = strings.toString();
318 }
319 return fFormattedValue;
320 }
321
322 }
323
324 /**
325 * CTF field implementation for arrays of arbitrary types.
326 *
327 * @author fdoray
328 */
329 final class CTFArrayField extends CtfTmfEventField {
330
331 private String fFormattedValue = null;
332
333 /**
334 * Constructor for CTFArrayField.
335 *
336 * @param name
337 * The name of this field
338 * @param elements
339 * The array elements of this field
340 */
341 CTFArrayField(String name, CtfTmfEventField[] elements) {
342 super(name, elements, elements);
343 }
344
345 @Override
346 public CtfTmfEventField[] getValue() {
347 return (CtfTmfEventField[]) super.getValue();
348 }
349
350 @Override
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());
356 }
357 fFormattedValue = strings.toString();
358 }
359 return fFormattedValue;
360 }
361 }
362
363 /**
364 * CTF field implementation for floats.
365 *
366 * @author emathko
367 */
368 final class CTFFloatField extends CtfTmfEventField {
369
370 /**
371 * Constructor for CTFFloatField.
372 *
373 * @param value
374 * The float value (actually a double) of this field
375 * @param name
376 * The name of this field
377 */
378 protected CTFFloatField(String name, double value) {
379 super(name, value, null);
380 }
381
382 @Override
383 public Double getValue() {
384 return (Double) super.getValue();
385 }
386 }
387
388 /**
389 * The CTF field implementation for Enum fields
390 *
391 * @author Bernd Hufmann
392 */
393 final class CTFEnumField extends CtfTmfEventField {
394
395 /**
396 * Constructor for CTFEnumField.
397 *
398 * @param enumValue
399 * The Enum value consisting of a pair of Enum value name and its
400 * long value
401 * @param name
402 * The name of this field
403 */
404 CTFEnumField(String name, CtfEnumPair enumValue) {
405 super(name, new CtfEnumPair(enumValue.getFirst(),
406 enumValue.getSecond()), null);
407 }
408
409 @Override
410 public CtfEnumPair getValue() {
411 return (CtfEnumPair) super.getValue();
412 }
413 }
414
415 /**
416 * The CTF field implementation for struct fields with sub-fields
417 *
418 * @author gbastien
419 */
420 final class CTFStructField extends CtfTmfEventField {
421
422 /**
423 * Constructor for CTFStructField.
424 *
425 * @param fields
426 * The children of this field
427 * @param name
428 * The name of this field
429 */
430 CTFStructField(String name, CtfTmfEventField[] fields) {
431 super(name, fields, fields);
432 }
433
434 @Override
435 public CtfTmfEventField[] getValue() {
436 return (CtfTmfEventField[]) super.getValue();
437 }
438
439 @Override
440 public String getFormattedValue() {
441 return Arrays.toString(getValue());
442 }
443
444 }
445
446 /**
447 * The CTF field implementation for variant fields its child
448 *
449 * @author gbastien
450 */
451 final class CTFVariantField extends CtfTmfEventField {
452
453 /**
454 * Constructor for CTFVariantField.
455 *
456 * @param field
457 * The field selected for this variant
458 * @param name
459 * The name of this field
460 */
461 CTFVariantField(String name, CtfTmfEventField field) {
462 super(name, field, new CtfTmfEventField[] { field });
463 }
464
465 @Override
466 public CtfTmfEventField getValue() {
467 return (CtfTmfEventField) super.getValue();
468 }
469
470 }
471
472 /* Implement other possible fields types here... */
This page took 0.044406 seconds and 4 git commands to generate.