Skip to content

Commit f56f325

Browse files
committed
improves MimetypeService API with additional methods
1 parent c268d95 commit f56f325

File tree

4 files changed

+248
-25
lines changed

4 files changed

+248
-25
lines changed

dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/service/MimetypeServiceImpl.java

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,10 @@
88
import org.apache.tika.io.TikaInputStream;
99
import org.apache.tika.metadata.Metadata;
1010
import org.apache.tika.mime.MediaType;
11-
import org.slf4j.Logger;
12-
import org.slf4j.LoggerFactory;
1311
import org.springframework.beans.factory.InitializingBean;
1412

1513
public class MimetypeServiceImpl implements MimetypeService, InitializingBean
1614
{
17-
private static final Logger logger = LoggerFactory.getLogger(MimetypeServiceImpl.class);
18-
1915
private final Detector detector;
2016

2117
public MimetypeServiceImpl(Detector detector)
@@ -30,10 +26,9 @@ public void afterPropertiesSet() throws Exception
3026
}
3127

3228
@Override
33-
public void validate(InputStream stream, String declared)
29+
public ValidationResult validateWithResult(InputStream stream, String declared)
3430
{
3531
MediaType declaredMimeType = MediaType.parse(declared);
36-
MediaType detectedMimeType;
3732

3833
try
3934
{
@@ -44,21 +39,14 @@ public void validate(InputStream stream, String declared)
4439
Metadata metadata = new Metadata();
4540
metadata.add(Metadata.CONTENT_TYPE, declaredMimeType.toString());
4641

47-
detectedMimeType = detector.detect(input, metadata);
42+
MediaType detectedMimeType = detector.detect(input, metadata);
43+
44+
return new ValidationResult(declaredMimeType.getType(), declaredMimeType.getSubtype(),
45+
detectedMimeType.getType(), detectedMimeType.getSubtype());
4846
}
4947
catch (IOException exception)
5048
{
5149
throw new RuntimeException("Error while detecting mimetype", exception);
5250
}
53-
54-
if (!declaredMimeType.equals(detectedMimeType))
55-
logger.warn("Declared full mimetype {} does not match detected full mimetype {}",
56-
declaredMimeType.toString(), detectedMimeType.toString());
57-
58-
if (!declaredMimeType.getType().equals(detectedMimeType.getType()))
59-
{
60-
throw new RuntimeException("Declared base mimetype of '" + declaredMimeType.toString()
61-
+ "' does not match detected base mimetype of '" + detectedMimeType.toString() + "'");
62-
}
6351
}
6452
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package dev.dsf.bpe.v2.service;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertTrue;
5+
import static org.junit.Assert.fail;
6+
7+
import java.io.ByteArrayInputStream;
8+
import java.io.ByteArrayOutputStream;
9+
import java.io.IOException;
10+
import java.io.InputStream;
11+
import java.util.zip.ZipEntry;
12+
import java.util.zip.ZipOutputStream;
13+
14+
import org.junit.Test;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
18+
import dev.dsf.bpe.v2.service.detector.CombinedDetectors;
19+
import dev.dsf.bpe.v2.service.detector.NdJsonDetector;
20+
import dev.dsf.bpe.v2.variables.JsonVariableSerializationTest;
21+
22+
public class MimetypeServiceTest
23+
{
24+
private static final Logger logger = LoggerFactory.getLogger(JsonVariableSerializationTest.class);
25+
26+
private final MimetypeService mimetypeService = new MimetypeServiceImpl(
27+
CombinedDetectors.withDefaultAndNdJson(NdJsonDetector.DEFAULT_LINES_TO_CHECK));
28+
29+
@Test
30+
public void testCsv()
31+
{
32+
String content = """
33+
Apple;Banana;Cherry;Date;Elderberry;Fig;Grape;Honeydew;Indian Fig;Jackfruit
34+
Kiwi;Lemon;Mango;Nectarine;Orange;Papaya;Quince;Raspberry;Strawberry;Tomato
35+
Ugli Fruit;Vanilla Bean;Watermelon;Xigua;Yellow Passionfruit;Zucchini;Apricot;Blackberry;Cantaloupe;Dragonfruit
36+
Eggplant;Feijoa;Grapefruit;Hackberry;Ilama;Jujube;Kumquat;Lime;Mulberry;Naranjilla
37+
Olive;Peach;Queen Anne Cherry;Rambutan;Soursop;Tamarind;Uva;Voavanga;White Currant;Ziziphus
38+
""";
39+
40+
test(content.getBytes(), "text/csv");
41+
}
42+
43+
@Test
44+
public void testNdJson()
45+
{
46+
String content = """
47+
{"name": "Apple", "color": "Red", "type": "Pome"}
48+
{"name": "Banana", "color": "Yellow", "type": "Berry"}
49+
{"name": "Cherry", "color": "Red", "type": "Drupe"}
50+
{"name": "Mango", "color": "Orange", "type": "Drupe"}
51+
{"name": "Blueberry", "color": "Blue", "type": "Berry"}
52+
""";
53+
54+
test(content.getBytes(), "application/x-ndjson");
55+
}
56+
57+
@Test
58+
public void testBundle()
59+
{
60+
String content = """
61+
<Bundle xmlns="http://hl7.org/fhir">
62+
<type value="collection"/>
63+
<entry>
64+
<resource>
65+
<Patient>
66+
<id value="example"/>
67+
<name>
68+
<use value="official"/>
69+
<family value="Doe"/>
70+
<given value="John"/>
71+
</name>
72+
<gender value="male"/>
73+
<birthDate value="1990-01-01"/>
74+
</Patient>
75+
</resource>
76+
</entry>
77+
</Bundle>
78+
""";
79+
80+
test(content.getBytes(), "application/fhir+xml");
81+
}
82+
83+
@Test
84+
public void testZip()
85+
{
86+
String csv = """
87+
Apple;Banana;Cherry;Date;Elderberry;Fig;Grape;Honeydew;Indian Fig;Jackfruit
88+
Kiwi;Lemon;Mango;Nectarine;Orange;Papaya;Quince;Raspberry;Strawberry;Tomato
89+
Ugli Fruit;Vanilla Bean;Watermelon;Xigua;Yellow Passionfruit;Zucchini;Apricot;Blackberry;Cantaloupe;Dragonfruit
90+
Eggplant;Feijoa;Grapefruit;Hackberry;Ilama;Jujube;Kumquat;Lime;Mulberry;Naranjilla
91+
Olive;Peach;Queen Anne Cherry;Rambutan;Soursop;Tamarind;Uva;Voavanga;White Currant;Ziziphus
92+
""";
93+
94+
ByteArrayOutputStream out = new ByteArrayOutputStream();
95+
try (ZipOutputStream file = new ZipOutputStream(out))
96+
{
97+
file.putNextEntry(new ZipEntry("fruits.csv"));
98+
file.write(csv.getBytes());
99+
file.closeEntry();
100+
}
101+
catch (IOException e)
102+
{
103+
throw new RuntimeException(e);
104+
}
105+
106+
byte[] content = out.toByteArray();
107+
test(content, "application/zip");
108+
}
109+
110+
private void test(byte[] content, String mimeType)
111+
{
112+
InputStream contentStream = new ByteArrayInputStream(content);
113+
114+
String[] split = mimeType.split("/");
115+
String baseType = split[0];
116+
String subType = split[1];
117+
118+
MimetypeService.ValidationResult validationResult = mimetypeService.validateWithResult(contentStream, mimeType);
119+
120+
assertEquals(baseType, validationResult.detectedBaseType());
121+
assertEquals(subType, validationResult.detectedSubType());
122+
assertEquals(mimeType, validationResult.declared());
123+
assertEquals(mimeType, validationResult.detected());
124+
assertTrue(validationResult.mimetypesMatch());
125+
126+
boolean booleanResult = mimetypeService.validateWithBoolean(contentStream, mimeType);
127+
assertTrue(booleanResult);
128+
129+
try
130+
{
131+
mimetypeService.validateWithException(contentStream, mimeType);
132+
}
133+
catch (Exception e)
134+
{
135+
logger.info("Validation failed - {}", e.getMessage());
136+
fail();
137+
}
138+
}
139+
}

dsf-bpe/dsf-bpe-process-api-v2/src/main/java/dev/dsf/bpe/v2/service/MimetypeService.java

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,89 @@
33
import java.io.ByteArrayInputStream;
44
import java.io.InputStream;
55

6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
69
public interface MimetypeService
710
{
11+
Logger logger = LoggerFactory.getLogger(MimetypeService.class);
12+
13+
record ValidationResult(String declaredBaseType, String declaredSubType, String detectedBaseType,
14+
String detectedSubType)
15+
{
16+
public String declared()
17+
{
18+
return declaredBaseType + "/" + declaredSubType;
19+
}
20+
21+
public String detected()
22+
{
23+
return detectedBaseType + "/" + detectedSubType;
24+
}
25+
26+
public boolean mimetypesMatch()
27+
{
28+
return declared().equals(detected());
29+
}
30+
}
31+
832
/**
933
* Detects the mimetype of the provided byte array and validates if the detected mimetype equals the declared
10-
* mimetype. Logs a warning if the full mimetypes do not match, throws a {@link RuntimeException} if the base
11-
* mimetypes do not match.
34+
* mimetype. Returns a {@link ValidationResult} containing both the declared and detected MIME types. This result
35+
* can be used to drive custom logic based on whether the detected type matches the declared type.
36+
*
37+
* @param stream
38+
* input stream of which the mimetype should be detected
39+
* @param declared
40+
* the declared mimetype of the data
41+
* @return {@link ValidationResult} containing the declared and detected mimetypes.
42+
*/
43+
ValidationResult validateWithResult(InputStream stream, String declared);
44+
45+
/**
46+
* Detects the mimetype of the provided byte array and validates if the detected mimetype equals the declared
47+
* mimetype. Returns a {@link ValidationResult} containing both the declared and detected MIME types. This result
48+
* can be used to drive custom logic based on whether the detected type matches the declared type.
1249
*
1350
* @param data
1451
* byte array of which the mimetype should be detected
1552
* @param declared
1653
* the declared mimetype of the data
17-
* @throws RuntimeException
18-
* if the detected and the declared base mimetype do not match
54+
* @return {@link ValidationResult} containing the declared and detected mimetypes.
55+
*/
56+
default ValidationResult validateWithResult(byte[] data, String declared)
57+
{
58+
return validateWithResult(new ByteArrayInputStream(data), declared);
59+
}
60+
61+
/**
62+
* Detects the mimetype of the provided byte array and validates if the detected mimetype equals the declared
63+
* mimetype. Returns <code>true</code> if the full mimetype matches, <code>false</code> otherwise.
64+
*
65+
* @param stream
66+
* input stream of which the mimetype should be detected
67+
* @param declared
68+
* the declared mimetype of the data
69+
* @return <code>true</code> if the full mimetype matches, <code>false</code> otherwise
1970
*/
20-
default void validate(byte[] data, String declared)
71+
default boolean validateWithBoolean(InputStream stream, String declared)
2172
{
22-
validate(new ByteArrayInputStream(data), declared);
73+
return validateWithResult(stream, declared).mimetypesMatch();
74+
}
75+
76+
/**
77+
* Detects the mimetype of the provided byte array and validates if the detected mimetype equals the declared
78+
* mimetype. Returns <code>true</code> if the full mimetype matches, <code>false</code> otherwise.
79+
*
80+
* @param data
81+
* byte array of which the mimetype should be detected
82+
* @param declared
83+
* the declared mimetype of the data
84+
* @return <code>true</code> if the full mimetype matches, <code>false</code> otherwise
85+
*/
86+
default boolean validateWithBoolean(byte[] data, String declared)
87+
{
88+
return validateWithResult(new ByteArrayInputStream(data), declared).mimetypesMatch();
2389
}
2490

2591
/**
@@ -34,5 +100,35 @@ default void validate(byte[] data, String declared)
34100
* @throws RuntimeException
35101
* if the detected and the declared base mimetype do not match
36102
*/
37-
void validate(InputStream stream, String declared);
103+
default void validateWithException(InputStream stream, String declared)
104+
{
105+
ValidationResult result = validateWithResult(stream, declared);
106+
107+
if (!result.mimetypesMatch())
108+
logger.warn("Declared full mimetype {} does not match detected full mimetype {}", result.declared(),
109+
result.detected());
110+
111+
if (!result.declaredBaseType().equals(result.detectedBaseType()))
112+
{
113+
throw new RuntimeException("Declared base mimetype of '" + result.declared()
114+
+ "' does not match detected base mimetype of '" + result.detected() + "'");
115+
}
116+
}
117+
118+
/**
119+
* Detects the mimetype of the provided byte array and validates if the detected mimetype equals the declared
120+
* mimetype. Logs a warning if the full mimetypes do not match, throws a {@link RuntimeException} if the base
121+
* mimetypes do not match.
122+
*
123+
* @param data
124+
* byte array of which the mimetype should be detected
125+
* @param declared
126+
* the declared mimetype of the data
127+
* @throws RuntimeException
128+
* if the detected and the declared base mimetype do not match
129+
*/
130+
default void validateWithException(byte[] data, String declared)
131+
{
132+
validateWithException(new ByteArrayInputStream(data), declared);
133+
}
38134
}

dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/MimetypeServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ private void testResourcesStream(List<Resource> resources, MimetypeService mimet
9090
InputStream data = getDataStream(resource);
9191
String expected = getMimetype(resource);
9292

93-
mimetypeService.validate(data, expected);
93+
mimetypeService.validateWithException(data, expected);
9494
}
9595
}
9696

0 commit comments

Comments
 (0)