package org.zwobble.mammoth.internal.docx; import org.zwobble.mammoth.internal.documents.NumberingLevel; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import static org.zwobble.mammoth.internal.util.Maps.lookup; import static org.zwobble.mammoth.internal.util.Maps.map; public class Numbering { public static class AbstractNum { private final Map levels; private final Optional numStyleLink; public AbstractNum(Map levels, Optional numStyleLink) { this.levels = levels; this.numStyleLink = numStyleLink; } } public static class AbstractNumLevel { public static AbstractNumLevel ordered(String levelIndex) { return new AbstractNumLevel(levelIndex, true, Optional.empty()); } public static AbstractNumLevel unordered(String levelIndex) { return new AbstractNumLevel(levelIndex, false, Optional.empty()); } private final String levelIndex; private final boolean isOrdered; private final Optional paragraphStyleId; public AbstractNumLevel(String levelIndex, boolean isOrdered, Optional paragraphStyleId) { this.levelIndex = levelIndex; this.isOrdered = isOrdered; this.paragraphStyleId = paragraphStyleId; } public NumberingLevel toNumberingLevel() { return new NumberingLevel(levelIndex, isOrdered); } } public static class Num { private final Optional abstractNumId; public Num(Optional abstractNumId) { this.abstractNumId = abstractNumId; } } public static final Numbering EMPTY = new Numbering(map(), map(), Styles.EMPTY); private final Map abstractNums; private final Map levelsByParagraphStyleId; private final Map nums; private final Styles styles; public Numbering( Map abstractNums, Map nums, Styles styles ) { this.abstractNums = abstractNums; this.levelsByParagraphStyleId = abstractNums.values().stream() .flatMap(abstractNum -> abstractNum.levels.values().stream()) .filter(level -> level.paragraphStyleId.isPresent()) .collect(Collectors.toMap(level -> level.paragraphStyleId.get(), level -> level)); this.nums = nums; this.styles = styles; } public Optional findLevel(String numId, String level) { return lookup(nums, numId) .flatMap(num -> num.abstractNumId) .flatMap(abstractNumId -> lookup(this.abstractNums, abstractNumId)) .flatMap(abstractNum -> { if (abstractNum.numStyleLink.isPresent()) { return abstractNum.numStyleLink .flatMap(numStyleLink -> styles.findNumberingStyleById(numStyleLink)) .flatMap(style -> style.getNumId()) .flatMap(linkedNumId -> findLevel(linkedNumId, level)); } else { return lookup(abstractNum.levels, level).map(value -> value.toNumberingLevel()); } }); } public Optional findLevelByParagraphStyleId(String styleId) { return lookup(levelsByParagraphStyleId, styleId).map(value -> value.toNumberingLevel()); } }