package org.eclipse.tracecompass.tmf.core.tests.parsers.custom;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.BufferedWriter;
import java.io.File;
import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTraceDefinition;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTraceDefinition.Tag;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtEvent;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTrace;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition;
/**
* Constructor
*
- * @param name The name of the test
- * @param data The test data
+ * @param name
+ * The name of the test
+ * @param data
+ * The test data
*/
public CustomTxtTraceDataTest(String name, @NonNull ICustomTestData data) {
super(data);
}
-
private static CustomTxtTraceDefinition getDefinition(int index) {
CustomTxtTraceDefinition[] definitions = CustomTxtTraceDefinition.loadAll(new File(DEFINITION_PATH).toString());
return definitions[index];
};
+ private static final ICustomTestData CUSTOM_TXT_EXTRA_FIELDS = new ICustomTestData() {
+
+ private static final int NB_EVENTS = 6;
+ private static final String FOO = "foo";
+ private static final String BAR = "bar";
+ private static final String BAZ = "baz";
+ private static final String MESSAGE = "message";
+ private CustomTxtTraceDefinition fDefinition;
+
+ @Override
+ public ITmfTrace getTrace() throws IOException, TmfTraceException {
+ fDefinition = getDefinition(2);
+ final File file = new File(TRACE_PATH);
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(file));) {
+ // Event with one field to set
+ String eventStr = String.format("1 %s %s=%s\n", MESSAGE, FOO, BAR);
+ writer.write(eventStr);
+ // Event with 2 different fields and different values
+ eventStr = String.format("2 %s %s=%s %s=%s\n", MESSAGE, FOO, BAR, BAR, FOO);
+ writer.write(eventStr);
+ // Event with an extra field that conflicts with a built-in field
+ eventStr = String.format("3 %s Message=%s\n", MESSAGE, FOO);
+ writer.write(eventStr);
+ // Event with 2 extra fields with same name where the values
+ // should be appended
+ eventStr = String.format("4 %s %s=%s %s=%s\n", MESSAGE, FOO, BAR, FOO, BAZ);
+ writer.write(eventStr);
+ // Event with 2 extra fields with same name, where the values
+ // should be set
+ eventStr = String.format("5 %s %s=%s %s=%s %s=%s\n", MESSAGE, FOO, BAR, FOO, BAZ, BAR, BAZ);
+ writer.write(eventStr);
+ // Event with 2 non matching number extra field names/values
+ eventStr = String.format("6 %s %s=%s other %s\n", MESSAGE, FOO, BAR, BAZ);
+ writer.write(eventStr);
+ }
+ return new CustomTxtTrace(null, fDefinition, file.getPath(), BLOCK_SIZE);
+ }
+
+ @Override
+ public void validateEvent(ITmfEvent event) {
+ assertTrue(event instanceof CustomTxtEvent);
+ long ts = event.getTimestamp().getValue();
+ switch ((int) ts) {
+ case 1:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAR, event.getContent().getField(FOO).getValue());
+ assertNull(event.getContent().getField(BAR));
+ break;
+ case 2:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAR, event.getContent().getField(FOO).getValue());
+ assertNotNull(event.getContent().getField(BAR));
+ assertEquals(FOO, event.getContent().getField(BAR).getValue());
+ break;
+ case 3:
+ assertNotNull(event.getContent().getField(Tag.MESSAGE.toString()));
+ assertEquals(MESSAGE, event.getContent().getField(Tag.MESSAGE.toString()).getValue());
+ break;
+ case 4:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAR + CustomTraceDefinition.SEPARATOR + BAZ, event.getContent().getField(FOO).getValue());
+ assertNull(event.getContent().getField(BAR));
+ break;
+ case 5:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAZ, event.getContent().getField(FOO).getValue());
+ assertNotNull(event.getContent().getField(BAR));
+ assertEquals(BAZ, event.getContent().getField(BAR).getValue());
+ break;
+ case 6:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAR + CustomTraceDefinition.SEPARATOR + BAZ, event.getContent().getField(FOO).getValue());
+ assertNull(event.getContent().getField(BAR));
+ break;
+ default:
+ fail("unknown timestamp " + ts);
+ }
+ assertEquals("Event name and type", event.getType().getName(), event.getName());
+ }
+
+ @Override
+ public void validateEventCount(int eventCount) {
+ assertEquals("Event count", NB_EVENTS, eventCount);
+ }
+
+ };
+
/**
* @return The arrays of parameters
*/
public static Iterable<Object[]> getParameters() {
return Arrays.asList(new Object[][] {
{ "Base parser", CUSTOM_TXT },
- { "Parse with event name", CUSTOM_TXT_EVENT_NAME }
+ { "Parse with event name", CUSTOM_TXT_EVENT_NAME },
+ { "Parse with extra fields", CUSTOM_TXT_EXTRA_FIELDS }
});
}
package org.eclipse.tracecompass.tmf.core.tests.parsers.custom;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.BufferedWriter;
import java.io.File;
import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTraceDefinition;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlEvent;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTrace;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTraceDefinition;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTraceDefinition.Tag;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
};
+ private static final ICustomTestData CUSTOM_XML_EXTRA_FIELDS = new ICustomTestData() {
+
+ private static final int NB_EVENTS = 5;
+ private static final String FOO = "foo";
+ private static final String BAR = "bar";
+ private static final String BAZ = "baz";
+ private static final String MESSAGE = "message";
+ private CustomXmlTraceDefinition fDefinition;
+
+ @Override
+ public ITmfTrace getTrace() throws IOException, TmfTraceException {
+ fDefinition = getDefinition(2);
+ final File file = new File(TRACE_PATH);
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(file));) {
+ writer.write("<trace>");
+ // Event with one field to set
+ String eventStr = String.format("<event timestamp=\"%s\" name=\"%s\">\n", "1", MESSAGE);
+ eventStr += String.format("<field name=\"%s\" value=\"%s\"/>\n", FOO, BAR);
+ eventStr += "</event>\n";
+ writer.write(eventStr);
+ // Event with 2 different fields and different values
+ eventStr = String.format("<event timestamp=\"%s\" name=\"%s\">\n", "2", MESSAGE);
+ eventStr += String.format("<field name=\"%s\" value=\"%s\"/>\n", FOO, BAR);
+ eventStr += String.format("<field name=\"%s\" value=\"%s\"/>\n", BAR, FOO);
+ eventStr += "</event>\n";
+ writer.write(eventStr);
+ // Event with an extra field that conflicts with a built-in field
+ eventStr = String.format("<event timestamp=\"%s\" name=\"%s\">\n", "3", MESSAGE);
+ eventStr += String.format("<field name=\"Message\" value=\"%s\"/>\n", FOO);
+ eventStr += "</event>\n";
+ writer.write(eventStr);
+ // Event with 2 extra fields with same name where the values
+ // should be appended
+ eventStr = String.format("<event timestamp=\"%s\" name=\"%s\">\n", "4", MESSAGE);
+ eventStr += String.format("<field name=\"%s\" value=\"%s\"/>\n", FOO, BAR);
+ eventStr += String.format("<field name=\"%s\" value=\"%s\"/>\n", FOO, BAZ);
+ eventStr += "</event>\n";
+ writer.write(eventStr);
+ // Event with 2 non matching number extra field names/values
+ eventStr = String.format("<event timestamp=\"%s\" name=\"%s\">\n", "5", MESSAGE);
+ eventStr += String.format("<fieldName value=\"%s\"/>\n", FOO);
+ eventStr += String.format("<fieldValue value=\"%s\"/>\n", BAR);
+ eventStr += String.format("<fieldValue value=\"%s\"/>\n", BAZ);
+ eventStr += "</event>\n";
+ writer.write(eventStr);
+ writer.write("</trace>");
+ }
+ return new CustomXmlTrace(null, fDefinition, file.getPath(), BLOCK_SIZE);
+ }
+
+ @Override
+ public void validateEvent(ITmfEvent event) {
+ assertTrue(event instanceof CustomXmlEvent);
+ long ts = event.getTimestamp().getValue();
+ switch ((int) ts) {
+ case 1:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAR, event.getContent().getField(FOO).getValue());
+ assertNull(event.getContent().getField(BAR));
+ break;
+ case 2:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAR, event.getContent().getField(FOO).getValue());
+ assertNotNull(event.getContent().getField(BAR));
+ assertEquals(FOO, event.getContent().getField(BAR).getValue());
+ break;
+ case 3:
+ assertNotNull(event.getContent().getField(Tag.MESSAGE.toString()));
+ assertEquals(MESSAGE, event.getContent().getField(Tag.MESSAGE.toString()).getValue());
+ break;
+ case 4:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAR + CustomTraceDefinition.SEPARATOR + BAZ, event.getContent().getField(FOO).getValue());
+ assertNull(event.getContent().getField(BAR));
+ break;
+ case 5:
+ assertNotNull(event.getContent().getField(FOO));
+ assertEquals(BAZ, event.getContent().getField(FOO).getValue());
+ assertNull(event.getContent().getField(BAR));
+ break;
+ default:
+ fail("unknown timestamp " + ts);
+ }
+ assertEquals("Event name and type", event.getType().getName(), event.getName());
+ }
+
+ @Override
+ public void validateEventCount(int eventCount) {
+ assertEquals("Event count", NB_EVENTS, eventCount);
+ }
+
+ };
+
/**
* @return The arrays of parameters
*/
public static Iterable<Object[]> getParameters() {
return Arrays.asList(new Object[][] {
{ "Base parser", CUSTOM_XML },
- { "Parse with event name", CUSTOM_XML_EVENT_NAME }
+ { "Parse with event name", CUSTOM_XML_EVENT_NAME },
+ { "Parse with extra fields", CUSTOM_XML_EXTRA_FIELDS }
});
}
<OutputColumn name="Timestamp" tag="TIMESTAMP"/>
<OutputColumn name="Event type" tag="EVENT_TYPE"/>
</Definition>
+<Definition category="Custom Text" name="testtxtcustomfields">
+<TimeStampOutputFormat>dd/MM/yyyy HH:mm:ss:SSS</TimeStampOutputFormat>
+<InputLine>
+<Cardinality max="2147483647" min="0"/>
+<RegEx>(\d*) ([\w|\d]*)\s*([\w|\d]*)=([\w|\d]*)</RegEx>
+<InputData action="0" format="Tn" name="Timestamp" tag="TIMESTAMP"/>
+<InputData action="0" format="" name="Message" tag="MESSAGE"/>
+<InputData action="0" format="" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+<InputData action="2" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+</InputLine>
+<InputLine>
+<Cardinality max="2147483647" min="0"/>
+<RegEx>(\d*) ([\w|\d]*)\s*([\w|\d]*)=([\w|\d]*)\s*([\w|\d]*)=([\w|\d]*)</RegEx>
+<InputData action="0" format="Tn" name="Timestamp" tag="TIMESTAMP"/>
+<InputData action="0" format="" name="Message" tag="MESSAGE"/>
+<InputData action="2" format="" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+<InputData action="2" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+<InputData action="2" format="" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+<InputData action="2" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+</InputLine>
+<InputLine>
+<Cardinality max="2147483647" min="0"/>
+<RegEx>(\d*) ([\w|\d]*)\s*([\w|\d]*)=([\w|\d]*) other ([\w|\d]*)</RegEx>
+<InputData action="0" format="Tn" name="Timestamp" tag="TIMESTAMP"/>
+<InputData action="0" format="" name="Message" tag="MESSAGE"/>
+<InputData action="2" format="" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+<InputData action="2" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+<InputData action="2" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+</InputLine>
+<InputLine>
+<Cardinality max="2147483647" min="0"/>
+<RegEx>(\d*) ([\w|\d]*)\s*([\w|\d]*)=([\w|\d]*)\s*([\w|\d]*)=([\w|\d]*)\s*([\w|\d]*)=([\w|\d]*)</RegEx>
+<InputData action="0" format="Tn" name="Timestamp" tag="TIMESTAMP"/>
+<InputData action="0" format="" name="Message" tag="MESSAGE"/>
+<InputData action="0" format="" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+<InputData action="0" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+<InputData action="0" format="" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+<InputData action="0" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+<InputData action="0" format="" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+<InputData action="0" format="" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+</InputLine>
+<OutputColumn name="Timestamp" tag="TIMESTAMP"/>
+<OutputColumn name="Message" tag="MESSAGE"/>
+<OutputColumn name="Extra fields" tag="EXTRA_FIELDS"/>
+</Definition>
</CustomTxtTraceDefinitionList>
<OutputColumn name="Timestamp" tag="TIMESTAMP"/>
<OutputColumn name="Event type" tag="EVENT_TYPE"/>
</Definition>
+<Definition category="Custom XML" name="xmleventfields">
+<TimeStampOutputFormat>Tn</TimeStampOutputFormat>
+<InputElement name="trace">
+<InputElement logentry="true" name="event">
+<InputData action="0" name="Ignore" tag="IGNORE"/>
+<Attribute name="name">
+<InputData action="0" name="Message" tag="MESSAGE"/>
+</Attribute>
+<Attribute name="timestamp">
+<InputData action="0" format="Tn" name="Timestamp" tag="TIMESTAMP"/>
+</Attribute>
+<InputElement name="field">
+<InputData action="0" name="Ignore" tag="IGNORE"/>
+<Attribute name="name">
+<InputData action="2" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+</Attribute>
+<Attribute name="value">
+<InputData action="2" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+</Attribute>
+</InputElement>
+<InputElement name="fieldName">
+<InputData action="0" name="Ignore" tag="IGNORE"/>
+<Attribute name="value">
+<InputData action="0" name="Extra field name" tag="EXTRA_FIELD_NAME"/>
+</Attribute>
+</InputElement>
+<InputElement name="fieldValue">
+<InputData action="0" name="Ignore" tag="IGNORE"/>
+<Attribute name="value">
+<InputData action="0" name="Extra field value" tag="EXTRA_FIELD_VALUE"/>
+</Attribute>
+</InputElement>
+</InputElement>
+</InputElement>
+<OutputColumn name="Message" tag="MESSAGE"/>
+<OutputColumn name="Timestamp" tag="TIMESTAMP"/>
+<OutputColumn name="Extra fields" tag="EXTRA_FIELDS"/>
+</Definition>
</CustomXMLTraceDefinitionList>
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 2.1.0.qualifier
+Bundle-Version: 2.2.0.qualifier
Bundle-Localization: plugin
Bundle-SymbolicName: org.eclipse.tracecompass.tmf.core;singleton:=true
Bundle-Activator: org.eclipse.tracecompass.internal.tmf.core.Activator
package org.eclipse.tracecompass.internal.tmf.core.parsers.custom;
+import java.util.ArrayList;
+import java.util.List;
+
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
* @return The set of event aspects for the given trace
*/
public static @NonNull Iterable<ITmfEventAspect<?>> generateAspects(CustomTraceDefinition definition) {
+ List<String> fieldNames = new ArrayList<>();
ImmutableList.Builder<ITmfEventAspect<?>> builder = new ImmutableList.Builder<>();
for (OutputColumn output : definition.outputs) {
+
if (output.tag.equals(Tag.TIMESTAMP) &&
(definition.timeStampOutputFormat == null || definition.timeStampOutputFormat.isEmpty())) {
builder.add(TmfBaseAspects.getTimestampAspect());
+ fieldNames.add(output.name);
} else if (output.tag.equals(Tag.EVENT_TYPE)) {
builder.add(TmfBaseAspects.getEventTypeAspect());
+ fieldNames.add(output.name);
+ } else if (output.tag.equals(Tag.EXTRA_FIELD_NAME) || output.tag.equals(Tag.EXTRA_FIELD_VALUE)) {
+ // These tags should have been substituted with Tag.EXTRA_FIELDS
+ continue;
+ } else if (output.tag.equals(Tag.EXTRA_FIELDS)) {
+ builder.add(new CustomExtraFieldsAspect());
} else {
builder.add(new TmfContentFieldAspect(output.name, output.name));
+ fieldNames.add(output.name);
}
}
return builder.build();
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.core.parsers.custom;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
+
+/**
+ * A type of field for the custom parser's extra field.
+ *
+ * @author Geneviève Bastien
+ */
+public class CustomExtraField extends TmfEventField {
+
+ /**
+ * Full constructor
+ *
+ * @param name
+ * the event field id
+ * @param value
+ * the event field value
+ * @param fields
+ * the list of subfields
+ * @throws IllegalArgumentException
+ * If 'name' is null, or if 'fields' has duplicate field names.
+ */
+ public CustomExtraField(@NonNull String name, @Nullable Object value, ITmfEventField @Nullable [] fields) {
+ super(name, value, fields);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param field
+ * the other event field
+ */
+ public CustomExtraField(final TmfEventField field) {
+ super(field);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.core.parsers.custom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
+import org.eclipse.tracecompass.tmf.core.parsers.custom.Messages;
+
+/**
+ * An aspect for a custom event's extra fields
+ *
+ * @author Geneviève Bastien
+ */
+public class CustomExtraFieldsAspect implements ITmfEventAspect<String> {
+
+ /**
+ * Constructor
+ */
+ public CustomExtraFieldsAspect() {
+ }
+
+ @Override
+ public @NonNull String getName() {
+ return NonNullUtils.nullToEmptyString(Messages.CustomExtraFieldsAspect_extraFieldsAspectName);
+ }
+
+ @Override
+ public @NonNull String getHelpText() {
+ return NonNullUtils.nullToEmptyString(Messages.CustomExtraFieldsAspect_extraFieldsAspectHelp);
+ }
+
+ @Override
+ public @Nullable String resolve(@NonNull ITmfEvent event) {
+ List<String> fields = new ArrayList<>();
+ for (ITmfEventField field : event.getContent().getFields()) {
+ // Add the fields that do not have another aspect associated
+ if (field instanceof CustomExtraField) {
+ fields.add(field.getName() + '=' + field.getValue());
+ }
+ }
+ return String.join(", ", fields); //$NON-NLS-1$
+ }
+
+}
import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
import java.text.ParseException;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
+import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.internal.tmf.core.parsers.custom.CustomExtraField;
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
import org.eclipse.tracecompass.tmf.core.event.ITmfEventType;
import org.eclipse.tracecompass.tmf.core.event.TmfEvent;
public CustomEvent(CustomTraceDefinition definition) {
super(null, ITmfContext.UNKNOWN_RANK, null, null, null);
fDefinition = definition;
- fData = new HashMap<>();
+ fData = new LinkedHashMap<>();
customEventTimestamp = TmfTimestamp.ZERO;
}
public CustomEvent(CustomTraceDefinition definition, @NonNull TmfEvent other) {
super(other);
fDefinition = definition;
- fData = new HashMap<>();
+ fData = new LinkedHashMap<>();
/* Set our overridden fields */
customEventTimestamp = other.getTimestamp();
/* Do not use upstream's fields for stuff we override */
super(parentTrace, ITmfContext.UNKNOWN_RANK, null, null, null);
fDefinition = definition;
- fData = new HashMap<>();
+ fData = new LinkedHashMap<>();
/* Set our overridden fields */
if (timestamp == null) {
}
private void processData() {
- String timestampString = fData.get(Tag.TIMESTAMP);
- String timestampInputFormat = fData.get(Key.TIMESTAMP_INPUT_FORMAT);
+ // Remove the values as they are processed, so we can process the extra values at the end
+ String timestampString = fData.remove(Tag.TIMESTAMP);
+ String timestampInputFormat = fData.remove(Key.TIMESTAMP_INPUT_FORMAT);
ITmfTimestamp timestamp = null;
if (timestampInputFormat != null && timestampString != null) {
TmfTimestampFormat timestampFormat = new TmfTimestampFormat(timestampInputFormat);
}
// Update the custom event type of this event if set
- String eventName = fData.get(Tag.EVENT_TYPE);
+ String eventName = fData.remove(Tag.EVENT_TYPE);
ITmfEventType type = getType();
if (eventName != null && type instanceof CustomEventType) {
((CustomEventType) type).setName(eventName);
}
- List<ITmfEventField> fields = new ArrayList<>(fDefinition.outputs.size());
+ Map<String, TmfEventField> fieldMap = new LinkedHashMap<>();
for (OutputColumn outputColumn : fDefinition.outputs) {
- Object key = (outputColumn.tag.equals(Tag.OTHER) ? outputColumn.name : outputColumn.tag);
if (outputColumn.tag.equals(Tag.TIMESTAMP)) {
if (timestamp != null && fDefinition.timeStampOutputFormat != null && !fDefinition.timeStampOutputFormat.isEmpty()) {
TmfTimestampFormat timestampFormat = new TmfTimestampFormat(fDefinition.timeStampOutputFormat);
- fields.add(new TmfEventField(outputColumn.name, timestampFormat.format(timestamp.getValue()), null));
+ fieldMap.put(outputColumn.name, new TmfEventField(outputColumn.name, timestampFormat.format(timestamp.getValue()), null));
}
- } else if (!outputColumn.tag.equals(Tag.EVENT_TYPE)){
- fields.add(new TmfEventField(outputColumn.name, nullToEmptyString(fData.get(key)), null));
+ } else if (outputColumn.tag.equals(Tag.OTHER) || outputColumn.tag.equals(Tag.MESSAGE)) {
+ Object key = (outputColumn.tag.equals(Tag.OTHER) ? outputColumn.name : outputColumn.tag);
+ fieldMap.put(outputColumn.name, new TmfEventField(outputColumn.name, nullToEmptyString(fData.remove(key)), null));
}
}
- setContent(new CustomEventContent(customEventContent.getName(), customEventContent.getValue(), fields.toArray(new ITmfEventField[0])));
+ // This event contains extra values, we process them now
+ for (Entry<Object, String> entry : fData.entrySet()) {
+ String fieldName = nullToEmptyString(entry.getKey().toString());
+ // Ignore extra fields if a field of same name is already set
+ if (!fieldMap.containsKey(fieldName)) {
+ fieldMap.put(fieldName, new CustomExtraField(fieldName, nullToEmptyString(entry.getValue()), null));
+ }
+ }
+ setContent(new CustomEventContent(customEventContent.getName(), customEventContent.getValue(), fieldMap.values().toArray(new ITmfEventField[fieldMap.size()])));
fData = null;
}
EVENT_TYPE(TmfBaseAspects.getEventTypeAspect().getName()),
/** Message */
MESSAGE(Messages.CustomTraceDefinition_messageTag),
+ /** Extra field name
+ * @since 2.2*/
+ EXTRA_FIELD_NAME(Messages.CustomTraceDefinition_extraFieldNameTag),
+ /** Extra field value
+ * @since 2.2*/
+ EXTRA_FIELD_VALUE(Messages.CustomTraceDefinition_extraFieldValueTag),
+ /**
+ * Extra fields
+ * <p>
+ * Used as output tag corresponding to the {@link #EXTRA_FIELD_NAME} and
+ * {@link #EXTRA_FIELD_VALUE} input tags.
+ * @since 2.2
+ */
+ EXTRA_FIELDS(Messages.CustomExtraFieldsAspect_extraFieldsAspectName),
/** Other */
OTHER(Messages.CustomTraceDefinition_otherTag);
}
}
+ /**
+ * Separator to use with the
+ * {@link CustomTraceDefinition#ACTION_APPEND_WITH_SEPARATOR}
+ *
+ * @since 2.2
+ */
+ public static final @NonNull String SEPARATOR = " | "; //$NON-NLS-1$
+
/** Timestamp tag
* @deprecated Use {@link Tag#TIMESTAMP} instead. */
@Deprecated
*/
public class CustomTxtEvent extends CustomEvent {
+ private String fLastExtraFieldName = null;
+
/**
* Constructor
*
continue;
}
Object key = (column.tag.equals(Tag.OTHER) ? column.name : column.tag);
+ if (key.equals(Tag.EXTRA_FIELD_NAME)) {
+ // If tag extra field name, save the extra field name for
+ // the next extra field value and add the field to the map
+ fLastExtraFieldName = value;
+ if (!fData.containsKey(value)) {
+ fData.put(value, null);
+ }
+ continue;
+ } else if (key.equals(Tag.EXTRA_FIELD_VALUE)) {
+ // If tag extra field value, use the extra field name as key
+ if (fLastExtraFieldName == null) {
+ continue;
+ }
+ key = fLastExtraFieldName;
+ }
if (column.action == CustomTraceDefinition.ACTION_SET) {
fData.put(key, value);
if (key.equals(Tag.TIMESTAMP)) {
} else if (column.action == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {
String s = fData.get(key);
if (s != null) {
- fData.put(key, s + " | " + value); //$NON-NLS-1$
+ fData.put(key, s + CustomTraceDefinition.SEPARATOR + value);
} else {
fData.put(key, value);
}
*/
public class CustomXmlEvent extends CustomEvent {
+ private String fLastExtraFieldName = null;
+
/**
* Constructor defining only the trace definition
*
return;
}
Object key = (inputTag.equals(Tag.OTHER) ? inputName : inputTag);
+ if (key.equals(Tag.EXTRA_FIELD_NAME)) {
+ // If tag extra field name, save the extra field name for
+ // the next extra field value and add the field to the map
+ fLastExtraFieldName = value;
+ if (!fData.containsKey(value)) {
+ fData.put(value, null);
+ }
+ return;
+ } else if (key.equals(Tag.EXTRA_FIELD_VALUE)) {
+ // If tag extra field value, use the extra field name as key
+ if (fLastExtraFieldName == null) {
+ return;
+ }
+ key = fLastExtraFieldName;
+ }
if (inputAction == CustomTraceDefinition.ACTION_SET) {
fData.put(key, value);
if (key.equals(Tag.TIMESTAMP)) {
} else if (inputAction == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {
String s = fData.get(key);
if (s != null) {
- fData.put(key, s + " | " + value); //$NON-NLS-1$
+ fData.put(key, s + CustomTraceDefinition.SEPARATOR + value);
} else {
fData.put(key, value);
}
private static final String BUNDLE_NAME = "org.eclipse.tracecompass.tmf.core.parsers.custom.messages"; //$NON-NLS-1$
+ /** @since 2.2*/
+ public static String CustomExtraFieldsAspect_extraFieldsAspectHelp;
+ /** @since 2.2*/
+ public static String CustomExtraFieldsAspect_extraFieldsAspectName;
+
public static String CustomTrace_FileNotFound;
// TODO: These strings should not be externalized
public static String CustomTraceDefinition_messageTag;
public static String CustomTraceDefinition_otherTag;
public static String CustomTraceDefinition_timestampTag;
+ /** @since 2.2*/
+ public static String CustomTraceDefinition_extraFieldNameTag;
+ /** @since 2.2*/
+ public static String CustomTraceDefinition_extraFieldValueTag;
public static String CustomTxtTraceDefinition_action;
public static String CustomTxtTraceDefinition_cardinality;
public static String CustomTxtTraceDefinition_category;
# Ericsson - Initial API and implementation
###############################################################################
+CustomExtraFieldsAspect_extraFieldsAspectHelp=Extra fields
+CustomExtraFieldsAspect_extraFieldsAspectName=Extra fields
CustomTrace_FileNotFound=File not found
CustomTraceDefinition_eventTypeTag=Event type
CustomTraceDefinition_messageTag=Message
CustomTraceDefinition_otherTag=Other
CustomTraceDefinition_timestampTag=Time Stamp
+CustomTraceDefinition_extraFieldNameTag=Extra field name
+CustomTraceDefinition_extraFieldValueTag=Extra field value
CustomTxtTraceDefinition_action=action
CustomTxtTraceDefinition_cardinality=Cardinality
CustomTxtTraceDefinition_category=category
} else if (input.action == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {
String s = data.get(key);
if (s != null) {
- data.put(key, s + " | " + value); //$NON-NLS-1$
+ data.put(key, s + CustomTraceDefinition.SEPARATOR + value);
} else {
data.put(key, value);
}
if (input.tag.equals(Tag.TIMESTAMP)) {
if (timeStampFormat != null) {
- timeStampFormat += " | " + input.format; //$NON-NLS-1$
+ timeStampFormat += CustomTraceDefinition.SEPARATOR + input.format;
} else {
timeStampFormat = input.format;
}
}
eventTypeText.addModifyListener(updateListener);
-
if (inputLine.columns != null) {
for (InputData inputData : inputLine.columns) {
InputGroup inputGroup = new InputGroup(group, this, inputs.size() + 1);
inputGroup.tagLabel.setVisible(true);
inputGroup.tagText.setVisible(true);
inputGroup.tagText.addModifyListener(updateListener);
+ inputGroup.actionCombo.setVisible(true);
} else if (inputData.tag.equals(Tag.EVENT_TYPE)) {
inputGroup.tagCombo.select(1);
+ inputGroup.actionCombo.setVisible(true);
} else if (inputData.tag.equals(Tag.MESSAGE)) {
inputGroup.tagCombo.select(2);
- } else {
+ inputGroup.actionCombo.setVisible(true);
+ } else if (inputData.tag.equals(Tag.EXTRA_FIELD_NAME)) {
inputGroup.tagCombo.select(3);
+ inputGroup.actionCombo.setVisible(false);
+ } else if (inputData.tag.equals(Tag.EXTRA_FIELD_VALUE)) {
+ inputGroup.tagCombo.select(4);
+ inputGroup.actionCombo.setVisible(true);
+ } else {
+ inputGroup.tagCombo.select(5);
inputGroup.tagText.setText(inputData.name);
inputGroup.tagLabel.setText(Messages.CustomTxtParserInputWizardPage_name);
inputGroup.tagLabel.setVisible(true);
inputGroup.tagText.setVisible(true);
inputGroup.tagText.addModifyListener(updateListener);
+ inputGroup.actionCombo.setVisible(true);
}
inputGroup.actionCombo.select(inputData.action);
inputs.add(inputGroup);
Tag.TIMESTAMP.toString(),
Tag.EVENT_TYPE.toString(),
Tag.MESSAGE.toString(),
+ Tag.EXTRA_FIELD_NAME.toString(),
+ Tag.EXTRA_FIELD_VALUE.toString(),
Tag.OTHER.toString()});
tagCombo.select(2);
tagCombo.addSelectionListener(new SelectionListener() {
tagLabel.setVisible(true);
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
break;
case 1: // Event type
tagLabel.setVisible(false);
tagText.setVisible(false);
+ actionCombo.setVisible(true);
break;
case 2: // Message
tagLabel.setVisible(false);
tagText.setVisible(false);
+ actionCombo.setVisible(true);
+ break;
+ case 3: // Field name
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(false);
+ break;
+ case 4: // Field type
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(true);
break;
- case 3: // Other
+ case 5: // Other
tagLabel.setText(Messages.CustomTxtParserInputWizardPage_name);
tagLabel.setVisible(true);
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
break;
default:
break;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
this.definition = wizard.inputPage.getDefinition();
final List<Entry<Tag, String>> inputs = wizard.inputPage.getInputs();
+ // substitute extra field name/value with extra fields tag
+ Iterator<Entry<Tag, String>> iterator = inputs.iterator();
+ boolean addExtraFields = false;
+ while (iterator.hasNext()) {
+ Entry<Tag, String> entry = iterator.next();
+ if (entry.getKey().equals(Tag.EXTRA_FIELD_NAME) ||
+ entry.getKey().equals(Tag.EXTRA_FIELD_VALUE)) {
+ iterator.remove();
+ addExtraFields = true;
+ }
+ }
+ if (addExtraFields) {
+ inputs.add(new SimpleEntry<>(Tag.EXTRA_FIELDS, Tag.EXTRA_FIELDS.toString()));
+ }
+
// dispose outputs that have been removed in the input page
final Iterator<Output> iter = outputs.iterator();
while (iter.hasNext()) {
Tag.TIMESTAMP.toString(),
Tag.EVENT_TYPE.toString(),
Tag.MESSAGE.toString(),
+ Tag.EXTRA_FIELD_NAME.toString(),
+ Tag.EXTRA_FIELD_VALUE.toString(),
Tag.OTHER.toString() });
tagCombo.setVisibleItemCount(tagCombo.getItemCount());
tagCombo.addSelectionListener(new SelectionListener() {
tagText.setVisible(false);
actionCombo.setVisible(true);
break;
- case 4: // Other
+ case 4: // Field names
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(false);
+ break;
+ case 5: // Field values
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(true);
+ break;
+ case 6: // Other
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagLabel.setVisible(true);
if (tagText.getText().trim().length() == 0) {
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_format);
tagText.setText(inputElement.getInputFormat());
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
} else if (inputElement.getInputTag().equals(Tag.EVENT_TYPE)) {
tagCombo.select(2);
tagLabel.setVisible(false);
tagText.setVisible(false);
+ actionCombo.setVisible(true);
} else if (inputElement.getInputTag().equals(Tag.MESSAGE)) {
tagCombo.select(3);
tagLabel.setVisible(false);
tagText.setVisible(false);
- } else {
+ actionCombo.setVisible(true);
+ } else if (inputElement.getInputTag().equals(Tag.EXTRA_FIELD_NAME)) {
tagCombo.select(4);
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(false);
+ } else if (inputElement.getInputTag().equals(Tag.EXTRA_FIELD_VALUE)) {
+ tagCombo.select(5);
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(true);
+ } else {
+ tagCombo.select(6);
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagText.setText(inputElement.getInputName());
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
}
eventTypeButton = new Button(group, SWT.CHECK);
}
} else if (actionCombo.getSelectionIndex() == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {
if (timeStampValue != null) {
- timeStampValue += " | " + value; //$NON-NLS-1$
- timeStampFormat += " | " + tagText.getText().trim(); //$NON-NLS-1$
+ timeStampValue += CustomTraceDefinition.SEPARATOR + value;
+ timeStampFormat += CustomTraceDefinition.SEPARATOR + tagText.getText().trim();
} else {
timeStampValue = value;
timeStampFormat = tagText.getText().trim();
Tag.TIMESTAMP.toString(),
Tag.EVENT_TYPE.toString(),
Tag.MESSAGE.toString(),
+ Tag.EXTRA_FIELD_NAME.toString(),
+ Tag.EXTRA_FIELD_VALUE.toString(),
Tag.OTHER.toString() });
tagCombo.select(3); // Other
tagCombo.addSelectionListener(new SelectionListener() {
tagLabel.setVisible(true);
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
break;
case 1: // Event type
tagLabel.setVisible(false);
tagText.setVisible(false);
+ actionCombo.setVisible(true);
break;
case 2: // Message
tagLabel.setVisible(false);
tagText.setVisible(false);
+ actionCombo.setVisible(true);
+ break;
+ case 3: // Field names
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(false);
+ break;
+ case 4: // Field values
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(true);
break;
- case 3: // Other
+ case 5: // Other
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagLabel.setVisible(true);
if (tagText.getText().trim().length() == 0) {
}
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
break;
default:
break;
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_format);
tagText.setText(inputAttribute.getInputFormat());
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
} else if (inputAttribute.getInputTag().equals(Tag.EVENT_TYPE)) {
tagCombo.select(1);
tagLabel.setVisible(false);
tagText.setVisible(false);
+ actionCombo.setVisible(true);
} else if (inputAttribute.getInputTag().equals(Tag.MESSAGE)) {
tagCombo.select(2);
tagLabel.setVisible(false);
tagText.setVisible(false);
- } else {
+ actionCombo.setVisible(true);
+ } else if (inputAttribute.getInputTag().equals(Tag.EXTRA_FIELD_NAME)) {
tagCombo.select(3);
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(false);
+ } else if (inputAttribute.getInputTag().equals(Tag.EXTRA_FIELD_VALUE)) {
+ tagCombo.select(4);
+ tagLabel.setVisible(false);
+ tagText.setVisible(false);
+ actionCombo.setVisible(true);
+ } else {
+ tagCombo.select(5);
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagText.setText(inputAttribute.getInputName());
tagText.addModifyListener(updateListener);
+ actionCombo.setVisible(true);
}
}
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
this.definition = wizard.inputPage.getDefinition();
final List<Entry<Tag, String>> inputs = wizard.inputPage.getInputs();
+ // substitute extra field name/value with extra fields tag
+ Iterator<Entry<Tag, String>> iterator = inputs.iterator();
+ boolean addExtraFields = false;
+ while (iterator.hasNext()) {
+ Entry<Tag, String> entry = iterator.next();
+ if (entry.getKey().equals(Tag.EXTRA_FIELD_NAME) ||
+ entry.getKey().equals(Tag.EXTRA_FIELD_VALUE)) {
+ iterator.remove();
+ addExtraFields = true;
+ }
+ }
+ if (addExtraFields) {
+ inputs.add(new SimpleEntry<>(Tag.EXTRA_FIELDS, Tag.EXTRA_FIELDS.toString()));
+ }
+
// dispose outputs that have been removed in the input page
final Iterator<Output> iter = outputs.iterator();
while (iter.hasNext()) {