Replaced Map.Entry with StandardImageMetadataSupport.TextEntry

This commit is contained in:
Harald Kuhr 2022-10-10 14:15:57 +02:00
parent 7ed5663633
commit b9b1a35408
3 changed files with 97 additions and 37 deletions

View File

@ -6,10 +6,11 @@ import javax.imageio.metadata.IIOMetadataNode;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static com.twelvemonkeys.imageio.StandardImageMetadataSupport.ColorSpaceType.*;
@ -42,7 +43,7 @@ public class StandardImageMetadataSupport extends AbstractMetadata {
protected final String formatVersion;
protected final SubimageInterpretation subimageInterpretation;
private final Calendar documentCreationTime; // TODO: This field should be a LocalDateTime or other java.time type, Consider a long timestamp + TimeZone to avoid messing up the API...
private final Collection<Map.Entry<String, String>> textEntries;
private final Collection<TextEntry> textEntries;
protected StandardImageMetadataSupport(Builder builder) {
notNull(builder, "builder");
@ -98,7 +99,7 @@ public class StandardImageMetadataSupport extends AbstractMetadata {
private String formatVersion;
private SubimageInterpretation subimageInterpretation;
private Calendar documentCreationTime; // TODO: This field should be a LocalDateTime or other java.time type
private final Collection<Map.Entry<String, String>> textEntries = new ArrayList<>();
private final Collection<TextEntry> textEntries = new ArrayList<>();
protected Builder(ImageTypeSpecifier type) {
this.type = notNull(type, "type");
@ -193,10 +194,21 @@ public class StandardImageMetadataSupport extends AbstractMetadata {
}
public Builder withTextEntries(Map<String, String> entries) {
return withTextEntries(notNull(entries, "entries").entrySet());
return withTextEntries(toTextEntries(notNull(entries, "entries").entrySet()));
}
public Builder withTextEntries(Collection<Map.Entry<String, String>> entries) {
private Collection<TextEntry> toTextEntries(Collection<Map.Entry<String, String>> entries) {
TextEntry[] result = new TextEntry[entries.size()];
int i = 0;
for (Map.Entry<String, String> entry : entries) {
result[i++] = new TextEntry(entry.getKey(), entry.getValue());
}
return Arrays.asList(result);
}
public Builder withTextEntries(Collection<TextEntry> entries) {
this.textEntries.addAll(notNull(entries, "entries"));
return this;
@ -204,7 +216,7 @@ public class StandardImageMetadataSupport extends AbstractMetadata {
public Builder withTextEntry(String keyword, String value) {
if (value != null && !value.isEmpty()) {
this.textEntries.add(new SimpleImmutableEntry<>(notNull(keyword, "keyword"), value));
this.textEntries.add(new TextEntry(notNull(keyword, "keyword"), value));
}
return this;
@ -389,6 +401,28 @@ public class StandardImageMetadataSupport extends AbstractMetadata {
throw new IllegalArgumentException("Unknown ColorSpace type: " + colorSpace);
}
protected static final class TextEntry {
static final List<String> COMPRESSIONS = Arrays.asList("none", "lzw", "zip", "bzip", "other");
final String keyword;
final String value;
final String language;
final String encoding;
final String compression;
public TextEntry(final String keyword, final String value) {
this(keyword, value, null, null, null);
}
public TextEntry(final String keyword, final String value, final String language, final String encoding, final String compression) {
this.keyword = keyword;
this.value = notNull(value, "value");
this.language = language;
this.encoding = encoding;
this.compression = isTrue(compression == null || COMPRESSIONS.contains(compression), compression, String.format("Unknown compression: %s (expected: %s)", compression, COMPRESSIONS));
}
}
@Override
protected IIOMetadataNode getStandardCompressionNode() {
if (compressionName == null) {
@ -547,11 +581,22 @@ public class StandardImageMetadataSupport extends AbstractMetadata {
// DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright:
// /Text/TextEntry@keyword = field name, /Text/TextEntry@value = field value.
for (Map.Entry<String, String> entry : textEntries) {
for (TextEntry entry : textEntries) {
IIOMetadataNode textEntryNode = new IIOMetadataNode("TextEntry");
textNode.appendChild(textEntryNode);
textEntryNode.setAttribute("keyword", entry.getKey());
textEntryNode.setAttribute("value", entry.getValue());
if (entry.keyword != null) {
textEntryNode.setAttribute("keyword", entry.keyword);
}
textEntryNode.setAttribute("value", entry.value);
if (entry.language != null) {
textEntryNode.setAttribute("language", entry.language);
}
if (entry.encoding != null) {
textEntryNode.setAttribute("encoding", entry.encoding);
}
if (entry.compression != null) {
textEntryNode.setAttribute("compression", entry.compression);
}
}
return textNode;

View File

@ -4,6 +4,7 @@ import com.twelvemonkeys.imageio.StandardImageMetadataSupport.ColorSpaceType;
import com.twelvemonkeys.imageio.StandardImageMetadataSupport.ImageOrientation;
import com.twelvemonkeys.imageio.StandardImageMetadataSupport.PlanarConfiguration;
import com.twelvemonkeys.imageio.StandardImageMetadataSupport.SubimageInterpretation;
import com.twelvemonkeys.imageio.StandardImageMetadataSupport.TextEntry;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import org.junit.Test;
@ -12,7 +13,6 @@ import org.w3c.dom.NodeList;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import java.awt.image.*;
import java.util.AbstractMap.SimpleEntry;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
@ -22,10 +22,7 @@ import java.util.Map;
import java.util.Map.Entry;
import static com.twelvemonkeys.imageio.StandardImageMetadataSupport.builder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
public class StandardImageMetadataSupportTest {
@Test(expected = IllegalArgumentException.class)
@ -52,7 +49,8 @@ public class StandardImageMetadataSupportTest {
@Test
public void builderValid() {
IIOMetadata metadata = builder(ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB))
.build();
.build();
assertNotNull(metadata);
}
@ -198,11 +196,12 @@ public class StandardImageMetadataSupportTest {
@Test
public void withTextValuesList() {
List<Entry<String, String>> entries = Arrays.<Entry<String, String>>asList(
new SimpleEntry<>((String) null, "foo"), // No key allowed
new SimpleEntry<>("foo", "bar"),
new SimpleEntry<>("bar", "xyzzy"),
new SimpleEntry<>("bar", "nothing happens...") // Duplicates allowed
List<TextEntry> entries = Arrays.asList(
new TextEntry(null, "foo"), // No key allowed
new TextEntry("foo", "bar"),
new TextEntry("bar", "xyzzy"),
new TextEntry("bar", "nothing happens..."), // Duplicates allowed
new TextEntry("everything", "válüè", "unknown", "UTF-8", "zip")
);
StandardImageMetadataSupport metadata = (StandardImageMetadataSupport) builder(ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY))
@ -216,11 +215,25 @@ public class StandardImageMetadataSupportTest {
assertEquals(entries.size(), textEntries.getLength());
for (int i = 0; i < entries.size(); i++) {
Entry<String, String> entry = entries.get(i);
TextEntry entry = entries.get(i);
IIOMetadataNode textEntry = (IIOMetadataNode) textEntries.item(i);
assertEquals(entry.getKey(), textEntry.getAttribute("keyword"));
assertEquals(entry.getValue(), textEntry.getAttribute("value"));
assertAttributeEqualOrAbsent(entry.keyword, textEntry, "keyword");
assertEquals(entry.value, textEntry.getAttribute("value"));
assertAttributeEqualOrAbsent(entry.language, textEntry, "language");
assertAttributeEqualOrAbsent(entry.encoding, textEntry, "encoding");
assertAttributeEqualOrAbsent(entry.compression, textEntry, "compression");
}
}
private static void assertAttributeEqualOrAbsent(final String expectedValue, IIOMetadataNode node, final String attribute) {
if (expectedValue != null) {
assertEquals(expectedValue, node.getAttribute(attribute));
}
else {
assertFalse(node.hasAttribute(attribute));
}
}
@ -236,8 +249,9 @@ public class StandardImageMetadataSupportTest {
for (ColorSpaceType value : ColorSpaceType.values()) {
StandardImageMetadataSupport metadata = (StandardImageMetadataSupport) builder(ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY))
.withColorSpaceType(value)
.build();
.withColorSpaceType(value)
.build();
assertNotNull(metadata);
IIOMetadataNode documentNode = metadata.getStandardChromaNode();
@ -256,8 +270,9 @@ public class StandardImageMetadataSupportTest {
for (PlanarConfiguration value : PlanarConfiguration.values()) {
StandardImageMetadataSupport metadata = (StandardImageMetadataSupport) builder(ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR))
.withPlanarConfiguration(value)
.build();
.withPlanarConfiguration(value)
.build();
assertNotNull(metadata);
IIOMetadataNode documentNode = metadata.getStandardDataNode();
@ -276,8 +291,9 @@ public class StandardImageMetadataSupportTest {
for (ImageOrientation value : ImageOrientation.values()) {
StandardImageMetadataSupport metadata = (StandardImageMetadataSupport) builder(ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY))
.withOrientation(value)
.build();
.withOrientation(value)
.build();
assertNotNull(metadata);
IIOMetadataNode documentNode = metadata.getStandardDimensionNode();
@ -300,8 +316,9 @@ public class StandardImageMetadataSupportTest {
for (SubimageInterpretation value : SubimageInterpretation.values()) {
StandardImageMetadataSupport metadata = (StandardImageMetadataSupport) builder(ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB))
.withSubimageInterpretation(value)
.build();
.withSubimageInterpretation(value)
.build();
assertNotNull(metadata);
IIOMetadataNode documentNode = metadata.getStandardDocumentNode();

View File

@ -35,10 +35,8 @@ import com.twelvemonkeys.imageio.StandardImageMetadataSupport;
import javax.imageio.ImageTypeSpecifier;
import java.awt.image.*;
import java.nio.charset.StandardCharsets;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.twelvemonkeys.imageio.plugins.iff.IFF.*;
import static com.twelvemonkeys.imageio.plugins.iff.IFFUtil.toChunkStr;
@ -119,15 +117,15 @@ final class IFFImageMetadata extends StandardImageMetadataSupport {
}
}
private static List<Map.Entry<String, String>> textEntries(Form header) {
private static List<TextEntry> textEntries(Form header) {
if (header.meta.isEmpty()) {
return emptyList();
}
List<Map.Entry<String, String>> text = new ArrayList<>();
List<TextEntry> text = new ArrayList<>();
for (GenericChunk chunk : header.meta) {
text.add(new SimpleImmutableEntry<>(toChunkStr(chunk.chunkId),
new String(chunk.data, chunk.chunkId == IFF.CHUNK_UTF8 ? StandardCharsets.UTF_8 : StandardCharsets.US_ASCII)));
text.add(new TextEntry(toChunkStr(chunk.chunkId),
new String(chunk.data, chunk.chunkId == IFF.CHUNK_UTF8 ? StandardCharsets.UTF_8:StandardCharsets.US_ASCII)));
}
return text;