feat: Add asObjectMap to get the EvaluationContext as Map<String,Object> (#75)

* Add asObjectMap to get the EvaluationContext as Map<String,Object>

Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>

* Fix liniting issue

Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>

* fix PMD issue

Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>

Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
This commit is contained in:
Thomas Poignant 2022-09-16 16:17:58 +02:00 committed by GitHub
parent 5db90f1a38
commit 2eec1a5519
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 133 additions and 7 deletions

View File

@ -1,11 +1,10 @@
package dev.openfeature.javasdk;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import dev.openfeature.javasdk.exceptions.ValueNotConvertableError;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ -66,9 +65,9 @@ public class Structure {
return this;
}
/**
/**
* Add date-time relevant key.
*
*
* @param key feature key
* @param value date-time value
* @return Structure
@ -90,10 +89,73 @@ public class Structure {
/**
* Get all values.
*
*
* @return all attributes on the structure
*/
public Map<String, Value> asMap() {
return new HashMap<>(this.attributes);
}
/**
* Get all values, with primitives types.
*
* @return all attributes on the structure into a Map
*/
public Map<String, Object> asObjectMap() {
return attributes
.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> convertValue(getValue(e.getKey()))
));
}
/**
* convertValue is converting the object type Value in a primitive type.
* @param value - Value object to convert
* @return an Object containing the primitive type.
*/
private Object convertValue(Value value) {
if (value.isBoolean()) {
return value.asBoolean();
}
if (value.isNumber()) {
Double valueAsDouble = value.asDouble();
if (valueAsDouble == Math.floor(valueAsDouble) && !Double.isInfinite(valueAsDouble)) {
return value.asInteger();
}
return valueAsDouble;
}
if (value.isString()) {
return value.asString();
}
if (value.isInstant()) {
return value.asInstant();
}
if (value.isList()) {
return value.asList()
.stream()
.map(this::convertValue)
.collect(Collectors.toList());
}
if (value.isStructure()) {
Structure s = value.asStructure();
return s.asMap()
.keySet()
.stream()
.collect(
Collectors.toMap(
key -> key,
key -> convertValue(s.getValue(key))
)
);
}
throw new ValueNotConvertableError();
}
}

View File

@ -0,0 +1,12 @@
package dev.openfeature.javasdk.exceptions;
import dev.openfeature.javasdk.ErrorCode;
import lombok.Getter;
import lombok.experimental.StandardException;
@StandardException
public class ValueNotConvertableError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter
private final ErrorCode errorCode = ErrorCode.GENERAL;
}

View File

@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -148,4 +149,55 @@ public class EvalContextTest {
ctxMerged = EvaluationContext.merge(ctx1, ctx2);
assertEquals(key1, ctxMerged.getTargetingKey());
}
@Test void asObjectMap() {
String key1 = "key1";
EvaluationContext ctx = new EvaluationContext(key1);
ctx.add("stringItem", "stringValue");
ctx.add("boolItem", false);
ctx.add("integerItem", 1);
ctx.add("doubleItem", 1.2);
ctx.add("instantItem", Instant.ofEpochSecond(1663331342));
List<Value> listItem = new ArrayList<>();
listItem.add(new Value("item1"));
listItem.add(new Value("item2"));
ctx.add("listItem", listItem);
List<Value> listItem2 = new ArrayList<>();
listItem2.add(new Value(true));
listItem2.add(new Value(false));
ctx.add("listItem2", listItem2);
Map<String, Value> structureValue = new HashMap<>();
structureValue.put("structStringItem", new Value("stringValue"));
structureValue.put("structBoolItem", new Value(false));
structureValue.put("structIntegerItem", new Value(1));
structureValue.put("structDoubleItem", new Value(1.2));
structureValue.put("structInstantItem", new Value(Instant.ofEpochSecond(1663331342)));
Structure structure = new Structure(structureValue);
ctx.add("structureItem", structure);
Map<String, Object> want = new HashMap<>();
want.put("stringItem", "stringValue");
want.put("boolItem", false);
want.put("integerItem", 1);
want.put("doubleItem", 1.2);
want.put("instantItem", Instant.ofEpochSecond(1663331342));
List<String> wantListItem = new ArrayList<>();
wantListItem.add("item1");
wantListItem.add("item2");
want.put("listItem", wantListItem);
List<Boolean> wantListItem2 = new ArrayList<>();
wantListItem2.add(true);
wantListItem2.add(false);
want.put("listItem2", wantListItem2);
Map<String, Object> wantStructureValue = new HashMap<>();
wantStructureValue.put("structStringItem", "stringValue");
wantStructureValue.put("structBoolItem", false);
wantStructureValue.put("structIntegerItem", 1);
wantStructureValue.put("structDoubleItem", 1.2);
wantStructureValue.put("structInstantItem", Instant.ofEpochSecond(1663331342));
want.put("structureItem",wantStructureValue);
assertEquals(want,ctx.asObjectMap());
}
}