1 /*******************************************************************************
2 * Copyright (c) 2010, 2016 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made 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 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.core
.parsers
.custom
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.nullToEmptyString
;
18 import java
.text
.ParseException
;
19 import java
.util
.Collection
;
20 import java
.util
.LinkedHashMap
;
22 import java
.util
.Map
.Entry
;
23 import java
.util
.Objects
;
25 import org
.eclipse
.jdt
.annotation
.NonNull
;
26 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.parsers
.custom
.CustomExtraField
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventType
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEvent
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEventField
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEventType
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.parsers
.custom
.CustomTraceDefinition
.OutputColumn
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.parsers
.custom
.CustomTraceDefinition
.Tag
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestampFormat
;
37 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
40 import com
.google
.common
.collect
.Iterables
;
43 * Base event for custom text parsers.
45 * @author Patrick Tassé
47 public class CustomEvent
extends TmfEvent
{
49 /** Payload data map key
52 /** Timestamp input format */
53 TIMESTAMP_INPUT_FORMAT
57 * @deprecated Use {@link Key#TIMESTAMP_INPUT_FORMAT} instead. */
59 protected static final String TIMESTAMP_INPUT_FORMAT_KEY
= "CE_TS_I_F"; //$NON-NLS-1$
62 protected static final String NO_MESSAGE
= ""; //$NON-NLS-1$
64 /** Replacement for the super-class' timestamp field */
65 private @NonNull ITmfTimestamp customEventTimestamp
;
67 /** Replacement for the super-class' content field */
68 private ITmfEventField customEventContent
;
70 /** Replacement for the super-class' type field */
71 private ITmfEventType customEventType
;
73 /** The trace to which this event belongs */
74 protected CustomTraceDefinition fDefinition
;
77 * The payload data of this event, where the key is one of: the {@link Tag},
78 * the field name string if the tag is {@link Tag#OTHER}, or
79 * {@link Key#TIMESTAMP_INPUT_FORMAT}.
81 protected Map
<Object
, String
> fData
;
87 * The trace definition to which this event belongs
89 public CustomEvent(CustomTraceDefinition definition
) {
90 super(null, ITmfContext
.UNKNOWN_RANK
, null, null, null);
91 fDefinition
= definition
;
92 fData
= new LinkedHashMap
<>();
93 customEventTimestamp
= TmfTimestamp
.ZERO
;
97 * Build a new CustomEvent from an existing TmfEvent.
100 * The trace definition to which this event belongs
102 * The TmfEvent to copy
104 public CustomEvent(CustomTraceDefinition definition
, @NonNull TmfEvent other
) {
106 fDefinition
= definition
;
107 fData
= new LinkedHashMap
<>();
109 /* Set our overridden fields */
110 customEventTimestamp
= other
.getTimestamp();
111 customEventContent
= other
.getContent();
112 customEventType
= other
.getType();
119 * Trace definition of this event
121 * Parent trace object
123 * Timestamp of this event
127 public CustomEvent(CustomTraceDefinition definition
, ITmfTrace parentTrace
,
128 ITmfTimestamp timestamp
, TmfEventType type
) {
129 /* Do not use upstream's fields for stuff we override */
130 super(parentTrace
, ITmfContext
.UNKNOWN_RANK
, null, null, null);
131 fDefinition
= definition
;
132 fData
= new LinkedHashMap
<>();
134 /* Set our overridden fields */
135 if (timestamp
== null) {
136 customEventTimestamp
= TmfTimestamp
.ZERO
;
138 customEventTimestamp
= timestamp
;
140 customEventContent
= null;
141 customEventType
= type
;
144 // ------------------------------------------------------------------------
145 // Overridden getters
146 // ------------------------------------------------------------------------
149 public ITmfTimestamp
getTimestamp() {
153 return customEventTimestamp
;
157 public ITmfEventField
getContent() {
161 return customEventContent
;
165 public ITmfEventType
getType() {
166 return customEventType
;
170 public String
getName() {
174 return super.getName();
177 // ------------------------------------------------------------------------
179 // ------------------------------------------------------------------------
182 * Set this event's timestamp
187 protected void setTimestamp(@NonNull ITmfTimestamp timestamp
) {
188 customEventTimestamp
= timestamp
;
192 * Set this event's content
197 protected void setContent(ITmfEventField content
) {
198 customEventContent
= content
;
202 * Get this event's content value.
204 * This does not process the payload data and is therefore safe to call in
205 * the middle of parsing an event.
207 * @return the event's content value.
209 Object
getContentValue() {
210 return customEventContent
.getValue();
214 * Set this event's type
219 protected void setType(ITmfEventType type
) {
220 customEventType
= type
;
223 // ------------------------------------------------------------------------
225 // ------------------------------------------------------------------------
228 * Get the contents of an event table cell for this event's row.
231 * The ID/index of the field to display. This corresponds to the
232 * index in the event content.
233 * @return The String to display in the cell
234 * @deprecated Use {@link ITmfEventField#getField(String...)} instead.
237 public String
getEventString(int index
) {
238 Collection
<?
extends ITmfEventField
> fields
= getContent().getFields();
239 if (index
< 0 || index
>= fields
.size()) {
240 return ""; //$NON-NLS-1$
243 return nullToEmptyString(checkNotNull(Iterables
.get(fields
, index
)).getValue());
246 private void processData() {
247 // Remove the values as they are processed, so we can process the extra values at the end
248 String timestampString
= fData
.remove(Tag
.TIMESTAMP
);
249 String timestampInputFormat
= fData
.remove(Key
.TIMESTAMP_INPUT_FORMAT
);
250 ITmfTimestamp timestamp
= null;
251 if (timestampInputFormat
!= null && timestampString
!= null) {
252 TmfTimestampFormat timestampFormat
= new TmfTimestampFormat(timestampInputFormat
);
254 long time
= timestampFormat
.parseValue(timestampString
);
255 timestamp
= TmfTimestamp
.fromNanos(getTrace().getTimestampTransform().transform(time
));
256 setTimestamp(timestamp
);
257 } catch (ParseException e
) {
258 setTimestamp(TmfTimestamp
.ZERO
);
261 setTimestamp(TmfTimestamp
.ZERO
);
264 // Update the custom event type of this event if set
265 String eventName
= fData
.remove(Tag
.EVENT_TYPE
);
266 ITmfEventType type
= getType();
267 if (eventName
!= null && type
instanceof CustomEventType
) {
268 ((CustomEventType
) type
).setName(eventName
);
271 Map
<String
, TmfEventField
> fieldMap
= new LinkedHashMap
<>();
272 for (OutputColumn outputColumn
: fDefinition
.outputs
) {
273 if (outputColumn
.tag
.equals(Tag
.TIMESTAMP
)) {
274 if (timestamp
!= null && fDefinition
.timeStampOutputFormat
!= null && !fDefinition
.timeStampOutputFormat
.isEmpty()) {
275 TmfTimestampFormat timestampFormat
= new TmfTimestampFormat(fDefinition
.timeStampOutputFormat
);
276 fieldMap
.put(outputColumn
.name
, new TmfEventField(outputColumn
.name
, timestampFormat
.format(timestamp
.getValue()), null));
278 } else if (outputColumn
.tag
.equals(Tag
.OTHER
) || outputColumn
.tag
.equals(Tag
.MESSAGE
)) {
279 Object key
= (outputColumn
.tag
.equals(Tag
.OTHER
) ? outputColumn
.name
: outputColumn
.tag
);
280 fieldMap
.put(outputColumn
.name
, new TmfEventField(outputColumn
.name
, nullToEmptyString(fData
.remove(key
)), null));
283 // This event contains extra values, we process them now
284 for (Entry
<Object
, String
> entry
: fData
.entrySet()) {
285 String fieldName
= nullToEmptyString(entry
.getKey().toString());
286 // Ignore extra fields if a field of same name is already set
287 if (!fieldMap
.containsKey(fieldName
)) {
288 fieldMap
.put(fieldName
, new CustomExtraField(fieldName
, nullToEmptyString(entry
.getValue()), null));
291 setContent(new CustomEventContent(customEventContent
.getName(), customEventContent
.getValue(), fieldMap
.values().toArray(new ITmfEventField
[fieldMap
.size()])));
296 public int hashCode() {
297 final int prime
= 31;
298 int result
= super.hashCode();
299 result
= prime
* result
+ ((fDefinition
== null) ?
0 : fDefinition
.hashCode());
300 result
= prime
* result
+ customEventTimestamp
.hashCode();
301 result
= prime
* result
+ ((customEventContent
== null) ?
0 : customEventContent
.hashCode());
302 result
= prime
* result
+ ((customEventType
== null) ?
0 : customEventType
.hashCode());
307 public boolean equals(Object obj
) {
311 if (!super.equals(obj
)) {
314 if (!(obj
instanceof CustomEvent
)) {
317 CustomEvent other
= (CustomEvent
) obj
;
318 if (!Objects
.equals(fDefinition
, other
.fDefinition
)) {
322 if (!customEventTimestamp
.equals(other
.customEventTimestamp
)) {
326 if (!Objects
.equals(customEventContent
, other
.customEventContent
)) {
330 if (!Objects
.equals(customEventType
, other
.customEventType
)) {