Skip to content

Commit c79014c

Browse files
authored
feat: cel expression api (#68)
* feat: cel expression api * chore: pr remarks
1 parent bd9569a commit c79014c

File tree

45 files changed

+2046
-81
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2046
-81
lines changed

extensions/cel/cel-extension/src/main/java/org/eclipse/edc/virtualized/policy/cel/engine/CelExpressionEngineImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public boolean canEvaluate(String leftOperand) {
7979
public Set<String> evaluationScopes(String leftOperand) {
8080
return fetch(leftOperand)
8181
.stream()
82-
.flatMap(expr -> expr.scopes().stream())
82+
.flatMap(expr -> expr.getScopes().stream())
8383
.collect(Collectors.toSet());
8484
}
8585

@@ -136,7 +136,7 @@ private Result<Boolean> evaluateAst(CelAbstractSyntaxTree ast, Object leftOperan
136136

137137
private Result<List<CelAbstractSyntaxTree>> fetchAndCompile(String leftOperand) {
138138
return fetch(leftOperand).stream()
139-
.map(expr -> compile(expr.expression()))
139+
.map(expr -> compile(expr.getExpression()))
140140
.collect(Result.collector());
141141
}
142142

extensions/cel/cel-extension/src/main/java/org/eclipse/edc/virtualized/policy/cel/service/CelPolicyExpressionServiceImpl.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package org.eclipse.edc.virtualized.policy.cel.service;
1616

17+
import org.eclipse.edc.spi.query.Criterion;
1718
import org.eclipse.edc.spi.query.QuerySpec;
1819
import org.eclipse.edc.spi.result.ServiceResult;
1920
import org.eclipse.edc.transaction.spi.TransactionContext;
@@ -38,7 +39,7 @@ public CelPolicyExpressionServiceImpl(CelExpressionStore store, TransactionConte
3839
@Override
3940
public ServiceResult<Void> create(CelExpression expression) {
4041
return tx.execute(() -> {
41-
var validationResult = engine.validate(expression.expression());
42+
var validationResult = engine.validate(expression.getExpression());
4243
if (validationResult.failed()) {
4344
return validationResult;
4445
}
@@ -51,10 +52,23 @@ public ServiceResult<Void> create(CelExpression expression) {
5152
});
5253
}
5354

55+
@Override
56+
public ServiceResult<CelExpression> findById(String id) {
57+
return tx.execute(() -> {
58+
var query = QuerySpec.Builder.newInstance().filter(Criterion.criterion("id", "=", id)).build();
59+
var results = store.query(query);
60+
if (results.isEmpty()) {
61+
return ServiceResult.notFound("CelExpression with id " + id + " not found");
62+
} else {
63+
return ServiceResult.success(results.get(0));
64+
}
65+
});
66+
}
67+
5468
@Override
5569
public ServiceResult<Void> update(CelExpression expression) {
5670
return tx.execute(() -> {
57-
var validationResult = engine.validate(expression.expression());
71+
var validationResult = engine.validate(expression.getExpression());
5872
if (validationResult.failed()) {
5973
return validationResult;
6074
}

extensions/cel/cel-extension/src/main/java/org/eclipse/edc/virtualized/policy/cel/store/InMemoryCelExpressionStore.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ public InMemoryCelExpressionStore(CriterionOperatorRegistry criterionOperatorReg
3737

3838
@Override
3939
public StoreResult<Void> create(CelExpression expression) {
40-
return expressions.putIfAbsent(expression.id(), expression) == null
40+
return expressions.putIfAbsent(expression.getId(), expression) == null
4141
? StoreResult.success()
42-
: StoreResult.alreadyExists(alreadyExistsErrorMessage(expression.id()));
42+
: StoreResult.alreadyExists(alreadyExistsErrorMessage(expression.getId()));
4343
}
4444

4545
@Override
4646
public StoreResult<Void> update(CelExpression expression) {
47-
return expressions.replace(expression.id(), expression) != null
47+
return expressions.replace(expression.getId(), expression) != null
4848
? StoreResult.success()
49-
: StoreResult.notFound(notFoundErrorMessage(expression.id()));
49+
: StoreResult.notFound(notFoundErrorMessage(expression.getId()));
5050
}
5151

5252
@Override

extensions/cel/cel-extension/src/test/java/org/eclipse/edc/virtualized/policy/cel/engine/CelExpressionEngineImplTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,11 @@ void canEvaluate_noMatching() {
229229
}
230230

231231
private CelExpression expression(String expr) {
232-
return new CelExpression("id", "test", expr, "desc");
232+
return CelExpression.Builder.newInstance().id("id")
233+
.leftOperand("test")
234+
.expression(expr)
235+
.description("description")
236+
.build();
233237
}
234238

235239
private @NotNull Map<String, Object> credential() {

extensions/cel/cel-extension/src/test/java/org/eclipse/edc/virtualized/policy/cel/service/CelPolicyExpressionServiceImplTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ void delete() {
134134
}
135135

136136
private CelExpression celExpression(String id) {
137-
return new CelExpression(id, "leftOperand", "expression", "description");
137+
return CelExpression.Builder.newInstance().id(id)
138+
.leftOperand("leftOperand")
139+
.expression("expression")
140+
.description("description")
141+
.build();
138142
}
139143
}

extensions/cel/cel-spi/src/main/java/org/eclipse/edc/virtualized/policy/cel/model/CelExpression.java

Lines changed: 108 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,122 @@
1414

1515
package org.eclipse.edc.virtualized.policy.cel.model;
1616

17-
import java.time.Clock;
17+
import org.eclipse.edc.spi.entity.Entity;
18+
19+
import java.util.HashSet;
20+
import java.util.Objects;
1821
import java.util.Set;
1922

23+
import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE;
24+
2025
/**
2126
* Represents a CEL (Common Expression Language) expression used in policy definitions.
2227
*
23-
* @param id the unique identifier of the CEL expression
24-
* @param leftOperand the left operand of the expression
25-
* @param expression the CEL expression string
26-
* @param description a description of the expression
27-
* @param createdAt the timestamp when the expression was created
28-
* @param updatedAt the timestamp when the expression was last updated
2928
*/
30-
public record CelExpression(String id, Set<String> scopes, String leftOperand, String expression,
31-
String description, Long createdAt, Long updatedAt) {
29+
public class CelExpression extends Entity {
30+
31+
public static final String CEL_EXPRESSION_TYPE_TERM = "CelExpression";
32+
public static final String CEL_EXPRESSION_TYPE_IRI = EDC_NAMESPACE + CEL_EXPRESSION_TYPE_TERM;
33+
public static final String CEL_EXPRESSION_SCOPES_TERM = "scopes";
34+
public static final String CEL_EXPRESSION_SCOPES_IRI = EDC_NAMESPACE + CEL_EXPRESSION_SCOPES_TERM;
35+
public static final String CEL_EXPRESSION_LEFT_OPERAND_TERM = "leftOperand";
36+
public static final String CEL_EXPRESSION_LEFT_OPERAND_IRI = EDC_NAMESPACE + CEL_EXPRESSION_LEFT_OPERAND_TERM;
37+
public static final String CEL_EXPRESSION_EXPRESSION_TERM = "expression";
38+
public static final String CEL_EXPRESSION_EXPRESSION_IRI = EDC_NAMESPACE + CEL_EXPRESSION_EXPRESSION_TERM;
39+
public static final String CEL_EXPRESSION_DESCRIPTION_TERM = "description";
40+
public static final String CEL_EXPRESSION_DESCRIPTION_IRI = EDC_NAMESPACE + CEL_EXPRESSION_DESCRIPTION_TERM;
41+
public static final String MATCH_ALL_SCOPE = "*.";
42+
43+
private Set<String> scopes = new HashSet<>();
44+
private String leftOperand;
45+
private String expression;
46+
private String description;
47+
private long updatedAt;
3248

3349

34-
public CelExpression(String id, String leftOperand, String expression, String description) {
35-
this(id, Set.of("*."), leftOperand, expression, description, Clock.systemUTC().millis(), Clock.systemUTC().millis());
50+
private CelExpression() {
51+
}
52+
53+
public Set<String> getScopes() {
54+
return scopes;
55+
}
56+
57+
public String getDescription() {
58+
return description;
3659
}
3760

61+
public String getExpression() {
62+
return expression;
63+
}
64+
65+
public String getLeftOperand() {
66+
return leftOperand;
67+
}
68+
69+
public long getUpdatedAt() {
70+
return updatedAt;
71+
}
72+
73+
public static class Builder extends Entity.Builder<CelExpression, Builder> {
74+
75+
private Builder() {
76+
super(new CelExpression());
77+
}
78+
79+
public static Builder newInstance() {
80+
return new Builder();
81+
}
82+
83+
public Builder id(String id) {
84+
entity.id = id;
85+
return this;
86+
}
87+
88+
@Override
89+
public Builder self() {
90+
return this;
91+
}
92+
93+
public Builder scopes(Set<String> scopes) {
94+
entity.scopes = scopes;
95+
return this;
96+
}
97+
98+
public Builder leftOperand(String leftOperand) {
99+
entity.leftOperand = leftOperand;
100+
return this;
101+
}
102+
103+
public Builder expression(String expression) {
104+
entity.expression = expression;
105+
return this;
106+
}
107+
108+
public Builder description(String description) {
109+
entity.description = description;
110+
return this;
111+
}
112+
113+
public Builder updatedAt(Long updatedAt) {
114+
entity.updatedAt = updatedAt;
115+
return this;
116+
}
117+
118+
public CelExpression build() {
119+
Objects.requireNonNull(entity.leftOperand, "CelExpression leftOperand cannot be null");
120+
Objects.requireNonNull(entity.expression, "CelExpression expression cannot be null");
121+
Objects.requireNonNull(entity.description, "CelExpression description cannot be null");
122+
123+
if (entity.getUpdatedAt() == 0L) {
124+
entity.updatedAt = entity.getCreatedAt();
125+
}
126+
127+
if (entity.scopes.isEmpty()) {
128+
entity.scopes.add(MATCH_ALL_SCOPE);
129+
}
130+
131+
return super.build();
132+
}
133+
134+
}
38135
}

extensions/cel/cel-spi/src/main/java/org/eclipse/edc/virtualized/policy/cel/service/CelPolicyExpressionService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ public interface CelPolicyExpressionService {
3434
*/
3535
ServiceResult<Void> create(CelExpression expression);
3636

37+
/**
38+
* Finds a CEL expression by its ID.
39+
*
40+
* @param id the ID of the expression to find
41+
* @return a service result containing the found expression or an error
42+
*/
43+
ServiceResult<CelExpression> findById(String id);
44+
3745
/**
3846
* Updates an existing CEL expression.
3947
*

extensions/cel/cel-spi/src/testFixtures/java/org/eclipse/edc/virtualized/policy/cel/CelExpressionStoreTestBase.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ void delete() {
135135
var expr = celExpression("expr-to-delete");
136136
getStore().create(expr);
137137

138-
var deleteRes = getStore().delete(expr.id());
138+
var deleteRes = getStore().delete(expr.getId());
139139
assertThat(deleteRes).isSucceeded();
140140
}
141141

@@ -150,6 +150,10 @@ private CelExpression celExpression(String id) {
150150
}
151151

152152
private CelExpression celExpression(String id, String leftOperand) {
153-
return new CelExpression(id, leftOperand, "expression", "description");
153+
return CelExpression.Builder.newInstance().id(id)
154+
.leftOperand(leftOperand)
155+
.expression("expression")
156+
.description("description")
157+
.build();
154158
}
155159
}

extensions/cel/cel-store-sql/src/main/java/org/eclipse/edc/virtual/connector/store/sql/cel/SqlCelExpressionStore.java

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,35 @@ private CelExpression mapResultSet(ResultSet resultSet) throws Exception {
6262
var description = resultSet.getString(statements.getDescriptionColumn());
6363
var created = resultSet.getLong(statements.getCreateTimestampColumn());
6464
var lastModified = resultSet.getLong(statements.getLastModifiedTimestampColumn());
65-
return new CelExpression(id, new HashSet<>(scopes), leftOperand, expression, description, created, lastModified);
65+
66+
return CelExpression.Builder.newInstance()
67+
.id(id)
68+
.scopes(new HashSet<>(scopes))
69+
.leftOperand(leftOperand)
70+
.expression(expression)
71+
.description(description)
72+
.createdAt(created)
73+
.updatedAt(lastModified)
74+
.build();
6675
}
6776

6877
@Override
6978
public StoreResult<Void> create(CelExpression expression) {
7079
return transactionContext.execute(() -> {
7180
try (var connection = getConnection()) {
72-
if (findByIdInternal(connection, expression.id()) != null) {
73-
return alreadyExists(alreadyExistsErrorMessage(expression.id()));
81+
if (findByIdInternal(connection, expression.getId()) != null) {
82+
return alreadyExists(alreadyExistsErrorMessage(expression.getId()));
7483
}
7584

7685
var stmt = statements.getInsertTemplate();
7786
queryExecutor.execute(connection, stmt,
78-
expression.id(),
79-
expression.leftOperand(),
80-
expression.expression(),
81-
expression.description(),
82-
toJson(expression.scopes()),
83-
expression.createdAt(),
84-
expression.updatedAt()
87+
expression.getId(),
88+
expression.getLeftOperand(),
89+
expression.getExpression(),
90+
expression.getDescription(),
91+
toJson(expression.getScopes()),
92+
expression.getCreatedAt(),
93+
expression.getUpdatedAt()
8594
);
8695
return success();
8796

@@ -95,19 +104,19 @@ public StoreResult<Void> create(CelExpression expression) {
95104
public StoreResult<Void> update(CelExpression expression) {
96105
return transactionContext.execute(() -> {
97106
try (var connection = getConnection()) {
98-
if (findByIdInternal(connection, expression.id()) != null) {
107+
if (findByIdInternal(connection, expression.getId()) != null) {
99108
queryExecutor.execute(connection,
100109
statements.getUpdateTemplate(),
101-
expression.leftOperand(),
102-
expression.expression(),
103-
expression.description(),
104-
toJson(expression.scopes()),
105-
expression.createdAt(),
106-
expression.updatedAt(),
107-
expression.id());
110+
expression.getLeftOperand(),
111+
expression.getExpression(),
112+
expression.getDescription(),
113+
toJson(expression.getScopes()),
114+
expression.getCreatedAt(),
115+
expression.getUpdatedAt(),
116+
expression.getId());
108117
return StoreResult.success();
109118
}
110-
return StoreResult.notFound(notFoundErrorMessage(expression.id()));
119+
return StoreResult.notFound(notFoundErrorMessage(expression.getId()));
111120
} catch (SQLException e) {
112121
throw new EdcPersistenceException(e);
113122
}

extensions/common/api/lib/management-api-lib/build.gradle.kts renamed to extensions/common/api/lib/v-management-api-lib/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies {
2020
api(libs.edc.spi.jsonld)
2121
api(libs.edc.spi.web)
2222
api(libs.edc.spi.contract)
23+
api(libs.edc.lib.mgmtapi)
2324

2425
testImplementation(libs.edc.junit)
2526
testImplementation(libs.edc.lib.jsonld)

0 commit comments

Comments
 (0)