Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce typed transformation problem reporting #3004

Merged
merged 4 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.eclipse.edc.connector.core.transform;

import org.eclipse.edc.transform.spi.ProblemBuilder;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -44,6 +45,11 @@ public void reportProblem(String problem) {
problems.add(problem);
}

@Override
public ProblemBuilder problem() {
return new ProblemBuilder(this);
}

@Override
public <INPUT, OUTPUT> @Nullable OUTPUT transform(INPUT object, Class<OUTPUT> outputType) {
if (object == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
import org.eclipse.edc.catalog.spi.CatalogRequestMessage;
import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.lang.String.format;
import static jakarta.json.JsonValue.ValueType.ARRAY;
import static jakarta.json.JsonValue.ValueType.OBJECT;
import static org.eclipse.edc.protocol.dsp.catalog.transform.DspCatalogPropertyAndTypeNames.DSPACE_CATALOG_REQUEST_TYPE;
import static org.eclipse.edc.protocol.dsp.catalog.transform.DspCatalogPropertyAndTypeNames.DSPACE_FILTER_PROPERTY;

/**
Expand All @@ -44,21 +45,35 @@ public JsonObjectToCatalogRequestMessageTransformer(ObjectMapper mapper) {
public @Nullable CatalogRequestMessage transform(@NotNull JsonObject object, @NotNull TransformerContext context) {
var builder = CatalogRequestMessage.Builder.newInstance();

if (object.get(DSPACE_FILTER_PROPERTY) != null) {
builder.querySpec(transformQuerySpec(object.get(DSPACE_FILTER_PROPERTY), context));
var querySpec = transformQuerySpec(object, context);
if (querySpec != null) {
builder.querySpec(querySpec);
}

return builder.build();
}

private QuerySpec transformQuerySpec(JsonValue value, TransformerContext context) {
@Nullable
private QuerySpec transformQuerySpec(JsonObject object, TransformerContext context) {
var value = object.get(DSPACE_FILTER_PROPERTY);
if (value == null) {
return null;
}

if (value instanceof JsonObject) {
return mapper.convertValue(value, QuerySpec.class);
} else if (value instanceof JsonArray) {
var array = (JsonArray) value;
return transformQuerySpec(array.getJsonObject(0), context);
} else {
context.reportProblem(format("Expected filter to be JsonObject or JsonArray, but was %s", value.getClass().getSimpleName()));
context.problem()
.unexpectedType()
.type(DSPACE_CATALOG_REQUEST_TYPE)
.property(DSPACE_FILTER_PROPERTY)
.actual(value.getValueType())
.expected(OBJECT)
.expected(ARRAY)
.report();
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ public JsonObjectFromContractAgreementMessageTransformer(JsonBuilderFactory json

var policy = context.transform(agreement.getPolicy(), JsonObject.class);
if (policy == null) {
context.reportProblem("Cannot transform from ContractAgreementMessage with null policy");
context.problem()
.nullProperty()
.type(ContractAgreementMessage.class)
.property("policy")
.report();
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,16 @@ public JsonObjectFromContractNegotiationTransformer(JsonBuilderFactory jsonFacto
}

private String state(Integer state, TransformerContext context) {
switch (ContractNegotiationStates.from(state)) {
var negotiationState = ContractNegotiationStates.from(state);
if (negotiationState == null) {
context.problem()
.nullProperty()
.type(ContractNegotiation.class)
.property(DSPACE_NEGOTIATION_PROPERTY_STATE)
.report();
return null;
}
switch (negotiationState) {
case REQUESTING:
case REQUESTED:
return DSPACE_NEGOTIATION_STATE_REQUESTED;
Expand All @@ -83,7 +92,13 @@ private String state(Integer state, TransformerContext context) {
case TERMINATED:
return DSPACE_NEGOTIATION_STATE_TERMINATED;
default:
context.reportProblem(String.format("Could not map state %s in ContractNegotiation", state));
context.problem()
.unexpectedType()
.type(ContractNegotiation.class)
.property("state")
.actual(negotiationState.toString())
.expected(ContractNegotiationStates.class)
.report();
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ public JsonObjectFromContractRequestMessageTransformer(JsonBuilderFactory jsonFa
builder.add(DSPACE_NEGOTIATION_PROPERTY_DATASET, requestMessage.getContractOffer().getAssetId());
var policy = context.transform(requestMessage.getContractOffer().getPolicy(), JsonObject.class);
if (policy == null) {
context.reportProblem("Cannot transform from ContractRequestMessage policy");
context.problem()
.nullProperty()
.type(ContractRequestMessage.class)
.property("contractOffer")
.report();
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
import java.time.format.DateTimeParseException;
import java.util.Set;

import static java.lang.String.format;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_AGREEMENT_MESSAGE;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_AGREEMENT;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID;
Expand All @@ -50,7 +51,11 @@ public JsonObjectToContractAgreementMessageTransformer() {
public @Nullable ContractAgreementMessage transform(@NotNull JsonObject object, @NotNull TransformerContext context) {
var messageBuilder = ContractAgreementMessage.Builder.newInstance();
if (!transformMandatoryString(object.get(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID), messageBuilder::processId, context)) {
context.reportProblem(format("No '%s' specified on ContractAgreementMessage", DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID));
context.problem()
.missingProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID)
.report();
return null;
}

Expand All @@ -63,13 +68,17 @@ public JsonObjectToContractAgreementMessageTransformer() {

var policy = context.transform(filteredJsonAgreement, Policy.class);
if (policy == null) {
context.reportProblem("Cannot transform to ContractAgreementMessage with invalid policy");
context.problem()
.invalidProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_AGREEMENT)
.report();
return null;
}

var agreement = contractAgreement(jsonAgreement, policy, context);
if (agreement == null) {
context.reportProblem("Cannot transform to ContractAgreementMessage with null agreement");
// problem already reported
return null;
}

Expand All @@ -91,18 +100,30 @@ private ContractAgreement contractAgreement(JsonObject jsonAgreement, Policy pol
var builder = ContractAgreement.Builder.newInstance();
var agreementId = nodeId(jsonAgreement);
if (agreementId == null) {
context.reportProblem("No id specified on ContractAgreement");
context.problem()
.missingProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE)
.property(ID)
.report();
return null;
}
builder.id(agreementId);

if (!transformMandatoryString(jsonAgreement.get(DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID), builder::consumerId, context)) {
context.reportProblem(format("No '%s' specified on ContractAgreement", DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID));
context.problem()
.missingProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_CONSUMER_ID)
.report();
return null;
}

if (!transformMandatoryString(jsonAgreement.get(DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID), builder::providerId, context)) {
context.reportProblem(format("No '%s' specified on ContractAgreement", DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID));
context.problem()
.missingProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_PROVIDER_ID)
.report();
return null;
}

Expand All @@ -111,13 +132,23 @@ private ContractAgreement contractAgreement(JsonObject jsonAgreement, Policy pol

var timestamp = transformString(jsonAgreement.get(DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP), context);
if (timestamp == null) {
context.reportProblem(format("No '%s' specified on ContractAgreement", DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP));
context.problem()
.missingProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP)
.report();
return null;
}
try {
builder.contractSigningDate(Instant.parse(timestamp).getEpochSecond());
} catch (DateTimeParseException e) {
context.reportProblem(format("Invalid '%s' specified on ContractAgreement: %s", DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP, e.getMessage()));
context.problem()
.invalidProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_TIMESTAMP)
.value(timestamp)
.error(e.getMessage())
.report();
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.lang.String.format;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_AGREEMENT_VERIFICATION_MESSAGE;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID;

/**
Expand All @@ -37,7 +37,11 @@ public JsonObjectToContractAgreementVerificationMessageTransformer() {
public @Nullable ContractAgreementVerificationMessage transform(@NotNull JsonObject object, @NotNull TransformerContext context) {
var builder = ContractAgreementVerificationMessage.Builder.newInstance();
if (!transformMandatoryString(object.get(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID), builder::processId, context)) {
context.reportProblem(format("ContractAgreementVerificationMessage is missing the '%s' property", DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID));
context.problem()
.missingProperty()
.type(DSPACE_NEGOTIATION_AGREEMENT_VERIFICATION_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID)
.report();
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.lang.String.format;
import static org.eclipse.edc.connector.contract.spi.types.agreement.ContractNegotiationEventMessage.Type.ACCEPTED;
import static org.eclipse.edc.connector.contract.spi.types.agreement.ContractNegotiationEventMessage.Type.FINALIZED;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_EVENT_MESSAGE;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE_ACCEPTED;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE_FINALIZED;
Expand All @@ -44,7 +44,11 @@ public JsonObjectToContractNegotiationEventMessageTransformer() {
var builder = ContractNegotiationEventMessage.Builder.newInstance();

if (!transformMandatoryString(object.get(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID), builder::processId, context)) {
context.reportProblem(format("ContractNegotiationEventMessage is missing the %s property", DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID));
context.problem()
.missingProperty()
.type(DSPACE_NEGOTIATION_EVENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID)
.report();
return null;
}

Expand All @@ -54,7 +58,13 @@ public JsonObjectToContractNegotiationEventMessageTransformer() {
} else if (DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE_FINALIZED.equals(eventType)) {
builder.type(FINALIZED);
} else {
context.reportProblem(format("Could not map '%s' in ContractNegotiationEventMessage: %s", DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE, eventType));
context.problem()
.unexpectedType()
.type(DSPACE_NEGOTIATION_EVENT_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE)
.expected(DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE_ACCEPTED)
.expected(DSPACE_NEGOTIATION_PROPERTY_EVENT_TYPE_FINALIZED)
.report();
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@

package org.eclipse.edc.protocol.dsp.negotiation.transform.to;

import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiationTerminationMessage;
import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.lang.String.format;
import static jakarta.json.JsonValue.ValueType.ARRAY;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_CODE;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_PROPERTY_REASON;
import static org.eclipse.edc.protocol.dsp.negotiation.transform.DspNegotiationPropertyAndTypeNames.DSPACE_NEGOTIATION_TERMINATION_MESSAGE;

/**
* Creates a {@link ContractNegotiationTerminationMessage} from a {@link JsonObject}.
Expand All @@ -39,7 +41,9 @@ public JsonObjectToContractNegotiationTerminationMessageTransformer() {
public @Nullable ContractNegotiationTerminationMessage transform(@NotNull JsonObject object, @NotNull TransformerContext context) {
var builder = ContractNegotiationTerminationMessage.Builder.newInstance();

transformString(object.get(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID), builder::processId, context);
if (!transformMandatoryString(object.get(DSPACE_NEGOTIATION_PROPERTY_PROCESS_ID), builder::processId, context)) {
return null;
}

var code = object.get(DSPACE_NEGOTIATION_PROPERTY_CODE);
if (code != null) { // optional property
Expand All @@ -48,13 +52,19 @@ public JsonObjectToContractNegotiationTerminationMessageTransformer() {

var reasons = object.get(DSPACE_NEGOTIATION_PROPERTY_REASON);
if (reasons != null) { // optional property
var result = typeValueArray(reasons, context);
if (result == null) {
context.reportProblem(format("Cannot transform property %s in ContractNegotiationTerminationMessage", DSPACE_NEGOTIATION_PROPERTY_REASON));
} else {
if (result.size() > 0) {
builder.rejectionReason(result.toString());
if (reasons instanceof JsonArray) {
var array = (JsonArray) reasons;
if (array.size() > 0) {
builder.rejectionReason(array.toString());
}
} else {
context.problem()
.unexpectedType()
.type(DSPACE_NEGOTIATION_TERMINATION_MESSAGE)
.property(DSPACE_NEGOTIATION_PROPERTY_REASON)
.actual(reasons.getValueType().toString())
.expected(ARRAY)
.report();
}
}

Expand Down
Loading