Merge pull request #61 from open-feature/numbers-in-structs
breaking: store all numbers as doubles
This commit is contained in:
commit
b626789693
|
|
@ -41,6 +41,11 @@ public class Structure {
|
||||||
}
|
}
|
||||||
|
|
||||||
// adders
|
// adders
|
||||||
|
public Structure add(String key, Value value) {
|
||||||
|
attributes.put(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Structure add(String key, Boolean value) {
|
public Structure add(String key, Boolean value) {
|
||||||
attributes.put(key, new Value(value));
|
attributes.put(key, new Value(value));
|
||||||
return this;
|
return this;
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Values server as a return type for provider objects. Providers may deal in protobufs or JSON in the backend and
|
* Values serve as a return type for provider objects.
|
||||||
* have no reasonable way to convert that into a type that users care about (e.g. an instance of `T`). This
|
* Providers may deal in JSON, protobuf, XML or some other data-interchange format.
|
||||||
* intermediate representation should provide a good medium of exchange.
|
* This intermediate representation provides a good medium of exchange.
|
||||||
*/
|
*/
|
||||||
@ToString
|
@ToString
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
|
|
@ -18,6 +18,10 @@ public class Value {
|
||||||
|
|
||||||
private final Object innerObject;
|
private final Object innerObject;
|
||||||
|
|
||||||
|
public Value() {
|
||||||
|
this.innerObject = null;
|
||||||
|
}
|
||||||
|
|
||||||
public Value(Value value) {
|
public Value(Value value) {
|
||||||
this.innerObject = value.innerObject;
|
this.innerObject = value.innerObject;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +35,7 @@ public class Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value(Integer value) {
|
public Value(Integer value) {
|
||||||
this.innerObject = value;
|
this.innerObject = value.doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value(Double value) {
|
public Value(Double value) {
|
||||||
|
|
@ -50,6 +54,15 @@ public class Value {
|
||||||
this.innerObject = value;
|
this.innerObject = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this Value represents null.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isNull() {
|
||||||
|
return this.innerObject == null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this Value represents a Boolean.
|
* Check if this Value represents a Boolean.
|
||||||
*
|
*
|
||||||
|
|
@ -69,20 +82,11 @@ public class Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this Value represents an Integer.
|
* Check if this Value represents a numeric value.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public boolean isInteger() {
|
public boolean isNumber() {
|
||||||
return this.innerObject instanceof Integer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this Value represents a Double.
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public boolean isDouble() {
|
|
||||||
return this.innerObject instanceof Double;
|
return this.innerObject instanceof Double;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,24 +144,25 @@ public class Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the underlying Integer value, or null.
|
* Retrieve the underlying numeric value as an Integer, or null.
|
||||||
|
* If the value is not an integer, it will be rounded using Math.round().
|
||||||
*
|
*
|
||||||
* @return Integer
|
* @return Integer
|
||||||
*/
|
*/
|
||||||
public Integer asInteger() {
|
public Integer asInteger() {
|
||||||
if (this.isInteger()) {
|
if (this.isNumber()) {
|
||||||
return (Integer)this.innerObject;
|
return (int)Math.round((Double)this.innerObject);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the underlying Double value, or null.
|
* Retrieve the underlying numeric value as a Double, or null.
|
||||||
*
|
*
|
||||||
* @return Double
|
* @return Double
|
||||||
*/
|
*/
|
||||||
public Double asDouble() {
|
public Double asDouble() {
|
||||||
if (this.isDouble()) {
|
if (this.isNumber()) {
|
||||||
return (Double)this.innerObject;
|
return (Double)this.innerObject;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package dev.openfeature.javasdk;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class StructureTest {
|
||||||
|
@Test public void noArgShouldContainEmptyAttributes() {
|
||||||
|
Structure structure = new Structure();
|
||||||
|
assertEquals(0, structure.asMap().keySet().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void mapArgShouldContainNewMap() {
|
||||||
|
String KEY = "key";
|
||||||
|
Map<String, Value> map = new HashMap<String, Value>() {
|
||||||
|
{
|
||||||
|
put(KEY, new Value(KEY));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Structure structure = new Structure(map);
|
||||||
|
assertEquals(KEY, structure.asMap().get(KEY).asString());
|
||||||
|
assertNotSame(structure.asMap(), map); // should be a copy
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void addAndGetAddAndReturnValues() {
|
||||||
|
String BOOL_KEY = "bool";
|
||||||
|
String STRING_KEY = "string";
|
||||||
|
String INT_KEY = "int";
|
||||||
|
String DOUBLE_KEY = "double";
|
||||||
|
String DATE_KEY = "date";
|
||||||
|
String STRUCT_KEY = "struct";
|
||||||
|
String LIST_KEY = "list";
|
||||||
|
String VALUE_KEY = "value";
|
||||||
|
|
||||||
|
boolean BOOL_VAL = true;
|
||||||
|
String STRING_VAL = "val";
|
||||||
|
int INT_VAL = 13;
|
||||||
|
double DOUBLE_VAL = .5;
|
||||||
|
ZonedDateTime DATE_VAL = ZonedDateTime.now();
|
||||||
|
Structure STRUCT_VAL = new Structure();
|
||||||
|
List<Value> LIST_VAL = new ArrayList<Value>();
|
||||||
|
Value VALUE_VAL = new Value();
|
||||||
|
|
||||||
|
Structure structure = new Structure();
|
||||||
|
structure.add(BOOL_KEY, BOOL_VAL);
|
||||||
|
structure.add(STRING_KEY, STRING_VAL);
|
||||||
|
structure.add(INT_KEY, INT_VAL);
|
||||||
|
structure.add(DOUBLE_KEY, DOUBLE_VAL);
|
||||||
|
structure.add(DATE_KEY, DATE_VAL);
|
||||||
|
structure.add(STRUCT_KEY, STRUCT_VAL);
|
||||||
|
structure.add(LIST_KEY, LIST_VAL);
|
||||||
|
structure.add(VALUE_KEY, VALUE_VAL);
|
||||||
|
|
||||||
|
assertEquals(BOOL_VAL, structure.getValue(BOOL_KEY).asBoolean());
|
||||||
|
assertEquals(STRING_VAL, structure.getValue(STRING_KEY).asString());
|
||||||
|
assertEquals(INT_VAL, structure.getValue(INT_KEY).asInteger());
|
||||||
|
assertEquals(DOUBLE_VAL, structure.getValue(DOUBLE_KEY).asDouble());
|
||||||
|
assertEquals(DATE_VAL, structure.getValue(DATE_KEY).asZonedDateTime());
|
||||||
|
assertEquals(STRUCT_VAL, structure.getValue(STRUCT_KEY).asStructure());
|
||||||
|
assertEquals(LIST_VAL, structure.getValue(LIST_KEY).asList());
|
||||||
|
assertTrue(structure.getValue(VALUE_KEY).isNull());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package dev.openfeature.javasdk;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class ValueTest {
|
||||||
|
@Test public void noArgShouldContainNull() {
|
||||||
|
Value value = new Value();
|
||||||
|
assertTrue(value.isNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void boolArgShouldContainBool() {
|
||||||
|
boolean innerValue = true;
|
||||||
|
Value value = new Value(innerValue);
|
||||||
|
assertTrue(value.isBoolean());
|
||||||
|
assertEquals(innerValue, value.asBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void numericArgShouldReturnDoubleOrInt() {
|
||||||
|
double innerDoubleValue = .75;
|
||||||
|
Value doubleValue = new Value(innerDoubleValue);
|
||||||
|
assertTrue(doubleValue.isNumber());
|
||||||
|
assertEquals(1, doubleValue.asInteger()); // should be rounded
|
||||||
|
assertEquals(.75, doubleValue.asDouble());
|
||||||
|
|
||||||
|
int innerIntValue = 100;
|
||||||
|
Value intValue = new Value(innerIntValue);
|
||||||
|
assertTrue(intValue.isNumber());
|
||||||
|
assertEquals(innerIntValue, intValue.asInteger());
|
||||||
|
assertEquals(innerIntValue, intValue.asDouble());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void stringArgShouldContainString() {
|
||||||
|
String innerValue = "hi!";
|
||||||
|
Value value = new Value(innerValue);
|
||||||
|
assertTrue(value.isString());
|
||||||
|
assertEquals(innerValue, value.asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void dateShouldContainDate() {
|
||||||
|
ZonedDateTime innerValue = ZonedDateTime.now();
|
||||||
|
Value value = new Value(innerValue);
|
||||||
|
assertTrue(value.isZonedDateTime());
|
||||||
|
assertEquals(innerValue, value.asZonedDateTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void structureShouldContainStructure() {
|
||||||
|
String INNER_KEY = "key";
|
||||||
|
String INNER_VALUE = "val";
|
||||||
|
Structure innerValue = new Structure().add(INNER_KEY, INNER_VALUE);
|
||||||
|
Value value = new Value(innerValue);
|
||||||
|
assertTrue(value.isStructure());
|
||||||
|
assertEquals(INNER_VALUE, value.asStructure().getValue(INNER_KEY).asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void listArgShouldContainList() {
|
||||||
|
String ITEM_VALUE = "val";
|
||||||
|
List<Value> innerValue = new ArrayList<Value>();
|
||||||
|
innerValue.add(new Value(ITEM_VALUE));
|
||||||
|
Value value = new Value(innerValue);
|
||||||
|
assertTrue(value.isList());
|
||||||
|
assertEquals(ITEM_VALUE, value.asList().get(0).asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue