001/*
002 * Copyright (C) 2014 konik.io
003 *
004 * This file is part of Konik library.
005 *
006 * Konik library is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU Affero General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * Konik library is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU Affero General Public License for more details.
015 *
016 * You should have received a copy of the GNU Affero General Public License
017 * along with Konik library.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package io.konik;
020
021import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
022import static javax.xml.bind.JAXBContext.newInstance;
023import io.konik.exception.TransformationException;
024import io.konik.zugferd.Invoice;
025
026import java.io.ByteArrayOutputStream;
027import java.io.File;
028import java.io.InputStream;
029import java.net.URL;
030
031import javax.inject.Inject;
032import javax.inject.Named;
033import javax.inject.Singleton;
034import javax.xml.bind.JAXBContext;
035import javax.xml.bind.JAXBElement;
036import javax.xml.bind.JAXBException;
037import javax.xml.bind.Marshaller;
038import javax.xml.bind.Unmarshaller;
039import javax.xml.transform.stream.StreamSource;
040import javax.xml.validation.Schema;
041import javax.xml.validation.SchemaFactory;
042import javax.xml.validation.Validator;
043
044import org.xml.sax.SAXException;
045
046/**
047 * Transforms invoices from one representation to another. In other words marshaling and unmarshalling.
048 * 
049 */
050@Named
051@Singleton
052public class InvoiceTransformer {
053
054   private static final String KONIK_CONTEXT = "io.konik.zugferd";
055  
056   private final JAXBContext jaxbContext;
057
058   /**
059    * Instantiates a new invoice transformer.
060    */
061   public InvoiceTransformer() {
062      try {
063         this.jaxbContext = newInstance(KONIK_CONTEXT);
064      } catch (JAXBException e) {
065         throw new TransformationException("Could not instantiate JaxB Context", e);
066      }
067   }
068   
069   /**
070    * Instantiates a new invoice transformer.
071    *
072    * @param jaxbContext the jaxb context
073    */
074   @Inject
075   public InvoiceTransformer(JAXBContext jaxbContext) {
076      this.jaxbContext = jaxbContext;
077   }
078   
079   /**
080    * Transform from XML input stream  to the invoice model.
081    * 
082    * @param xmlIs the xml input stream
083    * @return the invoice model
084    */
085   public Invoice from(InputStream xmlIs) {
086      try {
087         Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
088         return unmarshaller.unmarshal(new StreamSource(xmlIs), Invoice.class).getValue();
089      } catch (JAXBException e) {
090         throw new TransformationException("Marshalling error", e);
091      }
092   }
093
094   /**
095    * Transform from XML content from File to the invoice model.
096    * 
097    * @param file the file
098    * @return the invoice
099    */
100   @SuppressWarnings("unchecked")
101   public Invoice from(File file) {
102      try {
103         Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
104         return ((JAXBElement<Invoice>) unmarshaller.unmarshal(file)).getValue();
105      } catch (JAXBException e) {
106         throw new TransformationException("Marshalling error", e);
107      }
108   }
109   /**
110    * Transform from Invoice model to xml byte array.
111    * 
112    * @param invoice the invoice
113    * @return the byte[]
114    */
115   public byte[] from(Invoice invoice) {
116      ByteArrayOutputStream outputStream = new ByteArrayOutputStream(16000);
117      try {
118         Marshaller marshaller = jaxbContext.createMarshaller();
119         marshaller.marshal(invoice, outputStream);
120      } catch (JAXBException e) {
121         throw new TransformationException("Marshalling error", e);
122      }
123      return outputStream.toByteArray();
124   }
125   
126   /**
127    * Transform from Invoice model to output stream.
128    *
129    * @param invoice the invoice
130    * @param outputStream the output stream
131    */
132   public void from(Invoice invoice, ByteArrayOutputStream outputStream) {
133      try {
134         Marshaller marshaller = jaxbContext.createMarshaller();
135         marshaller.marshal(invoice, outputStream);
136      } catch (JAXBException e) {
137         throw new TransformationException("Marshalling error", e);
138      }
139   }
140
141
142   /**
143    * Gets the ZUGFeRD schema Validator.
144    * 
145    * @return the Schema Validator
146    * @throws SAXException the SAX exception
147    */
148   public Validator getZfSchemaValidator() throws SAXException {
149      SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
150      URL schemaInvoice = InvoiceTransformer.class.getResource("/zfSchema/Invoice.xsd");
151      Schema invoiceSchema = sf.newSchema(schemaInvoice);
152      return invoiceSchema.newValidator();
153   }
154}