aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-02-24 08:16:16 +0000
committerMichael Williamson <mike@zwobble.org>2016-02-24 08:16:16 +0000
commit3e2786a004eddf968a5fa7d5a92dff5b1b5f7734 (patch)
tree7fa1bcc1e484cd0ef782f64baf504ee83333d397 /src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java
parent0dc3a12affc2e46c1a0df2899cf51a1ae3fdbd61 (diff)
Create internal package
Diffstat (limited to 'src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java')
-rw-r--r--src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java329
1 files changed, 0 insertions, 329 deletions
diff --git a/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java b/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java
deleted file mode 100644
index 9a1f95b..0000000
--- a/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java
+++ /dev/null
@@ -1,329 +0,0 @@
-package org.zwobble.mammoth.docx;
-
-import com.google.common.collect.ImmutableSet;
-import org.zwobble.mammoth.documents.*;
-import org.zwobble.mammoth.results.Result;
-import org.zwobble.mammoth.results.Warning;
-import org.zwobble.mammoth.util.InputStreamSupplier;
-import org.zwobble.mammoth.util.MammothOptionals;
-import org.zwobble.mammoth.xml.XmlElement;
-import org.zwobble.mammoth.xml.XmlElementLike;
-import org.zwobble.mammoth.xml.XmlElementList;
-import org.zwobble.mammoth.xml.XmlNode;
-
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static org.zwobble.mammoth.docx.ReadResult.EMPTY_SUCCESS;
-import static org.zwobble.mammoth.docx.ReadResult.success;
-import static org.zwobble.mammoth.results.Warning.warning;
-import static org.zwobble.mammoth.util.MammothLists.list;
-import static org.zwobble.mammoth.util.MammothStrings.trimLeft;
-
-public class BodyXmlReader {
- private static final Set<String> IMAGE_TYPES_SUPPORTED_BY_BROWSERS = ImmutableSet.of(
- "image/png", "image/gif", "image/jpeg", "image/svg+xml", "image/tiff");
-
- private final Styles styles;
- private final Numbering numbering;
- private final Relationships relationships;
- private final ContentTypes contentTypes;
- private final DocxFile file;
- private final FileReader fileReader;
-
- public BodyXmlReader(
- Styles styles,
- Numbering numbering,
- Relationships relationships,
- ContentTypes contentTypes,
- DocxFile file,
- FileReader fileReader)
- {
- this.styles = styles;
- this.numbering = numbering;
- this.relationships = relationships;
- this.contentTypes = contentTypes;
- this.file = file;
- this.fileReader = fileReader;
- }
-
- public ReadResult readElement(XmlElement element) {
- switch (element.getName()) {
- case "w:t":
- return success(new Text(element.innerText()));
- case "w:r":
- return readRun(element);
- case "w:p":
- return readParagraph(element);
-
- case "w:tab":
- return success(Tab.TAB);
- case "w:br":
- return readBreak(element);
-
- case "w:tbl":
- return readElements(element.children()).map(Table::new);
- case "w:tr":
- return readElements(element.children()).map(TableRow::new);
- case "w:tc":
- return readElements(element.children()).map(TableCell::new);
-
- case "w:hyperlink":
- return readHyperlink(element);
- case "w:bookmarkStart":
- return readBookmark(element);
- case "w:footnoteReference":
- return readNoteReference(NoteType.FOOTNOTE, element);
- case "w:endnoteReference":
- return readNoteReference(NoteType.ENDNOTE, element);
-
- case "w:pict":
- return readPict(element);
-
- case "v:imagedata":
- return readImagedata(element);
-
- case "wp:inline":
- case "wp:anchor":
- return readInline(element);
-
- case "w:ins":
- case "w:smartTag":
- case "w:drawing":
- case "v:roundrect":
- case "v:shape":
- case "v:textbox":
- case "w:txbxContent":
- return readElements(element.children());
-
- case "office-word:wrap":
- case "v:shadow":
- case "v:shapetype":
- case "w:bookmarkEnd":
- case "w:sectPr":
- case "w:proofErr":
- case "w:lastRenderedPageBreak":
- case "w:commentRangeStart":
- case "w:commentRangeEnd":
- case "w:commentReference":
- case "w:del":
- case "w:footnoteRef":
- case "w:endnoteRef":
- case "w:pPr":
- case "w:rPr":
- case "w:tblPr":
- case "w:tblGrid":
- case "w:tcPr":
- return EMPTY_SUCCESS;
-
- default:
- Warning warning = warning("An unrecognised element was ignored: " + element.getName());
- return ReadResult.emptyWithWarning(warning);
- }
- }
-
- private ReadResult readRun(XmlElement element) {
- XmlElementLike properties = element.findChildOrEmpty("w:rPr");
- return ReadResult.map(
- readRunStyle(properties),
- readElements(element.children()),
- (style, children) -> new Run(
- isBold(properties),
- isItalic(properties),
- isUnderline(properties),
- isStrikethrough(properties),
- readVerticalAlignment(properties),
- style,
- children));
- }
-
- private boolean isBold(XmlElementLike properties) {
- return properties.hasChild("w:b");
- }
-
- private boolean isItalic(XmlElementLike properties) {
- return properties.hasChild("w:i");
- }
-
- private boolean isUnderline(XmlElementLike properties) {
- return properties.hasChild("w:u");
- }
-
- private boolean isStrikethrough(XmlElementLike properties) {
- return properties.hasChild("w:strike");
- }
-
- private VerticalAlignment readVerticalAlignment(XmlElementLike properties) {
- String verticalAlignment = readVal(properties, "w:vertAlign").orElse("");
- switch (verticalAlignment) {
- case "superscript":
- return VerticalAlignment.SUPERSCRIPT;
- case "subscript":
- return VerticalAlignment.SUBSCRIPT;
- default:
- // TODO: warn if set?
- return VerticalAlignment.BASELINE;
- }
- }
-
- private Result<Optional<Style>> readRunStyle(XmlElementLike properties) {
- return readStyle(properties, "w:rStyle", "Run", styles::findCharacterStyleById);
- }
-
- public ReadResult readElements(Iterable<XmlNode> nodes) {
- return ReadResult.concat(
- transform(
- filter(nodes, XmlElement.class),
- this::readElement));
- }
-
- private ReadResult readParagraph(XmlElement element) {
- XmlElementLike properties = element.findChildOrEmpty("w:pPr");
- Optional<NumberingLevel> numbering = readNumbering(properties);
- return ReadResult.map(
- readParagraphStyle(properties),
- readElements(element.children()),
- (style, children) -> new Paragraph(style, numbering, children)).appendExtra();
- }
-
- private Result<Optional<Style>> readParagraphStyle(XmlElementLike properties) {
- return readStyle(properties, "w:pStyle", "Paragraph", styles::findParagraphStyleById);
- }
-
- private Result<Optional<Style>> readStyle(
- XmlElementLike properties,
- String styleTagName,
- String styleType,
- Function<String, Optional<Style>> findStyleById)
- {
- return readVal(properties, styleTagName)
- .map(styleId -> findStyleById(styleType, styleId, findStyleById))
- .orElse(Result.empty());
- }
-
- private Result<Optional<Style>> findStyleById(
- String styleType,
- String styleId,
- Function<String, Optional<Style>> findStyleById)
- {
- Optional<Style> style = findStyleById.apply(styleId);
- if (style.isPresent()) {
- return Result.success(style);
- } else {
- return new Result<>(
- Optional.of(new Style(styleId, Optional.empty())),
- list(warning(styleType + " style with ID " + styleId + " was referenced but not defined in the document")));
- }
-
- }
-
- private Optional<NumberingLevel> readNumbering(XmlElementLike properties) {
- XmlElementLike numberingProperties = properties.findChildOrEmpty("w:numPr");
- return MammothOptionals.flatMap(
- readVal(numberingProperties, "w:numId"),
- readVal(numberingProperties, "w:ilvl"),
- numbering::findLevel);
- }
-
- private ReadResult readBreak(XmlElement element) {
- String breakType = element.getAttributeOrNone("w:type").orElse("");
- if (breakType.equals("")) {
- return success(LineBreak.LINE_BREAK);
- } else {
- return ReadResult.emptyWithWarning(warning("Unsupported break type: " + breakType));
- }
- }
-
- private ReadResult readHyperlink(XmlElement element) {
- Optional<String> relationshipId = element.getAttributeOrNone("r:id");
- Optional<String> anchor = element.getAttributeOrNone("w:anchor");
- ReadResult childrenResult = readElements(element.children());
- if (relationshipId.isPresent()) {
- return childrenResult.map(children -> Hyperlink.href(
- relationships.findRelationshipById(relationshipId.get()).getTarget(), children));
- } else if (anchor.isPresent()) {
- return childrenResult.map(children -> Hyperlink.anchor(
- anchor.get(), children));
- } else {
- return childrenResult;
- }
- }
-
- private ReadResult readBookmark(XmlElement element) {
- String name = element.getAttribute("w:name");
- if (name.equals("_GoBack")) {
- return ReadResult.EMPTY_SUCCESS;
- } else {
- return success(new Bookmark(name));
- }
- }
-
- private ReadResult readNoteReference(NoteType noteType, XmlElement element) {
- String noteId = element.getAttribute("w:id");
- return success(new NoteReference(noteType, noteId));
- }
-
- private ReadResult readPict(XmlElement element) {
- return readElements(element.children()).toExtra();
- }
-
- private ReadResult readImagedata(XmlElement element) {
- Optional<String> title = element.getAttributeOrNone("o:title");
- String relationshipId = element.getAttribute("r:id");
- String imagePath = relationshipIdToDocxPath(relationshipId);
- return readImage(imagePath, title, () -> DocxFile.getInputStream(file, imagePath));
- }
-
- private ReadResult readInline(XmlElement element) {
- Optional<String> altText = element.findChildOrEmpty("wp:docPr").getAttributeOrNone("descr");
- XmlElementList blips = element.findChildren("a:graphic")
- .findChildren("a:graphicData")
- .findChildren("pic:pic")
- .findChildren("pic:blipFill")
- .findChildren("a:blip");
- return readBlips(blips, altText);
- }
-
- private ReadResult readBlips(XmlElementList blips, Optional<String> altText) {
- return ReadResult.concat(transform(blips, blip -> readBlip(blip, altText)));
- }
-
- private ReadResult readBlip(XmlElement blip, Optional<String> altText) {
- Optional<String> embedRelationshipId = blip.getAttributeOrNone("r:embed");
- Optional<String> linkRelationshipId = blip.getAttributeOrNone("r:link");
- if (embedRelationshipId.isPresent()) {
- String imagePath = relationshipIdToDocxPath(embedRelationshipId.get());
- return readImage(imagePath, altText, () -> DocxFile.getInputStream(file, imagePath));
- } else if (linkRelationshipId.isPresent()) {
- String imagePath = relationships.findRelationshipById(linkRelationshipId.get()).getTarget();
- return readImage(imagePath, altText, () -> fileReader.getInputStream(imagePath));
- } else {
- // TODO: emit warning
- return ReadResult.EMPTY_SUCCESS;
- }
- }
-
- private ReadResult readImage(String imagePath, Optional<String> altText, InputStreamSupplier open) {
- Optional<String> contentType = contentTypes.findContentType(imagePath);
- Image image = new Image(altText, contentType, open);
-
- String contentTypeString = contentType.orElse("(unknown)");
- if (IMAGE_TYPES_SUPPORTED_BY_BROWSERS.contains(contentTypeString)) {
- return success(image);
- } else {
- return ReadResult.withWarning(image, warning("Image of type " + contentTypeString + " is unlikely to display in web browsers"));
- }
- }
-
- private String relationshipIdToDocxPath(String relationshipId) {
- Relationship relationship = relationships.findRelationshipById(relationshipId);
- return "word/" + trimLeft(relationship.getTarget(), '/');
- }
-
- private Optional<String> readVal(XmlElementLike element, String name) {
- return element.findChildOrEmpty(name).getAttributeOrNone("w:val");
- }
-}