001package ball.activation;
002/*-
003 * ##########################################################################
004 * Utilities
005 * %%
006 * Copyright (C) 2008 - 2022 Allen D. Ball
007 * %%
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *      http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 * ##########################################################################
020 */
021import java.io.IOException;
022import java.io.InputStream;
023import java.io.OutputStream;
024import javax.xml.bind.JAXBContext;
025import javax.xml.bind.JAXBException;
026import javax.xml.bind.Marshaller;
027import javax.xml.bind.Unmarshaller;
028
029/**
030 * {@link ReaderWriterDataSource} implementation to provide
031 * {@link Marshaller} marshalling and {@link Unmarshaller} unmarshalling
032 * services.
033 *
034 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
035 */
036public class JAXBDataSource extends ReaderWriterDataSource {
037
038    /**
039     * Construct and marshal the argument {@link Object}.
040     *
041     * @param   object          The {@link Object} to marshal.
042     */
043    public JAXBDataSource(Object object) {
044        this();
045
046        try {
047            marshal(object);
048        } catch (Exception exception) {
049            throw new ExceptionInInitializerError(exception);
050        }
051    }
052
053    /**
054     * No-argument constructor.
055     */
056    public JAXBDataSource() { super(null, APPLICATION_XML); }
057
058    /**
059     * Marshal the argument {@link Object}.
060     *
061     * @param   object          The {@link Object} to marshal.
062     *
063     * @throws  IOException     If an I/O exception occurs.
064     * @throws  JAXBException   If a JAXB exception occurs.
065     */
066    public void marshal(Object object) throws IOException, JAXBException {
067        marshal(JAXBContext.newInstance(object.getClass()), object);
068    }
069
070    /**
071     * Marshal the argument {@link Object}.
072     *
073     * @param   context         The {@link JAXBContext}.
074     * @param   object          The {@link Object} to marshal.
075     *
076     * @throws  IOException     If an I/O exception occurs.
077     * @throws  JAXBException   If a JAXB exception occurs.
078     */
079    public void marshal(JAXBContext context, Object object) throws IOException, JAXBException {
080        try (OutputStream out = getOutputStream()) {
081            Marshaller marshaller = context.createMarshaller();
082
083            marshaller.setProperty("jaxb.encoding", getCharset().name());
084            marshaller.setProperty("jaxb.formatted.output", true);
085            marshaller.marshal(object, out);
086        }
087    }
088
089    /**
090     * Unmarshal the argument {@link Object}.
091     *
092     * @param   <T>             The target type.
093     * @param   type            The target {@link Class}.
094     *
095     * @return  The unmarshalled {@link Object}.
096     *
097     * @throws  IOException     If an I/O exception occurs.
098     * @throws  JAXBException   If a JAXB exception occurs.
099     */
100    public <T> T unmarshal(Class<? extends T> type) throws IOException, JAXBException {
101        return unmarshal(JAXBContext.newInstance(type), type);
102    }
103
104    /**
105     * Unmarshal the argument {@link Object}.
106     *
107     * @param   <T>             The target type.
108     * @param   context         The {@link JAXBContext}.
109     * @param   type            The target {@link Class}.
110     *
111     * @return  The unmarshalled {@link Object}.
112     *
113     * @throws  IOException     If an I/O exception occurs.
114     * @throws  JAXBException   If a JAXB exception occurs.
115     */
116    public <T> T unmarshal(JAXBContext context, Class<? extends T> type) throws IOException, JAXBException {
117        T object = null;
118
119        try (InputStream in = getInputStream()) {
120            Unmarshaller unmarshaller = context.createUnmarshaller();
121
122            object = type.cast(unmarshaller.unmarshal(in));
123        }
124
125        return object;
126    }
127}