Skip to content

Commit 1cb6755

Browse files
committed
♻️ 💥 LocalResponse class should be version-specific (#311)
1 parent 1add925 commit 1cb6755

16 files changed

Lines changed: 315 additions & 207 deletions

src/main/java/com/mindee/input/LocalResponse.java renamed to src/main/java/com/mindee/parsing/BaseLocalResponse.java

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
package com.mindee.input;
1+
package com.mindee.parsing;
22

3-
import com.fasterxml.jackson.databind.ObjectMapper;
4-
import com.mindee.MindeeException;
5-
import com.mindee.v2.parsing.CommonResponse;
63
import java.io.BufferedReader;
74
import java.io.File;
85
import java.io.IOException;
@@ -24,16 +21,15 @@
2421
* A Mindee response saved locally.
2522
*/
2623
@Getter
27-
public class LocalResponse {
28-
private final byte[] file;
29-
private static final ObjectMapper mapper = new ObjectMapper();
24+
public abstract class BaseLocalResponse {
25+
protected final byte[] file;
3026

3127
/**
3228
* Load from an {@link InputStream}.
3329
*
3430
* @param input will be decoded as UTF-8.
3531
*/
36-
public LocalResponse(InputStream input) {
32+
public BaseLocalResponse(InputStream input) {
3733
this.file = this
3834
.getBytes(new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines());
3935
}
@@ -43,7 +39,10 @@ public LocalResponse(InputStream input) {
4339
*
4440
* @param input will be decoded as UTF-8.
4541
*/
46-
public LocalResponse(String input) {
42+
public BaseLocalResponse(String input) {
43+
if (input == null || input.isEmpty()) {
44+
throw new IllegalArgumentException("Input string cannot be empty or null.");
45+
}
4746
this.file = input.getBytes(StandardCharsets.UTF_8);
4847
}
4948

@@ -52,7 +51,7 @@ public LocalResponse(String input) {
5251
*
5352
* @param input will be decoded as UTF-8.
5453
*/
55-
public LocalResponse(File input) throws IOException {
54+
public BaseLocalResponse(File input) throws IOException {
5655
this.file = this.getBytes(Files.lines(input.toPath(), StandardCharsets.UTF_8));
5756
}
5857

@@ -61,7 +60,7 @@ public LocalResponse(File input) throws IOException {
6160
*
6261
* @param input will be decoded as UTF-8.
6362
*/
64-
public LocalResponse(Path input) throws IOException {
63+
public BaseLocalResponse(Path input) throws IOException {
6564
this.file = this.getBytes(Files.lines(input, StandardCharsets.UTF_8));
6665
}
6766

@@ -106,24 +105,4 @@ public String getHmacSignature(String secretKey) {
106105
public boolean isValidHmacSignature(String secretKey, String signature) {
107106
return signature.equals(getHmacSignature(secretKey));
108107
}
109-
110-
/**
111-
* Deserialize this local JSON payload into a specific {@link CommonResponse}
112-
* subtype: {@code InferenceResponse}, {@code JobResponse}.
113-
*
114-
* @param responseClass the concrete class to instantiate
115-
* @param <T> generic {@link CommonResponse}
116-
* @return Either a {@code InferenceResponse} or {@code JobResponse} instance.
117-
* @throws MindeeException if the payload cannot be deserialized into the requested type
118-
*/
119-
public <T extends CommonResponse> T deserializeResponse(Class<T> responseClass) {
120-
ObjectMapper mapper = new ObjectMapper();
121-
try {
122-
T response = mapper.readValue(this.file, responseClass);
123-
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
124-
return response;
125-
} catch (Exception ex) {
126-
throw new MindeeException("Invalid class specified for deserialization.", ex);
127-
}
128-
}
129108
}

src/main/java/com/mindee/v1/MindeeClient.java

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package com.mindee.v1;
22

3-
import com.fasterxml.jackson.databind.JavaType;
4-
import com.fasterxml.jackson.databind.ObjectMapper;
53
import com.mindee.AsyncPollingOptions;
64
import com.mindee.MindeeException;
75
import com.mindee.input.InputSourceUtils;
86
import com.mindee.input.LocalInputSource;
9-
import com.mindee.input.LocalResponse;
107
import com.mindee.input.PageOptions;
118
import com.mindee.pdf.PdfBoxApi;
129
import com.mindee.pdf.PdfOperation;
@@ -1071,28 +1068,4 @@ public <T extends GeneratedV1> AsyncPredictResponse<T> parseQueued(
10711068
) {
10721069
return this.mindeeApi.documentQueueGet(type, endpoint, jobId);
10731070
}
1074-
1075-
/**
1076-
* Load a local prediction.
1077-
* Typically used when wanting to load from a webhook callback.
1078-
* However, any kind of Mindee response may be loaded.
1079-
*
1080-
* @param <T> Type of inference.
1081-
* @param type Type of inference.
1082-
* @param localResponse A loaded local response.
1083-
* @return an instance of {@link AsyncPredictResponse}.
1084-
* @throws IOException Throws if the file can't be accessed.
1085-
*/
1086-
public <T extends Inference> AsyncPredictResponse<T> loadPrediction(
1087-
Class<T> type,
1088-
LocalResponse localResponse
1089-
) throws IOException {
1090-
ObjectMapper objectMapper = new ObjectMapper();
1091-
objectMapper.findAndRegisterModules();
1092-
JavaType parametricType = objectMapper
1093-
.getTypeFactory()
1094-
.constructParametricType(AsyncPredictResponse.class, type);
1095-
return objectMapper.readValue(localResponse.getFile(), parametricType);
1096-
}
1097-
10981071
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.mindee.v1.parsing;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.mindee.MindeeException;
6+
import com.mindee.parsing.BaseLocalResponse;
7+
import com.mindee.v1.parsing.common.AsyncPredictResponse;
8+
import com.mindee.v1.parsing.common.Inference;
9+
import com.mindee.v1.parsing.common.PredictResponse;
10+
import java.io.File;
11+
import java.io.IOException;
12+
import java.io.InputStream;
13+
import java.nio.charset.StandardCharsets;
14+
import java.nio.file.Path;
15+
16+
/**
17+
* A Mindee response saved locally.
18+
*/
19+
public class LocalResponse extends BaseLocalResponse {
20+
21+
public LocalResponse(InputStream input) {
22+
super(input);
23+
}
24+
25+
public LocalResponse(String input) {
26+
super(input);
27+
}
28+
29+
public LocalResponse(File input) throws IOException {
30+
super(input);
31+
}
32+
33+
public LocalResponse(Path input) throws IOException {
34+
super(input);
35+
}
36+
37+
private <P extends Inference, R> R deserialize(
38+
Class<R> responseClass,
39+
Class<P> productClass
40+
) throws IOException {
41+
var mapper = new ObjectMapper().findAndRegisterModules();
42+
var type = mapper.getTypeFactory().constructParametricType(responseClass, productClass);
43+
try {
44+
return mapper.readValue(this.file, type);
45+
} catch (Exception e) {
46+
if (e instanceof JacksonException) {
47+
throw new MindeeException("Invalid JSON payload.", e);
48+
}
49+
throw e;
50+
}
51+
}
52+
53+
/**
54+
* Deserialize this local JSON payload into a specific {@link AsyncPredictResponse}.
55+
* subtype: {@code InferenceResponse}, {@code JobResponse}.
56+
*
57+
* @param productClass the concrete class to instantiate
58+
* @param <T> generic {@link Inference}
59+
* @return A {@link AsyncPredictResponse} instance.
60+
* @throws MindeeException if the payload cannot be deserialized into the requested type
61+
*/
62+
public <T extends Inference> AsyncPredictResponse<T> deserializeAsyncResponse(
63+
Class<T> productClass
64+
) throws IOException {
65+
AsyncPredictResponse<T> response = deserialize(AsyncPredictResponse.class, productClass);
66+
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
67+
return response;
68+
}
69+
70+
/**
71+
* Deserialize this local JSON payload into a specific {@link PredictResponse}.
72+
*
73+
* @param productClass the concrete class to instantiate
74+
* @param <T> generic {@link Inference}
75+
* @return A {@link PredictResponse} instance.
76+
* @throws MindeeException if the payload cannot be deserialized into the requested type
77+
*/
78+
public <T extends Inference> PredictResponse<T> deserializeSyncResponse(
79+
Class<T> productClass
80+
) throws IOException {
81+
PredictResponse<T> response = deserialize(PredictResponse.class, productClass);
82+
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
83+
return response;
84+
}
85+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.mindee.v2.parsing;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.mindee.MindeeException;
5+
import com.mindee.parsing.BaseLocalResponse;
6+
import java.io.File;
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.nio.charset.StandardCharsets;
10+
import java.nio.file.Path;
11+
12+
/**
13+
* A Mindee response saved locally.
14+
*/
15+
public class LocalResponse extends BaseLocalResponse {
16+
17+
public LocalResponse(InputStream input) {
18+
super(input);
19+
}
20+
21+
public LocalResponse(String input) {
22+
super(input);
23+
}
24+
25+
public LocalResponse(File input) throws IOException {
26+
super(input);
27+
}
28+
29+
public LocalResponse(Path input) throws IOException {
30+
super(input);
31+
}
32+
33+
/**
34+
* Deserialize this local JSON payload into a specific {@link CommonResponse}
35+
* subtype: {@code InferenceResponse}, {@code JobResponse}.
36+
*
37+
* @param responseClass the concrete class to instantiate
38+
* @param <T> generic {@link CommonResponse}
39+
* @return Either a {@code InferenceResponse} or {@code JobResponse} instance.
40+
* @throws MindeeException if the payload cannot be deserialized into the requested type
41+
*/
42+
public <T extends CommonResponse> T deserializeResponse(Class<T> responseClass) {
43+
var mapper = new ObjectMapper().findAndRegisterModules();
44+
try {
45+
var response = mapper.readValue(this.file, responseClass);
46+
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
47+
return response;
48+
} catch (Exception e) {
49+
throw new MindeeException("Invalid JSON payload.", e);
50+
}
51+
}
52+
}

src/test/java/com/mindee/input/LocalResponseV1Test.java

Lines changed: 0 additions & 61 deletions
This file was deleted.

src/test/java/com/mindee/v1/MindeeClientTest.java

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
package com.mindee.v1;
22

3-
import static com.mindee.TestingUtilities.assertStringEqualsFile;
43
import static com.mindee.TestingUtilities.getResourcePath;
5-
import static com.mindee.TestingUtilities.getV1ResourcePathString;
64

75
import com.mindee.input.LocalInputSource;
8-
import com.mindee.input.LocalResponse;
96
import com.mindee.input.PageOptions;
107
import com.mindee.input.PageOptionsOperation;
118
import com.mindee.v1.clientOptions.PredictOptions;
129
import com.mindee.v1.parsing.common.AsyncPredictResponse;
1310
import com.mindee.v1.parsing.common.Document;
1411
import com.mindee.v1.parsing.common.Job;
1512
import com.mindee.v1.parsing.common.PredictResponse;
16-
import com.mindee.v1.product.internationalid.InternationalIdV2;
1713
import com.mindee.v1.product.invoice.InvoiceV4;
18-
import java.io.File;
1914
import java.io.IOException;
2015
import java.net.URL;
2116
import java.nio.file.Files;
@@ -156,30 +151,4 @@ void givenAnAsyncUrl_whenEnqueued_shouldInvokeApiCorrectly() throws IOException
156151

157152
Assertions.assertEquals("someid", jobId);
158153
}
159-
160-
@Test
161-
void givenJsonInput_whenSync_shouldDeserializeCorrectly() throws IOException {
162-
File file = new File(getV1ResourcePathString("products/invoices/response_v4/complete.json"));
163-
LocalResponse localResponse = new LocalResponse(file);
164-
AsyncPredictResponse<InvoiceV4> predictResponse = new MindeeClient()
165-
.loadPrediction(InvoiceV4.class, localResponse);
166-
assertStringEqualsFile(
167-
predictResponse.getDocumentObj().toString(),
168-
getV1ResourcePathString("/products/invoices/response_v4/summary_full.rst")
169-
);
170-
}
171-
172-
@Test
173-
void givenJsonInput_whenAsync_shouldDeserializeCorrectly() throws IOException {
174-
File file = new File(
175-
getV1ResourcePathString("products/international_id/response_v2/complete.json")
176-
);
177-
LocalResponse localResponse = new LocalResponse(file);
178-
AsyncPredictResponse<InternationalIdV2> predictResponse = new MindeeClient()
179-
.loadPrediction(InternationalIdV2.class, localResponse);
180-
assertStringEqualsFile(
181-
predictResponse.getDocumentObj().toString(),
182-
getV1ResourcePathString("products/international_id/response_v2/summary_full.rst")
183-
);
184-
}
185154
}

0 commit comments

Comments
 (0)