-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added implementation of immutable evaluation context (#210)
added immutable context implementation Signed-off-by: thiyagu06 <[email protected]> Co-authored-by: Todd Baert <[email protected]>
- Loading branch information
Showing
19 changed files
with
619 additions
and
175 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package dev.openfeature.sdk; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import lombok.Getter; | ||
import lombok.ToString; | ||
import lombok.experimental.Delegate; | ||
|
||
/** | ||
* The EvaluationContext is a container for arbitrary contextual data | ||
* that can be used as a basis for dynamic evaluation. | ||
* The ImmutableContext is an EvaluationContext implementation which is threadsafe, and whose attributes can | ||
* not be modified after instantiation. | ||
*/ | ||
@ToString | ||
@SuppressWarnings("PMD.BeanMembersShouldSerialize") | ||
public final class ImmutableContext implements EvaluationContext { | ||
|
||
@Getter | ||
private final String targetingKey; | ||
@Delegate | ||
private final Structure structure; | ||
|
||
/** | ||
* Create an immutable context with an empty targeting_key and attributes provided. | ||
*/ | ||
public ImmutableContext() { | ||
this("", new HashMap<>()); | ||
} | ||
|
||
/** | ||
* Create an immutable context with given targeting_key provided. | ||
* | ||
* @param targetingKey targeting key | ||
*/ | ||
public ImmutableContext(String targetingKey) { | ||
this(targetingKey, new HashMap<>()); | ||
} | ||
|
||
/** | ||
* Create an immutable context with an attributes provided. | ||
* | ||
* @param attributes evaluation context attributes | ||
*/ | ||
public ImmutableContext(Map<String, Value> attributes) { | ||
this("", attributes); | ||
} | ||
|
||
/** | ||
* Create an immutable context with given targetingKey and attributes provided. | ||
* | ||
* @param targetingKey targeting key | ||
* @param attributes evaluation context attributes | ||
*/ | ||
public ImmutableContext(String targetingKey, Map<String, Value> attributes) { | ||
this.structure = new ImmutableStructure(attributes); | ||
this.targetingKey = targetingKey; | ||
} | ||
|
||
/** | ||
* Mutating targeting key is not supported in ImmutableContext and will be removed. | ||
*/ | ||
@Override | ||
@Deprecated | ||
public void setTargetingKey(String targetingKey) { | ||
throw new UnsupportedOperationException("changing of targeting key is not allowed"); | ||
} | ||
|
||
/** | ||
* Merges this EvaluationContext object with the passed EvaluationContext, overriding in case of conflict. | ||
* | ||
* @param overridingContext overriding context | ||
* @return resulting merged context | ||
*/ | ||
@Override | ||
public EvaluationContext merge(EvaluationContext overridingContext) { | ||
if (overridingContext == null) { | ||
return new ImmutableContext(this.targetingKey, this.asMap()); | ||
} | ||
String newTargetingKey = ""; | ||
if (this.getTargetingKey() != null && !this.getTargetingKey().trim().equals("")) { | ||
newTargetingKey = this.getTargetingKey(); | ||
} | ||
|
||
if (overridingContext.getTargetingKey() != null && !overridingContext.getTargetingKey().trim().equals("")) { | ||
newTargetingKey = overridingContext.getTargetingKey(); | ||
} | ||
Map<String, Value> merged = new HashMap<>(); | ||
|
||
merged.putAll(this.asMap()); | ||
merged.putAll(overridingContext.asMap()); | ||
return new ImmutableContext(newTargetingKey, merged); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package dev.openfeature.sdk; | ||
|
||
import lombok.EqualsAndHashCode; | ||
import lombok.ToString; | ||
|
||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* {@link ImmutableStructure} represents a potentially nested object type which is used to represent | ||
* structured data. | ||
* The ImmutableStructure is a Structure implementation which is threadsafe, and whose attributes can | ||
* not be modified after instantiation. | ||
*/ | ||
@ToString | ||
@EqualsAndHashCode | ||
@SuppressWarnings({"PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType"}) | ||
public final class ImmutableStructure implements Structure { | ||
|
||
private final Map<String, Value> attributes; | ||
|
||
/** | ||
* create an immutable structure with the empty attributes. | ||
*/ | ||
public ImmutableStructure() { | ||
this(new HashMap<>()); | ||
} | ||
|
||
/** | ||
* create immutable structure with the given attributes. | ||
* | ||
* @param attributes attributes. | ||
*/ | ||
public ImmutableStructure(Map<String, Value> attributes) { | ||
Map<String, Value> copy = attributes.entrySet() | ||
.stream() | ||
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone())); | ||
this.attributes = new HashMap<>(copy); | ||
} | ||
|
||
@Override | ||
public Set<String> keySet() { | ||
return new HashSet<>(this.attributes.keySet()); | ||
} | ||
|
||
// getters | ||
@Override | ||
public Value getValue(String key) { | ||
Value value = this.attributes.get(key); | ||
return value.clone(); | ||
} | ||
|
||
/** | ||
* Get all values. | ||
* | ||
* @return all attributes on the structure | ||
*/ | ||
@Override | ||
public Map<String, Value> asMap() { | ||
return attributes | ||
.entrySet() | ||
.stream() | ||
.collect(Collectors.toMap( | ||
Map.Entry::getKey, | ||
e -> getValue(e.getKey()) | ||
)); | ||
} | ||
|
||
/** | ||
* Get all values, with primitives types. | ||
* | ||
* @return all attributes on the structure into a Map | ||
*/ | ||
@Override | ||
public Map<String, Object> asObjectMap() { | ||
return attributes | ||
.entrySet() | ||
.stream() | ||
.collect(Collectors.toMap( | ||
Map.Entry::getKey, | ||
e -> convertValue(getValue(e.getKey())) | ||
)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.