001/*
002 * Java Genetic Algorithm Library (jenetics-7.2.0).
003 * Copyright (c) 2007-2023 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020package io.jenetics.xml.stream;
021
022import static java.util.Objects.requireNonNull;
023
024import java.io.InputStream;
025import java.io.OutputStream;
026
027import javax.xml.stream.XMLInputFactory;
028import javax.xml.stream.XMLOutputFactory;
029import javax.xml.stream.XMLStreamException;
030
031/**
032 * This class contains helper methods for creating
033 * {@link javax.xml.stream.XMLStreamReader} and
034 * {@link javax.xml.stream.XMLStreamWriter} objects.
035 * <p>
036 * Creating a new XML stream reader:
037 * <pre>{@code
038 * try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
039 *     // Move XML stream to first element.
040 *     xml.next();
041 *     return reader.read(xml);
042 * }
043 * }</pre>
044 *
045 * Create a new XML stream reader:
046 * <pre>{@code
047 * try (AutoCloseableXMLStreamWriter xml = XML.writer(out)) {
048 *     writer.write(value, xml);
049 * }
050 * }</pre>
051 *
052 * Create a new XML stream reader with pretty-print-indentation:
053 * <pre>{@code
054 * final String indent = "    ";
055 * try (AutoCloseableXMLStreamWriter xml = XML.writer(out, indent)) {
056 *     writer.write(value, xml);
057 * }
058 * }</pre>
059 *
060 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
061 * @version 3.9
062 * @since 3.9
063 */
064public final class XML {
065        private XML() {}
066
067        /**
068         * Create a new XML stream reader from the given {@code input} stream.
069         * <em>
070         * The caller is responsible for closing the returned {@code XMLStreamReader}.
071         * </em>
072         *
073         * <pre>{@code
074         * try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
075         *     // Move XML stream to first element.
076         *     xml.next();
077         *     return reader.read(xml);
078         * }
079         * }</pre>
080         *
081         * @param input the input stream
082         * @return a new {@code Closeable} XML stream reader
083         * @throws XMLStreamException if the creation of the XML stream reader fails
084         * @throws NullPointerException if the given {@code input} stream is
085         *         {@code null}
086         */
087        public static AutoCloseableXMLStreamReader reader(final InputStream input)
088                throws XMLStreamException
089        {
090                requireNonNull(input);
091
092                //final XMLInputFactory factory = XMLInputFactory
093                //      .newFactory(XMLInputFactory.class.getName(), null);
094                final XMLInputFactory factory = XMLInputFactory.newFactory();
095                return new XMLReaderProxy(
096                        factory.createXMLStreamReader(input, "UTF-8"));
097        }
098
099        /**
100         * Create a new {@code XMLStreamWriter} from the given output stream.
101         * <em>
102         * The caller is responsible for closing the returned {@code XMLStreamWriter}.
103         * </em>
104         *
105         * <pre>{@code
106         * try (AutoCloseableXMLStreamWriter xml = XML.writer(out, "    ")) {
107         *     writer.write(value, xml);
108         * }
109         * }</pre>
110         *
111         * @param output the underlying output stream
112         * @param indent the element indent used for the XML output
113         * @return a new {@code XMLStreamWriter} instance
114         * @throws XMLStreamException if an error occurs while creating the XML
115         *         stream writer
116         * @throws NullPointerException if the given {@code output} stream is
117         *         {@code null}
118         */
119        public static AutoCloseableXMLStreamWriter writer(
120                final OutputStream output,
121                final String indent
122        )
123                throws XMLStreamException
124        {
125                requireNonNull(output);
126
127                final XMLOutputFactory factory = XMLOutputFactory.newFactory();
128                return indent != null
129                        ? new IndentingXMLWriter(
130                                factory.createXMLStreamWriter(output, "UTF-8"), indent)
131                        : new XMLWriterProxy(
132                                factory.createXMLStreamWriter(output, "UTF-8"));
133        }
134
135        /**
136         * Create a new {@code XMLStreamWriter} from the given output stream.
137         * <em>
138         * The caller is responsible for closing the returned {@code XMLStreamWriter}.
139         * </em>
140         *
141         * <pre>{@code
142         * try (AutoCloseableXMLStreamWriter xml = XML.writer(out)) {
143         *     writer.write(value, xml);
144         * }
145         * }</pre>
146         *
147         * @param output the underlying output stream
148         * @return a new {@code XMLStreamWriter} instance
149         * @throws XMLStreamException if an error occurs while creating the XML
150         *         stream writer
151         * @throws NullPointerException if the given {@code output} stream is
152         *         {@code null}
153         */
154        public static AutoCloseableXMLStreamWriter writer(final OutputStream output)
155                throws XMLStreamException
156        {
157                return writer(output, null);
158        }
159
160}