From 853ed35d873b5a3e95d5d332ffeb2211f772edfe Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Thu, 31 Dec 2015 17:22:57 +0000 Subject: Add reading of numbering.xml --- .../zwobble/mammoth/documents/NumberingLevel.java | 19 ++++++++ .../java/org/zwobble/mammoth/docx/Numbering.java | 19 ++++++++ .../org/zwobble/mammoth/docx/NumberingXml.java | 56 ++++++++++++++++++++++ .../org/zwobble/mammoth/xml/NullXmlElement.java | 20 ++++++++ .../java/org/zwobble/mammoth/xml/XmlElement.java | 28 +++++++++-- .../org/zwobble/mammoth/xml/XmlElementLike.java | 8 ++++ 6 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/zwobble/mammoth/documents/NumberingLevel.java create mode 100644 src/main/java/org/zwobble/mammoth/docx/Numbering.java create mode 100644 src/main/java/org/zwobble/mammoth/docx/NumberingXml.java create mode 100644 src/main/java/org/zwobble/mammoth/xml/NullXmlElement.java create mode 100644 src/main/java/org/zwobble/mammoth/xml/XmlElementLike.java (limited to 'src/main') diff --git a/src/main/java/org/zwobble/mammoth/documents/NumberingLevel.java b/src/main/java/org/zwobble/mammoth/documents/NumberingLevel.java new file mode 100644 index 0000000..ca134b9 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/documents/NumberingLevel.java @@ -0,0 +1,19 @@ +package org.zwobble.mammoth.documents; + +public class NumberingLevel { + private final String levelIndex; + private final boolean isOrdered; + + public NumberingLevel(String levelIndex, boolean isOrdered) { + this.levelIndex = levelIndex; + this.isOrdered = isOrdered; + } + + public String getLevelIndex() { + return levelIndex; + } + + public boolean isOrdered() { + return isOrdered; + } +} diff --git a/src/main/java/org/zwobble/mammoth/docx/Numbering.java b/src/main/java/org/zwobble/mammoth/docx/Numbering.java new file mode 100644 index 0000000..43b3e56 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/docx/Numbering.java @@ -0,0 +1,19 @@ +package org.zwobble.mammoth.docx; + +import org.zwobble.mammoth.documents.NumberingLevel; + +import java.util.Map; +import java.util.Optional; + +public class Numbering { + private final Map> numbering; + + public Numbering(Map> numbering) { + this.numbering = numbering; + } + + public Optional findLevel(String numId, String level) { + return Optional.ofNullable(numbering.get(numId)) + .flatMap(levels -> Optional.ofNullable(levels.get(level))); + } +} diff --git a/src/main/java/org/zwobble/mammoth/docx/NumberingXml.java b/src/main/java/org/zwobble/mammoth/docx/NumberingXml.java new file mode 100644 index 0000000..9c3e286 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/docx/NumberingXml.java @@ -0,0 +1,56 @@ +package org.zwobble.mammoth.docx; + +import org.zwobble.mammoth.documents.NumberingLevel; +import org.zwobble.mammoth.xml.XmlElement; +import org.zwobble.mammoth.xml.XmlElementList; + +import java.util.Map; +import java.util.Optional; + +import static com.google.common.collect.Maps.immutableEntry; +import static org.zwobble.mammoth.util.MammothMaps.toMap; + +public class NumberingXml { + public static Numbering readNumberingXmlElement(XmlElement element) { + Map> abstractNums = readAbstractNums(element.findChildren("w:abstractNum")); + return new Numbering(readNums(element.findChildren("w:num"), abstractNums)); + } + + private static Map> readAbstractNums(XmlElementList children) { + return toMap(children, NumberingXml::readAbstractNum); + } + + private static Map.Entry> readAbstractNum(XmlElement element) { + // TODO: in python-mammoth, we allow None here. Check whether that's actually possible or not + String abstractNumId = element.getAttribute("w:abstractNumId"); + return immutableEntry(abstractNumId, readAbstractNumLevels(element)); + } + + private static Map readAbstractNumLevels(XmlElement element) { + return toMap(element.findChildren("w:lvl"), NumberingXml::readAbstractNumLevel); + } + + private static Map.Entry readAbstractNumLevel(XmlElement element) { + String levelIndex = element.getAttribute("w:ilvl"); + Optional numFmt = element.findChildOrEmpty("w:numFmt").getAttributeOrNone("w:val"); + boolean isOrdered = !numFmt.equals(Optional.of("bullet")); + return immutableEntry(levelIndex, new NumberingLevel(levelIndex, isOrdered)); + } + + private static Map> readNums( + XmlElementList numElements, + Map> abstractNums + ) { + return toMap(numElements, numElement -> readNum(numElement, abstractNums)); + } + + private static Map.Entry> readNum( + XmlElement numElement, + Map> abstractNums + ) { + // TODO: in python-mammoth, we allow None here. Check whether that's actually possible or not + String numId = numElement.getAttribute("w:numId"); + String abstractNumId = numElement.findChild("w:abstractNumId").getAttribute("w:val"); + return immutableEntry(numId, Optional.ofNullable(abstractNums.get(abstractNumId)).get()); + } +} diff --git a/src/main/java/org/zwobble/mammoth/xml/NullXmlElement.java b/src/main/java/org/zwobble/mammoth/xml/NullXmlElement.java new file mode 100644 index 0000000..05bfa78 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/xml/NullXmlElement.java @@ -0,0 +1,20 @@ +package org.zwobble.mammoth.xml; + +import java.util.Optional; + +public class NullXmlElement implements XmlElementLike { + public static final XmlElementLike INSTANCE = new NullXmlElement(); + + private NullXmlElement() { + } + + @Override + public XmlElementLike findChildOrEmpty(String name) { + return this; + } + + @Override + public Optional getAttributeOrNone(String name) { + return Optional.empty(); + } +} diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlElement.java b/src/main/java/org/zwobble/mammoth/xml/XmlElement.java index a42a1b7..8c3a011 100644 --- a/src/main/java/org/zwobble/mammoth/xml/XmlElement.java +++ b/src/main/java/org/zwobble/mammoth/xml/XmlElement.java @@ -2,15 +2,15 @@ package org.zwobble.mammoth.xml; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; import java.util.List; import java.util.Map; import java.util.Optional; import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getFirst; -public class XmlElement implements XmlNode { +public class XmlElement implements XmlNode, XmlElementLike { public XmlElement(String name) { this(name, ImmutableMap.of()); } @@ -39,7 +39,12 @@ public class XmlElement implements XmlNode { public String getAttribute(String name) { // TODO: throw more informative error message - return Optional.ofNullable(attributes.get(name)).get(); + return getAttributeOrNone(name).get(); + } + + @Override + public Optional getAttributeOrNone(String name) { + return Optional.ofNullable(attributes.get(name)); } public List getChildren() { @@ -62,9 +67,22 @@ public class XmlElement implements XmlNode { } public XmlElementList findChildren(String name) { - Iterable filtered = filter( + Iterable filtered = findChildrenIterable(name); + return new XmlElementList(ImmutableList.copyOf(filtered)); + } + + public XmlElement findChild(String name) { + return findChildrenIterable(name).iterator().next(); + } + + @Override + public XmlElementLike findChildOrEmpty(String name) { + return getFirst(findChildrenIterable(name), NullXmlElement.INSTANCE); + } + + private Iterable findChildrenIterable(String name) { + return filter( filter(children, XmlElement.class), child -> child.getName().equals(name)); - return new XmlElementList(ImmutableList.copyOf(filtered)); } } diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlElementLike.java b/src/main/java/org/zwobble/mammoth/xml/XmlElementLike.java new file mode 100644 index 0000000..06193a7 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/xml/XmlElementLike.java @@ -0,0 +1,8 @@ +package org.zwobble.mammoth.xml; + +import java.util.Optional; + +public interface XmlElementLike { + XmlElementLike findChildOrEmpty(String name); + Optional getAttributeOrNone(String name); +} -- cgit v1.2.3