diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2Exporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2Exporter.java deleted file mode 100644 index 72c348f2..00000000 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2Exporter.java +++ /dev/null @@ -1,698 +0,0 @@ -package org.mustangproject.ZUGFeRD; -/** - * Mustangproject's ZUGFeRD implementation - * ZUGFeRD exporter - * Licensed under the APLv2 - * @date 2014-07-12 - * @version 1.1 - * @author jstaerk - * */ - - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.transform.TransformerException; - -import org.apache.pdfbox.cos.COSArray; -import org.apache.pdfbox.cos.COSBase; -import org.apache.pdfbox.cos.COSDictionary; -import org.apache.pdfbox.cos.COSName; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDDocumentCatalog; -import org.apache.pdfbox.pdmodel.PDDocumentInformation; -import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary; -import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode; -import org.apache.pdfbox.pdmodel.common.COSObjectable; -import org.apache.pdfbox.pdmodel.common.PDMetadata; -import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification; -import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; -import org.apache.xmpbox.XMPMetadata; - - - -public class ZUGFeRD2Exporter { - /*** - * You will need Apache PDFBox. To use the ZUGFeRD exporter, - implement IZUGFeRDExportableTransaction in yourTransaction - (which will require you to implement Product, Item and Contact) - then call - doc = PDDocument.load(PDFfilename); - // automatically add Zugferd to all outgoing invoices - ZUGFeRDExporter ze = new ZUGFeRDExporter(); - ze.PDFmakeA3compliant(doc, "Your application name", - System.getProperty("user.name"), true); - ze.PDFattachZugferdFile(doc, yourTransaction); - - doc.save(PDFfilename); - - * @author jstaerk - * - */ - - - - private class LineCalc { - private IZUGFeRDExportableItem currentItem=null; - private BigDecimal totalGross; - private BigDecimal itemTotalNetAmount; - private BigDecimal itemTotalVATAmount; - - public LineCalc(IZUGFeRDExportableItem currentItem) { - this.currentItem=currentItem; - BigDecimal multiplicator=currentItem.getProduct().getVATPercent().divide(new BigDecimal(100)).add(new BigDecimal(1)); -// priceGross=currentItem.getPrice().multiply(multiplicator); - totalGross=currentItem.getPrice().multiply(multiplicator).multiply(currentItem.getQuantity()); - itemTotalNetAmount=currentItem.getQuantity().multiply(currentItem.getPrice()).setScale(2,BigDecimal.ROUND_HALF_UP); - itemTotalVATAmount=totalGross.subtract(itemTotalNetAmount); - } - - public BigDecimal getItemTotalNetAmount() { - return itemTotalNetAmount; - } - - public BigDecimal getItemTotalVATAmount() { - return itemTotalVATAmount; - } - - } - - - - //// MAIN CLASS - - private String conformanceLevel = "U"; - private String versionStr = "1.2.0"; - - // BASIC, COMFORT etc - may be set from outside. - private String ZUGFeRDConformanceLevel = null; - - - /** - * Data (XML invoice) to be added to the ZUGFeRD PDF. It may be externally set, in which case passing a - * IZUGFeRDExportableTransaction is not necessary. By default it is null meaning the caller needs to - * pass a IZUGFeRDExportableTransaction for the XML to be populated. - */ - byte[] zugferdData = null; - private boolean isTest; - IZUGFeRDExportableTransaction trans=null; - - - private String nDigitFormat(BigDecimal value, int scale) { - /* - * I needed 123,45, locale independent.I tried - * NumberFormat.getCurrencyInstance().format( 12345.6789 ); but that is - * locale specific.I also tried DecimalFormat df = new DecimalFormat( - * "0,00" ); df.setDecimalSeparatorAlwaysShown(true); - * df.setGroupingUsed(false); DecimalFormatSymbols symbols = new - * DecimalFormatSymbols(); symbols.setDecimalSeparator(','); - * symbols.setGroupingSeparator(' '); - * df.setDecimalFormatSymbols(symbols); - * - * but that would not switch off grouping. Although I liked very much - * the (incomplete) "BNF diagram" in - * http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html - * in the end I decided to calculate myself and take eur+sparator+cents - * - * This function will cut off, i.e. floor() subcent values Tests: - * System.err.println(utils.currencyFormat(new BigDecimal(0), - * ".")+"\n"+utils.currencyFormat(new BigDecimal("-1.10"), - * ",")+"\n"+utils.currencyFormat(new BigDecimal("-1.1"), - * ",")+"\n"+utils.currencyFormat(new BigDecimal("-1.01"), - * ",")+"\n"+utils.currencyFormat(new BigDecimal("20000123.3489"), - * ",")+"\n"+utils.currencyFormat(new BigDecimal("20000123.3419"), - * ",")+"\n"+utils.currencyFormat(new BigDecimal("12"), ",")); - * - * results 0.00 -1,10 -1,10 -1,01 20000123,34 20000123,34 12,00 - */ - value=value.setScale( scale, BigDecimal.ROUND_HALF_UP ); // first, round so that e.g. 1.189999999999999946709294817992486059665679931640625 becomes 1.19 - char[] repeat = new char[scale]; - Arrays.fill(repeat, '0'); - - DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(); - otherSymbols.setDecimalSeparator('.'); - DecimalFormat dec = new DecimalFormat("0."+new String(repeat), otherSymbols); - return dec.format(value); - - } - - private String vatFormat(BigDecimal value) { - return nDigitFormat(value, 2); - } - - private String currencyFormat(BigDecimal value) { - return nDigitFormat(value, 2); - } - - private String priceFormat(BigDecimal value) { - return nDigitFormat(value, 4); - } - private String quantityFormat(BigDecimal value) { - return nDigitFormat(value, 4); - } - - /** - All files are PDF/A-3, setConformance refers to the level conformance. - - PDF/A-3 has three coformance levels, called "A", "U" and "B". - - PDF/A-3-B where B means only visually - preservable, U -standard for Mustang- means visually and unicode - preservable and A means full compliance, i.e. visually, - unicode and structurally preservable and tagged PDF, i.e. useful metainformation for blind people. - - Feel free to pass "A" as new level if you know what you are doing :-) - - - */ - public void setConformanceLevel(String newLevel) { - conformanceLevel=newLevel; - } - - /** - * enables the flag to indicate a test invoice in the XML structure - * */ - public void setTest() { - isTest=true; - } - - /** - * Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on - * the metadata level, this will not e.g. convert graphics to JPG-2000) - * */ - public PDDocumentCatalog PDFmakeA3compliant(PDDocument doc, String producer, String creator, - boolean attachZugferdHeaders) throws IOException, - TransformerException { - String fullProducer=producer + " (via mustangproject.org " + versionStr + ")"; - PDDocumentCatalog cat = doc.getDocumentCatalog(); - PDMetadata metadata = new PDMetadata(doc); - cat.setMetadata(metadata); - // we're using the jempbox org.apache.jempbox.xmp.XMPMetadata version, - // not the xmpbox one - XMPMetadata xmp = new XMPMetadata(); - - XMPSchemaPDFAId pdfaid = new XMPSchemaPDFAId(xmp); - pdfaid.setAbout(""); //$NON-NLS-1$ - xmp.addSchema(pdfaid); - - XMPSchemaDublinCore dc = xmp.addDublinCoreSchema(); - dc.addCreator(creator); - dc.setAbout(""); //$NON-NLS-1$ - - XMPSchemaBasic xsb = xmp.addBasicSchema(); - xsb.setAbout(""); //$NON-NLS-1$ - - xsb.setCreatorTool(creator); - xsb.setCreateDate(GregorianCalendar.getInstance()); - // PDDocumentInformation pdi=doc.getDocumentInformation(); - PDDocumentInformation pdi = new PDDocumentInformation(); - pdi.setProducer(fullProducer); - pdi.setAuthor(creator); - doc.setDocumentInformation(pdi); - - XMPSchemaPDF pdf = xmp.addPDFSchema(); - pdf.setProducer(fullProducer); - pdf.setAbout(""); //$NON-NLS-1$ - - /* - // Mandatory: PDF/A3-a is tagged PDF which has to be expressed using a - // MarkInfo dictionary (PDF A/3 Standard sec. 6.7.2.2) - PDMarkInfo markinfo = new PDMarkInfo(); - markinfo.setMarked(true); - doc.getDocumentCatalog().setMarkInfo(markinfo); -*/ -/* - * - To be on the safe side, we use level B without Markinfo because we can not - guarantee that the user correctly tagged the templates for the PDF. - - * */ - pdfaid.setConformance(conformanceLevel);//$NON-NLS-1$ //$NON-NLS-1$ - - pdfaid.setPart(3); - - if (attachZugferdHeaders) { - addZugferdXMP(xmp); /* - * this is the only line where we do something - * Zugferd-specific, i.e. add PDF metadata - * specifically for Zugferd, not generically for - * a embedded file - */ - } - - metadata.importXMPMetadata(xmp); - return cat; - } - - private String getZugferdXMLForTransaction(IZUGFeRDExportableTransaction trans) { - this.trans=trans; - - SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); //$NON-NLS-1$ - SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$ - String testBooleanStr="false"; - if (isTest) { - testBooleanStr="true"; - - } - String senderReg=""; - if (trans.getOwnOrganisationFullPlaintextInfo()!=null) { - senderReg="" - + "\n" - + " \n" - + trans.getOwnOrganisationFullPlaintextInfo() - + " \n" - + "REG\n" - + "\n"; - - } - String xml= "\n" //$NON-NLS-1$ - - + "\n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " urn:ferd:CrossIndustryDocument:invoice:1p0:comfort\n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+trans.getNumber()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " RECHNUNG\n" //$NON-NLS-1$ - + " 380\n" //$NON-NLS-1$ - + " "+zugferdDateFormat.format(trans.getIssueDate())+"\n" //date format was 20130605 //$NON-NLS-1$ //$NON-NLS-2$ - + senderReg -// + " \n" -// + " \n" -// + "Rechnung gemäß Bestellung Nr. 2013-471331 vom 01.03.2013.\n" -// + "\n" -// + " \n" -// + " \n" -// + " \n" -// + " \n" -// + "Es bestehen Rabatt- und Bonusvereinbarungen.\n" -// + " \n" -// + " AAK\n" -// + " \n" - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ -// + " AB-312\n" - + " \n" //$NON-NLS-1$ -// + " 4000001123452\n" - + " "+trans.getOwnOrganisationName()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" - + " "+trans.getOwnZIP()+"\n" - + " "+trans.getOwnStreet()+"\n" - + " "+trans.getOwnLocation()+"\n" - + " "+trans.getOwnCountry()+"\n" - + " \n" - + " \n" //$NON-NLS-1$ - + " "+trans.getOwnTaxID()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+trans.getOwnVATID()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ -// + " GE2020211\n" -// + " 4000001987658\n" - + " "+trans.getRecipient().getName()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " \n" -// + " xxx\n" -// + " \n" - + " \n" //$NON-NLS-1$ - + " "+trans.getRecipient().getZIP()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " "+trans.getRecipient().getStreet()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " "+trans.getRecipient().getLocation()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " "+trans.getRecipient().getCountry()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+trans.getRecipient().getVATID()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ -// + " \n" -// + " 20130301\n" -// + " 2013-471331\n" -// + " \n" - + " \n" //$NON-NLS-1$ - + " \n" - + " \n" - + " "+zugferdDateFormat.format(trans.getDeliveryDate())+"\n" - + " \n" - /* - + " \n" - + " 20130603\n" - + " 2013-51112\n" - + " \n" */ - + " \n" - + " \n" //$NON-NLS-1$ - + " "+trans.getNumber()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " EUR\n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " 42\n" //$NON-NLS-1$ - + " Überweisung\n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+trans.getOwnIBAN()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+trans.getOwnBIC()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " "+trans.getOwnBankName()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ - - - - HashMap VATPercentAmountMap=getVATPercentAmountMap(); - for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { - VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); - if (amount != null) { - xml += " \n" //$NON-NLS-1$ - + " "+currencyFormat(amount.getCalculated())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " VAT\n" //$NON-NLS-1$ - + " "+currencyFormat(amount.getBasis())+"\n" - + " S\n" //$NON-NLS-1$ - + " "+vatFormat(currentTaxPercent)+"\n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ - - - - } - } -/* xml+= " - + " \n" - + " false\n" - + " 10\n" - + " 1.00\n" - + " Sondernachlass\n" - + " \n" - + " VAT\n" - + " S\n" - + " 19\n" - + " \n" - + " \n" - + " \n" - + " false\n" - + " 137.30\n" - + " 13.73\n" - + " Sondernachlass\n" - + " \n" - + " VAT\n" - + " S\n" - + " 7\n" - + " \n" - + " \n" - + " \n" - + " Versandkosten\n" - + " 5.80\n" - + " \n" - + " VAT\n" - + " S\n" - + " 7\n" - + " \n" - + " \n"*/ - - xml=xml+ " \n" //$NON-NLS-1$ - + " Zahlbar ohne Abzug bis "+germanDateFormat.format(trans.getDueDate())+"\n" - + " "+zugferdDateFormat.format(trans.getDueDate())+"\n"//20130704 //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+currencyFormat(getTotal())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " 0.00\n" //$NON-NLS-1$ - + " 0.00\n" //$NON-NLS-1$ -// + " 5.80\n" -// + " 14.73\n" - + " "+currencyFormat(getTotal())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " "+currencyFormat(getTotalGross().subtract(getTotal()))+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " "+currencyFormat(getTotalGross())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " 0.00\n" - + " "+currencyFormat(getTotalGross())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ -// + " \n" -// + " \n" -// + " \n" -// + " Wir erlauben uns Ihnen folgende Positionen aus der Lieferung Nr. 2013-51112 in Rechnung zu stellen:\n" -// + " \n" -// + " \n" -// + " \n"; - - - int lineID=0; - for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { - lineID++; - - LineCalc lc=new LineCalc(currentItem); - xml=xml+ " \n"+ //$NON-NLS-1$ - " \n" //$NON-NLS-1$ - + " "+lineID+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+priceFormat(currentItem.getPrice())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " 1.0000\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " \n" -// + " false\n" -// + " 0.6667\n" -// + " Rabatt\n" -// + " \n" - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+priceFormat(currentItem.getPrice())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " 1.0000\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - - + " \n" //$NON-NLS-1$ - + " "+quantityFormat(currentItem.getQuantity())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " VAT\n" //$NON-NLS-1$ - + " S\n" //$NON-NLS-1$ - + " "+vatFormat(currentItem.getProduct().getVATPercent())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " "+currencyFormat(lc.getItemTotalNetAmount())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ -// + " 4012345001235\n" -// + " KR3M\n" -// + " 55T01\n" - + " "+currentItem.getProduct().getName()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " "+currentItem.getProduct().getDescription()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ - - - - } - - - xml=xml + " \n" //$NON-NLS-1$ - + ""; //$NON-NLS-1$ - return xml; - } - - - private BigDecimal getTotalGross() { - - BigDecimal res=getTotal(); - HashMap VATPercentAmountMap=getVATPercentAmountMap(); - for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { - VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); - res=res.add(amount.getCalculated()); - } - - - return res; - } - - private BigDecimal getTotal() { - BigDecimal res=new BigDecimal(0); - for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { - LineCalc lc=new LineCalc(currentItem); - res=res.add(lc.getItemTotalNetAmount()); - } - return res; - } - - /** - * which taxes have been used with which amounts in this transaction, - * empty for no taxes, or e.g. 19=>190 and 7=>14 if 1000 Eur were applicable - * to 19% VAT (=>190 EUR VAT) and 200 EUR were applicable to 7% (=>14 EUR VAT) - * 190 Eur - * @return - * - */ - private HashMap getVATPercentAmountMap() { - HashMap hm=new HashMap (); - - for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { - BigDecimal percent=currentItem.getProduct().getVATPercent(); - LineCalc lc=new LineCalc(currentItem); - VATAmount itemVATAmount=new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount() ) ; - VATAmount current=hm.get(percent); - if (current==null) { - hm.put(percent, itemVATAmount); - } else { - hm.put(percent, current.add(itemVATAmount)); - - } - } - - return hm; - } - - /** - * Embeds the Zugferd XML structure in a file named ZUGFeRD-invoice.xml. - * - * @param doc PDDocument to attach an XML invoice to - * @param trans a IZUGFeRDExportableTransaction that provides the data-model to populate the XML. - * This parameter may be null, if so the XML data should hav ebeen set via setZUGFeRDXMLData(byte[] zugferdData) - */ - public void PDFattachZugferdFile(PDDocument doc, IZUGFeRDExportableTransaction trans) throws IOException { - - if (zugferdData == null) // XML ZUGFeRD data not set externally, needs to be built - { - // create a dummy file stream, this would probably normally be a - // FileInputStream - - byte[] zugferdRaw = getZugferdXMLForTransaction(trans).getBytes("UTF-8"); //$NON-NLS-1$ - - if ((zugferdRaw[0]==(byte)0xEF)&&(zugferdRaw[1]==(byte)0xBB)&&(zugferdRaw[2]==(byte)0xBF)) { - // I don't like BOMs, lets remove it - zugferdData=new byte[zugferdRaw.length-3]; - System.arraycopy(zugferdRaw,3,zugferdData,0,zugferdRaw.length-3); - } else { - zugferdData=zugferdRaw; - } - } - - - PDFAttachGenericFile(doc, "ZUGFeRD-invoice.xml", "Alternative", "Invoice metadata conforming to ZUGFeRD standard (http://www.ferd-net.de/front_content.php?idcat=231&lang=4)", "text/xml", zugferdData); - } - - - /** - * Embeds an external file (generic - any type allowed) in the PDF. - * - * @param doc PDDocument to attach the file to. - * @param filename name of the file that will become attachment name in the PDF - * @param relationship how the file relates to the content, e.g. "Alternative" - * @param description Human-readable description of the file content - * @param subType type of the data e.g. could be "text/xml" - mime like - * @param data the binary data of the file/attachment - */ - public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description, String subType, byte[] data) - throws IOException - { - PDComplexFileSpecification fs = new PDComplexFileSpecification(); - fs.setFile(filename); - - COSDictionary dict = fs.getCOSDictionary(); - dict.setName("AFRelationship", relationship); - dict.setString("UF", filename); - dict.setString("Desc", description); - - ByteArrayInputStream fakeFile = new ByteArrayInputStream(data); - PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile); - ef.setSubtype(subType); - ef.setSize(data.length); - ef.setCreationDate(new GregorianCalendar()); - - ef.setModDate(GregorianCalendar.getInstance()); - - fs.setEmbeddedFile(ef); - - // In addition make sure the embedded file is set under /UF - dict = fs.getCOSDictionary(); - COSDictionary efDict = (COSDictionary)dict.getDictionaryObject(COSName.EF); - COSBase lowerLevelFile = efDict.getItem(COSName.F); - efDict.setItem(COSName.UF, lowerLevelFile); - - // now add the entry to the embedded file tree and set in the document. - PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog()); - PDEmbeddedFilesNameTreeNode efTree = names.getEmbeddedFiles(); - if (efTree == null) - { - efTree = new PDEmbeddedFilesNameTreeNode(); - } - - Map namesMap = new HashMap(); - Map oldNamesMap = efTree.getNames(); - if (oldNamesMap != null) - { - for (String key : oldNamesMap.keySet()) - { - namesMap.put(key, oldNamesMap.get(key)); - } - } - namesMap.put(filename, fs); - efTree.setNames(namesMap); - - names.setEmbeddedFiles(efTree); - doc.getDocumentCatalog().setNames(names); - - // AF entry (Array) in catalog with the FileSpec - COSArray cosArray = (COSArray)doc.getDocumentCatalog().getCOSDictionary().getItem("AF"); - if (cosArray == null) - { - cosArray = new COSArray(); - } - cosArray.add(fs); - doc.getDocumentCatalog().getCOSDictionary().setItem("AF", cosArray); - } - - - /** - * Sets the ZUGFeRD XML data to be attached as a single byte array. This is useful for - * use-cases where the XML has already been produced by some external API or component. - * - * @param zugferdData XML data to be set as a byte array (XML file in raw form). - */ - public void setZUGFeRDXMLData(byte[] zugferdData) - { - this.zugferdData = zugferdData; - } - - - /** - * Sets the ZUGFeRD conformance level (override). - * - * @param ZUGFeRDConformanceLevel the new conformance level - */ - public void setZUGFeRDConformanceLevel(String ZUGFeRDConformanceLevel) - { - this.ZUGFeRDConformanceLevel = ZUGFeRDConformanceLevel; - } - -/*** - * This will add both the RDF-indication which embedded file is Zugferd and the - * neccessary PDF/A schema extension description to be able to add this information to RDF - * @param metadata - */ - private void addZugferdXMP(XMPMetadata metadata) { - - XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, this.ZUGFeRDConformanceLevel); - zf.setAbout(""); //$NON-NLS-1$ - metadata.addSchema(zf); - - XMPSchemaPDFAExtensions pdfaex = new XMPSchemaPDFAExtensions(metadata); - pdfaex.setAbout(""); //$NON-NLS-1$ - metadata.addSchema(pdfaex); - - } - -}