org.jrimum.bopepo.pdf.PdfDocMix.java Source code

Java tutorial

Introduction

Here is the source code for org.jrimum.bopepo.pdf.PdfDocMix.java

Source

/*
 * Copyright 2011 JRimum Project
 * 
 * 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.
 * 
 * Created at: 14/04/2011 - 14:49:07
 * 
 * ================================================================================
 * 
 * Direitos autorais 2011 JRimum Project
 * 
 * Licenciado sob a Licena Apache, Verso 2.0 ("LICENA"); voc no pode usar
 * esse arquivo exceto em conformidade com a esta LICENA. Voc pode obter uma
 * cpia desta LICENA em http://www.apache.org/licenses/LICENSE-2.0 A menos que
 * haja exigncia legal ou acordo por escrito, a distribuio de software sob
 * esta LICENA se dar COMO EST??, SEM GARANTIAS OU CONDIES DE QUALQUER
 * TIPO, sejam expressas ou tcitas. Veja a LICENA para a redao especfica a
 * reger permisses e limitaes sob esta LICENA.
 * 
 * Criado em: 14/04/2011 - 14:49:07
 * 
 */

package org.jrimum.bopepo.pdf;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.jrimum.utilix.Collections.hasElement;
import static org.jrimum.utilix.Objects.checkNotNull;
import static org.jrimum.utilix.Objects.isNotNull;
import static org.jrimum.utilix.Objects.isNull;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.WeakHashMap;

import org.apache.log4j.Logger;
import org.jrimum.utilix.Collections;
import org.jrimum.utilix.Exceptions;
import org.jrimum.utilix.Objects;
import org.jrimum.utilix.text.Strings;

import com.lowagie.text.Image;
import com.lowagie.text.pdf.AcroFields;
import com.lowagie.text.pdf.PdfBoolean;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;

/**
 * Classe geradora de documentos PDF utilizando templates com fields.
 * 
 * @author <a href="http://gilmatryx.googlepages.com/">Gilmar P.S.L.</a>
 * @author <a href="mailto:romulomail@gmail.com">Rmulo Augusto</a>
 * 
 * @version 0.2.3
 * 
 * @since 0.2
 */
public class PdfDocMix {

    private static final Logger LOG = Logger.getLogger(PdfDocMix.class);

    private PdfReader reader;
    private PdfStamper stamper;
    private AcroFields form;

    private ByteArrayOutputStream outputStream;

    private Map<java.awt.Image, Image> imagesInUseMap = new WeakHashMap<java.awt.Image, Image>();

    /**
     * Template em byte array.
     */
    private byte[] template;

    /**
     * Informaes sobre o documento.
     */
    private PdfDocInfo docInfo = PdfDocInfo.create();

    /**
     * Map dos campos de texto do documento com nome e valor.
     */
    private Map<String, String> txtMap;

    /**
     * Map dos campos de imagem do documento com nome e valor.
     */
    private Map<String, java.awt.Image> imgMap;

    /**
     * Modo full compression do PDF, default = true.
     * 
     * @since 0.2
     */
    private boolean fullCompression = true;

    /**
     * Remove todos os campos do PDF, default = true.
     * 
     * @since 0.2
     */
    private boolean removeFields = true;

    /**
     * Indicao de que o ttulo do documento deve ser mostrado barra superior.
     * 
     * @since 0.2
     */
    private Boolean displayDocTitle;

    /**
     * Cria uma instncia sem o template que ser utilizado para construir o
     * documento.
     * 
     * @since 0.2
     */
    private PdfDocMix() {
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param template
     * 
     * @since 0.2
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix(byte[] template) {

        checkTemplateFile(template);
        setTemplate(template);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateUrl
     * 
     * @since 0.2
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix(URL templateUrl) {

        checkTemplateFile(templateUrl);
        setTemplate(templateUrl);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateInput
     * 
     * @since 0.2
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix(InputStream templateInput) {

        checkTemplateFile(templateInput);
        setTemplate(templateInput);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templatePath
     * 
     * @since 0.2
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix(String templatePath) {

        checkTemplatePath(templatePath);
        setTemplate(templatePath);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateFile
     * 
     * @since 0.2
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix(File templateFile) {

        checkTemplateFile(templateFile);
        setTemplate(templateFile);
    }

    /**
     * Cria uma instncia sem o template que ser utilizado para construir o
     * documento.
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     */
    public static PdfDocMix create() {

        return new PdfDocMix();
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param template
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public static PdfDocMix createWithTemplate(byte[] template) {

        checkTemplateFile(template);

        return new PdfDocMix(template);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateUrl
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public static PdfDocMix createWithTemplate(URL templateUrl) {

        checkTemplateFile(templateUrl);

        return new PdfDocMix(templateUrl);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateInput
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public static PdfDocMix createWithTemplate(InputStream templateInput) {

        checkTemplateFile(templateInput);

        return new PdfDocMix(templateInput);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templatePath
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public static PdfDocMix createWithTemplate(String templatePath) {

        checkTemplatePath(templatePath);

        return new PdfDocMix(templatePath);
    }

    /**
     * Cria uma instncia com o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateFile
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public static PdfDocMix createWithTemplate(File templateFile) {

        checkTemplateFile(templateFile);

        return new PdfDocMix(templateFile);
    }

    /**
     * Define o template que ser utilizado para construir o
     * documento.
     * 
     * @param template
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix withTemplate(byte[] template) {

        checkTemplateFile(template);

        return setTemplate(template);
    }

    /**
     * Define o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateUrl
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix withTemplate(URL templateUrl) {

        checkTemplateFile(templateUrl);

        return setTemplate(templateUrl);
    }

    /**
     * Define o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateInput
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix withTemplate(InputStream templateInput) {

        checkTemplateFile(templateInput);

        return setTemplate(templateInput);
    }

    /**
     * Define o template que ser utilizado para construir o
     * documento.
     * 
     * @param templatePath
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix withTemplate(String templatePath) {

        checkTemplatePath(templatePath);

        return setTemplate(templatePath);
    }

    /**
     * Define o template que ser utilizado para construir o
     * documento.
     * 
     * @param templateFile
     * 
     * @since 0.2
     * 
     * @return Esta instncia aps a operao
     * 
     * @throws IllegalArgumentException
     *             Caso o {@code template} seja nulo
     */
    public PdfDocMix withTemplate(File templateFile) {

        checkTemplateFile(templateFile);

        return setTemplate(templateFile);
    }

    /**
     * Retorna um {@code Map} com os campos e seus respectivos textos adicionados nessa
     * instncia.
     * 
     * @return Map de campo,texto
     * 
     * @since 0.2
     */
    public Map<String, String> getTextFields() {
        return this.txtMap;
    }

    /**
     * Coloca todos chave-valor na instncia, caso uma chave existe o valor ser
     * substitudo. Caso a instncia no contenha valores ainda, atribui o
     * {@code Map} informado para uso no preenchimento de campos de Texto na
     * instncia.
     * 
     * @param txtMap
     *            Map com os campos(key) e textos(value)
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     */
    public PdfDocMix putAllTexts(Map<String, String> txtMap) {

        Collections.checkNotEmpty(txtMap, "Campos ausentes!");

        if (isNull(this.txtMap)) {
            this.txtMap = txtMap;
        } else {
            this.txtMap.putAll(txtMap);
        }

        return this;
    }

    /**
     * Coloca um par {@code key,value} para uso no preenchimento de campos de
     * Texto na instncia.
     * 
     * @param name
     *            Nome do campo
     * @param value
     *            Valor em texto do campo
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     */
    public PdfDocMix put(String name, String value) {

        Strings.checkNotBlank(name, "Nome do campo ausente!");

        if (isNull(txtMap)) {
            this.txtMap = new WeakHashMap<String, String>();
        }

        this.txtMap.put(name, value);

        return this;
    }

    /**
     * Retorna um {@code Map} com os campos e suas respectivas imagens
     * adicionadas nessa instncia.
     * 
     * @return Map de campo,imagem
     * 
     * @since 0.2
     */
    public Map<String, java.awt.Image> getImageFields() {
        return this.imgMap;
    }

    /**
     * Coloca todos chave-valor na instncia, caso uma chave existe o valor
     * ser substitudo. Caso a instncia no contenha valores ainda, atribui o
     * {@code Map} informado para uso no preenchimento de campos de Imagem na
     * instncia.
     * 
     * @param imgMap
     *            Map com os campos(key) e imagens(value)
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     */
    public PdfDocMix putAllImages(Map<String, java.awt.Image> imgMap) {

        Collections.checkNotEmpty(imgMap, "Campos ausentes!");

        if (isNull(this.imgMap)) {
            this.imgMap = imgMap;
        } else {
            this.imgMap.putAll(imgMap);
        }

        return this;
    }

    /**
     * Coloca um par {@code key,value} para uso no preenchimento de campos de
     * Imagem na instncia.
     * 
     * @param name
     *            Nome do campo
     * @param value
     *            Valor em {@link java.awt.Image} do campo
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     */
    public PdfDocMix put(String name, java.awt.Image value) {

        Strings.checkNotBlank(name, "Nome do campo ausente!");

        if (isNull(imgMap)) {
            this.imgMap = new WeakHashMap<String, java.awt.Image>();
        }

        this.imgMap.put(name, value);

        return this;
    }

    /**
     * Habilita/Desabilita o modo full compression do PDF veja
     * {@link com.lowagie.text.pdf.PdfStamper#setFullCompression()}.
     * 
     * <p>
     * Itext doc: <i>Sets the document's compression to the new 1.5 mode with
     * object streams and xref streams.</i>
     * </p>
     * 
     * @param option
     *            Escolha de compresso
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     * 
     */
    public PdfDocMix withFullCompression(boolean option) {
        this.fullCompression = option;
        return this;
    }

    /**
     * Habilita/Desabilita a remoo dos campos do PDF.
     * 
     * <p>
     * Por padro os campos so removidos, ou seja, default = true.
     * </p>
     * 
     * @param option
     *            Escolha por remoo
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     * 
     */
    public PdfDocMix removeFields(boolean option) {
        this.removeFields = option;
        return this;
    }

    /**
     * Define o Ttulo do documento.
     * 
     * @param title
     * 
     * @return Esta instncia aps a operao
     */
    public PdfDocMix withTitle(String title) {
        docInfo.title(title);
        return this;
    }

    /**
     * Define o Autor do documento.
     * 
     * @param author
     * 
     * @return Esta instncia aps a operao
     */
    public PdfDocMix withAuthor(String author) {
        docInfo.author(author);
        return this;
    }

    /**
     * Define o Assunto do documento.
     * 
     * @param subject
     * 
     * @return Esta instncia aps a operao
     */
    public PdfDocMix withSubject(String subject) {
        docInfo.subject(subject);
        return this;
    }

    /**
     * Define as Palavras-chave do documento.
     * 
     * @param keywords
     * 
     * @return Esta instncia aps a operao
     */
    public PdfDocMix withKeywords(String keywords) {
        docInfo.keywords(keywords);
        return this;
    }

    /**
     * Define o Software/Ferramenta de criao do documento.
     * 
     * @param creator
     * 
     * @return Esta instncia aps a operao
     */
    public PdfDocMix withCreator(String creator) {
        docInfo.creator(creator);
        return this;
    }

    /**
     * Define a data de criao do documento.
     * 
     * @param date Data de criao
     * 
     * @return Esta instncia aps a operao
     */
    public PdfDocMix withCreation(Calendar date) {
        docInfo.creation(date);
        return this;
    }

    /**
     * Redefine as meta-informaes do documento, ex: ttulo, autor, data de
     * criao, etc.
     * 
     * <p>
     * Todas as informaes anteriormente atribudas por:
     * {@linkplain #withTitle(String)}, {@linkplain #withSubject(String)}, etc. sero
     * substitudas pelo contedo do {@code docInfo} nessa operao.
     * </p>
     * 
     * @param docInfo
     *            Informaes sobre o documento
     * 
     * @return Esta instncia aps a operao
     * 
     * @see org.jrimum.bopepo.pdf.PdfDocInfo
     */
    public PdfDocMix withDocInfo(PdfDocInfo docInfo) {

        checkNotNull(docInfo, "Valor null para docInfo no permitido!");

        this.docInfo = docInfo;

        return this;
    }

    /**
     * Define se o ttulo do documento ser exibido na barra superior do PDF.
     * 
     * <p>
     * Caso no seja informada uma opo, prevalece a definio do template PDF.
     * </p>
     * 
     * @param option
     * 
     * @return Esta instncia aps a operao
     */
    public PdfDocMix withDisplayDocTilteOption(boolean option) {

        this.displayDocTitle = option;

        return this;
    }

    /**
     * Retorna o documento em forma de arquivo PDF.
     * 
     * @param destPath
     *            Caminho completo do arquivo o qual o documento ser gerado
     * @return Documento em forma de arquivo PDF
     * 
     * @since 0.2
     * 
     */
    public File toFile(String destPath) {

        checkDestPath(destPath);

        return toFile(new File(destPath));
    }

    /**
     * Retorna o documento em forma de arquivo PDF.
     * 
     * @param destURL
     *            URL do arquivo o qual o documento ser gerado
     * @return Documento em forma de arquivo PDF
     * 
     * @since 0.2
     * 
     */
    public File toFile(URL destURL) {

        checkDestURL(destURL);

        try {

            return toFile(new File(destURL.toURI()));

        } catch (Exception e) {

            LOG.error("Erro durante a criao do arquivo! " + e.getLocalizedMessage(), e);

            return Exceptions.throwIllegalStateException(
                    "Erro ao tentar criar arquivo! " + "Causado por " + e.getLocalizedMessage(), e);
        }
    }

    /**
     * Retorna o documento em forma de arquivo PDF.
     * 
     * @param destFile
     *            Arquivo o qual o boleto ser gerado
     * @return Documento em forma de arquivo PDF
     * @throws IllegalStateException
     *             Caso ocorral algum problema imprevisto
     * 
     * @since 0.2
     * 
     */
    public File toFile(File destFile) {

        checkDestFile(destFile);

        try {

            process();

            return Files.bytesToFile(destFile, outputStream.toByteArray());

        } catch (Exception e) {

            LOG.error("Erro durante a criao do arquivo! " + e.getLocalizedMessage(), e);

            return Exceptions.throwIllegalStateException(
                    "Erro ao tentar criar arquivo! " + "Causado por " + e.getLocalizedMessage(), e);
        }
    }

    /**
     * Retorna o arquivo PDF em um stream de array de bytes.
     * 
     * @return O PDF em stream
     * 
     * @since 0.2
     * 
     */
    public ByteArrayOutputStream toStream() {

        try {

            process();

            return Files.bytesToStream(outputStream.toByteArray());

        } catch (Exception e) {

            LOG.error("Erro durante a criao do stream! " + e.getLocalizedMessage(), e);

            return Exceptions.throwIllegalStateException(
                    "Erro durante a criao do stream! " + "Causado por " + e.getLocalizedMessage(), e);
        }
    }

    /**
     * Retorna o arquivo PDF em array de bytes.
     * 
     * @return O PDF em array de bytes
     * 
     * @since 0.2
     * 
     */
    public byte[] toBytes() {

        try {

            process();

            return outputStream.toByteArray();

        } catch (Exception e) {

            LOG.error("Erro durante a criao do array de bytes! " + e.getLocalizedMessage(), e);

            return Exceptions.throwIllegalStateException(
                    "Erro durante a criao do array de bytes! " + "Causado por " + e.getLocalizedMessage(), e);
        }
    }

    /**
     * Retorna o uma cpia do template atual do viewer em array de bytes.
     * 
     * @return Template em bytes
     * 
     * @since 0.2
     * 
     */
    public byte[] getTemplate() {

        return template.clone();
    }

    /**
     * Define o template que ser utilizado para construir o documento.
     * 
     * @param template
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     * 
     */
    private PdfDocMix setTemplate(byte[] template) {
        this.template = template;
        return this;
    }

    /**
     * Define o template que ser utilizado para construir o documento.
     * 
     * @param templateUrl
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     * 
     */
    private PdfDocMix setTemplate(URL templateUrl) {
        try {
            setTemplate(templateUrl.openStream());
            return this;
        } catch (Exception e) {
            return Exceptions.throwIllegalStateException(e);
        }
    }

    /**
     * Define o template que ser utilizado para construir o documento.
     * 
     * @param templateInput
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     * 
     */
    private PdfDocMix setTemplate(InputStream templateInput) {
        try {
            setTemplate(Files.toByteArray(templateInput));
            return this;
        } catch (Exception e) {
            return Exceptions.throwIllegalStateException(e);
        }
    }

    /**
     * Define o template que ser utilizado para construir o documento.
     * 
     * @param templatePath
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     * 
     */
    private PdfDocMix setTemplate(String templatePath) {
        setTemplate(new File(templatePath));
        return this;
    }

    /**
     * Define o template que ser utilizado para construir o documento.
     * 
     * @param templateFile
     * 
     * @return Esta instncia aps a operao
     * 
     * @since 0.2
     * 
     */
    private PdfDocMix setTemplate(File templateFile) {
        try {
            setTemplate(Files.fileToBytes(templateFile));
            return this;
        } catch (Exception e) {
            return Exceptions.throwIllegalStateException(e);
        }
    }

    /**
     * Indica se o viewer foi habilitado a comprimir o pdf do documento gerado.
     * 
     * @see #withFullCompression(boolean)
     * 
     * @return indicativo de compresso
     * 
     * @since 0.2
     * 
     */
    private boolean isFullCompression() {
        return this.fullCompression;
    }

    /**
     * Indica se o viewer foi habilitado para remover todos os campos do pdf
     * gerado.
     * 
     * @see #removeFields
     * 
     * @return indicativo de compresso
     * 
     * @since 0.2
     */
    private boolean isRemoveFields() {
        return removeFields;
    }

    /**
     * Executa os seguintes mtodos na sequncia:
     * <ol>
     * <li>{@linkplain #init()}</li>
     * <li>{@linkplain #fillFields()}</li>
     * <li>{@linkplain #end()}</li>
     * </ol>
     * 
     * @since 0.2
     */
    private void process() {

        init();
        fillFields();
        end();
    }

    /**
     * Inicializa os principais objetos para a escrita dos dados do documento no
     * template PDF: {@code stamper}, {@code reader} e {@code outputStream}.
     * 
     * @since 0.2
     */
    private void init() {

        try {

            reader = new PdfReader(getTemplate());

            outputStream = new ByteArrayOutputStream();

            stamper = new PdfStamper(reader, outputStream);

            final String JRIMUM = "jrimum.org/bopepo";

            String creator = docInfo.creator();

            if (isBlank(creator)) {
                withCreator(JRIMUM);
            } else {
                withCreator(creator + " by (" + JRIMUM + ")");
            }

            if (isNull(docInfo.creation())) {
                docInfo.creation(Calendar.getInstance());
            }

            stamper.setMoreInfo((HashMap<?, ?>) docInfo.toMap());

            if (isNotNull(displayDocTitle)) {
                stamper.addViewerPreference(PdfName.DISPLAYDOCTITLE,
                        displayDocTitle ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
            }

            form = stamper.getAcroFields();

        } catch (Exception e) {

            Exceptions.throwIllegalStateException(e);
        }
    }

    /**
     * Preenche todos os campos do formulrio PDF com os dados do documento
     * contido na instncia.
     * 
     * @since 0.2
     */
    private void fillFields() {

        setTextFields();
        setImageFields();
    }

    /**
     * Adiciona, caso existam, os textos definidos em
     * {@linkplain #put(String, String)} ou {@linkplain #putAllTexts(Map)}.
     * 
     * @since 0.2
     */
    private void setTextFields() {

        if (hasElement(txtMap)) {
            for (Entry<String, String> e : txtMap.entrySet()) {
                try {
                    form.setField(e.getKey(), e.getValue());
                } catch (Exception ex) {
                    Exceptions.throwIllegalStateException(ex);
                }
            }
        }
    }

    /**
     * Coloca as imagens dos campos no pdf de acordo com o nome dos campos do
     * documento atribudos no map e templante.
     * 
     * @since 0.2
     */
    private void setImageFields() {

        if (hasElement(imgMap)) {
            for (Entry<String, java.awt.Image> e : imgMap.entrySet()) {
                setImage(e.getKey(), e.getValue());
            }
        }
    }

    /**
     * Coloca uma imagem no pdf de acordo com o nome do field no templante.
     * 
     * @param fieldName
     * @param image
     * 
     * @since 0.2
     */
    private void setImage(String fieldName, java.awt.Image image) {

        float posImgField[];

        if (isNotBlank(fieldName)) {

            posImgField = form.getFieldPositions(fieldName);

            if (isNotNull(posImgField)) {
                try {
                    PDFs.changeFieldToImage(stamper, posImgField, getPdfImage(image));
                } catch (Exception e) {
                    Exceptions.throwIllegalStateException(e);
                }
            } else {
                LOG.warn("Posicionamento do campo de imagem nao encontrado! CAMPO: " + fieldName);
            }
        }
    }

    public Image getPdfImage(java.awt.Image image) {

        Image pdfImage = imagesInUseMap.get(image);

        if (isNull(pdfImage)) {
            try {
                pdfImage = Image.getInstance(image, null);
                imagesInUseMap.put(image, pdfImage);
            } catch (Exception ex) {
                Exceptions.throwIllegalStateException(ex);
            }
        }
        return pdfImage;
    }

    /**
     * Finaliza a escrita de dados no template atravs do fechamento do
     * {@code stamper}, {@code reader} e {@code outputStream}.
     * 
     * @since 0.2
     */
    private void end() {

        if (isFullCompression()) {
            stamper.setFullCompression();
        }

        if (isRemoveFields()) {
            stamper.setFreeTextFlattening(true);
            stamper.setFormFlattening(true);
            reader.removeFields();
        } else {
            stamper.setFreeTextFlattening(false);
            stamper.setFormFlattening(false);
        }

        reader.consolidateNamedDestinations();

        reader.eliminateSharedStreams();

        try {
            // Send immediately
            outputStream.flush();
            // close All in this order
            outputStream.close();
            reader.close();
            stamper.close();

        } catch (Exception e) {
            Exceptions.throwIllegalStateException(e);
        }
    }

    private static void checkDestPath(String path) {

        checkString(path, "Caminho destinado a gerao do(s) arquivo(s) no contm informao!");
    }

    private static void checkTemplatePath(String path) {

        checkString(path, "Caminho do template no contm informao!");
    }

    private static void checkTemplateFile(Object template) {

        Objects.checkNotNull(template, "Arquivo de template nulo!");
    }

    private static void checkString(String str, String msg) {

        Objects.checkNotNull(str);
        Strings.checkNotBlank(str, msg);
    }

    private static void checkDestURL(URL url) {

        Objects.checkNotNull(url, "URL destinada a gerao do(s) documentos(s) nula!");
    }

    private static void checkDestFile(File file) {

        Objects.checkNotNull(file, "Arquivo destinado a gerao do(s) documentos(s) nulo!");
    }

}