Skip to content

Commit 91bb20a

Browse files
committed
✨ add typed accessors to list and object fields
1 parent 60b77e9 commit 91bb20a

File tree

4 files changed

+209
-30
lines changed

4 files changed

+209
-30
lines changed

src/main/java/com/mindee/parsing/v2/field/ListField.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
44
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import java.util.ArrayList;
56
import java.util.List;
67
import java.util.StringJoiner;
78
import lombok.AllArgsConstructor;
@@ -25,6 +26,38 @@ public final class ListField extends BaseField {
2526
@JsonProperty("items")
2627
private List<DynamicField> items;
2728

29+
/**
30+
* Retrieves the {@code items} as {@code SimpleField} objects.
31+
*
32+
* @return a list of {@code SimpleField} objects
33+
* @throws IllegalStateException if any dynamic field in the list is not of type {@code SIMPLE_FIELD}
34+
*/
35+
public List<SimpleField> getSimpleItems() throws IllegalStateException {
36+
List<SimpleField> simpleItems = new ArrayList<>();
37+
if (items != null) {
38+
for (DynamicField item : items) {
39+
simpleItems.add(item.getSimpleField());
40+
}
41+
}
42+
return simpleItems;
43+
}
44+
45+
/**
46+
* Retrieves the {@code items} as {@code ObjectField} objects.
47+
*
48+
* @return a list of {@code ObjectField} objects
49+
* @throws IllegalStateException if any dynamic field in the list is not of type {@code OBJECT_FIELD}
50+
*/
51+
public List<ObjectField> getObjectItems() throws IllegalStateException {
52+
List<ObjectField> objectItems = new ArrayList<>();
53+
if (items != null) {
54+
for (DynamicField item : items) {
55+
objectItems.add(item.getObjectField());
56+
}
57+
}
58+
return objectItems;
59+
}
60+
2861
@Override
2962
public String toString() {
3063
if (items == null || items.isEmpty()) {

src/main/java/com/mindee/parsing/v2/field/ObjectField.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
44
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import java.util.LinkedHashMap;
56
import lombok.AllArgsConstructor;
67
import lombok.EqualsAndHashCode;
78
import lombok.Getter;
@@ -23,6 +24,24 @@ public class ObjectField extends BaseField {
2324
@JsonProperty("fields")
2425
private InferenceFields fields;
2526

27+
/**
28+
* Retrieves all sub-fields from the {@code fields} map as a {@link LinkedHashMap} of
29+
* {@code SimpleField} objects, keyed by their field names.
30+
*
31+
* @return a {@link LinkedHashMap} containing the field names as keys and their corresponding
32+
* {@code SimpleField} instances as values
33+
* @throws IllegalStateException if any field is not of type {@code SIMPLE_FIELD}
34+
*/
35+
public LinkedHashMap<String, SimpleField> getSimpleFields() throws IllegalStateException {
36+
LinkedHashMap<String, SimpleField> simpleFields = new LinkedHashMap<>();
37+
if (fields != null) {
38+
for (String fieldName : fields.keySet()) {
39+
simpleFields.put(fieldName, fields.getSimpleField(fieldName));
40+
}
41+
}
42+
return simpleFields;
43+
}
44+
2645
@Override
2746
public String toString() {
2847
return "\n" + (fields != null ? fields.toString(1) : "");

src/main/java/com/mindee/parsing/v2/field/SimpleField.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@ public SimpleField(Object value, FieldConfidence confidence, List<FieldLocation>
2727
this.value = value;
2828
}
2929

30+
/**
31+
* Retrieves the value of the field as a string.
32+
*
33+
* @return the field value as a string
34+
* @throws ClassCastException if the value cannot be cast to a string
35+
*/
36+
public String getStringValue() throws ClassCastException {
37+
return (String) value;
38+
}
39+
40+
/**
41+
* Retrieves the value of the field as a Double.
42+
*
43+
* @return the field value as a Double
44+
* @throws ClassCastException if the value cannot be cast to a Double
45+
*/
46+
public Double getDoubleValue() throws ClassCastException {
47+
return (Double) value;
48+
}
49+
50+
/**
51+
* Retrieves the value of the field as a Boolean.
52+
*
53+
* @return the field value as a Boolean
54+
* @throws ClassCastException if the value cannot be cast to a Boolean
55+
*/
56+
public Boolean getBooleanValue() throws ClassCastException {
57+
return (Boolean) value;
58+
}
3059

3160
@Override
3261
public String toString() {

src/test/java/com/mindee/parsing/v2/InferenceTest.java

Lines changed: 128 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import com.mindee.parsing.v2.field.ObjectField;
1313
import com.mindee.parsing.v2.field.DynamicField.FieldType;
1414
import java.io.IOException;
15+
import java.util.HashMap;
16+
import java.util.LinkedHashMap;
1517
import java.util.List;
1618
import java.util.Map;
1719
import java.util.Objects;
@@ -189,8 +191,8 @@ void deepNestedFields_mustExposeCorrectTypes() throws IOException {
189191
class StandardFieldTypes {
190192

191193
@Test
192-
@DisplayName("simple / object / list variants must be recognised")
193-
void standardFieldTypes_mustExposeCorrectTypes() throws IOException {
194+
@DisplayName("simple fields must be recognised")
195+
void standardFieldTypes_mustExposeSimpleFieldValues() throws IOException {
194196
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
195197
Inference inference = response.getInference();
196198
assertNotNull(inference);
@@ -202,18 +204,25 @@ void standardFieldTypes_mustExposeCorrectTypes() throws IOException {
202204
SimpleField fieldSimpleString = fields.get("field_simple_string").getSimpleField();
203205
assertNotNull(fieldSimpleString);
204206
assertInstanceOf(String.class, fieldSimpleString.getValue());
207+
assertEquals(fieldSimpleString.getValue(), fieldSimpleString.getStringValue());
208+
assertThrows(ClassCastException.class, fieldSimpleString::getDoubleValue);
209+
assertThrows(ClassCastException.class, fieldSimpleString::getBooleanValue);
205210
assertEquals(FieldConfidence.Certain, fieldSimpleString.getConfidence());
206211
assertInstanceOf(List.class, fieldSimpleString.getLocations());
207212
assertEquals(1, fieldSimpleString.getLocations().size());
208213

209214
SimpleField fieldSimpleFloat = fields.get("field_simple_float").getSimpleField();
210215
assertNotNull(fieldSimpleFloat);
211216
assertInstanceOf(Double.class, fieldSimpleFloat.getValue());
217+
assertEquals(fieldSimpleFloat.getValue(), fieldSimpleFloat.getDoubleValue());
218+
assertThrows(ClassCastException.class, fieldSimpleFloat::getStringValue);
219+
assertThrows(ClassCastException.class, fieldSimpleFloat::getBooleanValue);
212220
assertEquals(FieldConfidence.High, fieldSimpleFloat.getConfidence());
213221

214222
SimpleField fieldSimpleInt = fields.get("field_simple_int").getSimpleField();
215223
assertNotNull(fieldSimpleInt);
216224
assertInstanceOf(Double.class, fieldSimpleInt.getValue());
225+
assertEquals(fieldSimpleInt.getValue(), fieldSimpleInt.getDoubleValue());
217226
assertEquals(FieldConfidence.Medium, fieldSimpleInt.getConfidence());
218227

219228
SimpleField fieldSimpleZero = fields.get("field_simple_zero").getSimpleField();
@@ -224,47 +233,136 @@ void standardFieldTypes_mustExposeCorrectTypes() throws IOException {
224233
SimpleField fieldSimpleBool = fields.get("field_simple_bool").getSimpleField();
225234
assertNotNull(fieldSimpleBool);
226235
assertInstanceOf(Boolean.class, fieldSimpleBool.getValue());
236+
assertEquals(fieldSimpleBool.getValue(), fieldSimpleBool.getBooleanValue());
237+
assertThrows(ClassCastException.class, fieldSimpleBool::getStringValue);
238+
assertThrows(ClassCastException.class, fieldSimpleBool::getDoubleValue);
227239

228240
SimpleField fieldSimpleNull = fields.get("field_simple_null").getSimpleField();
229241
assertNotNull(fieldSimpleNull);
230242
assertNull(fieldSimpleNull.getValue());
243+
assertNull(fieldSimpleNull.getStringValue());
244+
assertNull(fieldSimpleNull.getBooleanValue());
245+
assertNull(fieldSimpleNull.getDoubleValue());
246+
}
247+
248+
@Test
249+
@DisplayName("simple list fields must be recognised")
250+
void standardFieldTypes_mustExposeSimpleListFieldValues() throws IOException {
251+
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
252+
Inference inference = response.getInference();
253+
assertNotNull(inference);
254+
255+
InferenceFields fields = inference.getResult().getFields();
256+
257+
ListField listField = fields.get("field_simple_list").getListField();
258+
assertNotNull(listField);
259+
260+
// Low level (dynamic) access
261+
List<DynamicField> dynamicItems = listField.getItems();
262+
assertEquals(2, dynamicItems.size());
263+
SimpleField firstDynamicItem = dynamicItems.get(0).getSimpleField();
264+
assertNotNull(firstDynamicItem);
265+
assertEquals(FieldConfidence.Medium, firstDynamicItem.getConfidence());
266+
assertInstanceOf(String.class, firstDynamicItem.getValue());
267+
for (DynamicField item : dynamicItems) {
268+
SimpleField itemField = item.getSimpleField();
269+
assertInstanceOf(String.class, itemField.getValue());
270+
assertEquals(itemField.getValue(), itemField.getStringValue());
271+
assertEquals(1, itemField.getLocations().size());
272+
}
231273

232-
ListField fieldSimpleList = fields.get("field_simple_list").getListField();
233-
assertNotNull(fieldSimpleList);
234-
List<DynamicField> simpleItems = fieldSimpleList.getItems();
274+
// High level (typed) access
275+
List<SimpleField> simpleItems = listField.getSimpleItems();
235276
assertEquals(2, simpleItems.size());
236-
SimpleField firstSimpleItem = simpleItems.get(0).getSimpleField();
237-
assertNotNull(firstSimpleItem);
277+
SimpleField firstSimpleItem = simpleItems.get(0);
238278
assertEquals(FieldConfidence.Medium, firstSimpleItem.getConfidence());
239-
assertInstanceOf(String.class, firstSimpleItem.getValue());
240-
for (DynamicField item : fieldSimpleList.getItems()) {
241-
SimpleField itemField = item.getSimpleField();
279+
for (SimpleField itemField : simpleItems) {
242280
assertInstanceOf(String.class, itemField.getValue());
281+
assertEquals(itemField.getValue(), itemField.getStringValue());
243282
assertEquals(1, itemField.getLocations().size());
244283
}
245284

246-
ObjectField fieldObject = fields.get("field_object").getObjectField();
247-
assertNotNull(fieldObject);
248-
InferenceFields fieldObjectFields = fieldObject.getFields();
249-
assertEquals(2, fieldObjectFields.size());
250-
SimpleField subfield1 = fieldObjectFields.get("subfield_1").getSimpleField();
251-
assertInstanceOf(String.class, subfield1.getValue());
252-
assertEquals(FieldConfidence.High, subfield1.getConfidence());
253-
254-
ListField fieldObjectList = fields.get("field_object_list").getListField();
255-
assertNotNull(fieldObjectList);
256-
List<DynamicField> objectItems = fieldObjectList.getItems();
285+
assertThrows(IllegalStateException.class, listField::getObjectItems);
286+
}
287+
288+
@Test
289+
@DisplayName("object list fields must be recognised")
290+
void standardFieldTypes_mustExposeObjectListFieldValues() throws IOException {
291+
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
292+
Inference inference = response.getInference();
293+
assertNotNull(inference);
294+
295+
InferenceFields fields = inference.getResult().getFields();
296+
297+
ListField listField = fields.get("field_object_list").getListField();
298+
assertNotNull(listField);
299+
300+
List<DynamicField> dynamicItems = listField.getItems();
301+
assertEquals(2, dynamicItems.size());
302+
ObjectField firstDynamicItem = dynamicItems.get(0).getObjectField();
303+
assertEquals(
304+
FieldConfidence.Low,
305+
firstDynamicItem.getFields().get("subfield_1").getSimpleField().getConfidence()
306+
);
307+
for (DynamicField item : dynamicItems) {
308+
ObjectField itemField = item.getObjectField();
309+
assertNotNull(itemField);
310+
InferenceFields itemFields = itemField.getFields();
311+
assertEquals(2, itemFields.size());
312+
}
313+
314+
List<ObjectField> objectItems = listField.getObjectItems();
257315
assertEquals(2, objectItems.size());
258-
ObjectField firstObjectItem = objectItems.get(0).getObjectField();
259-
assertNotNull(firstObjectItem);
260-
assertInstanceOf(
261-
String.class,
262-
firstObjectItem.getFields().get("subfield_1").getSimpleField().getValue()
316+
ObjectField firstObjectItem = objectItems.get(0);
317+
assertEquals(
318+
FieldConfidence.Low,
319+
firstObjectItem.getSimpleFields().get("subfield_1").getConfidence()
263320
);
264-
for (DynamicField item : fieldObjectList.getItems()) {
265-
SimpleField listSubfield1 = item.getObjectField().getFields().get("subfield_1").getSimpleField();
266-
assertInstanceOf(String.class, listSubfield1.getValue());
267-
assertEquals(1, listSubfield1.getLocations().size());
321+
for (ObjectField itemField : objectItems) {
322+
assertNotNull(itemField);
323+
HashMap<String, SimpleField> itemFields = itemField.getSimpleFields();
324+
assertEquals(2, itemFields.size());
325+
InferenceFields itemSubFields = itemField.getFields();
326+
SimpleField itemSubfield1 = itemSubFields.getSimpleField("subfield_1");
327+
assertInstanceOf(String.class, itemSubfield1.getValue());
328+
for (Map.Entry<String, SimpleField> entry : itemFields.entrySet()) {
329+
SimpleField subfield = entry.getValue();
330+
assertEquals(subfield.getValue(), subfield.getStringValue());
331+
}
332+
}
333+
334+
assertThrows(IllegalStateException.class, listField::getSimpleItems);
335+
}
336+
337+
@Test
338+
@DisplayName("simple / object / list variants must be recognised")
339+
void standardFieldTypes_mustExposeObjectFieldValues() throws IOException {
340+
InferenceResponse response = loadFromResource("v2/inference/standard_field_types.json");
341+
Inference inference = response.getInference();
342+
assertNotNull(inference);
343+
344+
InferenceFields fields = inference.getResult().getFields();
345+
346+
ObjectField fieldObject = fields.get("field_object").getObjectField();
347+
assertNotNull(fieldObject);
348+
349+
InferenceFields subFieldsDynamic = fieldObject.getFields();
350+
assertEquals(2, subFieldsDynamic.size());
351+
SimpleField dynamicSubfield1 = subFieldsDynamic.get("subfield_1").getSimpleField();
352+
assertInstanceOf(String.class, dynamicSubfield1.getValue());
353+
assertEquals(FieldConfidence.High, dynamicSubfield1.getConfidence());
354+
for (Map.Entry<String, DynamicField> entry : subFieldsDynamic.entrySet()) {
355+
String fieldName = entry.getKey();
356+
SimpleField subField = entry.getValue().getSimpleField();
357+
}
358+
359+
LinkedHashMap<String, SimpleField> subFieldsSimple = fieldObject.getSimpleFields();
360+
assertEquals(2, subFieldsSimple.size());
361+
SimpleField simpleSubfield1 = subFieldsSimple.get("subfield_1");
362+
assertEquals(FieldConfidence.High, simpleSubfield1.getConfidence());
363+
for (Map.Entry<String, SimpleField> entry : subFieldsSimple.entrySet()) {
364+
String fieldName = entry.getKey();
365+
SimpleField subField = entry.getValue();
268366
}
269367
}
270368
}

0 commit comments

Comments
 (0)