* All resources of a Book (html, css, xml, fonts, images) are represented as Resources. See getResources() for access to these.
* A Book as 3 indexes into these Resources, as per the epub specification.
*
@@ -28,503 +27,513 @@
* The Content page may be in the Table of Contents, the Guide, but not in the Spine.
* Etc.
*
-
-
-
-
-
-
- * @author paul
+ *
+ *
+ *
+ *
*
+ * @author paul
*/
public class Book implements Serializable {
-
- private static final long serialVersionUID = 2068355170895770100L;
-
- private Resources resources = new Resources();
- private Metadata metadata = new Metadata();
- private Spine spine = new Spine();
- private TableOfContents tableOfContents = new TableOfContents();
- private Guide guide = new Guide();
- private Resource opfResource;
- private Resource ncxResource;
- private Resource coverImage;
-
- /**
- * Adds the resource to the table of contents of the book as a child section of the given parentSection
- *
- * @param parentSection
- * @param sectionTitle
- * @param resource
- * @return The table of contents
- */
- public TOCReference addSection(TOCReference parentSection, String sectionTitle,
- Resource resource) {
- getResources().add(resource);
- if (spine.findFirstResourceById(resource.getId()) < 0) {
- spine.addSpineReference(new SpineReference(resource));
- }
- return parentSection.addChildSection(new TOCReference(sectionTitle, resource));
- }
-
- public void generateSpineFromTableOfContents() {
- Spine spine = new Spine(tableOfContents);
-
- // in case the tocResource was already found and assigned
- spine.setTocResource(this.spine.getTocResource());
-
- this.spine = spine;
- }
-
- /**
- * Adds a resource to the book's set of resources, table of contents and if there is no resource with the id in the spine also adds it to the spine.
- *
- * @param title
- * @param resource
- * @return The table of contents
- */
- public TOCReference addSection(String title, Resource resource) {
- getResources().add(resource);
- TOCReference tocReference = tableOfContents.addTOCReference(new TOCReference(title, resource));
- if (spine.findFirstResourceById(resource.getId()) < 0) {
- spine.addSpineReference(new SpineReference(resource));
- }
- return tocReference;
- }
-
-
- /**
- * The Book's metadata (titles, authors, etc)
- *
- * @return The Book's metadata (titles, authors, etc)
- */
- public Metadata getMetadata() {
- return metadata;
- }
- public void setMetadata(Metadata metadata) {
- this.metadata = metadata;
- }
-
-
- public void setResources(Resources resources) {
- this.resources = resources;
- }
-
-
- public Resource addResource(Resource resource) {
- return resources.add(resource);
- }
-
- /**
- * The collection of all images, chapters, sections, xhtml files, stylesheets, etc that make up the book.
- *
- * @return The collection of all images, chapters, sections, xhtml files, stylesheets, etc that make up the book.
- */
- public Resources getResources() {
- return resources;
- }
-
-
- /**
- * The sections of the book that should be shown if a user reads the book from start to finish.
- *
- * @return The Spine
- */
- public Spine getSpine() {
- return spine;
- }
-
-
- public void setSpine(Spine spine) {
- this.spine = spine;
- }
-
-
- /**
- * The Table of Contents of the book.
- *
- * @return The Table of Contents of the book.
- */
- public TableOfContents getTableOfContents() {
- return tableOfContents;
- }
-
-
- public void setTableOfContents(TableOfContents tableOfContents) {
- this.tableOfContents = tableOfContents;
- }
-
- /**
- * The book's cover page as a Resource.
- * An XHTML document containing a link to the cover image.
- *
- * @return The book's cover page as a Resource
- */
- public Resource getCoverPage() {
- Resource coverPage = guide.getCoverPage();
- if (coverPage == null) {
- coverPage = spine.getResource(0);
- }
- return coverPage;
- }
-
-
- public void setCoverPage(Resource coverPage) {
- if (coverPage == null) {
- return;
- }
- if (! resources.containsByHref(coverPage.getHref())) {
- resources.add(coverPage);
- }
- guide.setCoverPage(coverPage);
- }
-
- /**
- * Gets the first non-blank title from the book's metadata.
- *
- * @return the first non-blank title from the book's metadata.
- */
- public String getTitle() {
- return getMetadata().getFirstTitle();
- }
-
-
- /**
- * The book's cover image.
- *
- * @return The book's cover image.
- */
- public Resource getCoverImage() {
- return coverImage;
- }
-
- public void setCoverImage(Resource coverImage) {
- if (coverImage == null) {
- return;
- }
- if (! resources.containsByHref(coverImage.getHref())) {
- resources.add(coverImage);
- }
- this.coverImage = coverImage;
- }
-
- /**
- * The guide; contains references to special sections of the book like colophon, glossary, etc.
- *
- * @return The guide; contains references to special sections of the book like colophon, glossary, etc.
- */
- public Guide getGuide() {
- return guide;
- }
-
- /**
- * All Resources of the Book that can be reached via the Spine, the TableOfContents or the Guide.
- *
- * Consists of a list of "reachable" resources:
- *
- *
The coverpage
- *
The resources of the Spine that are not already in the result
- *
The resources of the Table of Contents that are not already in the result
- *
The resources of the Guide that are not already in the result
- *
- * To get all html files that make up the epub file use {@link #getResources()}
- * @return All Resources of the Book that can be reached via the Spine, the TableOfContents or the Guide.
- */
- public List getContents() {
- Map result = new LinkedHashMap();
- addToContentsResult(getCoverPage(), result);
-
- for (SpineReference spineReference: getSpine().getSpineReferences()) {
- addToContentsResult(spineReference.getResource(), result);
- }
-
- for (Resource resource: getTableOfContents().getAllUniqueResources()) {
- addToContentsResult(resource, result);
- }
-
- for (GuideReference guideReference: getGuide().getReferences()) {
- addToContentsResult(guideReference.getResource(), result);
- }
-
- return new ArrayList(result.values());
- }
-
- private static void addToContentsResult(Resource resource, Map allReachableResources){
- if (resource != null && (! allReachableResources.containsKey(resource.getHref()))) {
- allReachableResources.put(resource.getHref(), resource);
- }
- }
-
- public Resource getOpfResource() {
- return opfResource;
- }
-
- public void setOpfResource(Resource opfResource) {
- this.opfResource = opfResource;
- }
-
- public void setNcxResource(Resource ncxResource) {
- this.ncxResource = ncxResource;
- }
-
- public Resource getNcxResource() {
- return ncxResource;
- }
+
+ private static final long serialVersionUID = 2068355170895770100L;
+
+ private Resources resources = new Resources();
+ private Metadata metadata = new Metadata();
+ private Spine spine = new Spine();
+ private TableOfContents tableOfContents = new TableOfContents();
+ private Guide guide = new Guide();
+ private Resource opfResource;
+ private Resource ncxResource;
+ private Resource coverImage;
+
+ /**
+ * Adds the resource to the table of contents of the book as a child section of the given parentSection
+ *
+ * @param parentSection
+ * @param sectionTitle
+ * @param resource
+ * @return The table of contents
+ */
+ public TOCReference addSection(TOCReference parentSection, String sectionTitle,
+ Resource resource) {
+ getResources().add(resource);
+ if (spine.findFirstResourceById(resource.getId()) < 0) {
+ spine.addSpineReference(new SpineReference(resource));
+ }
+ return parentSection.addChildSection(new TOCReference(sectionTitle, resource));
+ }
+
+ public void generateSpineFromTableOfContents() {
+ Spine spine = new Spine(tableOfContents);
+
+ // in case the tocResource was already found and assigned
+ spine.setTocResource(this.spine.getTocResource());
+
+ this.spine = spine;
+ }
+
+ /**
+ * Adds a resource to the book's set of resources, table of contents and if there is no resource with the id in the spine also adds it to the spine.
+ *
+ * @param title
+ * @param resource
+ * @return The table of contents
+ */
+ public TOCReference addSection(String title, Resource resource) {
+ getResources().add(resource);
+ TOCReference tocReference = tableOfContents.addTOCReference(new TOCReference(title, resource));
+ if (spine.findFirstResourceById(resource.getId()) < 0) {
+ spine.addSpineReference(new SpineReference(resource));
+ }
+ return tocReference;
+ }
+
+
+ /**
+ * The Book's metadata (titles, authors, etc)
+ *
+ * @return The Book's metadata (titles, authors, etc)
+ */
+ public Metadata getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(Metadata metadata) {
+ this.metadata = metadata;
+ }
+
+
+ public void setResources(Resources resources) {
+ this.resources = resources;
+ }
+
+
+ public Resource addResource(Resource resource) {
+ return resources.add(resource);
+ }
+
+ /**
+ * The collection of all images, chapters, sections, xhtml files, stylesheets, etc that make up the book.
+ *
+ * @return The collection of all images, chapters, sections, xhtml files, stylesheets, etc that make up the book.
+ */
+ public Resources getResources() {
+ return resources;
+ }
+
+
+ /**
+ * The sections of the book that should be shown if a user reads the book from start to finish.
+ *
+ * @return The Spine
+ */
+ public Spine getSpine() {
+ return spine;
+ }
+
+
+ public void setSpine(Spine spine) {
+ this.spine = spine;
+ }
+
+
+ /**
+ * The Table of Contents of the book.
+ *
+ * @return The Table of Contents of the book.
+ */
+ public TableOfContents getTableOfContents() {
+ return tableOfContents;
+ }
+
+
+ public void setTableOfContents(TableOfContents tableOfContents) {
+ this.tableOfContents = tableOfContents;
+ }
+
+ /**
+ * The book's cover page as a Resource.
+ * An XHTML document containing a link to the cover image.
+ *
+ * @return The book's cover page as a Resource
+ */
+ public Resource getCoverPage() {
+ Resource coverPage = guide.getCoverPage();
+ if (coverPage == null) {
+ coverPage = spine.getResource(0);
+ }
+ return coverPage;
+ }
+
+
+ public void setCoverPage(Resource coverPage) {
+ if (coverPage == null) {
+ return;
+ }
+ if (!resources.containsByHref(coverPage.getHref())) {
+ resources.add(coverPage);
+ }
+ guide.setCoverPage(coverPage);
+ }
+
+ /**
+ * Gets the first non-blank title from the book's metadata.
+ *
+ * @return the first non-blank title from the book's metadata.
+ */
+ public String getTitle() {
+ return getMetadata().getFirstTitle();
+ }
+
+
+ /**
+ * The book's cover image.
+ *
+ * @return The book's cover image.
+ */
+ public Resource getCoverImage() {
+ return coverImage;
+ }
+
+ public void setCoverImage(Resource coverImage) {
+ if (coverImage == null) {
+ return;
+ }
+ if (!resources.containsByHref(coverImage.getHref())) {
+ resources.add(coverImage);
+ }
+ this.coverImage = coverImage;
+ }
+
+ /**
+ * The guide; contains references to special sections of the book like colophon, glossary, etc.
+ *
+ * @return The guide; contains references to special sections of the book like colophon, glossary, etc.
+ */
+ public Guide getGuide() {
+ return guide;
+ }
+
+ /**
+ * All Resources of the Book that can be reached via the Spine, the TableOfContents or the Guide.
+ *
+ * Consists of a list of "reachable" resources:
+ *
+ *
The coverpage
+ *
The resources of the Spine that are not already in the result
+ *
The resources of the Table of Contents that are not already in the result
+ *
The resources of the Guide that are not already in the result
+ *
+ * To get all html files that make up the epub file use {@link #getResources()}
+ *
+ * @return All Resources of the Book that can be reached via the Spine, the TableOfContents or the Guide.
+ */
+ public List getContents() {
+ Map result = new LinkedHashMap();
+ addToContentsResult(getCoverPage(), result);
+
+ for (SpineReference spineReference : getSpine().getSpineReferences()) {
+ addToContentsResult(spineReference.getResource(), result);
+ }
+
+ for (Resource resource : getTableOfContents().getAllUniqueResources()) {
+ addToContentsResult(resource, result);
+ }
+
+ for (GuideReference guideReference : getGuide().getReferences()) {
+ addToContentsResult(guideReference.getResource(), result);
+ }
+
+ return new ArrayList(result.values());
+ }
+
+ private static void addToContentsResult(Resource resource, Map allReachableResources) {
+ if (resource != null && (!allReachableResources.containsKey(resource.getHref()))) {
+ allReachableResources.put(resource.getHref(), resource);
+ }
+ }
+
+ public Resource getOpfResource() {
+ return opfResource;
+ }
+
+ public void setOpfResource(Resource opfResource) {
+ this.opfResource = opfResource;
+ }
+
+ public void setNcxResource(Resource ncxResource) {
+ this.ncxResource = ncxResource;
+ }
+
+ public Resource getNcxResource() {
+ return ncxResource;
+ }
+
+ public String getEpubVersion() throws IOException {
+ Resource opfResource = getOpfResource();
+ String opfContent = new String(opfResource.getData());
+ int begin = opfContent.indexOf(" authors = new ArrayList();
- private List contributors = new ArrayList();
- private List dates = new ArrayList();
- private String language = DEFAULT_LANGUAGE;
- private Map otherProperties = new HashMap();
- private List rights = new ArrayList();
- private List titles = new ArrayList();
- private List identifiers = new ArrayList();
- private List subjects = new ArrayList();
- private String format = MediatypeService.EPUB.getName();
- private List types = new ArrayList();
- private List descriptions = new ArrayList();
- private List publishers = new ArrayList();
- private Map metaAttributes = new HashMap();
-
- public Metadata() {
- identifiers.add(new Identifier());
- autoGeneratedId = true;
- }
-
- public boolean isAutoGeneratedId() {
- return autoGeneratedId;
- }
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2437262888962149444L;
- /**
- * Metadata properties not hard-coded like the author, title, etc.
- *
- * @return Metadata properties not hard-coded like the author, title, etc.
- */
- public Map getOtherProperties() {
- return otherProperties;
- }
- public void setOtherProperties(Map otherProperties) {
- this.otherProperties = otherProperties;
- }
-
- public Date addDate(Date date) {
- this.dates.add(date);
- return date;
- }
-
- public List getDates() {
- return dates;
- }
- public void setDates(List dates) {
- this.dates = dates;
- }
+ public static final String DEFAULT_LANGUAGE = "en";
- public Author addAuthor(Author author) {
- authors.add(author);
- return author;
- }
-
- public List getAuthors() {
- return authors;
- }
- public void setAuthors(List authors) {
- this.authors = authors;
- }
-
- public Author addContributor(Author contributor) {
- contributors.add(contributor);
- return contributor;
- }
-
- public List getContributors() {
- return contributors;
- }
- public void setContributors(List contributors) {
- this.contributors = contributors;
- }
-
- public String getLanguage() {
- return language;
- }
- public void setLanguage(String language) {
- this.language = language;
- }
- public List getSubjects() {
- return subjects;
- }
- public void setSubjects(List subjects) {
- this.subjects = subjects;
- }
- public void setRights(List rights) {
- this.rights = rights;
- }
- public List getRights() {
- return rights;
- }
-
-
- /**
- * Gets the first non-blank title of the book.
- * Will return "" if no title found.
- *
- * @return the first non-blank title of the book.
- */
- public String getFirstTitle() {
- if (titles == null || titles.isEmpty()) {
- return "";
- }
- for (String title: titles) {
- if (StringUtil.isNotBlank(title)) {
- return title;
- }
- }
- return "";
- }
-
-
- public String addTitle(String title) {
- this.titles.add(title);
+ private boolean autoGeneratedId = true;
+ private List authors = new ArrayList();
+ private List contributors = new ArrayList();
+ private List dates = new ArrayList();
+ private String language = DEFAULT_LANGUAGE;
+ private Map otherProperties = new HashMap();
+ private List rights = new ArrayList();
+ private List titles = new ArrayList();
+ private List identifiers = new ArrayList();
+ private List subjects = new ArrayList();
+ private String format = MediatypeService.EPUB.getName();
+ private List types = new ArrayList();
+ private List descriptions = new ArrayList();
+ private List publishers = new ArrayList();
+ private Map metaAttributes = new HashMap();
+
+ public Metadata() {
+ identifiers.add(new Identifier());
+ autoGeneratedId = true;
+ }
+
+ public boolean isAutoGeneratedId() {
+ return autoGeneratedId;
+ }
+
+ /**
+ * Metadata properties not hard-coded like the author, title, etc.
+ *
+ * @return Metadata properties not hard-coded like the author, title, etc.
+ */
+ public Map getOtherProperties() {
+ return otherProperties;
+ }
+
+ public void setOtherProperties(Map otherProperties) {
+ this.otherProperties = otherProperties;
+ }
+
+ public Date addDate(Date date) {
+ this.dates.add(date);
+ return date;
+ }
+
+ public List getDates() {
+ return dates;
+ }
+
+ public void setDates(List dates) {
+ this.dates = dates;
+ }
+
+ public Author addAuthor(Author author) {
+ authors.add(author);
+ return author;
+ }
+
+ public List getAuthors() {
+ return authors;
+ }
+
+ public void setAuthors(List authors) {
+ this.authors = authors;
+ }
+
+ public Author addContributor(Author contributor) {
+ contributors.add(contributor);
+ return contributor;
+ }
+
+ public List getContributors() {
+ return contributors;
+ }
+
+ public void setContributors(List contributors) {
+ this.contributors = contributors;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ public String addSubject(String subject) {
+ subjects.add(subject);
+ return subject;
+ }
+
+ public List getSubjects() {
+ return subjects;
+ }
+
+ public void setSubjects(List subjects) {
+ this.subjects = subjects;
+ }
+
+ public void setRights(List rights) {
+ this.rights = rights;
+ }
+
+ public List getRights() {
+ return rights;
+ }
+
+ /**
+ * Gets the first non-blank title of the book. Will return "" if no title found.
+ *
+ * @return the first non-blank title of the book.
+ */
+ public String getFirstTitle() {
+ if (titles == null || titles.isEmpty()) {
+ return "";
+ }
+ for (String title : titles) {
+ if (StringUtil.isNotBlank(title)) {
return title;
+ }
}
- public void setTitles(List titles) {
- this.titles = titles;
- }
- public List getTitles() {
- return titles;
- }
-
- public String addPublisher(String publisher) {
- this.publishers.add(publisher);
- return publisher;
- }
- public void setPublishers(List publishers) {
- this.publishers = publishers;
- }
- public List getPublishers() {
- return publishers;
- }
-
- public String addDescription(String description) {
- this.descriptions.add(description);
- return description;
- }
- public void setDescriptions(List descriptions) {
- this.descriptions = descriptions;
- }
- public List getDescriptions() {
- return descriptions;
- }
-
- public Identifier addIdentifier(Identifier identifier) {
- if (autoGeneratedId && (! (identifiers.isEmpty()))) {
- identifiers.set(0, identifier);
- } else {
- identifiers.add(identifier);
- }
- autoGeneratedId = false;
- return identifier;
- }
- public void setIdentifiers(List identifiers) {
- this.identifiers = identifiers;
- autoGeneratedId = false;
- }
-
- public List getIdentifiers() {
- return identifiers;
- }
- public void setFormat(String format) {
- this.format = format;
- }
- public String getFormat() {
- return format;
- }
+ return "";
+ }
- public String addType(String type) {
- this.types.add(type);
- return type;
- }
-
- public List getTypes() {
- return types;
- }
- public void setTypes(List types) {
- this.types = types;
- }
+ public String addTitle(String title) {
+ this.titles.add(title);
+ return title;
+ }
- public String getMetaAttribute(String name) {
- return metaAttributes.get(name);
- }
+ public void setTitles(List titles) {
+ this.titles = titles;
+ }
- public void setMetaAttributes(Map metaAttributes) {
- this.metaAttributes = metaAttributes;
- }
+ public List getTitles() {
+ return titles;
+ }
+
+ public String addPublisher(String publisher) {
+ this.publishers.add(publisher);
+ return publisher;
+ }
+
+ public void setPublishers(List publishers) {
+ this.publishers = publishers;
+ }
+
+ public List getPublishers() {
+ return publishers;
+ }
+
+ public String addDescription(String description) {
+ this.descriptions.add(description);
+ return description;
+ }
+
+ public void setDescriptions(List descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public List getDescriptions() {
+ return descriptions;
+ }
+
+ public Identifier addIdentifier(Identifier identifier) {
+ if (autoGeneratedId && (!(identifiers.isEmpty()))) {
+ identifiers.set(0, identifier);
+ } else {
+ identifiers.add(identifier);
+ }
+ autoGeneratedId = false;
+ return identifier;
+ }
+
+ public void setIdentifiers(List identifiers) {
+ this.identifiers = identifiers;
+ autoGeneratedId = false;
+ }
+
+ public List getIdentifiers() {
+ return identifiers;
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ public String addType(String type) {
+ this.types.add(type);
+ return type;
+ }
+
+ public List getTypes() {
+ return types;
+ }
+
+ public void setTypes(List types) {
+ this.types = types;
+ }
+
+ public String getMetaAttribute(String name) {
+ return metaAttributes.get(name);
+ }
+
+ public void setMetaAttributes(Map metaAttributes) {
+ this.metaAttributes = metaAttributes;
+ }
}
diff --git a/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriter.java b/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriter.java
index f08d5587..102babcb 100644
--- a/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriter.java
+++ b/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriter.java
@@ -106,7 +106,7 @@ private void writeResource(Resource resource, ZipOutputStream resultStream)
}
- private void writePackageDocument(Book book, ZipOutputStream resultStream) throws IOException {
+ protected void writePackageDocument(Book book, ZipOutputStream resultStream) throws IOException {
resultStream.putNextEntry(new ZipEntry("OEBPS/content.opf"));
XmlSerializer xmlSerializer = EpubProcessorSupport.createXmlSerializer(resultStream);
PackageDocumentWriter.write(this, xmlSerializer, book);
diff --git a/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriter3.java b/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriter3.java
new file mode 100644
index 00000000..9275ddba
--- /dev/null
+++ b/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriter3.java
@@ -0,0 +1,40 @@
+package nl.siegmann.epublib.epub;
+
+import nl.siegmann.epublib.domain.Book;
+import nl.siegmann.epublib.domain.Resource;
+import nl.siegmann.epublib.service.MediatypeService;
+import nl.siegmann.epublib.util.IOUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.*;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Generates an epub file. Not thread-safe, single use object.
+ *
+ * @author paul
+ *
+ */
+public class EpubWriter3 extends EpubWriter {
+
+ public EpubWriter3() {
+ super();
+ }
+
+ public EpubWriter3(BookProcessor bookProcessor) {
+ super(bookProcessor);
+ }
+
+ @Override
+ protected void writePackageDocument(Book book, ZipOutputStream resultStream) throws IOException {
+ resultStream.putNextEntry(new ZipEntry("OEBPS/content.opf"));
+ XmlSerializer xmlSerializer = EpubProcessorSupport.createXmlSerializer(resultStream);
+ PackageDocumentWriter3.write(this, xmlSerializer, book);
+ xmlSerializer.flush();
+ }
+
+}
\ No newline at end of file
diff --git a/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriterFactory.java b/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriterFactory.java
new file mode 100644
index 00000000..53e804a2
--- /dev/null
+++ b/epublib-core/src/main/java/nl/siegmann/epublib/epub/EpubWriterFactory.java
@@ -0,0 +1,22 @@
+package nl.siegmann.epublib.epub;
+
+import nl.siegmann.epublib.domain.Book;
+
+import java.io.IOException;
+
+/**
+ * Created by Juan Francisco RodrÃguez
+ **/
+public class EpubWriterFactory {
+
+ public static EpubWriter createWriter(Book book, BookProcessor bookProcessor) throws IOException {
+ if(book.getEpubVersion().equals("3.0")) {
+ return new EpubWriter3(bookProcessor);
+ }
+ if(book.getEpubVersion().equals("2.0")) {
+ return new EpubWriter(bookProcessor);
+ }
+ return new EpubWriter(bookProcessor);
+ }
+
+}
diff --git a/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentBase.java b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentBase.java
index 564fc289..feb40515 100644
--- a/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentBase.java
+++ b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentBase.java
@@ -9,11 +9,14 @@
*/
public class PackageDocumentBase {
public static final String BOOK_ID_ID = "BookId";
+ public static final String EPUB2 = "2.0";
+ public static final String EPUB3 = "3.0";
public static final String NAMESPACE_OPF = "http://www.idpf.org/2007/opf";
public static final String NAMESPACE_DUBLIN_CORE = "http://purl.org/dc/elements/1.1/";
public static final String PREFIX_DUBLIN_CORE = "dc";
public static final String PREFIX_OPF = "opf";
public static final String dateFormat = "yyyy-MM-dd";
+ public static final String RENDITION_PREFIX = "rendition: http://www.idpf.org/vocab/rendition/# ibooks:http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/";
protected interface DCTags {
String title = "title";
@@ -68,6 +71,8 @@ protected interface OPFAttributes {
String version = "version";
String scheme = "scheme";
String property = "property";
+ String prefix = "prefix";
+ String xmlns = "xmlns";
}
protected interface OPFValues {
diff --git a/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentMetadataWriter3.java b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentMetadataWriter3.java
new file mode 100644
index 00000000..6ff32e59
--- /dev/null
+++ b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentMetadataWriter3.java
@@ -0,0 +1,150 @@
+package nl.siegmann.epublib.epub;
+
+import nl.siegmann.epublib.Constants;
+import nl.siegmann.epublib.domain.Author;
+import nl.siegmann.epublib.domain.Book;
+import nl.siegmann.epublib.domain.Date;
+import nl.siegmann.epublib.domain.Identifier;
+import nl.siegmann.epublib.util.StringUtil;
+import org.xmlpull.v1.XmlSerializer;
+
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class PackageDocumentMetadataWriter3 extends PackageDocumentBase {
+
+
+ /**
+ * Writes the book's metadata.
+ *
+ * @param book
+ * @param serializer
+ * @throws IOException
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ */
+ public static void writeMetaData(Book book, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ serializer.setPrefix(PREFIX_DUBLIN_CORE, NAMESPACE_DUBLIN_CORE);
+ serializer.setPrefix(PREFIX_OPF, NAMESPACE_OPF);
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.metadata);
+
+ writeIdentifiers(book.getMetadata().getIdentifiers(), serializer);
+ writeSimpleMetdataElements(DCTags.title, book.getMetadata().getTitles(), serializer);
+ writeSimpleMetdataElements(DCTags.subject, book.getMetadata().getSubjects(), serializer);
+ writeSimpleMetdataElements(DCTags.description, book.getMetadata().getDescriptions(), serializer);
+ writeSimpleMetdataElements(DCTags.publisher, book.getMetadata().getPublishers(), serializer);
+ writeSimpleMetdataElements(DCTags.type, book.getMetadata().getTypes(), serializer);
+ writeSimpleMetdataElements(DCTags.rights, book.getMetadata().getRights(), serializer);
+
+ // write authors
+ for(Author author: book.getMetadata().getAuthors()) {
+ serializer.startTag(NAMESPACE_DUBLIN_CORE, DCTags.creator);
+ serializer.attribute(NAMESPACE_OPF, OPFAttributes.role, author.getRelator().getCode());
+ serializer.attribute(NAMESPACE_OPF, OPFAttributes.file_as, author.getLastname() + ", " + author.getFirstname());
+ serializer.text(author.getFirstname() + " " + author.getLastname());
+ serializer.endTag(NAMESPACE_DUBLIN_CORE, DCTags.creator);
+ }
+
+ // write contributors
+ for(Author author: book.getMetadata().getContributors()) {
+ serializer.startTag(NAMESPACE_DUBLIN_CORE, DCTags.contributor);
+ serializer.attribute(NAMESPACE_OPF, OPFAttributes.role, author.getRelator().getCode());
+ serializer.attribute(NAMESPACE_OPF, OPFAttributes.file_as, author.getLastname() + ", " + author.getFirstname());
+ serializer.text(author.getFirstname() + " " + author.getLastname());
+ serializer.endTag(NAMESPACE_DUBLIN_CORE, DCTags.contributor);
+ }
+
+ // write dates
+ for (Date date: book.getMetadata().getDates()) {
+ serializer.startTag(NAMESPACE_DUBLIN_CORE, DCTags.date);
+ if (date.getEvent() != null) {
+ serializer.attribute(NAMESPACE_OPF, OPFAttributes.event, date.getEvent().toString());
+ }
+ serializer.text(date.getValue());
+ serializer.endTag(NAMESPACE_DUBLIN_CORE, DCTags.date);
+ }
+
+ // write language
+ if(StringUtil.isNotBlank(book.getMetadata().getLanguage())) {
+ serializer.startTag(NAMESPACE_DUBLIN_CORE, "language");
+ serializer.text(book.getMetadata().getLanguage());
+ serializer.endTag(NAMESPACE_DUBLIN_CORE, "language");
+ }
+
+ // write other properties
+ if(book.getMetadata().getOtherProperties() != null) {
+ for(Map.Entry mapEntry: book.getMetadata().getOtherProperties().entrySet()) {
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.meta);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.property, mapEntry.getKey().getLocalPart());
+ serializer.text(mapEntry.getValue());
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.meta);
+ }
+ }
+
+ // write coverimage
+ if(book.getCoverImage() != null) { // write the cover image
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.meta);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.name, OPFValues.meta_cover);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.content, book.getCoverImage().getId());
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.meta);
+ }
+
+ // write generator
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.meta);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.name, OPFValues.generator);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.content, Constants.EPUBLIB_GENERATOR_NAME);
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.meta);
+
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.metadata);
+ }
+
+ private static void writeSimpleMetdataElements(String tagName, List values, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ for(String value: values) {
+ if (StringUtil.isBlank(value)) {
+ continue;
+ }
+ serializer.startTag(NAMESPACE_DUBLIN_CORE, tagName);
+ serializer.text(value);
+ serializer.endTag(NAMESPACE_DUBLIN_CORE, tagName);
+ }
+ }
+
+
+ /**
+ * Writes out the complete list of Identifiers to the package document.
+ * The first identifier for which the bookId is true is made the bookId identifier.
+ * If no identifier has bookId == true then the first bookId identifier is written as the primary.
+ *
+ * @param identifiers
+ * @param serializer
+ * @throws IOException
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @
+ */
+ private static void writeIdentifiers(List identifiers, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ Identifier bookIdIdentifier = Identifier.getBookIdIdentifier(identifiers);
+ if(bookIdIdentifier == null) {
+ return;
+ }
+
+ serializer.startTag(NAMESPACE_DUBLIN_CORE, DCTags.identifier);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, DCAttributes.id, BOOK_ID_ID);
+ serializer.attribute(NAMESPACE_OPF, OPFAttributes.scheme, bookIdIdentifier.getScheme());
+ serializer.text(bookIdIdentifier.getValue());
+ serializer.endTag(NAMESPACE_DUBLIN_CORE, DCTags.identifier);
+
+ for(Identifier identifier: identifiers.subList(1, identifiers.size())) {
+ if(identifier == bookIdIdentifier) {
+ continue;
+ }
+ serializer.startTag(NAMESPACE_DUBLIN_CORE, DCTags.identifier);
+ serializer.attribute(NAMESPACE_OPF, "scheme", identifier.getScheme());
+ serializer.text(identifier.getValue());
+ serializer.endTag(NAMESPACE_DUBLIN_CORE, DCTags.identifier);
+ }
+ }
+
+}
diff --git a/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentWriter.java b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentWriter.java
index bcd62607..445ef693 100644
--- a/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentWriter.java
+++ b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentWriter.java
@@ -39,6 +39,7 @@ public static void write(EpubWriter epubWriter, XmlSerializer serializer, Book b
serializer.setPrefix(PREFIX_OPF, NAMESPACE_OPF);
serializer.setPrefix(PREFIX_DUBLIN_CORE, NAMESPACE_DUBLIN_CORE);
serializer.startTag(NAMESPACE_OPF, OPFTags.packageTag);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.xmlns, NAMESPACE_OPF);
serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.version, "2.0");
serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.uniqueIdentifier, BOOK_ID_ID);
diff --git a/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentWriter3.java b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentWriter3.java
new file mode 100644
index 00000000..23638d73
--- /dev/null
+++ b/epublib-core/src/main/java/nl/siegmann/epublib/epub/PackageDocumentWriter3.java
@@ -0,0 +1,196 @@
+package nl.siegmann.epublib.epub;
+
+import nl.siegmann.epublib.Constants;
+import nl.siegmann.epublib.domain.*;
+import nl.siegmann.epublib.service.MediatypeService;
+import nl.siegmann.epublib.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+
+/**
+ * Writes the opf package document as defined by namespace http://www.idpf.org/2007/opf
+ *
+ * @author paul
+ *
+ */
+public class PackageDocumentWriter3 extends PackageDocumentBase {
+
+ private static final Logger log = LoggerFactory.getLogger(PackageDocumentWriter3.class);
+
+ public static void write(EpubWriter3 epubWriter, XmlSerializer serializer, Book book) throws IOException {
+ try {
+ serializer.startDocument(Constants.CHARACTER_ENCODING, false);
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.packageTag);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.xmlns, NAMESPACE_OPF);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.version, EPUB3);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.uniqueIdentifier, BOOK_ID_ID);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.prefix, RENDITION_PREFIX);
+
+ PackageDocumentMetadataWriter3.writeMetaData(book, serializer);
+
+ writeManifest(book, epubWriter, serializer);
+ writeSpine(book, epubWriter, serializer);
+ writeGuide(book, epubWriter, serializer);
+
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.packageTag);
+ serializer.endDocument();
+ serializer.flush();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Writes the package's spine.
+ *
+ * @param book
+ * @param epubWriter
+ * @param serializer
+ * @throws IOException
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @throws XMLStreamException
+ */
+ private static void writeSpine(Book book, EpubWriter3 epubWriter, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.spine);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.toc, book.getSpine().getTocResource().getId());
+
+ if(book.getCoverPage() != null // there is a cover page
+ && book.getSpine().findFirstResourceById(book.getCoverPage().getId()) < 0) { // cover page is not already in the spine
+ // write the cover html file
+ serializer.startTag(NAMESPACE_OPF, OPFTags.itemref);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.idref, book.getCoverPage().getId());
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.linear, "no");
+ serializer.endTag(NAMESPACE_OPF, OPFTags.itemref);
+ }
+ writeSpineItems(book.getSpine(), serializer);
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.spine);
+ }
+
+
+ private static void writeManifest(Book book, EpubWriter3 epubWriter, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.manifest);
+
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.item);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.id, epubWriter.getNcxId());
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.href, epubWriter.getNcxHref());
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.media_type, epubWriter.getNcxMediaType());
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.item);
+
+// writeCoverResources(book, serializer);
+
+ for(Resource resource: getAllResourcesSortById(book)) {
+ writeItem(book, resource, serializer);
+ }
+
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.manifest);
+ }
+
+ private static List getAllResourcesSortById(Book book) {
+ List allResources = new ArrayList(book.getResources().getAll());
+ Collections.sort(allResources, new Comparator() {
+
+ @Override
+ public int compare(Resource resource1, Resource resource2) {
+ return resource1.getId().compareToIgnoreCase(resource2.getId());
+ }
+ });
+ return allResources;
+ }
+
+ /**
+ * Writes a resources as an item element
+ * @param resource
+ * @param serializer
+ * @throws IOException
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @throws XMLStreamException
+ */
+ private static void writeItem(Book book, Resource resource, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ if(resource == null ||
+ (resource.getMediaType() == MediatypeService.NCX
+ && book.getSpine().getTocResource() != null)) {
+ return;
+ }
+ if(StringUtil.isBlank(resource.getId())) {
+ log.error("resource id must not be empty (href: " + resource.getHref() + ", mediatype:" + resource.getMediaType() + ")");
+ return;
+ }
+ if(StringUtil.isBlank(resource.getHref())) {
+ log.error("resource href must not be empty (id: " + resource.getId() + ", mediatype:" + resource.getMediaType() + ")");
+ return;
+ }
+ if(resource.getMediaType() == null) {
+ log.error("resource mediatype must not be empty (id: " + resource.getId() + ", href:" + resource.getHref() + ")");
+ return;
+ }
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.item);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.id, resource.getId());
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.href, resource.getHref());
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.media_type, resource.getMediaType().getName());
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.item);
+ }
+
+ /**
+ * List all spine references
+ * @throws IOException
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ */
+ private static void writeSpineItems(Spine spine, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ for(SpineReference spineReference: spine.getSpineReferences()) {
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.itemref);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.idref, spineReference.getResourceId());
+ if (! spineReference.isLinear()) {
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.linear, OPFValues.no);
+ }
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.itemref);
+ }
+ }
+
+ private static void writeGuide(Book book, EpubWriter3 epubWriter, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.guide);
+ ensureCoverPageGuideReferenceWritten(book.getGuide(), epubWriter, serializer);
+ for (GuideReference reference: book.getGuide().getReferences()) {
+ writeGuideReference(reference, serializer);
+ }
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.guide);
+ }
+
+ private static void ensureCoverPageGuideReferenceWritten(Guide guide,
+ EpubWriter3 epubWriter, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ if (! (guide.getGuideReferencesByType(GuideReference.COVER).isEmpty())) {
+ return;
+ }
+ Resource coverPage = guide.getCoverPage();
+ if (coverPage != null) {
+ writeGuideReference(new GuideReference(guide.getCoverPage(), GuideReference.COVER, GuideReference.COVER), serializer);
+ }
+ }
+
+
+ private static void writeGuideReference(GuideReference reference, XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException {
+ if (reference == null) {
+ return;
+ }
+ serializer.startTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.reference);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.type, reference.getType());
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.href, reference.getCompleteHref());
+ if (StringUtil.isNotBlank(reference.getTitle())) {
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.title, reference.getTitle());
+ }
+ serializer.endTag(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFTags.reference);
+ }
+}
\ No newline at end of file
diff --git a/epublib-parent/target/epublib-parent-3.1.pom b/epublib-parent/target/epublib-parent-3.1.pom
deleted file mode 100644
index 8dc6e8a3..00000000
--- a/epublib-parent/target/epublib-parent-3.1.pom
+++ /dev/null
@@ -1,135 +0,0 @@
-
-
-
-
- 4.0.0
-
- nl.siegmann.epublib
- epublib-parent
- epublib-parent
- pom
- 3.1
- A java library for reading/writing/manipulating epub files
- http://www.siegmann.nl/epublib
- 2009
-
-
- UTF-8
- 1.6.1
-
-
-
- ../epublib-core
- ../epublib-tools
-
-
-
-
- LGPL
- http://www.gnu.org/licenses/lgpl.html
- repo
-
-
-
-
-
- paul
- Paul Siegmann
- paul.siegmann+epublib@gmail.com
- http://www.siegmann.nl/
- +1
-
-
-
-
- github
- http://github.com/psiegman/epublib/issues
-
-
-
-
- github.repo
- file:///D:/private/project/git-maven-repo/mvn-repo/releases
-
-
-
-
- http://github.com/psiegman/epublib
- scm:git:https://psiegman@github.com/psiegman/epublib.git
- scm:git:https://psiegman@github.com/psiegman/epublib.git
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 2.3.2
-
- 1.6
- 1.6
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.1.2
-
-
- attach-sources
-
- jar
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.9.1
-
-
- attach-javadocs
-
- jar
-
-
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.5
-
-
- sign-artifacts
- verify
-
- sign
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-site-plugin
- 3.0-beta-3
-
-
-
-
-
- maven
- http://repo1.maven.org/maven2/
-
-
- jboss
- https://repository.jboss.org/nexus/
-
-
-