001/*
002 * Java Genetic Algorithm Library (jenetics-8.3.0).
003 * Copyright (c) 2007-2025 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 * {@snippet lang="java":
038 * try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
039 *     // Move the XML stream to the first element.
040 *     xml.next();
041 *     return reader.read(xml);
042 * }
043 * }
044 *
045 * Create a new XML stream reader:
046 * {@snippet lang="java":
047 * try (AutoCloseableXMLStreamWriter xml = XML.writer(out)) {
048 *     writer.write(value, xml);
049 * }
050 * }
051 *
052 * Create a new XML stream reader with pretty-print-indentation:
053 * {@snippet lang="java":
054 * final String indent = "    ";
055 * try (AutoCloseableXMLStreamWriter xml = XML.writer(out, indent)) {
056 *     writer.write(value, xml);
057 * }
058 * }
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         * {@snippet lang="java":
073         * try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
074         *     // Move XML stream to first element.
075         *     xml.next();
076         *     return reader.read(xml);
077         * }
078         * }
079         *
080         * @param input the input stream
081         * @return a new {@code Closeable} XML stream reader
082         * @throws XMLStreamException if the creation of the XML stream reader fails
083         * @throws NullPointerException if the given {@code input} stream is
084         *         {@code null}
085         */
086        public static AutoCloseableXMLStreamReader reader(final InputStream input)
087                throws XMLStreamException
088        {
089                requireNonNull(input);
090
091                //final XMLInputFactory factory = XMLInputFactory
092                //      .newFactory(XMLInputFactory.class.getName(), null);
093                final XMLInputFactory factory = XMLInputFactory.newFactory();
094                return new XMLReaderProxy(
095                        factory.createXMLStreamReader(input, "UTF-8"));
096        }
097
098        /**
099         * Create a new {@code XMLStreamWriter} from the given output stream.
100         * <em>
101         * The caller is responsible for closing the returned {@code XMLStreamWriter}.
102         * </em>
103         * {@snippet lang="java":
104         * try (AutoCloseableXMLStreamWriter xml = XML.writer(out, "    ")) {
105         *     writer.write(value, xml);
106         * }
107         * }
108         *
109         * @param output the underlying output stream
110         * @param indent the element indent used for the XML output
111         * @return a new {@code XMLStreamWriter} instance
112         * @throws XMLStreamException if an error occurs while creating the XML
113         *         stream writer
114         * @throws NullPointerException if the given {@code output} stream is
115         *         {@code null}
116         */
117        public static AutoCloseableXMLStreamWriter writer(
118                final OutputStream output,
119                final String indent
120        )
121                throws XMLStreamException
122        {
123                requireNonNull(output);
124
125                final XMLOutputFactory factory = XMLOutputFactory.newFactory();
126                return indent != null
127                        ? new IndentingXMLWriter(
128                                factory.createXMLStreamWriter(output, "UTF-8"), indent)
129                        : new XMLWriterProxy(
130                                factory.createXMLStreamWriter(output, "UTF-8"));
131        }
132
133        /**
134         * Create a new {@code XMLStreamWriter} from the given output stream.
135         * <em>
136         * The caller is responsible for closing the returned {@code XMLStreamWriter}.
137         * </em>
138         * {@snippet lang="java":
139         * try (AutoCloseableXMLStreamWriter xml = XML.writer(out)) {
140         *     writer.write(value, xml);
141         * }
142         * }
143         *
144         * @param output the underlying output stream
145         * @return a new {@code XMLStreamWriter} instance
146         * @throws XMLStreamException if an error occurs while creating the XML
147         *         stream writer
148         * @throws NullPointerException if the given {@code output} stream is
149         *         {@code null}
150         */
151        public static AutoCloseableXMLStreamWriter writer(final OutputStream output)
152                throws XMLStreamException
153        {
154                return writer(output, null);
155        }
156
157}