package org.transgalactica.batch.salaire.item;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.MessageSource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.transgalactica.batch.salaire.bo.SalaireTo;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
/**
* <p>
* L'affichage Japonais nécessite l'installation des extensions de police du
* visualiseur PDF. Soit le package <code>poppler-data</code> pour Okular.
* </p>
* <p>
* L'affichage Arabe nécessite l'installation des polices Arabes (Arabeyes).
* </p>
*
* @author Thierry
*/
public class ITextFicheSalairePdfItemWriter implements ItemWriter<SalaireTo> {
private static final int HEADER_SPACING = 20;
private static final int CONTENT_SPACING = 10;
private static final int HEADER_FONT_SIZE = 18;
private static final int CONTENT_FONT_SIZE = 12;
@Inject
private MessageSource messageSource;
@Inject
private ResourceLoader resourceLoader;
private Date dateCalcul;
private Resource outputDirectory;
private Font textFont;
private Font titleFont;
private Font emphaseFont;
private int rundirection = PdfWriter.RUN_DIRECTION_DEFAULT;
protected ITextFicheSalairePdfItemWriter() {
}
@PostConstruct
public void initialiseFonts() throws DocumentException, IOException {
BaseFont baseFont = BaseFont
.createFont(getMessage("font.name"), getMessage("font.encoding"), BaseFont.EMBEDDED);
textFont = new Font(baseFont, CONTENT_FONT_SIZE);
titleFont = new Font(baseFont, HEADER_FONT_SIZE);
emphaseFont = new Font(baseFont, CONTENT_FONT_SIZE, Font.BOLD);
rundirection = Integer.valueOf(getMessage("font.runDirection"));
}
@Override
public void write(List<? extends SalaireTo> salaires) throws DocumentException, IOException {
for (SalaireTo salaire : salaires) {
write(salaire);
}
}
protected void write(SalaireTo salaire) throws DocumentException, IOException {
Document document = createPdf(salaire);
document.open();
addMetaData(document);
addEntete(document);
addEmployeInformation(document, salaire);
addElementsSalaire(document, salaire);
document.close();
}
private Document createPdf(SalaireTo salaire) throws DocumentException, IOException {
String resourceName = String.format("%1$s_%2$tY-%2$tm.pdf", salaire.getNomEmploye(), dateCalcul);
Resource resource = outputDirectory.createRelative(resourceName);
Document document = new Document(PageSize.A5);
PdfWriter.getInstance(document, new FileOutputStream(resource.getFile()));
return document;
}
private void addMetaData(Document document) {
document.addTitle(getMessage("message.metadata.titre", dateCalcul));
document.addAuthor(getMessage("message.metadata.auteur"));
document.addCreator(getMessage("message.metadata.auteur"));
}
private void addEntete(Document document) throws DocumentException, IOException {
Paragraph logo = new Paragraph();
logo.setSpacingAfter(HEADER_SPACING);
Resource logoresource = resourceLoader.getResource(getMessage("image.logo"));
Assert.notNull(logo);
logo.add(Image.getInstance(logoresource.getURL()));
document.add(logo);
Paragraph titre = new Paragraph(getMessage("message.entete.titre"), titleFont);
titre.setSpacingAfter(HEADER_SPACING);
titre.setAlignment(Element.ALIGN_CENTER);
// TODO plus de support de multicolumnText, pas de RunDirection sur le
// Paragraph, ColumnText ne fonctionne pas en mode composite ...
// MultiColumnText ct = new MultiColumnText();
// ct.addSimpleColumn(document.left(), document.right());
// ct.setRunDirection(rundirection);
// ct.addElement(titre);
//
// document.add(ct);
document.add(titre);
}
private void addEmployeInformation(Document document, SalaireTo salaire) throws DocumentException {
Paragraph info = new Paragraph();
info.setAlignment(Element.ALIGN_LEFT);
info.setSpacingAfter(CONTENT_SPACING);
info.setSpacingBefore(CONTENT_SPACING);
info.add(new Phrase(getMessage("message.info.employe", salaire.getNomEmploye()), textFont));
info.add(Chunk.NEWLINE);
info.add(new Phrase(getMessage("message.info.profession", salaire.getTypeEmploye().name()), textFont));
info.add(Chunk.NEWLINE);
info.add(new Phrase(getMessage("message.info.periode", dateCalcul), textFont));
// TODO plus de support de multicolumnText, pas de RunDirection sur le
// Paragraph, ColumnText ne fonctionne pas en mode composite ...
// MultiColumnText ct = new MultiColumnText();
// ct.addSimpleColumn(document.left(), document.right());
// ct.setRunDirection(rundirection);
// ct.addElement(info);
//
// document.add(ct);
document.add(info);
}
private void addElementsSalaire(Document document, SalaireTo salaire) throws DocumentException {
PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(100);
table.setWidths(new float[] { 65, 35 });
table.setExtendLastRow(true);
table.setRunDirection(rundirection);
table.setHeaderRows(2);
table.setFooterRows(1);
table.getDefaultCell().setPaddingTop(5);
table.getDefaultCell().setBackgroundColor(BaseColor.LIGHT_GRAY);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(new Phrase(getMessage("message.element.titreDetail"), textFont));
table.addCell(new Phrase(getMessage("message.element.titreMontant"), textFont));
table.getDefaultCell().setBackgroundColor(null);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
table.addCell(new Phrase(getMessage("message.element.total"), emphaseFont));
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(new Phrase(salaire.getSalaire().toString(), emphaseFont));
// detail des elements de salaire
table.getDefaultCell().setBorder(Rectangle.LEFT | Rectangle.RIGHT);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
table.addCell(new Phrase(getMessage("message.element.salaire"), textFont));
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(new Phrase(salaire.getSalaireBase().toString(), textFont));
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
table.addCell(new Phrase(getMessage("message.element.anciennete"), textFont));
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(new Phrase(salaire.getPrimeAnciennete().toString(), textFont));
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
table.addCell(new Phrase(getMessage("message.element.experience"), textFont));
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(new Phrase(salaire.getPrimeExperience().toString(), textFont));
document.add(table);
}
private String getMessage(String key, Object... params) {
return messageSource.getMessage(key, params, Locale.getDefault());
}
/*
* IOC
*/
@Required
public void setOutputDirectory(Resource outputDirectory) {
this.outputDirectory = outputDirectory;
}
/**
* @param dateCalcul
*/
@Required
public void setDateCalcul(LocalDate dateCalcul) {
// convert to localized date (format)
this.dateCalcul = Date.from(dateCalcul.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
}