From ab551e4500194e9acba726e99d2c7e174142aa5e Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 22 Nov 2020 09:37:02 +0000 Subject: [PATCH] Add support for adding custom metadata (#8) * add lombok dependency * Add methods addMetadata and addMetadataProperty * Version set to 1.1.0 * Introduce MetadataItem to replace multiple addMetadata methods --- pom.xml | 11 +- .../epub/creator/api/MetadataItem.java | 168 ++++++++++++++++++ .../epub/creator/api/OpfCreator.java | 2 + .../epub/creator/impl/OpfCreatorDefault.java | 36 +++- .../epub/creator/model/EpubBook.java | 6 + .../epub/creator/EpubCreatorTest.java | 7 + 6 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 src/main/java/coza/opencollab/epub/creator/api/MetadataItem.java diff --git a/pom.xml b/pom.xml index f4f1c5d..269b089 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ net.kemitix epub-creator - 1.0.2 + 1.1.0 scm:git:git@github.com:kemitix/epub-creator.git @@ -51,7 +51,14 @@ commons-collections 3.2.2 - + + + org.projectlombok + lombok + 1.18.16 + true + + diff --git a/src/main/java/coza/opencollab/epub/creator/api/MetadataItem.java b/src/main/java/coza/opencollab/epub/creator/api/MetadataItem.java new file mode 100644 index 0000000..7868854 --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/api/MetadataItem.java @@ -0,0 +1,168 @@ +package coza.opencollab.epub.creator.api; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class MetadataItem { + + private final String name; //e.g. dc:description + private final String id;// optional + private final String property;// optional + private final String refines;// optional + private final String value;// optional + + public String getName() { + return name; + } + + public boolean hasId() { + return id != null; + } + + public String getId() { + return id; + } + + public boolean hasProperty() { + return property != null; + } + + public String getProperty() { + return property; + } + + public boolean hasRefines() { + return refines != null; + } + + public String getRefines() { + return refines; + } + + public boolean hasValue() { + return value != null; + } + + public String getValue() { + return value; + } + + public static Builder builder() { + return new Builder() { + @Override + public Stage1 name(String name) { + return new Stage1() { + @Override + public Stage2 id(String id) { + return new Stage2() { + @Override + public Stage3 property(String property) { + return new Stage3() { + @Override + public Stage4 refines(String refines) { + return new Stage4() { + @Override + public MetadataItem value(String value) { + return new MetadataItem(name, id, property, refines, value); + } + + @Override + public MetadataItem build() { + return new MetadataItem(name, id, property, refines, null); + } + }; + } + + @Override + public MetadataItem value(String value) { + return new MetadataItem(name, id, property, null, value); + } + + @Override + public MetadataItem build() { + return new MetadataItem(name, id, property, null, null); + } + }; + } + + @Override + public MetadataItem value(String value) { + return new MetadataItem(name, id, null, null, value); + } + + @Override + public MetadataItem build() { + return new MetadataItem(name, id, null, null, null); + } + }; + } + + @Override + public Stage3 property(String property) { + return new Stage3() { + @Override + public Stage4 refines(String refines) { + return new Stage4() { + @Override + public MetadataItem value(String value) { + return new MetadataItem(name, null, property, refines, value); + } + + @Override + public MetadataItem build() { + return new MetadataItem(name, null, property, refines, null); + } + }; + } + + @Override + public MetadataItem value(String value) { + return new MetadataItem(name, null, property, null, value); + } + + @Override + public MetadataItem build() { + return new MetadataItem(name, null, property, null, null); + } + }; + } + + @Override + public MetadataItem value(String value) { + return new MetadataItem(name, null, null, null, value); + } + + @Override + public MetadataItem build() { + return new MetadataItem(name, null, null, null, null); + } + }; + } + }; + } + + public interface Builder { + Stage1 name(String name); + interface Stage1 { + Stage2 id(String id); + Stage3 property(String property); + MetadataItem value(String value); + MetadataItem build(); + } + interface Stage2 { + Stage3 property(String property); + MetadataItem value(String value); + MetadataItem build(); + } + interface Stage3 { + Stage4 refines(String refines); + MetadataItem value(String value); + MetadataItem build(); + } + interface Stage4 { + MetadataItem value(String value); + MetadataItem build(); + } + } +} diff --git a/src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java b/src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java index c9bf84a..aa2b958 100644 --- a/src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java +++ b/src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java @@ -30,6 +30,8 @@ import coza.opencollab.epub.creator.model.EpubBook; */ public interface OpfCreator { + void addMetadata(MetadataItem metadataItem); + /** * Creates the OPF file text from the EpubBook data * diff --git a/src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java b/src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java index 239baa6..fc49608 100644 --- a/src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java +++ b/src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java @@ -21,11 +21,10 @@ package coza.opencollab.epub.creator.impl; import coza.opencollab.epub.creator.EpubConstants; +import coza.opencollab.epub.creator.api.MetadataItem; import coza.opencollab.epub.creator.api.OpfCreator; import coza.opencollab.epub.creator.model.Content; import coza.opencollab.epub.creator.model.EpubBook; -import java.text.SimpleDateFormat; -import java.util.Date; import org.htmlcleaner.CleanerProperties; import org.htmlcleaner.ContentNode; import org.htmlcleaner.HtmlCleaner; @@ -33,6 +32,11 @@ import org.htmlcleaner.PrettyXmlSerializer; import org.htmlcleaner.Serializer; import org.htmlcleaner.TagNode; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + /** * Default implementation of the OpfCreator. This follows EPUB3 standards to * create the OPF file content. @@ -57,6 +61,8 @@ public class OpfCreatorDefault implements OpfCreator { */ private final Serializer htmlSetdown; + private final List metadataItems = new ArrayList<>(); + public OpfCreatorDefault() { cleaner = new HtmlCleaner(); CleanerProperties htmlProperties = cleaner.getProperties(); @@ -66,6 +72,11 @@ public class OpfCreatorDefault implements OpfCreator { htmlSetdown = new PrettyXmlSerializer(htmlProperties); } + @Override + public void addMetadata(MetadataItem metadataItem) { + this.metadataItems.add(metadataItem); + } + /** * {@inheritDoc} */ @@ -75,9 +86,30 @@ public class OpfCreatorDefault implements OpfCreator { addMetaDataTags(tagNode, book); addManifestTags(tagNode, book); addSpineTags(tagNode, book); + addCustomMetadata(tagNode, book); return htmlSetdown.getAsString(tagNode); } + private void addCustomMetadata(TagNode tagNode, EpubBook book) { + TagNode metaNode = tagNode.findElementByName("metadata", true); + metadataItems.forEach(item -> { + TagNode node = new TagNode(item.getName()); + if (item.hasId()) { + node.addAttribute("id", item.getId()); + } + if (item.hasProperty()) { + node.addAttribute("property", item.getProperty()); + } + if (item.hasRefines()) { + node.addAttribute("refines", item.getRefines()); + } + if (item.hasValue()) { + node.addChild(new ContentNode(item.getValue())); + } + metaNode.addChild(node); + }); + } + /** * Add the required meta data * diff --git a/src/main/java/coza/opencollab/epub/creator/model/EpubBook.java b/src/main/java/coza/opencollab/epub/creator/model/EpubBook.java index 0a06d8b..4ea0a8f 100644 --- a/src/main/java/coza/opencollab/epub/creator/model/EpubBook.java +++ b/src/main/java/coza/opencollab/epub/creator/model/EpubBook.java @@ -21,6 +21,7 @@ package coza.opencollab.epub.creator.model; import coza.opencollab.epub.creator.EpubConstants; +import coza.opencollab.epub.creator.api.MetadataItem; import coza.opencollab.epub.creator.util.EpubWriter; import java.io.IOException; import java.io.InputStream; @@ -426,4 +427,9 @@ public class EpubBook { return uniqueHrefs; } + public void addMetadata(MetadataItem metadataItem) { + getEpubCreator().getOpfCreator() + .addMetadata(metadataItem); + } + } diff --git a/src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java b/src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java index b121530..279990b 100644 --- a/src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java +++ b/src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java @@ -1,5 +1,6 @@ package coza.opencollab.epub.creator; +import coza.opencollab.epub.creator.api.MetadataItem; import coza.opencollab.epub.creator.model.EpubBook; import java.io.File; import java.io.FileOutputStream; @@ -18,6 +19,12 @@ public class EpubCreatorTest { try (FileOutputStream file = new FileOutputStream(new File("test.epub"))) { EpubBook book = new EpubBook("en", "Samuel .-__Id1", "Samuel Test Book", "Samuel Holtzkampf"); + MetadataItem.Builder builder = MetadataItem.builder(); + book.addMetadata(builder.name("dc:creator").value("Bob Smith")); + book.addMetadata(builder.name("meta") + .property("role").refines("#editor-id") + .value("Editor")); + book.addContent(this.getClass().getResourceAsStream("/epub30-overview.xhtml"), "application/xhtml+xml", "xhtml/epub30-overview.xhtml", true, true).setId("Overview"); book.addContent(this.getClass().getResourceAsStream("/idpflogo_web_125.jpg"),