com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xmlworker Show documentation
Show all versions of xmlworker Show documentation
Parses XML to PDF, with CSS support, using iText
/*
* $Id: 34b1478b3a1c7b6d03db3b0679be4d24a94314b8 $
*
* This file is part of the iText (R) project.
* Copyright (c) 1998-2015 iText Group NV
* Authors: Balder Van Camp, Emiel Ackermann, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
* OF THIRD PARTY RIGHTS
*
* This program 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 Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA, 02110-1301 USA, or download the license from the following URL:
* http://itextpdf.com/terms-of-use/
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* In accordance with Section 7(b) of the GNU Affero General Public License,
* a covered work must retain the producer line in every PDF that is created
* or manipulated using iText.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the iText software without
* disclosing the source code of your own applications.
* These activities include: offering paid services to customers as an ASP,
* serving PDFs on the fly in a web application, shipping iText with a closed
* source product.
*
* For more information, please contact iText Software Corp. at this
* address: [email protected]
*/
package com.itextpdf.tool.xml.pipeline.html;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import com.itextpdf.text.*;
import com.itextpdf.tool.xml.CustomContext;
import com.itextpdf.tool.xml.Experimental;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.css.apply.ListStyleTypeCssApplier;
import com.itextpdf.tool.xml.css.apply.MarginMemory;
import com.itextpdf.tool.xml.css.apply.PageSizeContainable;
import com.itextpdf.tool.xml.exceptions.NoDataException;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersAware;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Header;
import com.itextpdf.tool.xml.html.Image;
import com.itextpdf.tool.xml.html.TagProcessor;
import com.itextpdf.tool.xml.html.TagProcessorFactory;
import com.itextpdf.tool.xml.html.Tags;
/**
* The CustomContext object for the HtmlPipeline.
* Use this to configure your {@link HtmlPipeline}.
* @author redlab_b
*
*/
public class HtmlPipelineContext implements CustomContext, Cloneable, MarginMemory, PageSizeContainable,
CssAppliersAware {
/**
* Key for the memory, used to store bookmark nodes
*/
public static final String BOOKMARK_TREE = "header.autobookmark.RootNode";
/**
* Key for the memory, used in Html TagProcessing
*/
public static final String LAST_MARGIN_BOTTOM = "lastMarginBottom";
private final LinkedList queue;
private boolean acceptUnknown = true;
private TagProcessorFactory tagFactory;
private final List ctn = new ArrayList();
private ImageProvider imageProvider;
private String resourcesRootPath;
private Rectangle pageSize = PageSize.A4;
private Charset charset;
private List roottags = Arrays.asList(new String[] { "body", "div" });
private LinkProvider linkprovider;
private boolean autoBookmark = true;
private final Map memory;
private CssAppliers cssAppliers;
/**
* Construct a new HtmlPipelineContext object
*/
public HtmlPipelineContext(CssAppliers cssAppliers) {
this.queue = new LinkedList();
this.memory = new HashMap();
this.cssAppliers = cssAppliers;
if (this.cssAppliers == null) {
this.cssAppliers = new CssAppliersImpl(new XMLWorkerFontProvider());
}
}
/**
* @param tag the tag to find a TagProcessor for
* @param nameSpace the namespace.
* @return a TagProcessor
*/
protected TagProcessor resolveProcessor(final String tag, final String nameSpace) {
TagProcessor tp = tagFactory.getProcessor(tag, nameSpace);
if (tp instanceof CssAppliersAware) {
((CssAppliersAware) tp).setCssAppliers(this.cssAppliers);
}
return tp;
}
/**
* Add a {@link StackKeeper} to the top of the stack list.
* @param stackKeeper the {@link StackKeeper}
*/
protected void addFirst(final StackKeeper stackKeeper) {
this.queue.addFirst(stackKeeper);
}
/**
* Retrieves, but does not remove, the head (first element) of this list.
* @return a StackKeeper or null if there are no elements on the stack
*/
protected StackKeeper peek() {
if (!this.queue.isEmpty())
return this.queue.getFirst();
return null;
}
/**
* @return the current content of elements.
*/
protected List currentContent() {
return ctn;
}
/**
* @return if this pipelines tag processing accept unknown tags: true. False otherwise
*/
public boolean acceptUnknown() {
return this.acceptUnknown;
}
/**
* @return returns true if the stack is empty
*/
protected boolean isEmpty() {
return queue.isEmpty();
}
/**
* Retrieves and removes the top of the stack.
* @return a StackKeeper
* @throws NoStackException if there are no elements on the stack
*/
protected StackKeeper poll() throws NoStackException {
try {
return this.queue.removeFirst();
} catch (NoSuchElementException e) {
throw new NoStackException();
}
}
/**
* @return true if auto-bookmarks should be enabled. False otherwise.
*/
public boolean autoBookmark() {
return autoBookmark;
}
/**
* @return the memory
*/
public Map getMemory() {
return memory;
}
/**
* @return the image provider or null if there is no {@link ImageProvider}.
*
*/
public ImageProvider getImageProvider() {
return this.imageProvider;
}
/**
* Set a {@link Charset} to use.
* @param cSet the charset.
* @return this HtmlPipelineContext
*/
@Experimental
public HtmlPipelineContext charSet(final Charset cSet) {
this.charset = cSet;
return this;
}
/**
* @return the {@link Charset} to use, or null if none configured.
*/
public Charset charSet() {
return charset;
}
/**
* Returns a {@link Rectangle}
* @return the pagesize.
*/
public Rectangle getPageSize() {
return this.pageSize;
}
/**
* @return a list of tags to be taken as root-tags. This matters for
* margins. By default the root-tags are <body> and
* <div>
*/
public List getRootTags() {
return roottags;
}
/**
* Returns the LinkProvider, used to prepend e.g. http://www.example.org/ to
* found <a> tags that have no absolute url.
*
* @return the LinkProvider if any.
*/
public LinkProvider getLinkProvider() {
return linkprovider;
}
/**
* If no pageSize is set, the default value A4 is used.
* @param pageSize the pageSize to set
* @return this HtmlPipelineContext
*/
public HtmlPipelineContext setPageSize(final Rectangle pageSize) {
this.pageSize = pageSize;
return this;
}
/**
* Create a clone of this HtmlPipelineContext, the clone only contains the
* initial values, not the internal values. Beware, the state of the current
* Context is not copied to the clone. Only the configurational important
* stuff like the LinkProvider (same object), ImageProvider (new
* {@link AbstractImageProvider} with same ImageRootPath) ,
* TagProcessorFactory (same object), acceptUnknown (primitive), charset
* (Charset.forName to get a new charset), autobookmark (primitive) are
* copied.
*/
@Override
public HtmlPipelineContext clone() throws CloneNotSupportedException {
CssAppliers cloneCssApliers = this.cssAppliers.clone();
HtmlPipelineContext newCtx = new HtmlPipelineContext(cloneCssApliers);
if (this.imageProvider != null) {
newCtx.setImageProvider(imageProvider);
}
if (null != this.charset) {
newCtx.charSet(Charset.forName(this.charset.name()));
}
newCtx.setPageSize(new Rectangle(this.pageSize)).setLinkProvider(this.linkprovider)
.setRootTags(new ArrayList(this.roottags)).autoBookmark(this.autoBookmark)
.setTagFactory(this.tagFactory).setAcceptUnknown(this.acceptUnknown).setCssApplier(cloneCssApliers);
return newCtx;
}
/**
* Set to true to allow the HtmlPipeline to accept tags it does not find in
* the given {@link TagProcessorFactory}
*
* @param acceptUnknown true or false
* @return this HtmlPipelineContext
*/
public HtmlPipelineContext setAcceptUnknown(final boolean acceptUnknown) {
this.acceptUnknown = acceptUnknown;
return this;
}
/**
* Set the {@link TagProcessorFactory} to be used. For HTML use {@link Tags#getHtmlTagProcessorFactory()}
* @param tagFactory the {@link TagProcessorFactory} that should be used
* @return this HtmlPipelineContext
*/
public HtmlPipelineContext setTagFactory(final TagProcessorFactory tagFactory) {
this.tagFactory = tagFactory;
return this;
}
/**
* Set to true to enable the automatic creation of bookmarks on <h1>
* to <h6> tags. Works in conjunction with {@link Header}.
*
* @param autoBookmark true or false
* @return this HtmlPipelineContext
*/
public HtmlPipelineContext autoBookmark(final boolean autoBookmark) {
this.autoBookmark = autoBookmark;
return this;
}
/**
* Set the root-tags, this matters for margins. By default these are set to
* <body> and <div>.
*
* @param roottags the root tags
* @return this HtmlPipelineContext
*/
public HtmlPipelineContext setRootTags(final List roottags) {
this.roottags = roottags;
return this;
}
/**
* An ImageProvider can be provided and works in conjunction with
* {@link Image} and {@link ListStyleTypeCssApplier} for List Images.
*
* @param imageProvider the {@link ImageProvider} to use.
* @return this HtmlPipelineContext
*/
public HtmlPipelineContext setImageProvider(final ImageProvider imageProvider) {
this.imageProvider = imageProvider;
return this;
}
/**
* Set the LinkProvider to use if any.
*
* @param linkprovider the LinkProvider (@see
* {@link HtmlPipelineContext#getLinkProvider()}
* @return this HtmlPipelineContext
*/
public HtmlPipelineContext setLinkProvider(final LinkProvider linkprovider) {
this.linkprovider = linkprovider;
return this;
}
/* (non-Javadoc)
* @see com.itextpdf.tool.xml.css.MarginMemory#getLastMarginBottom()
*/
public Float getLastMarginBottom() throws NoDataException {
Map memory = getMemory();
Object o = memory.get(HtmlPipelineContext.LAST_MARGIN_BOTTOM);
if (null == o) {
throw new NoDataException();
} else {
return (Float) o;
}
}
/* (non-Javadoc)
* @see com.itextpdf.tool.xml.css.MarginMemory#setLastMarginBottom(float)
*/
public void setLastMarginBottom(final Float lmb) {
getMemory().put(HtmlPipelineContext.LAST_MARGIN_BOTTOM, lmb);
}
/*
* (non-Javadoc)
*
* @see com.itextpdf.tool.xml.html.CssAppliersAware#setCssAppliers(com.itextpdf.tool.xml.html.CssAppliers)
*/
public void setCssAppliers(final CssAppliers cssAppliers) {
this.cssAppliers = cssAppliers;
}
/*
* (non-Javadoc)
*
* @see com.itextpdf.tool.xml.html.CssAppliersAware#getCssAppliers()
*/
public CssAppliers getCssAppliers() {
return cssAppliers;
}
/**
* Fluent variant of {@link #setCssAppliers(CssAppliers)}
*
* @param cssAppliers the cssAppliers
* @return this
*/
public HtmlPipelineContext setCssApplier(final CssAppliers cssAppliers) {
this.cssAppliers = cssAppliers;
return this;
}
public String getResourcesRootPath() {
return resourcesRootPath;
}
public void setResourcesRootPath(String resourcesRootPath) {
this.resourcesRootPath = resourcesRootPath;
}
}