SectionUtil.java
package pro.verron.officestamper.core;
import org.docx4j.XmlUtils;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.P;
import org.docx4j.wml.PPr;
import org.docx4j.wml.SectPr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.verron.officestamper.api.OfficeStamperException;
import pro.verron.officestamper.utils.WmlFactory;
import java.util.List;
import java.util.Optional;
import static java.util.Optional.ofNullable;
/**
* Utility class to handle section breaks in paragraphs.
*
* @author Joseph Verron
* @version ${version}
* @since 1.6.2
*/
public class SectionUtil {
private static final Logger log = LoggerFactory.getLogger(SectionUtil.class);
private SectionUtil() {
throw new OfficeStamperException("Utility class shouldn't be instantiated");
}
/**
* Creates a new section break object.
*
* @param firstObject a {@link Object} object
* @param parent a {@link ContentAccessor} object
* @return a new section break object.
*/
public static Optional<SectPr> getPreviousSectionBreakIfPresent(Object firstObject, ContentAccessor parent) {
List<Object> parentContent = parent.getContent();
int pIndex = parentContent.indexOf(firstObject);
int i = pIndex - 1;
while (i >= 0) {
if (parentContent.get(i) instanceof P prevParagraph) {
// the first P preceding the object is the one potentially carrying a section break
return ofNullable(prevParagraph.getPPr())
.map(PPr::getSectPr);
}
else log.debug("The previous sibling was not a P, continuing search");
i--;
}
log.info("No previous section break found from : {}, first object index={}", parent, pIndex);
return Optional.empty();
}
/**
* Creates a new section break object.
*
* @param objects a {@link List} object
*
* @return a new section break object.
*/
public static boolean hasOddNumberOfSectionBreaks(List<Object> objects) {
return objects.stream()
.filter(P.class::isInstance)
.map(P.class::cast)
.filter(SectionUtil::hasSectionBreak)
.count() % 2 != 0;
}
private static boolean hasSectionBreak(P p) {
var pPPr = p.getPPr();
if (pPPr == null) return false;
var pPPrSectPr = pPPr.getSectPr();
return pPPrSectPr != null;
}
/**
* Creates a new section break object.
*
* @param sectPr a {@link SectPr} object
* @param paragraph a {@link P} object
*/
public static void applySectionBreakToParagraph(SectPr sectPr, P paragraph) {
PPr nextPPr = ofNullable(paragraph.getPPr()).orElseGet(WmlFactory::newPPr);
nextPPr.setSectPr(XmlUtils.deepCopy(sectPr));
paragraph.setPPr(nextPPr);
}
}