Java tutorial
package fi.riista.feature.permit.invoice.pdf; import com.google.common.base.Joiner; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDResources; import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDField; import org.apache.pdfbox.pdmodel.interactive.form.PDTextField; import org.springframework.core.io.ClassPathResource; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Objects; class PermitHarvestInvoicePdfBuilder { private static final ClassPathResource PDF_TEMPLATE = new ClassPathResource("tilisiirtolomake-bottom.pdf"); static byte[] getPdf(final PermitHarvestInvoicePdfModel model) throws IOException { try (final InputStream is = PDF_TEMPLATE.getInputStream(); final PDDocument pdfTemplate = PDDocument.load(is)) { return new PermitHarvestInvoicePdfBuilder(pdfTemplate, model).build(); } } private final PDDocument pdfDocument; private final PDPage pdfPage; private final PDAcroForm acroForm; private final PermitHarvestInvoicePdfModel model; private PermitHarvestInvoicePdfBuilder(final PDDocument pdfDocument, final PermitHarvestInvoicePdfModel model) { this.pdfDocument = Objects.requireNonNull(pdfDocument); this.pdfPage = Objects.requireNonNull(pdfDocument.getPage(0)); this.acroForm = Objects.requireNonNull(pdfDocument.getDocumentCatalog().getAcroForm()); this.model = Objects.requireNonNull(model); } private String i18n(final String finnish, final String swedish) { return model.getLocalisedString(finnish, swedish); } private void textField(final String fieldName, final String value) throws IOException { final PDField field = acroForm.getField(fieldName); if (field instanceof PDTextField) { final PDTextField textField = (PDTextField) field; textField.setValue(value); textField.setReadOnly(true); } else { throw new IllegalArgumentException("No such field " + fieldName); } } private void addInvoiceSender(final InvoicePdfWriter writer) throws IOException { writer.topOffsetMm(13).marginLeftMm(20).italicFont().writeLine("Lhettj / Avsndare").normalFont(); for (final String line : model.getInvoiceRecipient().formatAsLines()) { writer.writeLine(line); } } private void addInvoiceReceiver(final InvoicePdfWriter writer) throws IOException { writer.topOffsetMm(40).marginLeftMm(20).italicFont().writeLine("Vastaanottaja / Mottagare").boldFont() .writeLine(i18n("Suomen riistakeskus, lupahallintokirjaamo", "Finlands Viltcentral /Tillstndsfrvaltningens registratur")) .writeLine(i18n("Kuralankatu 2 ", "Kuralagatan 2")).writeLine(i18n("20540 Turku", "205040 bo")); } private void addInvoiceHeader(final InvoicePdfWriter writer) throws IOException { writer.topOffsetMm(13).marginLeftRelative(65).normalFont().writeLine(i18n("LASKU", "FAKTURA")) .writeEmptyLine().writeLine(model.getInvoiceDateString()); writer.topOffsetMm(45).marginLeftRelative(65).normalFont() .writeLine(i18n("Ptsnumero", "Beslutnummer")).writeLine(i18n("Asiakasnumero", "Kundnummer")); writer.topOffsetMm(45).marginLeftRelative(80).normalFont().writeLine(model.getPermitNumber()) .writeLine(model.getInvoiceRecipient().getCustomerNumber()); } private void addInvoiceText(final InvoicePdfWriter writer) throws IOException { writer.topOffsetMm(70).marginLeftMm(20).font(PDType1Font.HELVETICA_BOLD, 12) .writeLine(model.getInvoiceTitle()).addVerticalSpaceMm(2) .font(PDType1Font.HELVETICA_BOLD, 9.5f) .writeLine(i18n("Pyyntilupamaksu ja sen maksaminen", "Licensavgiften och dess betalning")) .addVerticalSpaceMm(2) .font(PDType1Font.HELVETICA, 9.5f) .writeParagraph(i18n( "Riistanhoitomaksusta ja pyyntilupamaksusta annetun lain (616/1993) 4 :n mukaan: " + "Metsstyslain 26 :ss tarkoitetusta hirvielimen pyyntiluvasta on suoritettava maksu " + "(pyyntilupamaksu) valtiolle. Pyyntilupamaksu suoritetaan kultakin kaadetulta " + "hirvielimelt. Luvan saajan on suoritettava pyyntilupamaksu viimeistn seitsemn " + "pivn kuluttua hirvielimen metsstyskauden pttymisest sen mukaan kuin " + "valtioneuvoston asetuksella sdetn.", "Lag om viltvrdsavgift och licensavgift (616/1993) 4 : Fr i 26 i jaktlagen avsedd " + "jaktlicens fr hjortdjur ska det betalas en avgift (jaktlicensavgift) till staten. " + "Jaktlicensavgiften bestms enligt antalet fllda hjortdjur. Licenshavaren ska betala " + "jaktlicensavgiften inom sju dagar efter det att jaktssongen fr hjortdjur r avslutad " + "i enlighet med vad som freskrivs genom frordning av statsrdet.")) .writeEmptyLine() .writeParagraph(i18n( "Metsstysasetuksen (666/1993) 9 :n mukaan metsstyksen tuloksesta tehtvn " + "ilmoitukseen on liitettv tosite pyyntilupamaksun suorittamisesta. Ilmoitus on tehtv " + "seitsemn vuorokauden kuluessa pyyntiluvassa mainittujen elinten tultua pyydystetyiksi " + "taikka, jos elimi on jnyt pyydystmtt, seitsemn vuorokauden kuluessa rauhoitusajan " + "alkamisesta.", "Enligt Jaktfrordningens (666/1993) 9 skall ett " + "verifikat ver att jaktlicensavgiften betalats fogas till byteanmlan. Anmlan ska gras inom " + "sju dygn efter det att de i jaktlicensen nmnda djuren fllts eller, om djur inte fllts, " + "inom sju dygn efter det att fredningstiden har brjat.")) .writeEmptyLine() .writeParagraph(i18n( "Valtiolle on maksettava maksu kaadetuista hirvielimist oheisella tilisiirtolomakkeella" + " (esim. pankissa tai nettipankissa).", "Betalning till staten skall gras fr de fllda hjortdjuren med det bifogade bankgirot" + " (tex i bank eller ntbank)")) .writeEmptyLine() .font(PDType1Font.HELVETICA_BOLD, 9.5f) .writeLine(i18n("Seuraamukset laiminlynneist", "Pfljd av frsummelse")) .addVerticalSpaceMm(2) .font(PDType1Font.HELVETICA, 9.5f) .writeParagraph(i18n( "Metsstyslain (615/1993) 74 :n mukaan em. ilmoitusvelvollisuuden laiminlyj syyllistyy metsstysrikkomukseen.", "Enligt jaktlagens (615/1993) 74 gr sig den som frsummar att gra den ovan nmnda bytesanmlan, sig skyldig till en jaktfrseelse.")) .writeEmptyLine() .writeParagraph(i18n("Riistanhoitomaksusta ja pyyntilupamaksusta annetun lain 5 :n mukaan: Jos " + "pyyntilupamaksua ei suoriteta mrajassa, Suomen riistakeskuksen on pantava se maksuun. " + "Maksun suorasta ulosottokelpoisuudesta ilman ulosottoperustetta sdetn verojen ja " + "maksujen tytntnpanosta annetussa laissa (706/2007).", "Enligt lagen om viltvrdsavgift och licensavgift (616 /1993) 5 : Betalas en " + "jaktlicensavgift inte inom freskriven tid ska Finlands viltcentral driva in avgiften. " + "Bestmmelser om avgiftens direkta utskbarhet utan utskningsgrund finns i lagen om " + "verkstllighet av skatter och avgifter (706/2007).")); } private void addPaymentTable(final InvoicePdfWriter writer) throws IOException { writer.font(PDType1Font.HELVETICA, 9.5f, 20f); final int baseTopOffset = 165; writer.topOffsetMm(baseTopOffset).marginLeftMm(25).writeLine(i18n("Saalis", "Byte")) .writeLine(i18n("Aikuiset", "Vuxna")).writeLine(i18n("Vasat", "Kalvar")); writer.topOffsetMm(baseTopOffset).marginLeftMm(43).writeLine(i18n("Uros", "Hane")).writeLine("______ +") .writeLine("______ +"); writer.topOffsetMm(baseTopOffset).marginLeftMm(63).writeLine(i18n("Naaras", "Hona")).writeLine("______ =") .writeLine("______ ="); writer.topOffsetMm(baseTopOffset).marginLeftMm(80).writeLine(i18n("yht/kpl", "tot/st")) .writeLine("_______ -").writeLine("_______ -"); writer.topOffsetMm(baseTopOffset - 4.5f).marginLeftMm(100).writeLine(i18n("Vhenn ML", "Dra av")) .addVerticalSpaceMm(-2.5f).writeLine(i18n("28 :n myn.", "beviljade enl.")) .writeLine(i18n("_________ kpl =", "_________ st =")) .writeLine(i18n("_________ kpl =", "_________ st =")); writer.topOffsetMm(baseTopOffset).marginLeftMm(130).writeLine(i18n("Maksettavat", "Skall betalas")) .writeLine(i18n("_________ kpl x", "_________ st x")) .writeLine(i18n("_________ kpl x", "_________ st x")); writer.topOffsetMm(baseTopOffset).marginLeftMm(162).writeLine(i18n("Euroa", "Euro")) .writeLine(String.format("%s = _________", model.getSpecimenPrice().formatAdultPrice())) .writeLine(String.format("%s = _________", model.getSpecimenPrice().formatYoungPrice())); } private void addFormFieldData() throws IOException { textField("iban", model.getInvoiceAccountDetails().getCombinedBankNameAndIbanString()); textField("bic", model.getInvoiceAccountDetails().getBic().toString()); textField("saaja", model.getPaymentRecipient()); textField("maksaja", Joiner.on('\n').join(model.getInvoiceRecipient().formatAsLines())); textField("summa", model.getAmountText()); textField("viitenumero", model.getInvoiceReferenceForHuman()); textField("lisatiedot", model.getInvoiceAdditionalInfo()); this.acroForm.setNeedAppearances(false); // Fix annotations for (PDPage page : this.pdfDocument.getPages()) { for (PDAnnotation annot : page.getAnnotations()) { annot.setPage(page); } } // Define font resources names used in PDF template final PDResources dr = new PDResources(); dr.put(COSName.getPDFName("Helv"), PDType1Font.HELVETICA); dr.put(COSName.getPDFName("HeBo"), PDType1Font.HELVETICA_BOLD); this.acroForm.setDefaultResources(dr); // Convert form fields to text this.acroForm.flatten(); } public byte[] build() throws IOException { try (final InvoicePdfWriter writer = new InvoicePdfWriter(pdfDocument, pdfPage)) { addInvoiceHeader(writer); addInvoiceSender(writer); addInvoiceReceiver(writer); addInvoiceText(writer); addPaymentTable(writer); writer.barCode(model.createBarCodeMessage(null)); writer.riistaLogo(10, 180, 20); } addFormFieldData(); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); pdfDocument.save(bos); pdfDocument.close(); return bos.toByteArray(); } }