Skip to content

Commit

Permalink
feat(policy): handle 'remedy' attribute in Prohibition
Browse files Browse the repository at this point in the history
  • Loading branch information
ndr-brt committed Mar 27, 2024
1 parent f2ca192 commit d6b84da
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import java.util.Optional;

import static jakarta.json.stream.JsonCollectors.toJsonArray;
import static java.util.UUID.randomUUID;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE;
Expand All @@ -65,6 +66,7 @@
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_SET;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PROHIBITION_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_REFINEMENT_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_REMEDY_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_RIGHT_OPERAND_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_XONE_CONSTRAINT_ATTRIBUTE;
Expand Down Expand Up @@ -195,6 +197,12 @@ public JsonObject visitPermission(Permission permission) {
public JsonObject visitProhibition(Prohibition prohibition) {
var prohibitionBuilder = visitRule(prohibition);

var remedies = prohibition.getRemedies();
if (remedies != null && !remedies.isEmpty()) {
var remediesJson = remedies.stream().map(this::visitDuty).collect(toJsonArray());
prohibitionBuilder.add(ODRL_REMEDY_ATTRIBUTE, remediesJson);
}

return prohibitionBuilder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer;
import org.eclipse.edc.policy.model.Action;
import org.eclipse.edc.policy.model.Constraint;
import org.eclipse.edc.policy.model.Duty;
import org.eclipse.edc.policy.model.Prohibition;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ACTION_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_CONSTRAINT_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_REMEDY_ATTRIBUTE;

/**
* Converts from an ODRL prohibition as a {@link JsonObject} in JSON-LD expanded form to a {@link Prohibition}.
Expand All @@ -39,15 +41,11 @@ public JsonObjectToProhibitionTransformer() {
public @Nullable Prohibition transform(@NotNull JsonObject object, @NotNull TransformerContext context) {
var builder = Prohibition.Builder.newInstance();

visitProperties(object, key -> {
switch (key) {
case ODRL_ACTION_ATTRIBUTE:
return value -> builder.action(transformObject(value, Action.class, context));
case ODRL_CONSTRAINT_ATTRIBUTE:
return value -> builder.constraints(transformArray(value, Constraint.class, context));
default:
return doNothing();
}
visitProperties(object, key -> switch (key) {
case ODRL_ACTION_ATTRIBUTE -> value -> builder.action(transformObject(value, Action.class, context));
case ODRL_CONSTRAINT_ATTRIBUTE -> value -> builder.constraints(transformArray(value, Constraint.class, context));
case ODRL_REMEDY_ATTRIBUTE -> value -> builder.remedies(transformArray(value, Duty.class, context));
default -> doNothing();
});

return builderResult(builder::build, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_SET;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PROHIBITION_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_REFINEMENT_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_REMEDY_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_RIGHT_OPERAND_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_XONE_CONSTRAINT_ATTRIBUTE;
Expand Down Expand Up @@ -237,14 +238,17 @@ void transform_permissionWithConstraintAndDuty_returnJsonObject() {
void transform_prohibitionWithConstraint_returnJsonObject() {
var constraint = getConstraint();
var action = getAction();
var remedy = Duty.Builder.newInstance().action(Action.Builder.newInstance().type("remedyAction").build()).build();
var prohibition = Prohibition.Builder.newInstance()
.action(action)
.constraint(constraint)
.remedy(remedy)
.build();
var policy = Policy.Builder.newInstance().prohibition(prohibition).build();

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


assertThat(result).isNotNull();
var prohibitionJson = result.get(ODRL_PROHIBITION_ATTRIBUTE).asJsonArray().get(0).asJsonObject();
assertThat(prohibitionJson.getJsonArray(ODRL_CONSTRAINT_ATTRIBUTE)).hasSize(1);

Expand All @@ -255,6 +259,12 @@ void transform_prohibitionWithConstraint_returnJsonObject() {
.isEqualTo(constraint.getOperator().getOdrlRepresentation());
assertThat(constraintJson.getJsonObject(ODRL_RIGHT_OPERAND_ATTRIBUTE).getJsonString(VALUE).getString())
.isEqualTo(((LiteralExpression) constraint.getRightExpression()).getValue());

assertThat(prohibitionJson.getJsonArray(ODRL_REMEDY_ATTRIBUTE)).hasSize(1).first()
.extracting(JsonValue::asJsonObject).satisfies(remedyJson -> {
assertThat(remedyJson.getJsonObject(ODRL_ACTION_ATTRIBUTE).getString(ODRL_ACTION_TYPE_ATTRIBUTE))
.isEqualTo("remedyAction");
});

verify(context, never()).reportProblem(anyString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,18 @@
import org.eclipse.edc.policy.model.Action;
import org.eclipse.edc.policy.model.AtomicConstraint;
import org.eclipse.edc.policy.model.Constraint;
import org.eclipse.edc.policy.model.Duty;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.edc.core.transform.transformer.TestInput.getExpanded;
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ACTION_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_CONSTRAINT_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_CONSTRAINT_TYPE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_REMEDY_ATTRIBUTE;
import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
Expand All @@ -43,59 +42,43 @@
import static org.mockito.Mockito.when;

class JsonObjectToProhibitionTransformerTest {
private static final String TARGET = "target";

private final TransformerContext context = mock(TransformerContext.class);

private final TransformerContext context = mock();
private final Action action = Action.Builder.newInstance().type("type").build();
private final Constraint constraint = AtomicConstraint.Builder.newInstance().build();

private JsonObjectToProhibitionTransformer transformer;
private final JsonObjectToProhibitionTransformer transformer = new JsonObjectToProhibitionTransformer();

@BeforeEach
void setUp() {
transformer = new JsonObjectToProhibitionTransformer();

when(context.transform(isA(JsonObject.class), eq(Action.class))).thenReturn(action);
when(context.transform(isA(JsonObject.class), eq(Constraint.class))).thenReturn(constraint);
}

@ParameterizedTest
@MethodSource("jsonSource")
void transform_attributesAsObjects_returnPermission(JsonObject prohibition) {
@Test
void transform_attributesAsObjects_returnPermission() {
var remedy = Duty.Builder.newInstance().build();
when(context.transform(isA(JsonObject.class), eq(Duty.class))).thenReturn(remedy);
var prohibition = Json.createObjectBuilder()
.add(ODRL_ACTION_ATTRIBUTE, Json.createObjectBuilder().add(TYPE, "Action"))
.add(ODRL_CONSTRAINT_ATTRIBUTE, Json.createObjectBuilder().add(TYPE, ODRL_CONSTRAINT_TYPE))
.add(ODRL_REMEDY_ATTRIBUTE, Json.createObjectBuilder().add(ODRL_ACTION_ATTRIBUTE, "remedyAction"))
.add(ODRL_TARGET_ATTRIBUTE, "target")
.build();

var result = transformer.transform(getExpanded(prohibition), context);

assertThat(result).isNotNull();
assertThat(result.getAction()).isEqualTo(action);
assertThat(result.getConstraints()).hasSize(1);
assertThat(result.getConstraints().get(0)).isEqualTo(constraint);
assertThat(result.getRemedies()).containsOnly(remedy);

verify(context, never()).reportProblem(anyString());
verify(context, times(1)).transform(isA(JsonObject.class), eq(Action.class));
verify(context, times(1)).transform(isA(JsonObject.class), eq(Constraint.class));
}

static Stream<JsonObject> jsonSource() {
var jsonFactory = Json.createBuilderFactory(Map.of());
var actionJson = jsonFactory.createObjectBuilder().add(TYPE, "action");
var constraintJson = jsonFactory.createObjectBuilder().add(TYPE, "constraint");

return Stream.of(
// object
jsonFactory.createObjectBuilder()
.add(ODRL_ACTION_ATTRIBUTE, actionJson)
.add(ODRL_CONSTRAINT_ATTRIBUTE, constraintJson)
.add(ODRL_TARGET_ATTRIBUTE, TARGET)
.build(),

// array version
jsonFactory.createObjectBuilder()
.add(ODRL_ACTION_ATTRIBUTE, jsonFactory.createArrayBuilder().add(actionJson))
.add(ODRL_CONSTRAINT_ATTRIBUTE, jsonFactory.createArrayBuilder().add(constraintJson))
.add(ODRL_TARGET_ATTRIBUTE, jsonFactory.createArrayBuilder().add(TARGET))
.build()

);
verify(context, times(1)).transform(isA(JsonObject.class), eq(Duty.class));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,27 @@

package org.eclipse.edc.policy.model;

import java.util.ArrayList;
import java.util.List;

import static java.util.stream.Collectors.joining;

/**
* Disallows an action if its constraints are satisfied.
*/
public class Prohibition extends Rule {

private final List<Duty> remedies = new ArrayList<>();

@Override
public <R> R accept(Visitor<R> visitor) {
return visitor.visitProhibition(this);
}

public List<Duty> getRemedies() {
return remedies;
}

@Override
public String toString() {
return "Prohibition constraints: [" + getConstraints().stream().map(Object::toString).collect(joining(",")) + "]";
Expand All @@ -42,6 +51,16 @@ public static Builder newInstance() {
return new Builder();
}

public Builder remedy(Duty remedy) {
rule.remedies.add(remedy);
return this;
}

public Builder remedies(List<Duty> remedies) {
rule.remedies.addAll(remedies);
return this;
}

public Prohibition build() {
return rule;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
import org.eclipse.edc.spi.asset.AssetIndex;
import org.eclipse.edc.spi.types.domain.DataAddress;
import org.eclipse.edc.spi.types.domain.asset.Asset;
import org.eclipse.edc.sql.testfixtures.PostgresqlEndToEndInstance;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.util.UUID;

Expand All @@ -38,6 +38,9 @@
import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.CoreConstants.EDC_PREFIX;
import static org.eclipse.edc.spi.query.Criterion.criterion;
import static org.eclipse.edc.sql.testfixtures.PostgresqlEndToEndInstance.createDatabase;
import static org.eclipse.edc.test.e2e.managementapi.Runtimes.inMemoryRuntime;
import static org.eclipse.edc.test.e2e.managementapi.Runtimes.postgresRuntime;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

Expand All @@ -48,25 +51,30 @@ public class AssetApiEndToEndTest {

@Nested
@EndToEndTest
class InMemory extends Tests implements InMemoryRuntime {
class InMemory extends Tests {

@RegisterExtension
public static final EdcRuntimeExtension RUNTIME = inMemoryRuntime();

InMemory() {
super(RUNTIME);
}

}

@Nested
@PostgresqlIntegrationTest
class Postgres extends Tests implements PostgresRuntime {
class Postgres extends Tests {

@RegisterExtension
static final BeforeAllCallback CREATE_DATABASE = context -> createDatabase("runtime");

@RegisterExtension
public static final EdcRuntimeExtension RUNTIME = postgresRuntime();

Postgres() {
super(RUNTIME);
}

@BeforeAll
static void beforeAll() {
PostgresqlEndToEndInstance.createDatabase("runtime");
}
}

abstract static class Tests extends ManagementApiEndToEndTestBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
import org.eclipse.edc.spi.asset.AssetIndex;
import org.eclipse.edc.spi.types.domain.DataAddress;
import org.eclipse.edc.spi.types.domain.asset.Asset;
import org.eclipse.edc.sql.testfixtures.PostgresqlEndToEndInstance;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.util.UUID;

Expand All @@ -40,13 +40,19 @@
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE;
import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;
import static org.eclipse.edc.spi.CoreConstants.EDC_PREFIX;
import static org.eclipse.edc.sql.testfixtures.PostgresqlEndToEndInstance.createDatabase;
import static org.eclipse.edc.test.e2e.managementapi.Runtimes.inMemoryRuntime;
import static org.eclipse.edc.test.e2e.managementapi.Runtimes.postgresRuntime;
import static org.hamcrest.Matchers.is;

public class CatalogApiEndToEndTest {

@Nested
@EndToEndTest
class InMemory extends Tests implements InMemoryRuntime {
class InMemory extends Tests {

@RegisterExtension
public static final EdcRuntimeExtension RUNTIME = inMemoryRuntime();

InMemory() {
super(RUNTIME);
Expand All @@ -56,17 +62,17 @@ class InMemory extends Tests implements InMemoryRuntime {

@Nested
@PostgresqlIntegrationTest
class Postgres extends Tests implements PostgresRuntime {
class Postgres extends Tests {

@RegisterExtension
static final BeforeAllCallback CREATE_DATABASE = context -> createDatabase("runtime");

@RegisterExtension
public static final EdcRuntimeExtension RUNTIME = postgresRuntime();

Postgres() {
super(RUNTIME);
}

@BeforeAll
static void beforeAll() {
PostgresqlEndToEndInstance.createDatabase("runtime");
}

}

abstract static class Tests extends ManagementApiEndToEndTestBase {
Expand Down
Loading

0 comments on commit d6b84da

Please sign in to comment.