Skip to content

Commit 2eec1a5

Browse files
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 <[email protected]> * Fix liniting issue Signed-off-by: Thomas Poignant <[email protected]> * fix PMD issue Signed-off-by: Thomas Poignant <[email protected]> Signed-off-by: Thomas Poignant <[email protected]>
1 parent 5db90f1 commit 2eec1a5

File tree

3 files changed

+133
-7
lines changed

3 files changed

+133
-7
lines changed

Diff for: src/main/java/dev/openfeature/javasdk/Structure.java

+69-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package dev.openfeature.javasdk;
22

33
import java.time.Instant;
4-
import java.util.HashMap;
5-
import java.util.List;
6-
import java.util.Map;
7-
import java.util.Set;
4+
import java.util.*;
5+
import java.util.stream.Collectors;
86

7+
import dev.openfeature.javasdk.exceptions.ValueNotConvertableError;
98
import lombok.EqualsAndHashCode;
109
import lombok.ToString;
1110

@@ -66,9 +65,9 @@ public Structure add(String key, Double value) {
6665
return this;
6766
}
6867

69-
/**
68+
/**
7069
* Add date-time relevant key.
71-
*
70+
*
7271
* @param key feature key
7372
* @param value date-time value
7473
* @return Structure
@@ -90,10 +89,73 @@ public <T> Structure add(String key, List<Value> value) {
9089

9190
/**
9291
* Get all values.
93-
*
92+
*
9493
* @return all attributes on the structure
9594
*/
9695
public Map<String, Value> asMap() {
9796
return new HashMap<>(this.attributes);
9897
}
98+
99+
/**
100+
* Get all values, with primitives types.
101+
*
102+
* @return all attributes on the structure into a Map
103+
*/
104+
public Map<String, Object> asObjectMap() {
105+
return attributes
106+
.entrySet()
107+
.stream()
108+
.collect(Collectors.toMap(
109+
Map.Entry::getKey,
110+
e -> convertValue(getValue(e.getKey()))
111+
));
112+
}
113+
114+
/**
115+
* convertValue is converting the object type Value in a primitive type.
116+
* @param value - Value object to convert
117+
* @return an Object containing the primitive type.
118+
*/
119+
private Object convertValue(Value value) {
120+
if (value.isBoolean()) {
121+
return value.asBoolean();
122+
}
123+
124+
if (value.isNumber()) {
125+
Double valueAsDouble = value.asDouble();
126+
if (valueAsDouble == Math.floor(valueAsDouble) && !Double.isInfinite(valueAsDouble)) {
127+
return value.asInteger();
128+
}
129+
return valueAsDouble;
130+
}
131+
132+
if (value.isString()) {
133+
return value.asString();
134+
}
135+
136+
if (value.isInstant()) {
137+
return value.asInstant();
138+
}
139+
140+
if (value.isList()) {
141+
return value.asList()
142+
.stream()
143+
.map(this::convertValue)
144+
.collect(Collectors.toList());
145+
}
146+
147+
if (value.isStructure()) {
148+
Structure s = value.asStructure();
149+
return s.asMap()
150+
.keySet()
151+
.stream()
152+
.collect(
153+
Collectors.toMap(
154+
key -> key,
155+
key -> convertValue(s.getValue(key))
156+
)
157+
);
158+
}
159+
throw new ValueNotConvertableError();
160+
}
99161
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dev.openfeature.javasdk.exceptions;
2+
3+
import dev.openfeature.javasdk.ErrorCode;
4+
import lombok.Getter;
5+
import lombok.experimental.StandardException;
6+
7+
@StandardException
8+
public class ValueNotConvertableError extends OpenFeatureError {
9+
private static final long serialVersionUID = 1L;
10+
@Getter
11+
private final ErrorCode errorCode = ErrorCode.GENERAL;
12+
}

Diff for: src/test/java/dev/openfeature/javasdk/EvalContextTest.java

+52
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java.time.Instant;
66
import java.util.ArrayList;
7+
import java.util.HashMap;
78
import java.util.List;
89
import java.util.Map;
910

@@ -148,4 +149,55 @@ public class EvalContextTest {
148149
ctxMerged = EvaluationContext.merge(ctx1, ctx2);
149150
assertEquals(key1, ctxMerged.getTargetingKey());
150151
}
152+
153+
@Test void asObjectMap() {
154+
String key1 = "key1";
155+
EvaluationContext ctx = new EvaluationContext(key1);
156+
ctx.add("stringItem", "stringValue");
157+
ctx.add("boolItem", false);
158+
ctx.add("integerItem", 1);
159+
ctx.add("doubleItem", 1.2);
160+
ctx.add("instantItem", Instant.ofEpochSecond(1663331342));
161+
List<Value> listItem = new ArrayList<>();
162+
listItem.add(new Value("item1"));
163+
listItem.add(new Value("item2"));
164+
ctx.add("listItem", listItem);
165+
List<Value> listItem2 = new ArrayList<>();
166+
listItem2.add(new Value(true));
167+
listItem2.add(new Value(false));
168+
ctx.add("listItem2", listItem2);
169+
Map<String, Value> structureValue = new HashMap<>();
170+
structureValue.put("structStringItem", new Value("stringValue"));
171+
structureValue.put("structBoolItem", new Value(false));
172+
structureValue.put("structIntegerItem", new Value(1));
173+
structureValue.put("structDoubleItem", new Value(1.2));
174+
structureValue.put("structInstantItem", new Value(Instant.ofEpochSecond(1663331342)));
175+
Structure structure = new Structure(structureValue);
176+
ctx.add("structureItem", structure);
177+
178+
179+
Map<String, Object> want = new HashMap<>();
180+
want.put("stringItem", "stringValue");
181+
want.put("boolItem", false);
182+
want.put("integerItem", 1);
183+
want.put("doubleItem", 1.2);
184+
want.put("instantItem", Instant.ofEpochSecond(1663331342));
185+
List<String> wantListItem = new ArrayList<>();
186+
wantListItem.add("item1");
187+
wantListItem.add("item2");
188+
want.put("listItem", wantListItem);
189+
List<Boolean> wantListItem2 = new ArrayList<>();
190+
wantListItem2.add(true);
191+
wantListItem2.add(false);
192+
want.put("listItem2", wantListItem2);
193+
Map<String, Object> wantStructureValue = new HashMap<>();
194+
wantStructureValue.put("structStringItem", "stringValue");
195+
wantStructureValue.put("structBoolItem", false);
196+
wantStructureValue.put("structIntegerItem", 1);
197+
wantStructureValue.put("structDoubleItem", 1.2);
198+
wantStructureValue.put("structInstantItem", Instant.ofEpochSecond(1663331342));
199+
want.put("structureItem",wantStructureValue);
200+
201+
assertEquals(want,ctx.asObjectMap());
202+
}
151203
}

0 commit comments

Comments
 (0)