Skip to content

Commit d7b4222

Browse files
authored
feat: fixes related to DSP conformance (#4544)
Fixes for DSP conformance
1 parent 9b94383 commit d7b4222

File tree

10 files changed

+251
-15
lines changed

10 files changed

+251
-15
lines changed

core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractnegotiation/ContractNegotiationProtocolServiceImplTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ public Stream<? extends Arguments> provideArguments(ExtensionContext extensionCo
488488
.counterPartyAddress("http://any")
489489
.consumerPid("consumerPid")
490490
.providerPid("providerPid")
491+
.policy(Policy.Builder.newInstance().build())
491492
.build(), PROVIDER, OFFERED),
492493
Arguments.of(verified, ContractAgreementVerificationMessage.Builder.newInstance()
493494
.protocol("protocol")

core/control-plane/control-plane-contract/src/main/java/org/eclipse/edc/connector/controlplane/contract/negotiation/ConsumerContractNegotiationManagerImpl.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,15 @@ private boolean processRequesting(ContractNegotiation negotiation) {
126126
}
127127

128128
/**
129-
* Processes {@link ContractNegotiation} in state ACCEPTING. Tries to send a dummy contract agreement to
130-
* the respective provider in order to approve the last offer sent by the provider. If this succeeds, the
131-
* ContractNegotiation is transitioned to state ACCEPTED. Else, it is transitioned to ACCEPTING
132-
* for a retry.
129+
* Processes {@link ContractNegotiation} in state ACCEPTING. If the dispatch succeeds, the
130+
* ContractNegotiation is transitioned to state ACCEPTED. Else, it is transitioned to ACCEPTING for a retry.
133131
*
134132
* @return true if processed, false otherwise
135133
*/
136134
@WithSpan
137135
private boolean processAccepting(ContractNegotiation negotiation) {
138136
var messageBuilder = ContractNegotiationEventMessage.Builder.newInstance().type(ACCEPTED);
139-
137+
messageBuilder.policy(negotiation.getLastContractOffer().getPolicy());
140138
return dispatch(messageBuilder, negotiation, Object.class)
141139
.onSuccess((n, result) -> transitionToAccepted(n))
142140
.onFailure((n, throwable) -> transitionToAccepting(n))

core/control-plane/control-plane-contract/src/test/java/org/eclipse/edc/connector/controlplane/contract/negotiation/ConsumerContractNegotiationManagerImplTest.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.eclipse.edc.connector.controlplane.contract.spi.negotiation.store.ContractNegotiationStore;
2222
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreement;
2323
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreementVerificationMessage;
24+
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractNegotiationEventMessage;
2425
import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation;
2526
import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiationStates;
2627
import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest;
@@ -210,12 +211,16 @@ void requesting_shouldSendMessageWithId_whenCorrelationIdIsNull_toSupportOldProt
210211
void accepting_shouldSendAcceptedMessageAndTransitionToApproved() {
211212
var negotiation = contractNegotiationBuilder().state(ACCEPTING.code()).contractOffer(contractOffer()).build();
212213
when(store.nextNotLeased(anyInt(), stateIs(ACCEPTING.code()))).thenReturn(List.of(negotiation)).thenReturn(emptyList());
213-
when(dispatcherRegistry.dispatch(any(), any())).thenReturn(completedFuture(StatusResult.success("any")));
214+
215+
var captor = ArgumentCaptor.forClass(ContractNegotiationEventMessage.class);
216+
when(dispatcherRegistry.dispatch(any(), captor.capture())).thenReturn(completedFuture(StatusResult.success("any")));
214217
when(store.findById(negotiation.getId())).thenReturn(negotiation);
215218

216219
manager.start();
217220

218221
await().untilAsserted(() -> {
222+
var message = captor.getValue();
223+
assertThat(message.getPolicy()).isNotNull();
219224
verify(store).save(argThat(p -> p.getState() == ACCEPTED.code()));
220225
verify(dispatcherRegistry, only()).dispatch(any(), any());
221226
verify(listener).accepted(any());

core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/odrl/to/JsonObjectToPolicyTransformer.java

+20-2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@ public JsonObjectToPolicyTransformer(ParticipantIdMapper participantIdMapper) {
8585
.error("Invalid type for ODRL policy, should be one of [%s, %s, %s]".formatted(ODRL_POLICY_TYPE_SET, ODRL_POLICY_TYPE_OFFER, ODRL_POLICY_TYPE_AGREEMENT))
8686
.report();
8787
return null;
88+
} else if (policyType == PolicyType.CONTRACT) {
89+
if (object.get(ODRL_ASSIGNEE_ATTRIBUTE) == null) {
90+
context.problem()
91+
.missingProperty()
92+
.property(ODRL_ASSIGNEE_ATTRIBUTE)
93+
.report();
94+
return null;
95+
}
96+
97+
if (object.get(ODRL_ASSIGNER_ATTRIBUTE) == null) {
98+
context.problem()
99+
.missingProperty()
100+
.property(ODRL_ASSIGNER_ATTRIBUTE)
101+
.report();
102+
return null;
103+
}
88104
}
89105

90106
builder.type(policyType);
@@ -94,8 +110,10 @@ public JsonObjectToPolicyTransformer(ParticipantIdMapper participantIdMapper) {
94110
case ODRL_PROHIBITION_ATTRIBUTE -> v -> builder.prohibitions(transformArray(v, Prohibition.class, context));
95111
case ODRL_OBLIGATION_ATTRIBUTE -> v -> builder.duties(transformArray(v, Duty.class, context));
96112
case ODRL_TARGET_ATTRIBUTE -> v -> builder.target(transformString(v, context));
97-
case ODRL_ASSIGNER_ATTRIBUTE -> v -> builder.assigner(participantIdMapper.fromIri(transformString(v, context)));
98-
case ODRL_ASSIGNEE_ATTRIBUTE -> v -> builder.assignee(participantIdMapper.fromIri(transformString(v, context)));
113+
case ODRL_ASSIGNER_ATTRIBUTE ->
114+
v -> builder.assigner(participantIdMapper.fromIri(transformString(v, context)));
115+
case ODRL_ASSIGNEE_ATTRIBUTE ->
116+
v -> builder.assignee(participantIdMapper.fromIri(transformString(v, context)));
99117
case ODRL_PROFILE_ATTRIBUTE -> v -> builder.profiles(transformProfile(v));
100118
default -> v -> builder.extensibleProperty(key, transformGenericProperty(v, context));
101119
});

core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/odrl/to/JsonObjectToPolicyTransformerTest.java

+4
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ void transform_differentPolicyTypes_returnPolicy(String type, PolicyType policyT
151151
var policy = jsonFactory.createObjectBuilder()
152152
.add(CONTEXT, JsonObject.EMPTY_JSON_OBJECT)
153153
.add(TYPE, type)
154+
.add(ODRL_ASSIGNEE_ATTRIBUTE, "assignee")
155+
.add(ODRL_ASSIGNER_ATTRIBUTE, "assigner")
154156
.build();
155157

156158
var result = transformer.transform(TestInput.getExpanded(policy), context);
@@ -179,6 +181,8 @@ void shouldGetTypeFromContext_whenSet() {
179181

180182
var policy = jsonFactory.createObjectBuilder()
181183
.add(ODRL_TARGET_ATTRIBUTE, TARGET)
184+
.add(ODRL_ASSIGNEE_ATTRIBUTE, "assignee")
185+
.add(ODRL_ASSIGNER_ATTRIBUTE, "assigner")
182186
.build();
183187

184188
var result = transformer.transform(TestInput.getExpanded(policy), context);

data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private <T> StatusResult<T> handleResponse(Response response, String protocol, C
152152
} else {
153153
var stringBody = Optional.ofNullable(responseBody)
154154
.map(this::asString)
155-
.orElse("Response body is null");
155+
.orElse("Response body is null. Error code: " + response.code());
156156

157157
var status = response.code() >= 400 && response.code() < 500 ? FATAL_ERROR : ERROR_RETRY;
158158

data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public <I extends RemoteMessage, R> Response updateResource(PostDspRequest<I, R>
189189
});
190190

191191
if (inputTransformation.failed()) {
192-
monitor.debug(() -> "DSP: Transformation failed: %s".formatted(validation.getFailureMessages()));
192+
monitor.debug(() -> "DSP: Transformation failed: %s".formatted(inputTransformation.getFailureMessages()));
193193
return type(request.getErrorType()).processId(request.getProcessId()).badRequest();
194194
}
195195

data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/test/java/org/eclipse/edc/protocol/dsp/negotiation/transform/from/JsonObjectFromContractNegotiationEventMessageTransformerTest.java

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import jakarta.json.Json;
1818
import jakarta.json.JsonBuilderFactory;
1919
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractNegotiationEventMessage;
20+
import org.eclipse.edc.policy.model.Policy;
2021
import org.eclipse.edc.transform.spi.TransformerContext;
2122
import org.junit.jupiter.api.Test;
2223

@@ -52,6 +53,7 @@ void transform() {
5253
.consumerPid("consumerPid")
5354
.providerPid("providerPid")
5455
.counterPartyAddress("https://test.com")
56+
.policy(Policy.Builder.newInstance().build())
5557
.type(ACCEPTED)
5658
.build();
5759

spi/control-plane/contract-spi/src/main/java/org/eclipse/edc/connector/controlplane/contract/spi/types/negotiation/ContractNegotiation.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import static java.lang.String.format;
3939
import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation.Type.CONSUMER;
4040
import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation.Type.PROVIDER;
41+
import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiationStates.FINALIZED;
4142
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
4243

4344
/**
@@ -190,7 +191,7 @@ public void transitionRequesting() {
190191
if (Type.PROVIDER == type) {
191192
throw new IllegalStateException("Provider processes have no REQUESTING state");
192193
}
193-
transition(ContractNegotiationStates.REQUESTING, ContractNegotiationStates.REQUESTING, ContractNegotiationStates.INITIAL);
194+
transition(ContractNegotiationStates.REQUESTING, ContractNegotiationStates.REQUESTING, ContractNegotiationStates.OFFERED, ContractNegotiationStates.INITIAL);
194195
}
195196

196197
/**
@@ -209,7 +210,7 @@ public void transitionRequested() {
209210
*/
210211
public void transitionOffering() {
211212
if (CONSUMER == type) {
212-
throw new IllegalStateException("Provider processes have no OFFERING state");
213+
throw new IllegalStateException("Consumer processes have no OFFERING state");
213214
}
214215

215216
transition(ContractNegotiationStates.OFFERING, ContractNegotiationStates.OFFERING, ContractNegotiationStates.OFFERED, ContractNegotiationStates.REQUESTED);
@@ -233,7 +234,7 @@ public void transitionAccepting() {
233234
if (Type.PROVIDER == type) {
234235
throw new IllegalStateException("Provider processes have no ACCEPTING state");
235236
}
236-
transition(ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.REQUESTED);
237+
transition(ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.ACCEPTING, ContractNegotiationStates.REQUESTED, ContractNegotiationStates.OFFERED);
237238
}
238239

239240
/**
@@ -301,7 +302,7 @@ public void transitionFinalizing() {
301302
* Transition to state FINALIZED.
302303
*/
303304
public void transitionFinalized() {
304-
transition(ContractNegotiationStates.FINALIZED, ContractNegotiationStates.FINALIZED, ContractNegotiationStates.FINALIZING, ContractNegotiationStates.AGREED, ContractNegotiationStates.VERIFIED);
305+
transition(FINALIZED, FINALIZED, ContractNegotiationStates.FINALIZING, ContractNegotiationStates.AGREED, ContractNegotiationStates.VERIFIED);
305306
}
306307

307308
/**
@@ -310,7 +311,7 @@ public void transitionFinalized() {
310311
* @return true if the negotiation can be terminated, false otherwise
311312
*/
312313
public boolean canBeTerminated() {
313-
return true;
314+
return FINALIZED.code() != state;
314315
}
315316

316317
/**

0 commit comments

Comments
 (0)