Java tutorial
/* * * 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.style; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import jodtemplate.Relationship; import jodtemplate.exception.JODTemplateException; import jodtemplate.pptx.PPTXDocument; import jodtemplate.pptx.Slide; import jodtemplate.style.Stylizer; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.Predicate; import org.jdom2.Element; import org.jdom2.Namespace; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Node; import org.jsoup.nodes.TextNode; public class HtmlStylizer implements Stylizer { private static final String BODY_TAG = "body"; private static final String P_TAG = "p"; private static final String U_TAG = "u"; private static final String I_TAG = "i"; private static final String B_TAG = "b"; private static final String BR_TAG = "br"; private static final String STRONG_TAG = "strong"; private static final String EM_TAG = "em"; private static final String INS_TAG = "ins"; private static final String OL_TAG = "ol"; private static final String UL_TAG = "ul"; private static final String LI_TAG = "li"; private static final String A_TAG = "a"; private static final String HREF_ATTR = "href"; private static final String ONE = "1"; private static final String SNG = "sng"; private static final int DEFAULT_INDENTATION = 457200; @Override public List<Element> stylize(final String text, final Element arPr, final Element apPr, final Slide slide) throws JODTemplateException { final Document htmlDoc = Jsoup.parse(text); try { return process(htmlDoc.body(), arPr, apPr, slide); } catch (IOException e) { throw new JODTemplateException("Stylizer error", e); } } private List<Element> process(final org.jsoup.nodes.Element element, final Element arPr, final Element apPr, final Slide slide) throws IOException { if (BR_TAG.equals(element.tagName())) { return Arrays.asList(new Element(PPTXDocument.BR_ELEMENT, getDrawingmlNamespace())); } final List<org.jsoup.nodes.Element> tags = getAllTags(element); final List<Element> elements = new ArrayList<>(); for (Node node : element.childNodes()) { if (node instanceof org.jsoup.nodes.Element) { elements.addAll(process((org.jsoup.nodes.Element) node, arPr, apPr, slide)); } else if (node instanceof TextNode) { final TextNode textNode = (TextNode) node; elements.add(createTextElement(tags, arPr, textNode, slide)); } } if (LI_TAG.equals(element.tagName())) { return createListElements(tags, elements, apPr, element); } if (P_TAG.equals(element.tagName())) { return Arrays.asList(createParagraphElement(elements, apPr)); } return elements; } private Element createTextElement(final List<org.jsoup.nodes.Element> tags, final Element arPr, final TextNode textNode, final Slide slide) { final Element ar = new Element(PPTXDocument.R_ELEMENT, getDrawingmlNamespace()); final Element formattedArPr = applyFormatting(tags, arPr, slide); if (formattedArPr.hasAttributes() || formattedArPr.getContentSize() != 0) { ar.addContent(formattedArPr); } final Element at = new Element(PPTXDocument.T_ELEMENT, getDrawingmlNamespace()); at.setText(textNode.getWholeText()); ar.addContent(at); return ar; } private List<Element> createListElements(final List<org.jsoup.nodes.Element> tags, final List<Element> elements, final Element apPr, final org.jsoup.nodes.Element element) { final Element ap = new Element(PPTXDocument.P_ELEMENT, getDrawingmlNamespace()); final Element apPrToAdd = applyListFormatting(tags, element, apPr); ap.addContent(apPrToAdd); final List<Element> listResult = new ArrayList<>(); listResult.add(ap); for (Element el : elements) { if (PPTXDocument.P_ELEMENT.equals(el.getName())) { listResult.add(el); } else { ap.addContent(el); } } return listResult; } private Element applyListFormatting(final List<org.jsoup.nodes.Element> tags, final org.jsoup.nodes.Element element, final Element apPr) { final Element apPrToAdd; if (apPr == null) { apPrToAdd = new Element(PPTXDocument.PPR_ELEMENT, getDrawingmlNamespace()); } else { apPrToAdd = apPr.clone(); } apPrToAdd.setAttribute(PPTXDocument.INDENT_ATTR, String.valueOf(-DEFAULT_INDENTATION)); final Element abuFont = new Element(PPTXDocument.BUFONT_ELEMENT, getDrawingmlNamespace()); apPrToAdd.addContent(abuFont); if (UL_TAG.equals(element.parent().tagName())) { abuFont.setAttribute(PPTXDocument.CHARSET_ATTR, "0"); abuFont.setAttribute(PPTXDocument.PANOSE_ATTR, "020B0604020202020204"); abuFont.setAttribute(PPTXDocument.PITCH_FAMILY_ATTR, "34"); abuFont.setAttribute(PPTXDocument.TYPEFACE_ATTR, "Arial"); final Element abuChar = new Element(PPTXDocument.BUCHAR_ELEMENT, getDrawingmlNamespace()); abuChar.setAttribute(PPTXDocument.CHAR_ATTR, ""); apPrToAdd.addContent(abuChar); } else if (OL_TAG.equals(element.parent().tagName())) { abuFont.setAttribute(PPTXDocument.TYPEFACE_ATTR, "+mj-lt"); final Element abuAutonum = new Element(PPTXDocument.BUAUTONUM_ELEMENT, getDrawingmlNamespace()); abuAutonum.setAttribute(PPTXDocument.TYPE_ATTR, "arabicPeriod"); apPrToAdd.addContent(abuAutonum); } final Collection<org.jsoup.nodes.Element> listItemTags = CollectionUtils.select(tags, new Predicate<org.jsoup.nodes.Element>() { @Override public boolean evaluate(final org.jsoup.nodes.Element tag) { return LI_TAG.equals(tag.tagName()); } }); final int listLevel = listItemTags.size(); if (listLevel > 1) { apPrToAdd.setAttribute(PPTXDocument.LVL_ATTR, String.valueOf(listLevel - 1)); } apPrToAdd.setAttribute(PPTXDocument.MAR_L_ATTR, String.valueOf(DEFAULT_INDENTATION * listLevel)); return apPrToAdd; } private Element createParagraphElement(final List<Element> elements, final Element apPr) { final Element ap = new Element(PPTXDocument.P_ELEMENT, getDrawingmlNamespace()); final Element apPrToAdd; if (apPr == null) { apPrToAdd = new Element(PPTXDocument.PPR_ELEMENT, getDrawingmlNamespace()); } else { apPrToAdd = apPr.clone(); } final Element abuNone = new Element(PPTXDocument.BUNONE_ELEMENT, getDrawingmlNamespace()); apPrToAdd.addContent(abuNone); ap.addContent(apPrToAdd); ap.addContent(elements); return ap; } private Element applyFormatting(final List<org.jsoup.nodes.Element> tags, final Element arPr, final Slide slide) { final Element formatted; if (arPr == null) { formatted = new Element(PPTXDocument.RPR_ELEMENT, getDrawingmlNamespace()); } else { formatted = arPr.clone(); } for (org.jsoup.nodes.Element tag : tags) { final String tagName = tag.tagName(); if (U_TAG.equals(tagName) || INS_TAG.equals(tagName)) { formatted.setAttribute(U_TAG, SNG); } else if (I_TAG.equals(tagName) || EM_TAG.equals(tagName)) { formatted.setAttribute(I_TAG, ONE); } else if (B_TAG.equals(tagName) || STRONG_TAG.equals(tagName)) { formatted.setAttribute(B_TAG, ONE); } else if (A_TAG.equals(tagName)) { createHyperlink(tag, formatted, slide); } } return formatted; } private void createHyperlink(final org.jsoup.nodes.Element tag, final Element formatted, final Slide slide) { Element hlinkClickElement = formatted.getChild(PPTXDocument.HLINK_CLICK_ELEMENT, getDrawingmlNamespace()); if (hlinkClickElement == null) { hlinkClickElement = new Element(PPTXDocument.HLINK_CLICK_ELEMENT, getDrawingmlNamespace()); formatted.addContent(hlinkClickElement); } final Relationship relationship = new Relationship(); relationship.setId(slide.getNextId()); relationship.setTarget(tag.attr(HREF_ATTR)); relationship.setTargetMode(Relationship.EXTERNAL_TARGET_MODE); relationship.setType(Relationship.HYPERLINK_TYPE); slide.addOtherRelationship(relationship); hlinkClickElement.setAttribute(PPTXDocument.ID_ATTR, relationship.getId(), getRelationshipsNamespace()); } private List<org.jsoup.nodes.Element> getAllTags(final org.jsoup.nodes.Element element) { final List<org.jsoup.nodes.Element> tags = new ArrayList<>(); org.jsoup.nodes.Element tempElement = element; while (!tempElement.tagName().equals(BODY_TAG)) { tags.add(tempElement); tempElement = tempElement.parent(); } return tags; } private Namespace getDrawingmlNamespace() { return Namespace.getNamespace(PPTXDocument.DRAWINGML_NAMESPACE_PREFIX, PPTXDocument.DRAWINGML_NAMESPACE); } private Namespace getRelationshipsNamespace() { return Namespace.getNamespace(PPTXDocument.RELATIONSHIPS_NAMESPACE_PREFIX, PPTXDocument.RELATIONSHIPS_NAMESPACE); } }