Skip to content

Commit 900ddc5

Browse files
authored
refactor: multi-namespace in dsp controllers (#4557)
* refactor: multi-namespace dsp controllers * pr suggestions
1 parent faf3c95 commit 900ddc5

File tree

11 files changed

+570
-383
lines changed

11 files changed

+570
-383
lines changed

data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@
3636
import org.eclipse.edc.protocol.dsp.http.spi.message.DspRequestHandler;
3737
import org.eclipse.edc.protocol.dsp.http.spi.message.GetDspRequest;
3838
import org.eclipse.edc.protocol.dsp.http.spi.message.PostDspRequest;
39+
import org.eclipse.edc.protocol.dsp.spi.type.DspNamespace;
3940

4041
import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION;
4142
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
4243
import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.BASE_PATH;
4344
import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.CATALOG_REQUEST;
4445
import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.DATASET_REQUEST;
4546
import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP;
46-
import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_IRI;
47+
import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_TERM;
48+
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_NAMESPACE_V_08;
4749

4850
/**
4951
* Provides the HTTP endpoint for receiving catalog requests.
@@ -57,16 +59,18 @@ public class DspCatalogApiController {
5759
private final DspRequestHandler dspRequestHandler;
5860
private final ContinuationTokenManager continuationTokenManager;
5961
private final String protocol;
62+
private final DspNamespace namespace;
6063

6164
public DspCatalogApiController(CatalogProtocolService service, DspRequestHandler dspRequestHandler, ContinuationTokenManager continuationTokenManager) {
62-
this(service, dspRequestHandler, continuationTokenManager, DATASPACE_PROTOCOL_HTTP);
65+
this(service, dspRequestHandler, continuationTokenManager, DATASPACE_PROTOCOL_HTTP, DSP_NAMESPACE_V_08);
6366
}
6467

65-
public DspCatalogApiController(CatalogProtocolService service, DspRequestHandler dspRequestHandler, ContinuationTokenManager continuationTokenManager, String protocol) {
68+
public DspCatalogApiController(CatalogProtocolService service, DspRequestHandler dspRequestHandler, ContinuationTokenManager continuationTokenManager, String protocol, DspNamespace namespace) {
6669
this.service = service;
6770
this.dspRequestHandler = dspRequestHandler;
6871
this.continuationTokenManager = continuationTokenManager;
6972
this.protocol = protocol;
73+
this.namespace = namespace;
7074
}
7175

7276
@POST
@@ -83,7 +87,7 @@ public Response requestCatalog(JsonObject jsonObject, @HeaderParam(AUTHORIZATION
8387

8488
var request = PostDspRequest.Builder.newInstance(CatalogRequestMessage.class, Catalog.class, CatalogError.class)
8589
.token(token)
86-
.expectedMessageType(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_IRI)
90+
.expectedMessageType(namespace.toIri(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_TERM))
8791
.message(messageJson)
8892
.serviceCall(service::getCatalog)
8993
.errorProvider(CatalogError.Builder::newInstance)

data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController20241.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
2525
import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.BASE_PATH;
2626
import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP_V_2024_1;
27+
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_NAMESPACE_V_2024_1;
2728
import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1_PATH;
2829

2930
/**
@@ -36,6 +37,6 @@ public class DspCatalogApiController20241 extends DspCatalogApiController {
3637

3738
public DspCatalogApiController20241(CatalogProtocolService service, DspRequestHandler dspRequestHandler,
3839
ContinuationTokenManager responseDecorator) {
39-
super(service, dspRequestHandler, responseDecorator, DATASPACE_PROTOCOL_HTTP_V_2024_1);
40+
super(service, dspRequestHandler, responseDecorator, DATASPACE_PROTOCOL_HTTP_V_2024_1, DSP_NAMESPACE_V_2024_1);
4041
}
4142
}

data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiControllerTest.java

+134-89
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.eclipse.edc.protocol.dsp.http.spi.message.GetDspRequest;
3131
import org.eclipse.edc.protocol.dsp.http.spi.message.PostDspRequest;
3232
import org.eclipse.edc.protocol.dsp.http.spi.message.ResponseDecorator;
33+
import org.eclipse.edc.protocol.dsp.spi.type.DspNamespace;
3334
import org.eclipse.edc.spi.result.Result;
3435
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
3536
import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase;
@@ -47,7 +48,10 @@
4748
import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.BASE_PATH;
4849
import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.CATALOG_REQUEST;
4950
import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.DATASET_REQUEST;
50-
import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_IRI;
51+
import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_TERM;
52+
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_NAMESPACE_V_08;
53+
import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_NAMESPACE_V_2024_1;
54+
import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1_PATH;
5155
import static org.mockito.ArgumentMatchers.any;
5256
import static org.mockito.ArgumentMatchers.eq;
5357
import static org.mockito.ArgumentMatchers.isA;
@@ -56,115 +60,156 @@
5660
import static org.mockito.Mockito.verifyNoInteractions;
5761
import static org.mockito.Mockito.when;
5862

59-
@ApiTest
60-
class DspCatalogApiControllerTest extends RestControllerTestBase {
61-
62-
private final TypeTransformerRegistry transformerRegistry = mock();
63-
private final CatalogProtocolService service = mock();
64-
private final DspRequestHandler dspRequestHandler = mock();
65-
private final ContinuationTokenManager continuationTokenManager = mock();
66-
67-
@Test
68-
void getDataset_shouldGetResource() {
69-
when(dspRequestHandler.getResource(any())).thenReturn(Response.ok().type(APPLICATION_JSON).build());
70-
71-
baseRequest()
72-
.get(DATASET_REQUEST + "/datasetId")
73-
.then()
74-
.statusCode(200)
75-
.contentType(JSON);
76-
77-
var captor = ArgumentCaptor.forClass(GetDspRequest.class);
78-
verify(dspRequestHandler).getResource(captor.capture());
79-
var request = captor.getValue();
80-
assertThat(request.getToken()).isEqualTo("auth");
81-
assertThat(request.getResultClass()).isEqualTo(Dataset.class);
82-
assertThat(request.getId()).isEqualTo("datasetId");
83-
}
84-
85-
@Override
86-
protected Object controller() {
87-
return new DspCatalogApiController(service, dspRequestHandler, continuationTokenManager);
88-
}
63+
class DspCatalogApiControllerTest {
8964

90-
private RequestSpecification baseRequest() {
91-
return given()
92-
.baseUri("http://localhost:" + port)
93-
.basePath(BASE_PATH)
94-
.header(HttpHeaders.AUTHORIZATION, "auth")
95-
.when();
96-
}
65+
abstract static class Tests extends RestControllerTestBase {
9766

98-
@Nested
99-
class RequestCatalog {
67+
protected final TypeTransformerRegistry transformerRegistry = mock();
68+
protected final CatalogProtocolService service = mock();
69+
protected final DspRequestHandler dspRequestHandler = mock();
70+
protected final ContinuationTokenManager continuationTokenManager = mock();
10071

10172
@Test
102-
void shouldCreateResource() {
103-
var requestBody = createObjectBuilder().add(TYPE, DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_IRI).build();
104-
var catalog = createObjectBuilder().add(JsonLdKeywords.TYPE, "catalog").build();
105-
when(transformerRegistry.transform(any(Catalog.class), eq(JsonObject.class))).thenReturn(Result.success(catalog));
106-
when(dspRequestHandler.createResource(any(), any())).thenReturn(Response.ok().type(APPLICATION_JSON_TYPE).build());
107-
when(continuationTokenManager.createResponseDecorator(any())).thenReturn(mock());
73+
void getDataset_shouldGetResource() {
74+
when(dspRequestHandler.getResource(any())).thenReturn(Response.ok().type(APPLICATION_JSON).build());
10875

10976
baseRequest()
110-
.contentType(JSON)
111-
.body(requestBody)
112-
.post(CATALOG_REQUEST)
77+
.get(DATASET_REQUEST + "/datasetId")
11378
.then()
11479
.statusCode(200)
11580
.contentType(JSON);
11681

117-
var captor = ArgumentCaptor.forClass(PostDspRequest.class);
118-
verify(dspRequestHandler).createResource(captor.capture(), isA(ResponseDecorator.class));
82+
var captor = ArgumentCaptor.forClass(GetDspRequest.class);
83+
verify(dspRequestHandler).getResource(captor.capture());
11984
var request = captor.getValue();
120-
assertThat(request.getInputClass()).isEqualTo(CatalogRequestMessage.class);
121-
assertThat(request.getResultClass()).isEqualTo(Catalog.class);
122-
assertThat(request.getExpectedMessageType()).isEqualTo(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_IRI);
123-
assertThat(request.getProcessId()).isNull();
12485
assertThat(request.getToken()).isEqualTo("auth");
125-
assertThat(request.getMessage()).isEqualTo(requestBody);
126-
verify(continuationTokenManager).createResponseDecorator("http://localhost:%d/catalog/request".formatted(port));
86+
assertThat(request.getResultClass()).isEqualTo(Dataset.class);
87+
assertThat(request.getId()).isEqualTo("datasetId");
12788
}
12889

129-
@Test
130-
void shouldApplyContinuationToken_whenPassed() {
131-
var requestBody = createObjectBuilder().add(TYPE, DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_IRI).build();
132-
var catalog = createObjectBuilder().add(JsonLdKeywords.TYPE, "catalog").build();
133-
when(transformerRegistry.transform(any(Catalog.class), eq(JsonObject.class))).thenReturn(Result.success(catalog));
134-
when(dspRequestHandler.createResource(any(), any())).thenReturn(Response.ok().type(APPLICATION_JSON_TYPE).build());
135-
when(continuationTokenManager.createResponseDecorator(any())).thenReturn(mock());
136-
var enrichedRequestBody = createObjectBuilder(requestBody).add("query", Json.createObjectBuilder()).build();
137-
when(continuationTokenManager.applyQueryFromToken(any(), any())).thenReturn(Result.success(enrichedRequestBody));
13890

139-
baseRequest()
140-
.contentType(JSON)
141-
.body(requestBody)
142-
.post(CATALOG_REQUEST + "?continuationToken=pagination-token")
143-
.then()
144-
.statusCode(200)
145-
.contentType(JSON);
91+
protected abstract String basePath();
14692

147-
var captor = ArgumentCaptor.forClass(PostDspRequest.class);
148-
verify(dspRequestHandler).createResource(captor.capture(), isA(ResponseDecorator.class));
149-
var request = captor.getValue();
150-
assertThat(request.getMessage()).isSameAs(enrichedRequestBody);
151-
verify(continuationTokenManager).applyQueryFromToken(requestBody, "pagination-token");
93+
protected abstract DspNamespace namespace();
94+
95+
private RequestSpecification baseRequest() {
96+
return given()
97+
.baseUri("http://localhost:" + port)
98+
.basePath(basePath())
99+
.header(HttpHeaders.AUTHORIZATION, "auth")
100+
.when();
152101
}
153102

154-
@Test
155-
void shouldReturnBadRequest_whenContinuationTokenIsNotValid() {
156-
var requestBody = createObjectBuilder().add(TYPE, DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_IRI).build();
157-
when(continuationTokenManager.applyQueryFromToken(any(), any())).thenReturn(Result.failure("error"));
103+
@Nested
104+
class RequestCatalog {
105+
106+
@Test
107+
void shouldCreateResource() {
108+
var requestBody = createObjectBuilder().add(TYPE, namespace().toIri(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_TERM)).build();
109+
var catalog = createObjectBuilder().add(JsonLdKeywords.TYPE, "catalog").build();
110+
when(transformerRegistry.transform(any(Catalog.class), eq(JsonObject.class))).thenReturn(Result.success(catalog));
111+
when(dspRequestHandler.createResource(any(), any())).thenReturn(Response.ok().type(APPLICATION_JSON_TYPE).build());
112+
when(continuationTokenManager.createResponseDecorator(any())).thenReturn(mock());
113+
114+
baseRequest()
115+
.contentType(JSON)
116+
.body(requestBody)
117+
.post(CATALOG_REQUEST)
118+
.then()
119+
.statusCode(200)
120+
.contentType(JSON);
121+
122+
var captor = ArgumentCaptor.forClass(PostDspRequest.class);
123+
verify(dspRequestHandler).createResource(captor.capture(), isA(ResponseDecorator.class));
124+
var request = captor.getValue();
125+
assertThat(request.getInputClass()).isEqualTo(CatalogRequestMessage.class);
126+
assertThat(request.getResultClass()).isEqualTo(Catalog.class);
127+
assertThat(request.getExpectedMessageType()).isEqualTo(namespace().toIri(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_TERM));
128+
assertThat(request.getProcessId()).isNull();
129+
assertThat(request.getToken()).isEqualTo("auth");
130+
assertThat(request.getMessage()).isEqualTo(requestBody);
131+
verify(continuationTokenManager).createResponseDecorator("http://localhost:%d%s".formatted(port, basePath() + CATALOG_REQUEST));
132+
}
133+
134+
@Test
135+
void shouldApplyContinuationToken_whenPassed() {
136+
var requestBody = createObjectBuilder().add(TYPE, namespace().toIri(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_TERM)).build();
137+
var catalog = createObjectBuilder().add(JsonLdKeywords.TYPE, "catalog").build();
138+
when(transformerRegistry.transform(any(Catalog.class), eq(JsonObject.class))).thenReturn(Result.success(catalog));
139+
when(dspRequestHandler.createResource(any(), any())).thenReturn(Response.ok().type(APPLICATION_JSON_TYPE).build());
140+
when(continuationTokenManager.createResponseDecorator(any())).thenReturn(mock());
141+
var enrichedRequestBody = createObjectBuilder(requestBody).add("query", Json.createObjectBuilder()).build();
142+
when(continuationTokenManager.applyQueryFromToken(any(), any())).thenReturn(Result.success(enrichedRequestBody));
143+
144+
baseRequest()
145+
.contentType(JSON)
146+
.body(requestBody)
147+
.post(CATALOG_REQUEST + "?continuationToken=pagination-token")
148+
.then()
149+
.statusCode(200)
150+
.contentType(JSON);
151+
152+
var captor = ArgumentCaptor.forClass(PostDspRequest.class);
153+
verify(dspRequestHandler).createResource(captor.capture(), isA(ResponseDecorator.class));
154+
var request = captor.getValue();
155+
assertThat(request.getMessage()).isSameAs(enrichedRequestBody);
156+
verify(continuationTokenManager).applyQueryFromToken(requestBody, "pagination-token");
157+
}
158+
159+
@Test
160+
void shouldReturnBadRequest_whenContinuationTokenIsNotValid() {
161+
var requestBody = createObjectBuilder().add(TYPE, namespace().toIri(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE_TERM)).build();
162+
when(continuationTokenManager.applyQueryFromToken(any(), any())).thenReturn(Result.failure("error"));
163+
164+
baseRequest()
165+
.contentType(JSON)
166+
.body(requestBody)
167+
.post(CATALOG_REQUEST + "?continuationToken=pagination-token")
168+
.then()
169+
.statusCode(400);
170+
171+
verifyNoInteractions(dspRequestHandler, transformerRegistry);
172+
}
173+
}
174+
}
158175

159-
baseRequest()
160-
.contentType(JSON)
161-
.body(requestBody)
162-
.post(CATALOG_REQUEST + "?continuationToken=pagination-token")
163-
.then()
164-
.statusCode(400);
176+
@ApiTest
177+
@Nested
178+
class DspCatalogApiControllerV08Test extends Tests {
179+
180+
@Override
181+
protected String basePath() {
182+
return BASE_PATH;
183+
}
184+
185+
@Override
186+
protected DspNamespace namespace() {
187+
return DSP_NAMESPACE_V_08;
188+
}
165189

166-
verifyNoInteractions(dspRequestHandler, transformerRegistry);
190+
@Override
191+
protected Object controller() {
192+
return new DspCatalogApiController(service, dspRequestHandler, continuationTokenManager);
167193
}
168194
}
169195

196+
@ApiTest
197+
@Nested
198+
class DspCatalogApiControllerV20241Test extends Tests {
199+
200+
@Override
201+
protected String basePath() {
202+
return V_2024_1_PATH + BASE_PATH;
203+
}
204+
205+
@Override
206+
protected DspNamespace namespace() {
207+
return DSP_NAMESPACE_V_2024_1;
208+
}
209+
210+
@Override
211+
protected Object controller() {
212+
return new DspCatalogApiController20241(service, dspRequestHandler, continuationTokenManager);
213+
}
214+
}
170215
}

0 commit comments

Comments
 (0)