Package org.bazu.jotex

Source Code of org.bazu.jotex.OdtEPUBlisher

/*
* OdtEPUBlisher.java
*
* Copyright (c) 2011, Luca Conte. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301  USA
*/
/**
* TODO:
*  -returns from footnote
*  -tables border
*  -List styles dotted or numbered wirh variants
*  -image types support
*  -remote images support (?) a lot of problems related
*
*/
package org.bazu.jotex;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.bazu.jotex.fonts.SinglePathFontLocator;
import org.bazu.jotex.images.ByteArrayImageDataSource;
import org.odftoolkit.odfdom.doc.OdfDocument;
import org.odftoolkit.odfdom.doc.OdfTextDocument;
import org.odftoolkit.odfdom.dom.element.OdfStylableElement;
import org.odftoolkit.odfdom.dom.element.OdfStyleBase;
import org.odftoolkit.odfdom.dom.element.draw.DrawTextBoxElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeBodyElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeDocumentContentElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeScriptsElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeTextElement;
import org.odftoolkit.odfdom.dom.element.style.StyleParagraphPropertiesElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableCellElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableRowElement;
import org.odftoolkit.odfdom.dom.element.text.TextAElement;
import org.odftoolkit.odfdom.dom.element.text.TextBookmarkElement;
import org.odftoolkit.odfdom.dom.element.text.TextListItemElement;
import org.odftoolkit.odfdom.dom.element.text.TextNoteBodyElement;
import org.odftoolkit.odfdom.dom.element.text.TextNoteCitationElement;
import org.odftoolkit.odfdom.dom.element.text.TextNoteElement;
import org.odftoolkit.odfdom.dom.element.text.TextSElement;
import org.odftoolkit.odfdom.dom.style.OdfStyleFamily;
import org.odftoolkit.odfdom.dom.style.props.OdfStyleProperty;
import org.odftoolkit.odfdom.incubator.doc.draw.OdfDrawFrame;
import org.odftoolkit.odfdom.incubator.doc.draw.OdfDrawImage;
import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeAutomaticStyles;
import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeStyles;
import org.odftoolkit.odfdom.incubator.doc.style.OdfDefaultStyle;
import org.odftoolkit.odfdom.incubator.doc.style.OdfStyle;
import org.odftoolkit.odfdom.incubator.doc.text.OdfTextHeading;
import org.odftoolkit.odfdom.incubator.doc.text.OdfTextList;
import org.odftoolkit.odfdom.incubator.doc.text.OdfTextParagraph;
import org.odftoolkit.odfdom.incubator.doc.text.OdfTextSpan;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import com.adobe.dp.css.CSSLength;
import com.adobe.dp.css.CSSName;
import com.adobe.dp.css.CSSQuotedString;
import com.adobe.dp.css.CSSValue;
import com.adobe.dp.css.Selector;
import com.adobe.dp.css.SelectorRule;
import com.adobe.dp.epub.io.DataSource;
import com.adobe.dp.epub.io.OCFContainerWriter;
import com.adobe.dp.epub.ncx.TOCEntry;
import com.adobe.dp.epub.opf.BitmapImageResource;
import com.adobe.dp.epub.opf.NCXResource;
import com.adobe.dp.epub.opf.OPSResource;
import com.adobe.dp.epub.opf.Publication;
import com.adobe.dp.epub.opf.Resource;
import com.adobe.dp.epub.opf.StyleResource;
import com.adobe.dp.epub.ops.Element;
import com.adobe.dp.epub.ops.HTMLElement;
import com.adobe.dp.epub.ops.HyperlinkElement;
import com.adobe.dp.epub.ops.ImageElement;
import com.adobe.dp.epub.style.Stylesheet;
import com.adobe.dp.epub.util.TOCLevel;
import com.adobe.dp.otf.FontLocator;

public class OdtEPUBlisher {
    // config fields
    private boolean debugMode = false;
    private String epubLanguage;
    private String epubFilename;
    private String odtFilename;
    // END config fields

    private Publication ePub;
    private OdfTextDocument odt;
    private Stylesheet _stylesheet;
    private StyleResource _styleResource;
    private OPSResource currentResource;
    private OPSResource footnotesResource;
    private OPSResource coverResource;
    private XPath xpath;

    private String fontsPath;
    private String coverPath;
    private boolean _hasFootnotes=false;
    private boolean exposeBookmarks;




    private int maxFilesSize = 0;

    private Map<String, Element> bookmarks;
    private Set<HyperlinkElement> internalLink;

    private Set<String> classesForDebug = new HashSet<String>();

    public static NamespaceContext XPATH_ODT_NS_CTX = new NamespaceContext() {

        public Iterator getPrefixes(String namespaceURI) {
            // fo=urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0
            return null;
        }

        public String getPrefix(String namespaceURI) {
            if (namespaceURI.equals("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0")) {
                return "draw";
            } else if (namespaceURI.equals("urn:oasis:names:tc:opendocument:xmlns:style:1.0")) {
                return "style";
            } else if (namespaceURI.equals("urn:oasis:names:tc:opendocument:xmlns:text:1.0")) {
                return "text";
            } else if (namespaceURI.equals("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0")) {
                return "fo";
            } else if (namespaceURI.equals("urn:oasis:names:tc:opendocument:xmlns:meta:1.0")) {
                return "meta";
            }

            return null;
        }

        public String getNamespaceURI(String prefix) {
            if (prefix.equals("draw")) {
                return "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";
            } else if (prefix.equals("style")) {
                return "urn:oasis:names:tc:opendocument:xmlns:style:1.0";
            } else if (prefix.equals("text")) {
                return "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
            } else if (prefix.equals("fo")) {
                return "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0";
            } else if (prefix.equals("meta")) {
                return "urn:oasis:names:tc:opendocument:xmlns:meta:1.0";
            }

            return "";
        }
    };

    private int breaksCount = 0;

    private Stack<TOCLevel> tocEntriesBuffer;

    public OdtEPUBlisher() {

    }

    public void startRippingSession() throws Exception {

        Utils.processMetadata(getOdt().getMetaDom(), getEpub(), getXpath());



         //System.out.println(getOdt().getDocumentStyles());
        extractDefaultStyles(getOdt().getDocumentStyles());
        if(getCoverPath()!=null&&getCoverPath().trim().length()>0){//a cover will be processed
           
          
           
            File fcover=new File(getCoverPath());
            if(fcover.exists()){
                try {
                    HTMLElement covelem=getCoverResource().getDocument().createElement("div");
                  
                    Resource r=addImage(fcover.getAbsolutePath(), covelem,getCoverResource());
                    if(r!=null){
                      r.setId("cover-image");
                      getEpub().addMetadata(null, "cover", "cover-image");
                      //
                      covelem.setClassName("cover");
                      Selector selector = getStylesheet().getSimpleSelector("div", "cover");
                      SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
                      rule.set("width", new CSSName("100%"));
                      rule.set("text-align", new CSSName("center"));
                      getCoverResource().getDocument().getBody().add(covelem);
                      //TODO: uncomment the following row for best practies. But doing this some readers put the cover at the epub's end and not at the epub's beginning
                      //getCoverResource().putSerializationAttribute(null, "linear", "no");
                      getEpub().addToSpine(getCoverResource());
                    }
                } catch (Exception e) {
                    // Unable to set the cover
                    e.printStackTrace();
                }
            
            }
           
        }
        createNewResource();
        traverse(getOdt().getContentDom(), null);

        // processURLSSession(rootTOCEntry,p);
        processInternalLinksCrossReferences();
        if(isExposeBookmarks()){
            bookmarksToToc();
        }
       
        if(_hasFootnotes){
            setFootnotesCSSStyles();
            getEpub().addToSpine(getFootnotesResource());
        }
        if (getMaxFilesSize() > 0) {
            getEpub().splitLargeChapters(getMaxFilesSize() * 1024);
        }

        // include fonts
        // embed fonts
        // NB: on non-Windows platforms you need to supply your own
        // FontLocator implementation or place fonts in ~/.epubfonts
        if (getFontsPath() != null && getFontsPath().trim().length() > 0) {
            FontLocator fontLocator = new SinglePathFontLocator(getFontsPath());
            getEpub().cascadeStyles();
            getEpub().addFonts(getStyleResource(), fontLocator);
        }
        OCFContainerWriter writer = new OCFContainerWriter(new FileOutputStream(getEpubFilename()));
        getEpub().serialize(writer);

       
        //TODO: uncomment  for testing stylesheet optimization
        //Utils.optimizeStylesheet(getStyleResource());
        if (isDebugMode()) {
            printClassesFound();
        }
    }

    public void traverse(Node e, Element dstElement) throws Exception {
        classesForDebug.add(e.getClass().toString());
        boolean skipChildren = false;
        Element newElement = null;
        /**
         * Original ODT's element evalutation
         */
        if (e instanceof TextNoteBodyElement) {// Corpo di una nota
            TextNoteBodyElement noteBody = (TextNoteBodyElement) e;
        } else if (e instanceof TextNoteCitationElement) {// Rimando ad una nota

        } else if (e instanceof OfficeTextElement) {// OFFICE
            OfficeTextElement ote = (OfficeTextElement) e;

        } else if (e instanceof OfficeScriptsElement) {// OFFICE

        } else if (e instanceof OfficeDocumentContentElement) {// OFFICE

        } else if (e instanceof OdfOfficeAutomaticStyles) {// OFFICE

        } else if (e instanceof OfficeBodyElement) {// OFFICE

        } else if (e instanceof TextSElement) {// ?
            TextSElement te = (TextSElement) e;

        } else if (e instanceof TextAElement) {// is an hyperlink
            TextAElement ta = (TextAElement) e;
            String ref = ta.getAttribute("xlink:href");

            HyperlinkElement a = getCurrentResource().getDocument().createHyperlinkElement("a");
            if (ref.startsWith("#")) {// internal Link
                a.setTitle(ta.getAttribute("xlink:href"));
                getInternalLink().add(a);
            } else {
                a.setExternalHRef(ref);
            }
            dstElement.add(a);
            // a.add("ciao");
            traverse(ta.getFirstChild(), a);
            skipChildren = true;

        } else if (e instanceof TextBookmarkElement) {// is bookmark in epub can
                                                      // be used to implement
                                                      // internal link anchors
            TextBookmarkElement ta = (TextBookmarkElement) e;

            HyperlinkElement a = getCurrentResource().getDocument().createHyperlinkElement("a");
            a.setId(ta.getAttribute("text:name"));
            dstElement.add(a);
            getBookmarks().put("#" + ta.getAttribute("text:name"), a);
        } else if (e instanceof TextNoteElement) {// Is a footnote container
            addFootnote((TextNoteElement) e, dstElement);
            skipChildren = true;
        } else if (e instanceof OdfDrawFrame) {
            OdfDrawFrame dframe = (OdfDrawFrame) e;
        // if(!(dframe.getParentNode().getParentNode() instanceof DrawTextBoxElement)){
            // here can be captured resize options
            newElement = addImageBox(dframe, dstElement);
         //}

        } else if (e instanceof DrawTextBoxElement) {
            DrawTextBoxElement didascalia = (DrawTextBoxElement) e;
       

        } else if (e instanceof OdfDrawImage) {
            addImage((OdfDrawImage) e, dstElement);

        } else if (e instanceof OdfTextList) {
            OdfTextList otl = (OdfTextList) e;
            dstElement = getCurrentResource().getDocument().getBody();
            /**
             * ul.a {list-style-type:circle;} ul.b {list-style-type:square;}
             * ol.c {list-style-type:upper-roman;} ol.d
             * {list-style-type:lower-alpha;}
             */
            Object n = getXpath().evaluate(
                    "//text:list-style[@style:name='" + otl.getTextStyleNameAttribute()
                            + "']/text:list-level-style-bullet", getOdt().getContentDom(), XPathConstants.NODE);
            if (n != null) {// is a bullet list
                newElement = getCurrentResource().getDocument().createElement("ul");
            } else {
                n = getXpath().evaluate(
                        "//text:list-style[@style:name='" + otl.getTextStyleNameAttribute()
                                + "']/text:list-level-style-number", getOdt().getContentDom(), XPathConstants.NODE);
                if (n != null) {
                    newElement = getCurrentResource().getDocument().createElement("ol");
                }
            }

            if (newElement != null) {
                dstElement.add(newElement);
                newElement.setClassName(otl.getTextStyleNameAttribute());
            }
            // title[@lang='eng']
        } else if (e instanceof TextListItemElement) {
            TextListItemElement li = (TextListItemElement) e;
            newElement = getCurrentResource().getDocument().createElement("li");
            dstElement.add(newElement);

        } else if (e instanceof TableTableElement) {
            TableTableElement otl = (TableTableElement) e;
            dstElement = getCurrentResource().getDocument().getBody();
            newElement = getCurrentResource().getDocument().createElement("table");
            dstElement.add(newElement);
            newElement.setClassName(otl.getStyleName());
            Selector selector = getStylesheet().getSimpleSelector(null, otl.getStyleName());
            SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
          
            rule.set("width", new CSSName("100%"));
            selector = getStylesheet().getSimpleSelector("table", null);
            rule = getStylesheet().getRuleForSelector(selector, true);
            rule.set("border-collapse", new CSSName("collapse"));
            rule.set("border", new CSSName("1px solid black"));
            selector = getStylesheet().getSimpleSelector("td",null);
            rule = getStylesheet().getRuleForSelector(selector, true);
            rule.set("border", new CSSName("1px solid black"));
            selector = getStylesheet().getSimpleSelector("tr", null);
            rule = getStylesheet().getRuleForSelector(selector, true);
            rule.set("border", new CSSName("1px solid black"));

        } else if (e instanceof TableTableRowElement) {
            TableTableRowElement otl = (TableTableRowElement) e;
            newElement = getCurrentResource().getDocument().createElement("tr");
            dstElement.add(newElement);
            newElement.setClassName(otl.getStyleName());

        } else if (e instanceof TableTableCellElement) {
            TableTableCellElement otl = (TableTableCellElement) e;
            newElement = getCurrentResource().getDocument().createElement("td");
            dstElement.add(newElement);
            newElement.setClassName(otl.getStyleName());
        } else if (e instanceof OdfTextHeading) {// text:p
            // System.out.println(e.getTextContent());
            OdfTextHeading oth = (OdfTextHeading) e;
            if (hasPageBreak(oth)) {
                createNewResource();
            }
            newElement = getCurrentResource().getDocument().createElement("h" + oth.getAttribute("text:outline-level"));
            if (dstElement != null) {
                dstElement.add(newElement);
            } else {
                getCurrentResource().getDocument().getBody().add(newElement);
            }
            newElement.setClassName(oth.getStyleName());
            if (oth.getTextContent() != null && oth.getTextContent().trim().length() > 0) {
                addTocEntry(oth.getTextContent(), Integer.parseInt(oth.getAttribute("text:outline-level")), newElement);
            }

            if (oth.getAutomaticStyle() != null) {// probabile che sia stato
                // oth.getAutomaticStyles() // modificato lo stile
                List<OdfStyleBase> classeCSS = new ArrayList<OdfStyleBase>();
                OdfStyleBase p = oth.getAutomaticStyle().getParentStyle();
                while (p != null) {
                    classeCSS.add(p);
                    p = p.getParentStyle();

                }
                Collections.reverse(classeCSS);
                for (OdfStyleBase odfStyleBase : classeCSS) {
                    stylesPropsToCSS(odfStyleBase.getStyleProperties(), newElement.getClassName());
                }
                stylesPropsToCSS(oth.getAutomaticStyle().getStyleProperties(), oth.getStyleName());
                if (newElement != null) {
                    newElement.setClassName(oth.getStyleName());
                }
                if (isDebugMode()) {
                    Utils.printStyleProps(oth.getAutomaticStyle().getStyleProperties());
                }
            }

            getOdt().getDocumentStyles().getElementsByTagName(oth.getTextStyleNameAttribute());

        } else if (e instanceof OdfTextParagraph) {// text:p
            // System.out.println(e.getTextContent());

            OdfTextParagraph otp = (OdfTextParagraph) e;
            if (hasPageBreak(otp)) {
                createNewResource();
            }

            newElement = getCurrentResource().getDocument().createElement("p");

            if (dstElement != null) {
                dstElement.add(newElement);
            } else {
                getCurrentResource().getDocument().getBody().add(newElement);
            }

            newElement.setClassName(otp.getStyleName().trim());

            if (otp.getAutomaticStyle() != null) {// probabile che sia stato
                                                  // modificato lo stile
                List<OdfStyleBase> classeCSS = new ArrayList<OdfStyleBase>();
                OdfStyleBase p = otp.getAutomaticStyle().getParentStyle();
                while (p != null) {
                    classeCSS.add(p);
                    p = p.getParentStyle();

                }
                Collections.reverse(classeCSS);
                for (OdfStyleBase odfStyleBase : classeCSS) {
                    stylesPropsToCSS(odfStyleBase.getStyleProperties(), newElement.getClassName());
                }

                // while(p!=null){
                // if(p.getAttribute("style:name")!=null&&p.getAttribute("style:name").trim().length()>0){
                // newElement.setClassName(p.getAttribute("style:name").trim()+" "+newElement.getClassName());
                // stylesPropsToCSS(p.getStyleProperties(),
                // p.getAttribute("style:name"));
                // }
                // p=p.getParentStyle();
                //
                // }
                // Object
                // n=getXpath().evaluate("//style:style[@style:name='Body_20_Text_20_3']",
                // getOdt().getDocumentStyles(), XPathConstants.NODE);
                // n=getXpath().evaluate("//style:style[@style:name='Standard']",
                // getOdt().getDocumentStyles(), XPathConstants.NODE);
                // getXpath().evaluate("//style:style[@style:name='P38']",
                // getOdt().getDocumentStyles(), XPathConstants.NODE)
                stylesPropsToCSS(otp.getAutomaticStyle().getStyleProperties(), otp.getStyleName());

                if (isDebugMode()) {
                    Utils.printStyleProps(otp.getAutomaticStyle().getStyleProperties());
                }
            }

        } else if (e instanceof OdfTextSpan) {// text:span
            // System.out.println(e.getTextContent());
            // sembra che se automatic.style � vuoto allora esiste uno stile
            // definito che pu� definire bold e italic
            OdfTextSpan ots = (OdfTextSpan) e;

            if (ots.getAutomaticStyle() != null) {// probabile che sia stato
                                                  // modificato lo stile
                newElement = getCurrentResource().getDocument().createElement("span");
                dstElement.add(newElement);
                newElement.setClassName(ots.getStyleName());
                stylesPropsToCSS(ots.getAutomaticStyle().getStyleProperties(), newElement.getClassName());
                if (isDebugMode()) {
                    Utils.printStyleProps(ots.getAutomaticStyle().getStyleProperties());
                }
            }

        } else if (e instanceof Text && e instanceof CharacterData) {
            dstElement.add(e.getTextContent());
            if (isDebugMode()) {
                System.out.println("Pezzo di testo: " + e.getTextContent());
            }
        }
        /**
         * End of Original ODT's element evalutation
         */
        for (int i = 0; i < e.getChildNodes().getLength() && !skipChildren; i++) {

            traverse(e.getChildNodes().item(i), newElement != null ? newElement : dstElement);
        }

    }

    public Publication getEpub() {
        if (ePub == null) {
            ePub = new Publication();

        }

        return ePub;
    }

    public String getEpubLanguage() {
        return epubLanguage;
    }

    public void setEpubLanguage(String epubLanguage) {
        this.epubLanguage = epubLanguage;
    }

    public String getEpubFilename() {
        return epubFilename;
    }

    public void setEpubFilename(String epubFilename) {
        this.epubFilename = epubFilename;
    }

    public NCXResource getToc() {
        return getEpub().getTOC();
    }

    public Stylesheet getStylesheet() {
        if (_stylesheet == null) {
            _stylesheet = getStyleResource().getStylesheet();
         

        }
        return _stylesheet;
    }

    protected void setStylesheet(Stylesheet stylesheet) {

        this._stylesheet = stylesheet;
    }

    public String getOdtFilename() {
        return odtFilename;
    }

    public void setOdtFilename(String odtFilename) {
        this.odtFilename = odtFilename;
    }

    protected int getNewBreakIndex() {
        breaksCount++;
        return breaksCount;
    }

    public OdfTextDocument getOdt() throws Exception {

        if (odt == null) {
            odt = (OdfTextDocument) OdfDocument.loadDocument(getOdtFilename());
        }

        return odt;
    }

    protected void createNewResource() {

        currentResource = getEpub().createOPSResource("OPS/content" + +getNewBreakIndex() + ".xhtml");
        getEpub().addToSpine(currentResource);
        currentResource.getDocument().addStyleResource(getStyleResource());
    }

    public OPSResource getCurrentResource() {

        if (currentResource == null) {
            createNewResource();

        }

        return currentResource;
    }

    protected void setCurrentResource(OPSResource currentResource) {
        this.currentResource = currentResource;
    }

    protected OPSResource getFootnotesResource() {
        if (footnotesResource == null) {
            footnotesResource = getEpub().createOPSResource("OPS/footnotes.xhtml");

            footnotesResource.getDocument().addStyleResource(getStyleResource());
        }
        return footnotesResource;
    }
    protected OPSResource getCoverResource() {
        if (coverResource == null) {
            coverResource = getEpub().createOPSResource("OPS/cover.xhtml");

            coverResource.getDocument().addStyleResource(getStyleResource());
        }
        return coverResource;
    }
    public void stylesPropsToCSS(Map<OdfStyleProperty, String> props, String className) {
        stylesPropsToCSS(props, null, className);

    }

    public void stylesPropsToCSS(Map<OdfStyleProperty, String> props, String elementName, String className) {
        Selector selector = getStylesheet().getSimpleSelector(elementName, className);
        for (Entry<OdfStyleProperty, String> e : props.entrySet()) {
            if (e.getKey().getName().getLocalName().equals("font-style")
                    || e.getKey().getName().getLocalName().equals("font-weight") ||

                    e.getKey().getName().getLocalName().equals("background-color")
                    || e.getKey().getName().getLocalName().equals("color")
                    || e.getKey().getName().getLocalName().equals("margin-left")
                    || e.getKey().getName().getLocalName().equals("margin-right")
                    || e.getKey().getName().getLocalName().equals("margin-top")
                    || e.getKey().getName().getLocalName().equals("margin-bottom")
                    || e.getKey().getName().getLocalName().equals("line-height")) {

                SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);

                rule.set(e.getKey().getName().getLocalName(), new CSSName(e.getValue()));
            } else if (e.getKey().getName().getLocalName().equals("font-size")) {
                SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
                String s = e.getValue();
                if (s.endsWith("pt")) {
                    s = s.substring(0, s.length() - 2);
                    BigDecimal ref = new BigDecimal(12);
                    BigDecimal val = new BigDecimal(s);

                    rule.set(e.getKey().getName().getLocalName(), new CSSLength(val
                            .divide(ref, 2, RoundingMode.HALF_UP).doubleValue(), "em"));
                } else {
                    rule.set(e.getKey().getName().getLocalName(), new CSSName(e.getValue()));
                }
            } else if (e.getKey().getName().getLocalName().equals("text-underline-style")&&!e.getValue().equals("none")) {
                SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
                rule.set("text-decoration", new CSSName("underline"));
                rule.set(e.getKey().getName().getLocalName(), new CSSName(e.getValue()));
            } else if (e.getKey().getName().getLocalName().equals("text-align")) {
                SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
                String val = e.getValue();
                if (val.equals("end")) {
                    val = "right";
                } else if (val.equals("start")) {
                    val = "left";
                }
                rule.set(e.getKey().getName().getLocalName(), new CSSName(val));
            } else if (e.getKey().getName().getLocalName().equals("font-name")) {
                SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);

                rule.set("font-family", new CSSQuotedString(e.getValue()));
            } else if (e.getKey().getName().getLocalName().equals("text-indent")) {
                SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);

                rule.set(e.getKey().getName().getLocalName(), new CSSName(e.getValue()));
            }else if (e.getKey().getName().getLocalName().equals("horizontal-pos")) {//for images
                SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
                String pos="center";
                if(e.getValue().contains("left")){
                  pos="left";
                }else if(e.getValue().contains("right")){
                  pos="right";
                }
               // rule.set("text-align", new CSSName(pos));
            }
           
           

        }

    }

    protected Element addImageBox(OdfDrawFrame box, Element dstElem) {
      
     
     
     
        Selector selector = getStylesheet().getSimpleSelector(null, box.getStyleName());
        SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
        rule.set("width", new CSSName("100%"));

        rule.set("text-align", new CSSName("center"));
        Element idiv = getFootnotesResource().getDocument().createElement("div");
        idiv.setClassName(box.getStyleName());
        stylesPropsToCSS(box.getAutomaticStyle().getStyleProperties(), idiv.getClassName());
        dstElem.add(idiv);
        return idiv;
    }

    protected void addImage(OdfDrawImage imgOdf, Element dstElem) {
           
            addImage(imgOdf.getImageUri().toString(), dstElem);
      

    }
    protected BitmapImageResource addImage(String imgUri, Element dstElem, OPSResource dstResource) {
        try {

            String mimetype = null;
            String ext = null;
            if (imgUri.toString().toUpperCase().endsWith("JPG")
                    || imgUri.toUpperCase().endsWith("JPEG")) {
                mimetype = "image/jpeg";
                ext = "jpg";
            } else if (imgUri.toUpperCase().endsWith("PNG")) {
                mimetype = "image/png";
                ext = "png";
            } else if (imgUri.toUpperCase().endsWith("GIF")) {
                mimetype = "image/gif";
                ext = "gif";
            }
            if (mimetype != null) {
                byte[] content=getOdt().getPackage().getBytes(
                        imgUri);
                if(content==null){
                    File f=new File(imgUri);
                    if(f.exists()){
                        content=Utils.getBytesFromFile(f);
                    }
                }
                if(content!=null){
                    DataSource dataSource = new ByteArrayImageDataSource(content);
   
                    BitmapImageResource imageResource = getEpub().createBitmapImageResource(
                            "OPS/images/" + System.currentTimeMillis() + (Math.random() * 100) + "." + ext, mimetype,
                            dataSource);
                    ImageElement bitmap = dstResource.getDocument().createImageElement("img");
                    bitmap.setImageResource(imageResource);
                   
                    dstElem.add(bitmap);
                   
                    return imageResource;
                }
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }
       
        return null;

    }
    protected void addImage(String imgUri, Element dstElem) {
        addImage(imgUri, dstElem,  getCurrentResource());

    }
   
    protected Element addFootnote(TextNoteElement e, Element dstElem) throws Exception {

        TextNoteCitationElement noteCit = (TextNoteCitationElement) getXpath().evaluate(".//text:note-citation", e,
                XPathConstants.NODE);

        // Element fn=addFootnoteLink(noteCit.getTextContent(),dstElem);

        Element fn = getFootnotesResource().getDocument().createElement("div");
        fn.setClassName("fnDiv");
        getFootnotesResource().getDocument().getBody().add(fn);

        HyperlinkElement a = getCurrentResource().getDocument().createHyperlinkElement("a");
        a.setClassName("fnLink");
        a.setXRef(fn.getSelfRef());
        a.add(noteCit.getTextContent());
        dstElem.add(a);

        Element noteId = getFootnotesResource().getDocument().createHyperlinkElement("p");
        noteId.setClassName("Footnote");
        noteId.add(noteCit.getTextContent() + ")");
        fn.add(noteId);

        HyperlinkElement ar = getFootnotesResource().getDocument().createHyperlinkElement("a");
        // ar.setClassName("fnLink");
        ar.setXRef(a.getSelfRef());
        ar.add(" \u21B5");

        // fn.add(ar);
        OPSResource temp = getCurrentResource();
        setCurrentResource(getFootnotesResource());
        traverse((Node) getXpath().evaluate(".//text:note-body", e, XPathConstants.NODE), fn);
        HTMLElement dst = (HTMLElement) fn.getLastChild();
        while (dst.getLastChild() != null && dst.getLastChild() instanceof Element
                && ((Element) dst.getLastChild()).getElementName().equals("p")) {
            dst = (HTMLElement) dst.getLastChild();
        }
        dst.add(ar);

        setCurrentResource(temp);
        _hasFootnotes=true;
        return fn;
    }

    /**
     * Used to prevent negative indentations and to set default styles
     */
    public void setFootnotesCSSStyles() {
        Selector selector = getStylesheet().getSimpleSelector(null, "fnDiv");
        SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
        rule.set("page-break-before", new CSSName("always"));
        rule.set("margin-left", new CSSName("0em"));
        rule.set("margin-right", new CSSName("0em"));
        // if(rule.get("text-indent")!=null&&rule.get("text-indent").toCSSString().startsWith("-")){
        // rule.set("text-indent", new CSSLength(0,"em"));
        // }
        selector = getStylesheet().getSimpleSelector(null, "Footnote");
        rule = getStylesheet().getRuleForSelector(selector, true);

        // if(rule.get("text-indent")!=null&&rule.get("text-indent").toCSSString().startsWith("-")){
        // rule.set("text-indent", new CSSLength(0,"em"));
        // }

        selector = getStylesheet().getSimpleSelector("a", "fnLink");
        rule = getStylesheet().getRuleForSelector(selector, true);
        rule.set("vertical-align", new CSSName("super"));
        rule.set("font-size", new CSSLength(0.80, "em"));
    }

    public boolean hasPageBreak(OdfStylableElement e) throws XPathExpressionException {
        if (e.getAutomaticStyle() != null) {
            StyleParagraphPropertiesElement sp = (StyleParagraphPropertiesElement) getXpath().evaluate(
                    ".//style:paragraph-properties", e.getAutomaticStyle(), XPathConstants.NODE);
            if (sp != null) {
                String pbreak = sp.getAttribute("fo:break-before");
                if (pbreak != null && pbreak.trim().length() > 0 && pbreak.equals("page")) {
                    return true;
                }
            }
        }
        return false;

    }

    public void addTocEntry(String title, int headingLevel, Element dstElem) {
        TOCEntry te = getToc().createTOCEntry(title, dstElem.getSelfRef());
        boolean found = false;
        for (int j = getTocEntriesBuffer().size() - 1; j >= 0; j--) {

            TOCLevel target = getTocEntriesBuffer().get(j);
            if (target.getHeadingLevel() < headingLevel) {
                target.getTOCEntry().add(te);
                found = true;
                break;
            }
        }
        if (!found) {
            getToc().getRootTOCEntry().add(te);
        }
        getTocEntriesBuffer().add(new TOCLevel(headingLevel, te));

    }

    public Stack<TOCLevel> getTocEntriesBuffer() {
        if (tocEntriesBuffer == null) {
            tocEntriesBuffer = new Stack<TOCLevel>();

        }

        return tocEntriesBuffer;
    }

    public StyleResource getStyleResource() {
        if (_styleResource == null) {
            _styleResource = getEpub().createStyleResource("OPS/styles.css");

        }

        return _styleResource;
    }

    protected void extractDefaultStyles(OdfOfficeStyles styles) {

        for (OdfStyle s : styles.getStylesForFamily(OdfStyleFamily.Paragraph)) {

            if (s.getAttribute("style:name").equals("Heading")) {
                stylesPropsToCSS(s.getStyleProperties(), "h1", null);
                stylesPropsToCSS(s.getStyleProperties(), "h2", null);
                stylesPropsToCSS(s.getStyleProperties(), "h3", null);
                stylesPropsToCSS(s.getStyleProperties(), "h4", null);
                stylesPropsToCSS(s.getStyleProperties(), "h5", null);
                stylesPropsToCSS(s.getStyleProperties(), "h6", null);
                stylesPropsToCSS(s.getStyleProperties(), "h7", null);
                stylesPropsToCSS(s.getStyleProperties(), "h8", null);
                stylesPropsToCSS(s.getStyleProperties(), "h9", null);
                stylesPropsToCSS(s.getStyleProperties(), "h10", null);

            }else    if (s.getAttribute("style:name").startsWith("Heading")) {
                String level = s.getAttribute("style:default-outline-level");
                if (level != null && level.trim().length() > 0) {
                    stylesPropsToCSS(s.getStyleProperties(), "h" + level, null);
                }
            }else  if (s.getAttribute("style:name").startsWith("Standard")) {

                stylesPropsToCSS(s.getStyleProperties(), "p", null);

            }else  if (s.getAttribute("style:name").startsWith("Footnote")) {
                stylesPropsToCSS(s.getStyleProperties(), null, "Footnote");
                stylesPropsToCSS(s.getStyleProperties(), null, "fnDiv");
            }else if (s.getAttribute("style:name")!=null&&!s.getAttribute("style:name").trim().equals("")) {
                stylesPropsToCSS(s.getStyleProperties(), null, s.getAttribute("style:name"));
            }
            if (isDebugMode()) {
                System.out.println("Nome: " + s.getAttribute("style:name") + " Classe: "
                        + s.getAttribute("style:class") + "Outline Level"
                        + s.getAttribute("style:default-outline-level"));
                System.out.println("{");
                Utils.printStyleProps(s.getStyleProperties());
                System.out.println("}");
            }
        }

        if (isDebugMode()) {
            System.out.println("-----");
            System.out.println("Stile di testo");
            for (OdfStyle s : styles.getStylesForFamily(OdfStyleFamily.Text)) {

                System.out.println("Nome: " + s.getAttribute("style:name") + " Classe: "
                        + s.getAttribute("style:class"));
                System.out.println("{");
                Utils.printStyleProps(s.getStyleProperties());
                System.out.println("}");
            }
            System.out.println("-----");
            System.out.println("Stili di default");
        }
        for (OdfDefaultStyle ds : styles.getDefaultStyles()) {
            stylesPropsToCSS(ds.getStyleProperties(), "body", null);
            if (isDebugMode()) {
                Utils.printStyleProps(ds.getStyleProperties());
            }
        }

       
        Selector selector = getStylesheet().getSimpleSelector("body", null);
        SelectorRule rule = getStylesheet().getRuleForSelector(selector, true);
        CSSValue minh = rule.get("font-size");
        selector = getStylesheet().getSimpleSelector("p", null);
        rule = getStylesheet().getRuleForSelector(selector, true);
        if (rule.get("margin-top") == null) {
            rule.set("margin-top", new CSSLength(0d, "em"));
        }
        if (rule.get("margin-bottom") == null) {
            rule.set("margin-bottom", new CSSLength(0d, "em"));
        }

        if (minh != null) {
            rule.set("min-height", minh);
        }

    }

    public XPath getXpath() {
        if (xpath == null) {
            xpath = XPathFactory.newInstance().newXPath();

        }

        return xpath;
    }

    public Map<String, Element> getBookmarks() {
        if (bookmarks == null) {
            bookmarks = new HashMap<String, Element>();

        }

        return bookmarks;
    }

    public Set<HyperlinkElement> getInternalLink() {
        if (internalLink == null) {
            internalLink = new HashSet<HyperlinkElement>();

        }

        return internalLink;
    }

    public void processInternalLinksCrossReferences() {
        for (HyperlinkElement h : getInternalLink()) {
            Element target = getBookmarks().get(h.getTitle());
            if (target != null) {
                h.setTitle("");
                h.setXRef(target.getSelfRef());
            }
        }

    }
   
    protected void  bookmarksToToc(){
        if(getBookmarks().size()>0){
            List<String> bl=new ArrayList();
            for (String e : getBookmarks().keySet()) {
                bl.add(e);
            }
            Collections.sort(bl);
           
            addTocEntry("Bookmarks", 0, getBookmarks().get(bl.get(0)));
           
            for (String k : bl) {
                Element el=getBookmarks().get(k);
                addTocEntry(el.getId(), 1, el);
            }
          
        }
    }

    private void printClassesFound() {
        for (String s : classesForDebug) {
            System.out.println(s);
        }
    }

    public boolean isDebugMode() {
        return debugMode;
    }

    public void setDebugMode(boolean debugMode) {
        this.debugMode = debugMode;
    }

    public int getMaxFilesSize() {
        return maxFilesSize;
    }

    public void setMaxFilesSize(int maxFilesSize) {
        this.maxFilesSize = maxFilesSize;
    }

    public String getFontsPath() {
        return fontsPath;
    }

    public void setFontsPath(String fontsPath) {
        this.fontsPath = fontsPath;
    }
   
    public String getCoverPath() {
        return coverPath;
    }

    public void setCoverPath(String coverPath) {
        this.coverPath = coverPath;
    }
    public boolean isExposeBookmarks() {
        return exposeBookmarks;
    }

    public void setExposeBookmarks(boolean exposeBookmarks) {
        this.exposeBookmarks = exposeBookmarks;
    }
}
TOP

Related Classes of org.bazu.jotex.OdtEPUBlisher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.