jodtemplate.pptx.postprocessor.StylePostprocessor.java Source code

Java tutorial

Introduction

Here is the source code for jodtemplate.pptx.postprocessor.StylePostprocessor.java

Source

/*
 * 
 * Copyright 2015 Andrey Yakovlev
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package jodtemplate.pptx.postprocessor;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import jodtemplate.DomProcessor;
import jodtemplate.exception.JODTemplateException;
import jodtemplate.pptx.Configuration;
import jodtemplate.pptx.PPTXDocument;
import jodtemplate.pptx.Slide;
import jodtemplate.resource.Resources;
import jodtemplate.style.Stylizer;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Comment;
import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.filter.Filters;
import org.jdom2.util.IteratorIterable;

public class StylePostprocessor implements DomProcessor {

    private static final String STYLIZED_KEYWORD = " stylized ";

    @Override
    public Document process(final Map<String, Object> context, final Document document, final Slide slide,
            final Resources resources, final Configuration configuration) throws JODTemplateException {
        final IteratorIterable<Element> atElements = document
                .getDescendants(Filters.element(PPTXDocument.T_ELEMENT, getNamespace()));
        final List<Element> atElementsList = new ArrayList<>();
        while (atElements.hasNext()) {
            atElementsList.add(atElements.next());
        }
        for (Element at : atElementsList) {
            if (at.getContentSize() != 0) {
                final Content content = at.getContent(0);
                if (content instanceof Comment) {
                    final Comment comment = (Comment) content;
                    processComment(comment, at, slide, configuration);
                }
            }
        }
        return document;
    }

    private void processComment(final Comment comment, final Element at, final Slide slide,
            final Configuration configuration) throws JODTemplateException {
        String commentText = comment.getText();
        if (commentText.startsWith(STYLIZED_KEYWORD)) {
            commentText = StringUtils.removeStart(commentText, STYLIZED_KEYWORD);
            final String className = StringUtils.substringBefore(commentText, ":");
            commentText = StringUtils.removeStart(commentText, className + ": ");
            final Stylizer stylizer = configuration.getStylizer(className);
            if (stylizer == null) {
                throw new JODTemplateException("Unable to find stylizer");
            }
            final String text = StringUtils.removeStart(commentText, " stylized: ");
            final Element ar = at.getParentElement();
            final Element ap = ar.getParentElement();
            final int arIndex = ap.indexOf(ar);
            final Element arPr = getArPrElement(ar);
            final Element apPr = getApPrElement(ap);
            final Element sourceApPr = ObjectUtils.clone(apPr);
            cleanApPrElement(apPr);

            final List<Element> stylizedElements = stylizer.stylize(text, arPr, apPr, slide);

            ap.removeContent(ar);
            final List<Element> remains = getRemainingElements(arIndex, ap);
            for (Element el : remains) {
                ap.removeContent(el);
            }

            final int currentApIndex = injectElementsInDocument(stylizedElements, ap, apPr, arIndex);
            injectRemainsInDocument(remains, ap, sourceApPr, currentApIndex);
        }
    }

    private int injectElementsInDocument(final List<Element> stylizedElements, final Element ap, final Element apPr,
            final int arIndex) {
        int index = arIndex;
        final Element txBody = ap.getParentElement();
        int apIndex = txBody.indexOf(ap) + 1;
        boolean createNewAp = false;
        Element currentAp = ap;
        for (Element element : stylizedElements) {
            if (element.getName().equals(PPTXDocument.P_ELEMENT)) {
                currentAp = element;
                txBody.addContent(apIndex, currentAp);
                apIndex++;
                createNewAp = true;
            } else {
                if (createNewAp) {
                    currentAp = new Element(PPTXDocument.P_ELEMENT, getNamespace());
                    Element apPrToAdd = ObjectUtils.clone(apPr);
                    if (apPrToAdd == null) {
                        apPrToAdd = new Element(PPTXDocument.PPR_ELEMENT, getNamespace());
                    }
                    final Element abuNone = new Element(PPTXDocument.BUNONE_ELEMENT, getNamespace());
                    apPrToAdd.addContent(abuNone);
                    currentAp.addContent(apPrToAdd);
                    txBody.addContent(apIndex, currentAp);
                    apIndex++;
                    createNewAp = false;
                }
                if (currentAp == ap) {
                    currentAp.addContent(index, element);
                    index++;
                } else {
                    currentAp.addContent(element);
                }
            }
        }
        return apIndex;
    }

    private void injectRemainsInDocument(final List<Element> remains, final Element ap, final Element apPr,
            final int apIndex) {
        if (CollectionUtils.isNotEmpty(remains)) {
            final Element txBody = ap.getParentElement();
            final Element apWithRemains = new Element(PPTXDocument.P_ELEMENT, getNamespace());
            if (apPr != null) {
                apWithRemains.addContent(apPr);
            }
            apWithRemains.addContent(remains);
            txBody.addContent(apIndex, apWithRemains);
        }
    }

    private List<Element> getRemainingElements(final int fromIndex, final Element ap) {
        final List<Element> remains = new ArrayList<>();
        for (int i = fromIndex; i < ap.getContentSize(); ++i) {
            final Content apChild = ap.getContent(i);
            if (apChild instanceof Element) {
                final Element apChildElement = (Element) apChild;
                if (PPTXDocument.R_ELEMENT.equals(apChildElement.getName())
                        || PPTXDocument.BR_ELEMENT.equals(apChildElement.getName())) {
                    remains.add(apChildElement);
                }
            }
        }
        return remains;
    }

    private Element getArPrElement(final Element ar) {
        final List<Element> arPrElements = ar.getContent(Filters.element(PPTXDocument.RPR_ELEMENT, getNamespace()));
        Element arPr = null;
        if (CollectionUtils.isNotEmpty(arPrElements)) {
            arPr = arPrElements.get(0).clone();
            arPr.removeAttribute("b", getNamespace());
            arPr.removeAttribute("i", getNamespace());
            arPr.removeAttribute("u", getNamespace());
        }
        return arPr;
    }

    private Element getApPrElement(final Element ap) {
        final List<Element> apPrElements = ap.getContent(Filters.element(PPTXDocument.PPR_ELEMENT, getNamespace()));
        if (CollectionUtils.isNotEmpty(apPrElements)) {
            return apPrElements.get(0).clone();
        }
        return null;
    }

    private void cleanApPrElement(final Element apPr) {
        if (apPr != null) {
            apPr.removeChild(PPTXDocument.BUNONE_ELEMENT, getNamespace());
            apPr.removeChild(PPTXDocument.BUCHAR_ELEMENT, getNamespace());
            apPr.removeChild(PPTXDocument.BUAUTONUM_ELEMENT, getNamespace());
            apPr.removeChild(PPTXDocument.BUFONT_ELEMENT, getNamespace());
        }
    }

    private Namespace getNamespace() {
        return Namespace.getNamespace(PPTXDocument.DRAWINGML_NAMESPACE_PREFIX, PPTXDocument.DRAWINGML_NAMESPACE);
    }

}