All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.konik.PdfHandler Maven / Gradle / Ivy

/* Copyright (C) 2014 konik.io
 *
 * This file is part of the Konik library.
 *
 * The Konik library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * The Konik 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with the Konik library. If not, see .
 */
package io.konik;

import com.google.common.collect.Lists;
import io.konik.csv.pdf.FileAppenderPriorityComparator;
import io.konik.harness.FileAppender;
import io.konik.harness.FileExtractor;
import io.konik.harness.appender.DefaultAppendParameter;
import io.konik.harness.exception.InvoiceAppendError;
import io.konik.zugferd.Invoice;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.*;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import java.util.logging.Logger;

import static io.konik.csv.pdf.FileAppenderPriorityComparator.Order;
import static java.util.logging.Level.WARNING;

/**
 * Transforms, appends or extracts invoices to PDFs.
 */
@Named
@Singleton
public class PdfHandler {

   private static final Logger LOG = Logger.getLogger(PdfHandler.class.getName());
   
   private final FileAppender fileAppender;
   private final FileExtractor fileExtractor;
   private final InvoiceTransformer transformer;

   /**
    * Instantiates a new PDF handler.
    *
    * @param fileAppender the file appender
    * @param fileExtractor the file extractor
    * @param transformer the invoice model transformer
    */
   @Inject
   public PdfHandler(FileAppender fileAppender, FileExtractor fileExtractor, InvoiceTransformer transformer) {
      this.fileAppender = fileAppender;
      this.fileExtractor = fileExtractor;
      this.transformer = transformer;
   }

   /**
    * Instantiates a default invoice transformer using the Service loader to inject an PDF carriage that should be on the classpath.
    * 
    * If error is thrown check you have a Konik PDF Carriage on the classpath.
    */
   public PdfHandler() {
      Iterator iterator = ServiceLoader.load(FileAppender.class).iterator();
      List appenders = Lists.newArrayList(iterator);

      if (appenders.isEmpty()) {
         throw new IllegalStateException("FileAppender implementation not found in the classpath!");
      }

      Collections.sort(appenders, new FileAppenderPriorityComparator(Order.DESC));

      this.fileAppender = appenders.get(0);
      this.fileExtractor = ServiceLoader.load(FileExtractor.class).iterator().next();
      this.transformer = new InvoiceTransformer();
   }

   /**
    * Append an invoice to a PDF.  
    * 
    * The resulting Pdf Output is based on the input PDF, but might be converted to PDF/A-3 when needed.
    * 
    * @param invoice that should be attached to the pdf.
    * @param inputPdf to witch we are going to append the invoice to, input will not be modified
    * @param resultingPdf is the modified copy of the input PDF with the invoice.
    */
   public void appendInvoice(final Invoice invoice, final InputStream inputPdf, final OutputStream resultingPdf) {
      try {
         append(invoice, inputPdf, resultingPdf);
      } catch (IOException e) {
         throw new InvoiceAppendError("Not able to append invoice to PDF", e);
      }
   }

   private void append(final Invoice invoice, final InputStream inputPdf, final OutputStream resultingPdf) throws IOException {
      PipedOutputStream pipedOutputStream = new PipedOutputStream();
      PipedInputStream pipedInputStream = new PipedInputStream(pipedOutputStream, 65536);
      try {
         String version = invoice.getContext().getGuideline().getVersion().versionAlt();
         String confomanceLevel = invoice.getContext().getGuideline().getConformanceLevel().name();
         transformer.fromModelAsync(invoice, pipedOutputStream);
         DefaultAppendParameter parameter = new DefaultAppendParameter(inputPdf, pipedInputStream, resultingPdf,
               version, confomanceLevel);
         fileAppender.append(parameter);
      } finally {
         pipedInputStream.close();
      }
   }

   /**
    * Extract invoice from given pdf file
    *
    * @param pdfFile the pdf file containing the ZUGFeRD XML File 
    * @return the transformed ZUGFeRD invoice
    * @throws FileNotFoundException if the pdf is not found 
    */
   public Invoice extractInvoice(File pdfFile) throws FileNotFoundException {
      byte[] xmlInvoice = fileExtractor.extract(new FileInputStream(pdfFile));
      return transformer.toModel(new ByteArrayInputStream(xmlInvoice));
   }

   /**
    * Extract invoice from given pdf stream
    *
    * @param pdfInputStream the pdf input stream
    * @return the transformed ZUGFeRD invoice
    */
   public Invoice extractInvoice(InputStream pdfInputStream) {
      InputStream invoiceInputStream = fileExtractor.extractToStream(pdfInputStream);
      Invoice invoiceModel = transformer.toModel(invoiceInputStream);
      closeQuietly(invoiceInputStream);
      return invoiceModel;
      
   }

   private static void closeQuietly(InputStream stream) {
      try {
         if (stream != null) {
            stream.close();
         }
      }catch(IOException e) {
         LOG.log(WARNING, "Could not close InputStream. This can be a memory leak as the PDF might still be open.", e);
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy