Skip to content

Commit 03bcdb4

Browse files
committed
server: Fix SeriesModel xValues swagger definition/serializers/tests
Use xValues for array of longs for x values, e.g. timestamps Use xCategoires for array of category strings for x values use XRanges for arrays of range (start/stop) for x values This simplifies the swagger definition and implemntation for xValues of SeriesModel for both server and client side. Update TSP version to 0.6.0 Signed-off-by: Bernd Hufmann <[email protected]>
1 parent 711a6bd commit 03bcdb4

File tree

7 files changed

+116
-135
lines changed

7 files changed

+116
-135
lines changed

trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/webapp/SamplingSerializerTest.java

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111

1212
package org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.webapp;
1313

14-
import static org.junit.Assert.*;
14+
import static org.junit.Assert.assertEquals;
1515

16+
import java.io.IOException;
17+
import java.io.Serializable;
1618
import java.util.List;
1719

1820
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.webapp.SamplingSerializer;
@@ -24,18 +26,22 @@
2426
import org.junit.Before;
2527
import org.junit.Test;
2628

29+
import com.fasterxml.jackson.core.JsonGenerator;
2730
import com.fasterxml.jackson.core.JsonProcessingException;
2831
import com.fasterxml.jackson.databind.ObjectMapper;
32+
import com.fasterxml.jackson.databind.SerializerProvider;
2933
import com.fasterxml.jackson.databind.module.SimpleModule;
34+
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
3035

3136
/**
32-
* Test suite for {@link SamplingSerializer} and {@link SamplingDeserializer}.
37+
* Test suite for {@link SamplingSerializer}.
3338
* <p>
3439
* Validates JSON round-trip behavior for different {@link ISampling}
3540
* subtypes: {@link Timestamps}, {@link Categories}, and {@link Ranges}.
3641
*
3742
* @author Siwei Zhang
3843
*/
44+
@SuppressWarnings("null")
3945
public class SamplingSerializerTest {
4046

4147
private ObjectMapper fMapper;
@@ -49,52 +55,85 @@ public void setup() {
4955
fMapper = new ObjectMapper();
5056
SimpleModule module = new SimpleModule();
5157
module.addSerializer(ISampling.class, new SamplingSerializer());
58+
module.addSerializer(TestSampling.class, new TestSamplingSerializer());
5259
fMapper.registerModule(module);
5360
}
5461

5562
/**
56-
* Test round-trip serialization and deserialization for
57-
* {@link ISampling.Timestamps}. The format is a flat array of @NonNull Longs.
63+
* Test round-trip serialization {@link ISampling.Timestamps}.
64+
* The format is a flat array of @NonNull Longs.
5865
*
5966
* @throws JsonProcessingException
6067
* if JSON processing fails
6168
*/
6269
@Test
6370
public void testTimestampsRoundTrip() throws JsonProcessingException {
64-
ISampling original = new Timestamps(new long[] { 1, 2, 3 });
71+
TestSampling original = new TestSampling(new Timestamps(new long[] { 1, 2, 3 }));
6572
String json = fMapper.writeValueAsString(original);
66-
assertEquals("[1,2,3]", json);
73+
assertEquals("{\"xValues\":[1,2,3]}", json);
6774
}
6875

6976
/**
70-
* Test round-trip serialization and deserialization for
71-
* {@link ISampling.Categories}. The format is an array of strings.
77+
* Test round-trip serialization {@link ISampling.Categories}.
78+
* The format is an array of strings.
7279
*
7380
* @throws JsonProcessingException
7481
* if JSON processing fails
7582
*/
7683
@Test
7784
public void testCategoriesRoundTrip() throws JsonProcessingException {
78-
ISampling original = new Categories(List.of("Read", "Write", "Idle"));
85+
TestSampling original = new TestSampling(new Categories(List.of("Read", "Write", "Idle")));
7986
String json = fMapper.writeValueAsString(original);
80-
assertEquals("[\"Read\",\"Write\",\"Idle\"]", json);
87+
assertEquals("{\"xCategories\":[\"Read\",\"Write\",\"Idle\"]}", json);
8188
}
8289

8390
/**
84-
* Test round-trip serialization and deserialization for
85-
* {@link ISampling.Ranges}. The format is an array of range json objects.
91+
* Test round-trip serialization {@link ISampling.Ranges}.
92+
* The format is an array of range json objects.
8693
*
8794
* @throws JsonProcessingException
8895
* if JSON processing fails
8996
*/
9097
@Test
9198
public void testTimeRangesRoundTrip() throws JsonProcessingException {
92-
ISampling original = new Ranges(List.of(
99+
TestSampling original = new TestSampling(new Ranges(List.of(
93100
new Range<>(1L, 2L),
94101
new Range<>(2L, 3L),
95-
new Range<>(3L, 4L)
102+
new Range<>(3L, 4L))
96103
));
97104
String json = fMapper.writeValueAsString(original);
98-
assertEquals("[{\"start\":1,\"end\":2},{\"start\":2,\"end\":3},{\"start\":3,\"end\":4}]", json);
105+
assertEquals("{\"xRanges\":[{\"start\":1,\"end\":2},{\"start\":2,\"end\":3},{\"start\":3,\"end\":4}]}", json);
106+
}
107+
108+
private class TestSampling implements Serializable {
109+
private static final long serialVersionUID = 4522987850097455165L;
110+
ISampling fSampling;
111+
112+
public TestSampling(ISampling sampling) {
113+
fSampling = sampling;
114+
}
115+
116+
public ISampling getSampling() {
117+
return fSampling;
118+
}
119+
}
120+
121+
private class TestSamplingSerializer extends StdSerializer<TestSampling> {
122+
123+
private static final long serialVersionUID = 4522987850097455165L;
124+
125+
/**
126+
* Constructor
127+
*/
128+
public TestSamplingSerializer() {
129+
super(TestSampling.class);
130+
}
131+
132+
@Override
133+
public void serialize(TestSampling value, JsonGenerator gen, SerializerProvider provider) throws IOException {
134+
gen.writeStartObject();
135+
gen.writeObject(value.getSampling());
136+
gen.writeEndObject();
137+
}
99138
}
100139
}

trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/model/StartEndRange.java renamed to trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/model/Range.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
* Represents a closed interval [start, end] for a sampling range.
88
*/
99
@Schema(
10-
name = "StartEndRange",
10+
name = "Range",
1111
description = "An object representing a closed interval with a start and end."
1212
)
13-
class StartEndRange {
13+
class Range {
1414
@Schema(description = "Start of the range (inclusive).", requiredMode = RequiredMode.REQUIRED)
1515
private final long start;
1616

1717
@Schema(description = "End of the range (inclusive).", requiredMode = RequiredMode.REQUIRED)
1818
private final long end;
1919

20-
public StartEndRange(long start, long end) {
20+
public Range(long start, long end) {
2121
this.start = start;
2222
this.end = end;
2323
}

trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/model/Sampling.java

Lines changed: 0 additions & 97 deletions
This file was deleted.

trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/model/SeriesModel.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
package org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model;
1313

14+
import java.util.List;
15+
1416
import org.eclipse.jdt.annotation.NonNull;
1517

1618
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -39,15 +41,25 @@ public interface SeriesModel {
3941
String getSeriesName();
4042

4143
/**
42-
* @return The X values.
44+
* @return The X values as list of longs
4345
*/
4446
@JsonProperty("xValues")
45-
@Schema(description = "Sampling values", requiredMode = RequiredMode.REQUIRED, oneOf = {
46-
Sampling.TimestampSampling.class,
47-
Sampling.CategorySampling.class,
48-
Sampling.RangeSampling.class
49-
})
50-
Sampling getXValues();
47+
@Schema(description = "X values as list of int64 values (e.g. timestamps). Example: [100, 200, 350]. Mutually exclusive with xCategories/xRanges.")
48+
public List<Long> getXValues();
49+
50+
/**
51+
* @return The X values as list of strings
52+
*/
53+
@JsonProperty("xCategories")
54+
@Schema(description = "X values as list of category strings. Example: [\"READ\", \"WRITE\"]. Mutually exclusive with xValues/xRanges.")
55+
public List<String> getXCategories();
56+
57+
/**
58+
* @return The X values as list of ranges
59+
*/
60+
@JsonProperty("xRanges")
61+
@Schema(description = "X values as list of start/end range objects. Example: [{\"start\": 10, \"end\": 20}, {\"start\": 50, \"end\": 75}]. Mutually exclusive with xValues/xCategories.")
62+
public List<Range> getXRanges();
5163

5264
/**
5365
* @return The Y values.

trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/services/EndpointConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public final class EndpointConstants {
8484
static final String LICENSE = "Apache 2"; //$NON-NLS-1$
8585
static final String LICENSE_URL = "http://www.apache.org/licenses/"; //$NON-NLS-1$
8686
/** The TSP version */
87-
public static final String VERSION = "0.5.0"; //$NON-NLS-1$
87+
public static final String VERSION = "0.6.0"; //$NON-NLS-1$
8888
static final String SERVER = "https://localhost:8080/tsp/api"; //$NON-NLS-1$
8989

9090
/**

trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/webapp/SamplingSerializer.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@
2626

2727
/**
2828
* Custom serializer for all Sampling subtypes.
29-
* - Timestamps → flat array: [1, 2, 3]
30-
* - Categories → array of strings: ["Read", "Write"]
31-
* - Ranges → array of objects: [{"start": 1, "end": 2}, {"start": 2, "end": 3}]
29+
*
30+
* Note: It serializes only the object content without JSON object start and end marker. Hence
31+
* ISampling has to be embedded inside an outer JSON object
32+
*
33+
* - Timestamps → flat array → "xValues": [1, 2, 3]
34+
* - Categories → array of strings → "xCategories": ["Read", "Write"]
35+
* - Ranges → array of Range → "xRanges": [{ "start": 1, "end": 2 }, { "start": 3, "end": 4 }]
3236
*/
3337
public class SamplingSerializer extends StdSerializer<ISampling> {
3438

@@ -43,17 +47,14 @@ public SamplingSerializer() {
4347

4448
@Override
4549
public void serialize(ISampling value, JsonGenerator gen, SerializerProvider provider) throws IOException {
50+
// Note that ISampling is not serialized as a json object, but only as json field.
51+
// Hence it has to be embedded in an outer JSON object
4652
if (value instanceof Timestamps timestamps) {
47-
gen.writeArray(timestamps.timestamps(), 0, timestamps.timestamps().length);
48-
53+
gen.writeObjectField("xValues", timestamps.timestamps()); //$NON-NLS-1$
4954
} else if (value instanceof Categories categories) {
50-
gen.writeStartArray();
51-
for (String category : categories.categories()) {
52-
gen.writeString(category);
53-
}
54-
gen.writeEndArray();
55-
55+
gen.writeObjectField("xCategories", categories.categories()); //$NON-NLS-1$
5656
} else if (value instanceof Ranges timeRanges) {
57+
gen.writeFieldName("xRanges"); //$NON-NLS-1$
5758
gen.writeStartArray();
5859
for (Range<@NonNull Long> range : timeRanges.ranges()) {
5960
gen.writeStartObject();

trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/webapp/SeriesModelSerializer.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
import org.eclipse.jdt.annotation.NonNull;
1717
import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
1818
import org.eclipse.tracecompass.tmf.core.model.StyleProperties;
19+
import org.eclipse.tracecompass.tmf.core.model.ISampling;
20+
import org.eclipse.tracecompass.tmf.core.model.ISampling.Categories;
21+
import org.eclipse.tracecompass.tmf.core.model.ISampling.Range;
22+
import org.eclipse.tracecompass.tmf.core.model.ISampling.Ranges;
23+
import org.eclipse.tracecompass.tmf.core.model.ISampling.Timestamps;
1924
import org.eclipse.tracecompass.tmf.core.model.xy.ISeriesModel;
2025

2126
import com.fasterxml.jackson.core.JsonGenerator;
@@ -47,7 +52,28 @@ public void serialize(ISeriesModel value, JsonGenerator gen, SerializerProvider
4752
gen.writeStartObject();
4853
gen.writeNumberField("seriesId", value.getId()); //$NON-NLS-1$
4954
gen.writeStringField("seriesName", value.getName()); //$NON-NLS-1$
50-
gen.writeObjectField("xValues", value.getSampling()); //$NON-NLS-1$
55+
56+
// Serialize the sampling
57+
ISampling sampling = value.getSampling();
58+
if (sampling instanceof Timestamps timestamps) {
59+
gen.writeObjectField("xValues", timestamps.timestamps()); //$NON-NLS-1$
60+
} else if (sampling instanceof Categories categories) {
61+
gen.writeObjectField("xCategories", categories.categories()); //$NON-NLS-1$
62+
} else if (sampling instanceof Ranges timeRanges) {
63+
gen.writeFieldName("xRanges"); //$NON-NLS-1$
64+
gen.writeStartArray();
65+
for (Range<@NonNull Long> range : timeRanges.ranges()) {
66+
gen.writeStartObject();
67+
gen.writeNumberField("start", range.start()); //$NON-NLS-1$
68+
gen.writeNumberField("end", range.end()); //$NON-NLS-1$
69+
gen.writeEndObject();
70+
}
71+
gen.writeEndArray();
72+
} else {
73+
throw new IllegalArgumentException("Unknown Sampling type: " + value.getClass().getName()); //$NON-NLS-1$
74+
}
75+
76+
gen.writeObject(value.getSampling());
5177
gen.writeObjectField("yValues", value.getData()); //$NON-NLS-1$
5278

5379
// no-op trim below, null-related (unlikely case) warning otherwise-

0 commit comments

Comments
 (0)