Skip to content

Commit 7e6259c

Browse files
committed
breaking: store all numbers as doubles
Signed-off-by: Todd Baert <toddbaert@gmail.com>
1 parent c701a6c commit 7e6259c

File tree

4 files changed

+171
-20
lines changed

4 files changed

+171
-20
lines changed

src/main/java/dev/openfeature/javasdk/Structure.java

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ public Value getValue(String key) {
4141
}
4242

4343
// adders
44+
public Structure add(String key, Value value) {
45+
attributes.put(key, value);
46+
return this;
47+
}
48+
4449
public Structure add(String key, Boolean value) {
4550
attributes.put(key, new Value(value));
4651
return this;

src/main/java/dev/openfeature/javasdk/Value.java

+25-20
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
import lombok.ToString;
88

99
/**
10-
* Values server as a return type for provider objects. Providers may deal in protobufs or JSON in the backend and
11-
* have no reasonable way to convert that into a type that users care about (e.g. an instance of `T`). This
12-
* intermediate representation should provide a good medium of exchange.
10+
* Values serve as a return type for provider objects.
11+
* Providers may deal in JSON, protobuf, XML or some other data-interchange format.
12+
* This intermediate representation provides a good medium of exchange.
1313
*/
1414
@ToString
1515
@EqualsAndHashCode
@@ -18,6 +18,10 @@ public class Value {
1818

1919
private final Object innerObject;
2020

21+
public Value() {
22+
this.innerObject = null;
23+
}
24+
2125
public Value(Value value) {
2226
this.innerObject = value.innerObject;
2327
}
@@ -31,7 +35,7 @@ public Value(String value) {
3135
}
3236

3337
public Value(Integer value) {
34-
this.innerObject = value;
38+
this.innerObject = value.doubleValue();
3539
}
3640

3741
public Value(Double value) {
@@ -51,38 +55,38 @@ public Value(ZonedDateTime value) {
5155
}
5256

5357
/**
54-
* Check if this Value represents a Boolean.
58+
* Check if this Value represents null.
5559
*
5660
* @return boolean
5761
*/
58-
public boolean isBoolean() {
59-
return this.innerObject instanceof Boolean;
62+
public boolean isNull() {
63+
return this.innerObject == null;
6064
}
6165

6266
/**
63-
* Check if this Value represents a String.
67+
* Check if this Value represents a Boolean.
6468
*
6569
* @return boolean
6670
*/
67-
public boolean isString() {
68-
return this.innerObject instanceof String;
71+
public boolean isBoolean() {
72+
return this.innerObject instanceof Boolean;
6973
}
7074

7175
/**
72-
* Check if this Value represents an Integer.
76+
* Check if this Value represents a String.
7377
*
7478
* @return boolean
7579
*/
76-
public boolean isInteger() {
77-
return this.innerObject instanceof Integer;
80+
public boolean isString() {
81+
return this.innerObject instanceof String;
7882
}
7983

8084
/**
81-
* Check if this Value represents a Double.
85+
* Check if this Value represents a numeric value.
8286
*
8387
* @return boolean
8488
*/
85-
public boolean isDouble() {
89+
public boolean isNumber() {
8690
return this.innerObject instanceof Double;
8791
}
8892

@@ -140,24 +144,25 @@ public String asString() {
140144
}
141145

142146
/**
143-
* Retrieve the underlying Integer value, or null.
147+
* Retrieve the underlying numeric value as an Integer, or null.
148+
* If the value is not an integer, it will be rounded using Math.round().
144149
*
145150
* @return Integer
146151
*/
147152
public Integer asInteger() {
148-
if (this.isInteger()) {
149-
return (Integer)this.innerObject;
153+
if (this.isNumber()) {
154+
return (int)Math.round((Double)this.innerObject);
150155
}
151156
return null;
152157
}
153158

154159
/**
155-
* Retrieve the underlying Double value, or null.
160+
* Retrieve the underlying numeric value as a Double, or null.
156161
*
157162
* @return Double
158163
*/
159164
public Double asDouble() {
160-
if (this.isDouble()) {
165+
if (this.isNumber()) {
161166
return (Double)this.innerObject;
162167
}
163168
return null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package dev.openfeature.javasdk;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNotSame;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import java.time.ZonedDateTime;
8+
import java.util.ArrayList;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
import org.junit.jupiter.api.Test;
14+
15+
public class StructureTest {
16+
@Test public void noArgShouldContainEmptyAttributes() {
17+
Structure structure = new Structure();
18+
assertEquals(0, structure.asMap().keySet().size());
19+
}
20+
21+
@Test public void mapArgShouldContainNewMap() {
22+
String KEY = "key";
23+
Map<String, Value> map = new HashMap<String, Value>() {
24+
{
25+
put(KEY, new Value(KEY));
26+
}
27+
};
28+
Structure structure = new Structure(map);
29+
assertEquals(KEY, structure.asMap().get(KEY).asString());
30+
assertNotSame(structure.asMap(), map); // should be a copy
31+
}
32+
33+
@Test public void addAndGetAddAndReturnValues() {
34+
String BOOL_KEY = "bool";
35+
String STRING_KEY = "string";
36+
String INT_KEY = "int";
37+
String DOUBLE_KEY = "double";
38+
String DATE_KEY = "date";
39+
String STRUCT_KEY = "struct";
40+
String LIST_KEY = "list";
41+
String VALUE_KEY = "value";
42+
43+
boolean BOOL_VAL = true;
44+
String STRING_VAL = "val";
45+
int INT_VAL = 13;
46+
double DOUBLE_VAL = .5;
47+
ZonedDateTime DATE_VAL = ZonedDateTime.now();
48+
Structure STRUCT_VAL = new Structure();
49+
List<Value> LIST_VAL = new ArrayList<Value>();
50+
Value VALUE_VAL = new Value();
51+
52+
Structure structure = new Structure();
53+
structure.add(BOOL_KEY, BOOL_VAL);
54+
structure.add(STRING_KEY, STRING_VAL);
55+
structure.add(INT_KEY, INT_VAL);
56+
structure.add(DOUBLE_KEY, DOUBLE_VAL);
57+
structure.add(DATE_KEY, DATE_VAL);
58+
structure.add(STRUCT_KEY, STRUCT_VAL);
59+
structure.add(LIST_KEY, LIST_VAL);
60+
structure.add(VALUE_KEY, VALUE_VAL);
61+
62+
assertEquals(BOOL_VAL, structure.getValue(BOOL_KEY).asBoolean());
63+
assertEquals(STRING_VAL, structure.getValue(STRING_KEY).asString());
64+
assertEquals(INT_VAL, structure.getValue(INT_KEY).asInteger());
65+
assertEquals(DOUBLE_VAL, structure.getValue(DOUBLE_KEY).asDouble());
66+
assertEquals(DATE_VAL, structure.getValue(DATE_KEY).asZonedDateTime());
67+
assertEquals(STRUCT_VAL, structure.getValue(STRUCT_KEY).asStructure());
68+
assertEquals(LIST_VAL, structure.getValue(LIST_KEY).asList());
69+
assertTrue(structure.getValue(VALUE_KEY).isNull());
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package dev.openfeature.javasdk;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import java.time.ZonedDateTime;
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
import org.junit.jupiter.api.Test;
11+
12+
public class ValueTest {
13+
@Test public void noArgShouldContainNull() {
14+
Value value = new Value();
15+
assertTrue(value.isNull());
16+
}
17+
18+
@Test public void boolArgShouldContainBool() {
19+
boolean innerValue = true;
20+
Value value = new Value(innerValue);
21+
assertTrue(value.isBoolean());
22+
assertEquals(innerValue, value.asBoolean());
23+
}
24+
25+
@Test public void numericArgShouldReturnDoubleOrInt() {
26+
double innerDoubleValue = .75;
27+
Value doubleValue = new Value(innerDoubleValue);
28+
assertTrue(doubleValue.isNumber());
29+
assertEquals(1, doubleValue.asInteger()); // should be rounded
30+
assertEquals(.75, doubleValue.asDouble());
31+
32+
int innerIntValue = 100;
33+
Value intValue = new Value(innerIntValue);
34+
assertTrue(intValue.isNumber());
35+
assertEquals(innerIntValue, intValue.asInteger());
36+
assertEquals(innerIntValue, intValue.asDouble());
37+
}
38+
39+
@Test public void stringArgShouldContainString() {
40+
String innerValue = "hi!";
41+
Value value = new Value(innerValue);
42+
assertTrue(value.isString());
43+
assertEquals(innerValue, value.asString());
44+
}
45+
46+
@Test public void dateShouldContainDate() {
47+
ZonedDateTime innerValue = ZonedDateTime.now();
48+
Value value = new Value(innerValue);
49+
assertTrue(value.isZonedDateTime());
50+
assertEquals(innerValue, value.asZonedDateTime());
51+
}
52+
53+
@Test public void structureShouldContainStructure() {
54+
String INNER_KEY = "key";
55+
String INNER_VALUE = "val";
56+
Structure innerValue = new Structure().add(INNER_KEY, INNER_VALUE);
57+
Value value = new Value(innerValue);
58+
assertTrue(value.isStructure());
59+
assertEquals(INNER_VALUE, value.asStructure().getValue(INNER_KEY).asString());
60+
}
61+
62+
@Test public void listArgShouldContainList() {
63+
String ITEM_VALUE = "val";
64+
List<Value> innerValue = new ArrayList<Value>();
65+
innerValue.add(new Value(ITEM_VALUE));
66+
Value value = new Value(innerValue);
67+
assertTrue(value.isList());
68+
assertEquals(ITEM_VALUE, value.asList().get(0).asString());
69+
}
70+
}

0 commit comments

Comments
 (0)