Skip to content

Commit 1c1de4e

Browse files
PatrickTasseMatthewKhouzam
authored andcommitted
tmf: Add generic object data provider
Signed-off-by: Patrick Tasse <[email protected]>
1 parent 0f9820a commit 1c1de4e

File tree

12 files changed

+419
-6
lines changed

12 files changed

+419
-6
lines changed

tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ Export-Package: org.eclipse.tracecompass.internal.provisional.tmf.core.model,
109109
org.eclipse.tracecompass.tmf.core.model.annotations,
110110
org.eclipse.tracecompass.tmf.core.model.filters,
111111
org.eclipse.tracecompass.tmf.core.model.genericxy,
112+
org.eclipse.tracecompass.tmf.core.model.object,
112113
org.eclipse.tracecompass.tmf.core.model.timegraph,
113114
org.eclipse.tracecompass.tmf.core.model.tree,
114115
org.eclipse.tracecompass.tmf.core.model.xy,

tmf/org.eclipse.tracecompass.tmf.core/plugin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,9 @@
7676
class="org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.TmfEventTableDataProviderFactory"
7777
id="org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.TmfEventTableDataProvider">
7878
</dataProviderFactory>
79+
<dataProviderFactory
80+
class="org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.TmfEventRawDataProviderFactory"
81+
id="org.eclipse.tracecompass.tmf.core.model.events.data">
82+
</dataProviderFactory>
7983
</extension>
8084
</plugin>

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/events/Messages.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**********************************************************************
2-
* Copyright (c) 2019 Ericsson
2+
* Copyright (c) 2019, 2025 Ericsson
33
*
44
* All rights reserved. This program and the accompanying materials are
55
* made available under the terms of the Eclipse Public License 2.0 which
@@ -14,7 +14,7 @@
1414
import org.eclipse.osgi.util.NLS;
1515

1616
/**
17-
* Message bundle for the new events table messages.
17+
* Message bundle for events data provider messages.
1818
*/
1919
public class Messages extends NLS {
2020
private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.messages"; //$NON-NLS-1$
@@ -26,6 +26,14 @@ public class Messages extends NLS {
2626
* The events table data provider help text
2727
*/
2828
public static @Nullable String EventsTableDataProviderFactory_DescriptionText;
29+
/**
30+
* The raw event data title
31+
*/
32+
public static @Nullable String EventsRawDataProvider_Title;
33+
/**
34+
* The raw event data provider help text
35+
*/
36+
public static @Nullable String EventsRawDataProviderFactory_DescriptionText;
2937

3038
static {
3139
// initialize resource bundle
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/**********************************************************************
2+
* Copyright (c) 2018, 2021 Ericsson
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License 2.0 which
6+
* accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
**********************************************************************/
11+
12+
package org.eclipse.tracecompass.internal.provisional.tmf.core.model.events;
13+
14+
import java.util.ArrayList;
15+
import java.util.LinkedHashMap;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.regex.Pattern;
19+
20+
import org.eclipse.core.runtime.IProgressMonitor;
21+
import org.eclipse.jdt.annotation.Nullable;
22+
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
23+
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
24+
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
25+
import org.eclipse.tracecompass.tmf.core.model.AbstractTmfTraceDataProvider;
26+
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage;
27+
import org.eclipse.tracecompass.tmf.core.model.object.IObjectDataProvider;
28+
import org.eclipse.tracecompass.tmf.core.model.object.ObjectModel;
29+
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse;
30+
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
31+
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
32+
import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
33+
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
34+
35+
import com.google.common.collect.ImmutableMap;
36+
import com.google.common.collect.ImmutableMap.Builder;
37+
38+
/**
39+
* This data provider will return an object representing an array of raw event
40+
* data.
41+
*
42+
* @author Patrick Tasse
43+
*/
44+
public class TmfEventRawDataProvider extends AbstractTmfTraceDataProvider implements IObjectDataProvider {
45+
46+
/**
47+
* Extension point ID.
48+
*/
49+
public static final String ID = "org.eclipse.tracecompass.tmf.core.model.events.data"; //$NON-NLS-1$
50+
51+
private static final int MAX_SIZE = 500;
52+
private static final String SELECTION_RANGE = "selection_range"; //$NON-NLS-1$
53+
private static final String NEXT = "next"; //$NON-NLS-1$
54+
private static final String PREVIOUS = "previous"; //$NON-NLS-1$
55+
private static final String TYPE = "type"; //$NON-NLS-1$
56+
private static final String FIELD = "field"; //$NON-NLS-1$
57+
private static final String START = "start"; //$NON-NLS-1$
58+
59+
/**
60+
* Constructor
61+
*
62+
* @param trace
63+
* A trace on which we are interested to fetch a raw event model
64+
*/
65+
public TmfEventRawDataProvider(ITmfTrace trace) {
66+
super(trace);
67+
}
68+
69+
@Override
70+
public String getId() {
71+
return ID;
72+
}
73+
74+
@Override
75+
public TmfModelResponse<ObjectModel> fetchData(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
76+
ITmfTrace trace = getTrace();
77+
long rank = 0L;
78+
Object selectionRangeObj = fetchParameters.get(SELECTION_RANGE);
79+
Object nextObj = fetchParameters.get(NEXT);
80+
Object previousObj = fetchParameters.get(PREVIOUS);
81+
Object typeObj = fetchParameters.get(TYPE);
82+
Object fieldObj = fetchParameters.get(FIELD);
83+
if (nextObj instanceof Number next) {
84+
rank = next.longValue();
85+
} else if (previousObj instanceof Number previous) {
86+
rank = previous.longValue();
87+
} else if (selectionRangeObj instanceof Map<?,?> selectionRange) {
88+
if (selectionRange.get(START) instanceof Number start) {
89+
rank = trace.seekEvent(TmfTimestamp.fromNanos(start.longValue())).getRank();
90+
}
91+
}
92+
Pattern eventTypePattern = null;
93+
if (typeObj instanceof String type) {
94+
eventTypePattern = Pattern.compile(type);
95+
}
96+
Pattern fieldPattern = null;
97+
if (fieldObj instanceof String field) {
98+
fieldPattern = Pattern.compile(field);
99+
}
100+
ITmfContext context = trace.seekEvent(rank);
101+
List<Object> object = new ArrayList<>();
102+
while (object.size() < MAX_SIZE) {
103+
long eventRank = context.getRank();
104+
ITmfEvent event = trace.getNext(context);
105+
if (event == null) {
106+
break;
107+
}
108+
if (eventTypePattern == null || eventTypePattern.matcher(event.getName()).find()) {
109+
Object eventObj = convertEvent(event, eventRank, fieldPattern);
110+
if (eventObj != null) {
111+
object.add(eventObj);
112+
}
113+
}
114+
}
115+
ObjectModel model = new ObjectModel(object);
116+
long next = context.getRank();
117+
if (trace.getNext(context) != null) {
118+
model.setNext(next);
119+
}
120+
if (rank > 0L) {
121+
model.setPrevious(Math.max(0L, rank - MAX_SIZE));
122+
}
123+
return new TmfModelResponse<>(model, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
124+
}
125+
126+
private static @Nullable Object convertEvent(ITmfEvent event, long rank, @Nullable Pattern fieldPattern) {
127+
Map<String, @Nullable Object> data = new LinkedHashMap<>();
128+
129+
// Add basic event information
130+
data.put("rank", rank);
131+
data.put(TmfBaseAspects.getTimestampAspect().getName(), event.getTimestamp().toNanos());
132+
data.put(TmfBaseAspects.getEventTypeAspect().getName(), event.getType().getName());
133+
Object contents = convertEventField(event.getContent(), fieldPattern);
134+
if (fieldPattern != null && contents instanceof Map map) {
135+
if (map.isEmpty()) {
136+
return null;
137+
}
138+
}
139+
data.put(TmfBaseAspects.getContentsAspect().getName(), contents);
140+
return data;
141+
}
142+
143+
private static @Nullable Object convertEventField(@Nullable ITmfEventField field, @Nullable Pattern fieldPattern) {
144+
if (field == null) {
145+
return null;
146+
}
147+
Builder<String, @Nullable Object> builder = ImmutableMap.builder();
148+
for (ITmfEventField subField : field.getFields()) {
149+
if (subField == null) {
150+
continue;
151+
}
152+
String name = subField.getName();
153+
if (fieldPattern == null || fieldPattern.matcher(name).find()) {
154+
Object value = subField.getValue();
155+
if (value instanceof ITmfEventField) {
156+
builder.put(name, convertEventField((ITmfEventField) value, null));
157+
} else {
158+
builder.put(name, value);
159+
}
160+
}
161+
}
162+
Object value = field.getValue();
163+
if (value instanceof ITmfEventField) {
164+
value = convertEventField((ITmfEventField) value, null);
165+
}
166+
ImmutableMap<String, @Nullable Object> fields = builder.build();
167+
if (value == null) {
168+
return fields;
169+
} else if (fields.isEmpty()) {
170+
return value;
171+
} else {
172+
return Map.of("value", value, "fields", fields); //$NON-NLS-1$ //$NON-NLS-2$
173+
}
174+
}
175+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**********************************************************************
2+
* Copyright (c) 2025 Ericsson
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License 2.0 which
6+
* accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
**********************************************************************/
11+
12+
package org.eclipse.tracecompass.internal.provisional.tmf.core.model.events;
13+
14+
import java.util.Collection;
15+
import java.util.Collections;
16+
17+
import org.eclipse.jdt.annotation.Nullable;
18+
import org.eclipse.tracecompass.common.core.NonNullUtils;
19+
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor;
20+
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType;
21+
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory;
22+
import org.eclipse.tracecompass.tmf.core.model.DataProviderCapabilities;
23+
import org.eclipse.tracecompass.tmf.core.model.DataProviderDescriptor;
24+
import org.eclipse.tracecompass.tmf.core.model.ITmfDataProvider;
25+
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
26+
27+
/**
28+
* {@link TmfEventRawDataProvider} factory, uses the data provider extension
29+
* point.
30+
*
31+
* @author Patrick Tasse
32+
*/
33+
public class TmfEventRawDataProviderFactory implements IDataProviderFactory {
34+
35+
private static final IDataProviderDescriptor DESCRIPTOR =
36+
new DataProviderDescriptor.Builder()
37+
.setId(TmfEventRawDataProvider.ID)
38+
.setName(NonNullUtils.nullToEmptyString(Messages.EventsRawDataProvider_Title))
39+
.setDescription(NonNullUtils.nullToEmptyString(Messages.EventsRawDataProviderFactory_DescriptionText))
40+
.setProviderType(ProviderType.DATA)
41+
.setCapabilities(new DataProviderCapabilities.Builder().setSelectionRange(true).build())
42+
.build();
43+
44+
@Override
45+
public @Nullable ITmfDataProvider createDataProvider(ITmfTrace trace) {
46+
return new TmfEventRawDataProvider(trace);
47+
}
48+
49+
@Override
50+
public Collection<IDataProviderDescriptor> getDescriptors(ITmfTrace trace) {
51+
return Collections.singleton(DESCRIPTOR);
52+
}
53+
}

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/events/messages.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2019 Ericsson
2+
# Copyright (c) 2019, 2025 Ericsson
33
#
44
# All rights reserved. This program and the accompanying materials
55
# are made available under the terms of the Eclipse Public License 2.0
@@ -11,3 +11,5 @@
1111

1212
EventsTableDataProvider_Title=Events Table
1313
EventsTableDataProviderFactory_DescriptionText=Show the raw events in table form for a given trace
14+
EventsRawDataProvider_Title=Events Data
15+
EventsRawDataProviderFactory_DescriptionText=Show the raw event data in object form for a given trace

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/IDataProviderCapabilities.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@
1515
/**
1616
* Interface to implement to indicate capabilities of a data provider, such as
1717
* "canCreate" and "canDelete" capability.
18-
*
18+
* <p>
1919
* "canCreate" indicates that a given data provider can create a derived data
2020
* provider. "canDelete" indicates that a given data provider can be deleted.
21-
*
21+
* <p>
2222
* Call method {@link IDataProviderFactory#getAdapter(Class)} with class
2323
* {@link ITmfDataProviderConfigurator} to obtain an instance of
2424
* {@link ITmfDataProviderConfigurator}, which implements the "canCreate" and
2525
* "canDelete" capabilities.
26+
* <p>
27+
* "selectionRange" indicates that a given data provider can use the selection
28+
* range to compute its data. Clients should include the selection range in
29+
* query parameters and refresh the data when the selection range changes.
2630
*
2731
* @since 9.6
2832
* @author Bernd Hufmann
@@ -43,4 +47,15 @@ public interface IDataProviderCapabilities {
4347
* {@code false}
4448
*/
4549
boolean canDelete();
50+
51+
/**
52+
* Whether the data provider uses the selection range.
53+
*
54+
* @return {@code true} if this data provider uses the selection range, else
55+
* {@code false}
56+
* @since 10.2
57+
*/
58+
default boolean selectionRange() {
59+
return false;
60+
}
4661
}

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/IDataProviderDescriptor.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ public enum ProviderType {
7878
* A provider for generic xy charts with a time-less x-axis
7979
* @since 10.1
8080
*/
81-
TREE_GENERIC_XY
81+
TREE_GENERIC_XY,
82+
/**
83+
* A provider of generic data objects
84+
* @since 10.2
85+
*/
86+
DATA
8287
}
8388

8489
/**

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/DataProviderCapabilities.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class DataProviderCapabilities implements IDataProviderCapabilities {
2929

3030
private final boolean canCreate;
3131
private final boolean canDelete;
32+
private final boolean selectionRange;
3233

3334
/**
3435
* Constructor
@@ -39,6 +40,7 @@ public class DataProviderCapabilities implements IDataProviderCapabilities {
3940
public DataProviderCapabilities(Builder builder) {
4041
canCreate = builder.canCreate;
4142
canDelete = builder.canDelete;
43+
selectionRange = builder.selectionRange;
4244
}
4345

4446
@Override
@@ -51,6 +53,11 @@ public boolean canDelete() {
5153
return canDelete;
5254
}
5355

56+
@Override
57+
public boolean selectionRange() {
58+
return selectionRange;
59+
}
60+
5461
@Override
5562
@SuppressWarnings("nls")
5663
public String toString() {
@@ -84,6 +91,7 @@ public boolean equals(@Nullable Object obj) {
8491
public static class Builder {
8592
private boolean canCreate = false;
8693
private boolean canDelete = false;
94+
private boolean selectionRange = false;
8795

8896
/**
8997
* Sets canCreate flag
@@ -111,6 +119,19 @@ public Builder setCanDelete(boolean canDelete) {
111119
return this;
112120
}
113121

122+
/**
123+
* Sets selectionRange flag
124+
*
125+
* @param selectionRange
126+
* {@code true} if this data provider uses the selection
127+
* range, else {@code false}
128+
* @return the builder instance.
129+
*/
130+
public Builder setSelectionRange(boolean selectionRange) {
131+
this.selectionRange = selectionRange;
132+
return this;
133+
}
134+
114135
/**
115136
* The method to construct an instance of
116137
* {@link IDataProviderCapabilities}

0 commit comments

Comments
 (0)