Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/main/java/com/mindee/parsing/v2/field/ListField.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import lombok.AllArgsConstructor;
Expand All @@ -25,6 +26,38 @@ public final class ListField extends BaseField {
@JsonProperty("items")
private List<DynamicField> items;

/**
* Retrieves the {@code items} as {@code SimpleField} objects.
*
* @return a list of {@code SimpleField} objects
* @throws IllegalStateException if any dynamic field in the list is not of type {@code SIMPLE_FIELD}
*/
public List<SimpleField> getSimpleItems() throws IllegalStateException {
List<SimpleField> simpleItems = new ArrayList<>();
if (items != null) {
for (DynamicField item : items) {
simpleItems.add(item.getSimpleField());
}
}
return simpleItems;
}

/**
* Retrieves the {@code items} as {@code ObjectField} objects.
*
* @return a list of {@code ObjectField} objects
* @throws IllegalStateException if any dynamic field in the list is not of type {@code OBJECT_FIELD}
*/
public List<ObjectField> getObjectItems() throws IllegalStateException {
List<ObjectField> objectItems = new ArrayList<>();
if (items != null) {
for (DynamicField item : items) {
objectItems.add(item.getObjectField());
}
}
return objectItems;
}

@Override
public String toString() {
if (items == null || items.isEmpty()) {
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/com/mindee/parsing/v2/field/ObjectField.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.LinkedHashMap;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
Expand All @@ -23,6 +24,24 @@ public class ObjectField extends BaseField {
@JsonProperty("fields")
private InferenceFields fields;

/**
* Retrieves all sub-fields from the {@code fields} map as a {@link LinkedHashMap} of
* {@code SimpleField} objects, keyed by their field names.
*
* @return a {@link LinkedHashMap} containing the field names as keys and their corresponding
* {@code SimpleField} instances as values
* @throws IllegalStateException if any field is not of type {@code SIMPLE_FIELD}
*/
public LinkedHashMap<String, SimpleField> getSimpleFields() throws IllegalStateException {
LinkedHashMap<String, SimpleField> simpleFields = new LinkedHashMap<>();
if (fields != null) {
for (String fieldName : fields.keySet()) {
simpleFields.put(fieldName, fields.getSimpleField(fieldName));
}
}
return simpleFields;
}

@Override
public String toString() {
return "\n" + (fields != null ? fields.toString(1) : "");
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/mindee/parsing/v2/field/SimpleField.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,35 @@ public SimpleField(Object value, FieldConfidence confidence, List<FieldLocation>
this.value = value;
}

/**
* Retrieves the value of the field as a string.
*
* @return the field value as a string
* @throws ClassCastException if the value cannot be cast to a string
*/
public String getStringValue() throws ClassCastException {
return (String) value;
}

/**
* Retrieves the value of the field as a Double.
*
* @return the field value as a Double
* @throws ClassCastException if the value cannot be cast to a Double
*/
public Double getDoubleValue() throws ClassCastException {
return (Double) value;
}

/**
* Retrieves the value of the field as a Boolean.
*
* @return the field value as a Boolean
* @throws ClassCastException if the value cannot be cast to a Boolean
*/
public Boolean getBooleanValue() throws ClassCastException {
return (Boolean) value;
}

@Override
public String toString() {
Expand Down
175 changes: 141 additions & 34 deletions src/test/java/com/mindee/parsing/v2/InferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.mindee.parsing.v2.field.ObjectField;
import com.mindee.parsing.v2.field.DynamicField.FieldType;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -188,9 +190,17 @@ void deepNestedFields_mustExposeCorrectTypes() throws IOException {
@DisplayName("standard_field_types.json")
class StandardFieldTypes {

private void testSimpleFieldString(SimpleField field) {
assertNotNull(field);
assertEquals(field.getValue(), field.getStringValue());
assertThrows(ClassCastException.class, field::getDoubleValue);
assertThrows(ClassCastException.class, field::getBooleanValue);
assertInstanceOf(List.class, field.getLocations());
}

@Test
@DisplayName("simple / object / list variants must be recognised")
void standardFieldTypes_mustExposeCorrectTypes() throws IOException {
@DisplayName("simple fields must be recognised")
void standardFieldTypes_mustExposeSimpleFieldValues() throws IOException {
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
Inference inference = response.getInference();
assertNotNull(inference);
Expand All @@ -200,20 +210,22 @@ void standardFieldTypes_mustExposeCorrectTypes() throws IOException {
assertNotNull(fields.get("field_simple_string").getSimpleField());

SimpleField fieldSimpleString = fields.get("field_simple_string").getSimpleField();
assertNotNull(fieldSimpleString);
assertInstanceOf(String.class, fieldSimpleString.getValue());
testSimpleFieldString(fieldSimpleString);
assertEquals(FieldConfidence.Certain, fieldSimpleString.getConfidence());
assertInstanceOf(List.class, fieldSimpleString.getLocations());
assertEquals(1, fieldSimpleString.getLocations().size());

SimpleField fieldSimpleFloat = fields.get("field_simple_float").getSimpleField();
assertNotNull(fieldSimpleFloat);
assertInstanceOf(Double.class, fieldSimpleFloat.getValue());
assertEquals(fieldSimpleFloat.getValue(), fieldSimpleFloat.getDoubleValue());
assertThrows(ClassCastException.class, fieldSimpleFloat::getStringValue);
assertThrows(ClassCastException.class, fieldSimpleFloat::getBooleanValue);
assertEquals(FieldConfidence.High, fieldSimpleFloat.getConfidence());

SimpleField fieldSimpleInt = fields.get("field_simple_int").getSimpleField();
assertNotNull(fieldSimpleInt);
assertInstanceOf(Double.class, fieldSimpleInt.getValue());
assertEquals(fieldSimpleInt.getValue(), fieldSimpleInt.getDoubleValue());
assertEquals(FieldConfidence.Medium, fieldSimpleInt.getConfidence());

SimpleField fieldSimpleZero = fields.get("field_simple_zero").getSimpleField();
Expand All @@ -224,47 +236,142 @@ void standardFieldTypes_mustExposeCorrectTypes() throws IOException {
SimpleField fieldSimpleBool = fields.get("field_simple_bool").getSimpleField();
assertNotNull(fieldSimpleBool);
assertInstanceOf(Boolean.class, fieldSimpleBool.getValue());
assertEquals(fieldSimpleBool.getValue(), fieldSimpleBool.getBooleanValue());
assertThrows(ClassCastException.class, fieldSimpleBool::getStringValue);
assertThrows(ClassCastException.class, fieldSimpleBool::getDoubleValue);

SimpleField fieldSimpleNull = fields.get("field_simple_null").getSimpleField();
assertNotNull(fieldSimpleNull);
assertNull(fieldSimpleNull.getValue());
assertNull(fieldSimpleNull.getStringValue());
assertNull(fieldSimpleNull.getBooleanValue());
assertNull(fieldSimpleNull.getDoubleValue());
}

@Test
@DisplayName("simple list fields must be recognised")
void standardFieldTypes_mustExposeSimpleListFieldValues() throws IOException {
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
Inference inference = response.getInference();
assertNotNull(inference);

InferenceFields fields = inference.getResult().getFields();

ListField listField = fields.get("field_simple_list").getListField();
assertNotNull(listField);

// Low level (dynamic) access
List<DynamicField> dynamicItems = listField.getItems();
assertEquals(2, dynamicItems.size());
SimpleField firstDynamicItem = dynamicItems.get(0).getSimpleField();
assertNotNull(firstDynamicItem);
assertEquals(FieldConfidence.Medium, firstDynamicItem.getConfidence());
assertInstanceOf(String.class, firstDynamicItem.getValue());
for (DynamicField item : dynamicItems) {
SimpleField itemField = item.getSimpleField();
testSimpleFieldString(itemField);
assertEquals(1, itemField.getLocations().size());
}

ListField fieldSimpleList = fields.get("field_simple_list").getListField();
assertNotNull(fieldSimpleList);
List<DynamicField> simpleItems = fieldSimpleList.getItems();
// High level (typed) access
List<SimpleField> simpleItems = listField.getSimpleItems();
assertEquals(2, simpleItems.size());
SimpleField firstSimpleItem = simpleItems.get(0).getSimpleField();
assertNotNull(firstSimpleItem);
SimpleField firstSimpleItem = simpleItems.get(0);
assertEquals(FieldConfidence.Medium, firstSimpleItem.getConfidence());
assertInstanceOf(String.class, firstSimpleItem.getValue());
for (DynamicField item : fieldSimpleList.getItems()) {
SimpleField itemField = item.getSimpleField();
assertInstanceOf(String.class, itemField.getValue());
for (SimpleField itemField : simpleItems) {
testSimpleFieldString(itemField);
assertEquals(1, itemField.getLocations().size());
}

ObjectField fieldObject = fields.get("field_object").getObjectField();
assertNotNull(fieldObject);
InferenceFields fieldObjectFields = fieldObject.getFields();
assertEquals(2, fieldObjectFields.size());
SimpleField subfield1 = fieldObjectFields.get("subfield_1").getSimpleField();
assertInstanceOf(String.class, subfield1.getValue());
assertEquals(FieldConfidence.High, subfield1.getConfidence());

ListField fieldObjectList = fields.get("field_object_list").getListField();
assertNotNull(fieldObjectList);
List<DynamicField> objectItems = fieldObjectList.getItems();
assertThrows(IllegalStateException.class, listField::getObjectItems);
}

private void testObjectSubFieldSimpleString(String fieldName, SimpleField subField) {
assertTrue(fieldName.startsWith("subfield_"));
testSimpleFieldString(subField);
}

@Test
@DisplayName("object list fields must be recognised")
void standardFieldTypes_mustExposeObjectListFieldValues() throws IOException {
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
Inference inference = response.getInference();
assertNotNull(inference);

InferenceFields fields = inference.getResult().getFields();

ListField listField = fields.get("field_object_list").getListField();
assertNotNull(listField);

List<DynamicField> dynamicItems = listField.getItems();
assertEquals(2, dynamicItems.size());
ObjectField firstDynamicItem = dynamicItems.get(0).getObjectField();
assertEquals(
FieldConfidence.Low,
firstDynamicItem.getFields().get("subfield_1").getSimpleField().getConfidence()
);
for (DynamicField item : dynamicItems) {
ObjectField itemField = item.getObjectField();
assertNotNull(itemField);
InferenceFields itemFields = itemField.getFields();
assertEquals(2, itemFields.size());
}

List<ObjectField> objectItems = listField.getObjectItems();
assertEquals(2, objectItems.size());
ObjectField firstObjectItem = objectItems.get(0).getObjectField();
assertNotNull(firstObjectItem);
assertInstanceOf(
String.class,
firstObjectItem.getFields().get("subfield_1").getSimpleField().getValue()
ObjectField firstObjectItem = objectItems.get(0);
assertEquals(
FieldConfidence.Low,
firstObjectItem.getSimpleFields().get("subfield_1").getConfidence()
);
for (DynamicField item : fieldObjectList.getItems()) {
SimpleField listSubfield1 = item.getObjectField().getFields().get("subfield_1").getSimpleField();
assertInstanceOf(String.class, listSubfield1.getValue());
assertEquals(1, listSubfield1.getLocations().size());
for (ObjectField itemField : objectItems) {
assertNotNull(itemField);
HashMap<String, SimpleField> itemFields = itemField.getSimpleFields();
assertEquals(2, itemFields.size());
InferenceFields itemSubFields = itemField.getFields();
SimpleField itemSubfield1 = itemSubFields.getSimpleField("subfield_1");
assertInstanceOf(String.class, itemSubfield1.getValue());
for (Map.Entry<String, SimpleField> entry : itemFields.entrySet()) {
String fieldName = entry.getKey();
SimpleField subfield = entry.getValue();
testObjectSubFieldSimpleString(fieldName, subfield);
}
}

assertThrows(IllegalStateException.class, listField::getSimpleItems);
}

@Test
@DisplayName("simple / object / list variants must be recognised")
void standardFieldTypes_mustExposeObjectFieldValues() throws IOException {
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
Inference inference = response.getInference();
assertNotNull(inference);

InferenceFields fields = inference.getResult().getFields();

ObjectField fieldObject = fields.get("field_object").getObjectField();
assertNotNull(fieldObject);

InferenceFields subFieldsDynamic = fieldObject.getFields();
assertEquals(2, subFieldsDynamic.size());
SimpleField dynamicSubfield1 = subFieldsDynamic.get("subfield_1").getSimpleField();
assertInstanceOf(String.class, dynamicSubfield1.getValue());
assertEquals(FieldConfidence.High, dynamicSubfield1.getConfidence());
for (Map.Entry<String, DynamicField> entry : subFieldsDynamic.entrySet()) {
String fieldName = entry.getKey();
SimpleField subField = entry.getValue().getSimpleField();
testObjectSubFieldSimpleString(fieldName, subField);
}

LinkedHashMap<String, SimpleField> subFieldsSimple = fieldObject.getSimpleFields();
assertEquals(2, subFieldsSimple.size());
SimpleField simpleSubfield1 = subFieldsSimple.get("subfield_1");
assertEquals(FieldConfidence.High, simpleSubfield1.getConfidence());
for (Map.Entry<String, SimpleField> entry : subFieldsSimple.entrySet()) {
String fieldName = entry.getKey();
SimpleField subField = entry.getValue();
testObjectSubFieldSimpleString(fieldName, subField);
}
}
}
Expand Down
Loading