|
| 1 | +# Typed Policy Scopes through Contexts |
| 2 | + |
| 3 | +## Decision |
| 4 | + |
| 5 | +We will bind the policy scope and the `PolicyContext` hierarchy. |
| 6 | + |
| 7 | +## Rationale |
| 8 | + |
| 9 | +At the moment implementing a new policy function for an adopter requires a "blind guess" about the content of the `PolicyContext` |
| 10 | +object, because it's designed as an unstructured map. |
| 11 | +Bounding the context structure to the scope will help documentation and usability of the Policy Engine. |
| 12 | + |
| 13 | +## Approach |
| 14 | + |
| 15 | +### Function interfaces |
| 16 | + |
| 17 | +The refactor is based on the modification of the "policy function interfaces" to add them the `PolicyContext` generic type, to permit implementations |
| 18 | +bound to the specific type. |
| 19 | +For every of these 3 interfaces (`AtomicConstraintFunction`, `DynamicAtomicConstraintFunction`, `RuleFunction`) will be defined a new interface with the same signature, |
| 20 | +plus the `C extends PolicyContext` generic type, e.g.: |
| 21 | +```java |
| 22 | +public interface AtomicConstraintRuleFunction<R extends Rule, C extends PolicyContext> { |
| 23 | + |
| 24 | + boolean evaluate(Operator operator, Object rightValue, R rule, C context); |
| 25 | + |
| 26 | + ... |
| 27 | +} |
| 28 | +``` |
| 29 | + |
| 30 | +The current interface will be deprecated and it will extend the new one setting `PolicyContext` as bound class. This will permit to avoid breaking changes: |
| 31 | +```java |
| 32 | +@Deprecated |
| 33 | +public interface AtomicConstraintFunction<R extends Rule> extends AtomicConstraintRuleFunction<R, PolicyContext> { } |
| 34 | +``` |
| 35 | + |
| 36 | +After then the current interfaces will be replaced by the new one in all the signature in the policy engine spi and implementation. |
| 37 | + |
| 38 | +### Policy Engine |
| 39 | + |
| 40 | +The `PolicyEngine` will have new methods to register validators/function that accept also a `Class<PolicyContext>`. E.g.: |
| 41 | +```java |
| 42 | +<R extends Rule, C extends PolicyContext> void registerFunction(Class<C> contextType, Class<R> type, String key, AtomicConstraintRuleFunction<R, C> function); |
| 43 | +``` |
| 44 | +Plus there will be a new `evaluate` method that will accept a typed context: |
| 45 | +```java |
| 46 | +<C extends PolicyContext> Result<Void> evaluate(Policy policy, C context); |
| 47 | +``` |
| 48 | + |
| 49 | +the registered `contextType` object will then be used to filter out validators and functions during the evaluation, the validator/function |
| 50 | +will be used only if the registered `contextType` `isAssignableFrom` the passed `context` class. |
| 51 | +This means that they will be used only if the type is the same or a super type of the passed context, this will permit to |
| 52 | +achieve scope inheritance, for example please consider: |
| 53 | +- scope `foo` associated with `FooContext` |
| 54 | +- scope `foo.bar` associated with `FooBarContext` that extends `FooContext` |
| 55 | + |
| 56 | +In this case, when a `FooBarContext` object is passed to the `evaluate` function, will select also functions that were registered |
| 57 | +on the `FooContext`. |
| 58 | + |
| 59 | +### Policy Contexts |
| 60 | + |
| 61 | +The `PolicyContexts` extensions class and the scope constants will be kept in separated `spi` modules so then they could be used by different core and extension modules. |
0 commit comments