001 /*
002 * Java GPX Library (jpx-3.1.0).
003 * Copyright (c) 2016-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 */
020 package io.jenetics.jpx;
021
022 import java.util.ArrayDeque;
023 import java.util.Deque;
024
025 import javax.xml.stream.XMLStreamException;
026 import javax.xml.stream.XMLStreamWriter;
027
028 /**
029 * {@link XMLStreamWriter} proxy for writing XML indentations.
030 *
031 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
032 * @version 1.0
033 * @since 1.0
034 */
035 final class IndentingXMLStreamWriter extends XMLStreamWriterAdapter {
036
037 private enum State {
038 SEEN_NOTHING,
039 SEEN_ELEMENT,
040 SEEN_DATA
041 }
042
043 private static final String NEW_LINE = System.lineSeparator();
044
045 private State _state;
046 private final Deque<State> _states = new ArrayDeque<>();
047 private final String _indent;
048 private int _depth;
049
050 IndentingXMLStreamWriter(final XMLStreamWriter writer, final String indent) {
051 super(writer);
052 _state = State.SEEN_NOTHING;
053 _indent = indent;
054 _depth = 0;
055 }
056
057 private void onStartElement() throws XMLStreamException {
058 _states.push(State.SEEN_ELEMENT);
059 _state = State.SEEN_NOTHING;
060 if (_depth > 0) {
061 super.writeCharacters(NEW_LINE);
062 }
063
064 doIndent();
065 ++_depth;
066 }
067
068 private void onEndElement() throws XMLStreamException {
069 --_depth;
070 if (_state == State.SEEN_ELEMENT) {
071 super.writeCharacters(NEW_LINE);
072 doIndent();
073 }
074
075 _state = _states.pop();
076 }
077
078 private void onEmptyElement() throws XMLStreamException {
079 _state = State.SEEN_ELEMENT;
080 if(_depth > 0) {
081 super.writeCharacters(NEW_LINE);
082 }
083
084 doIndent();
085 }
086
087 private void doIndent() throws XMLStreamException {
088 if (_depth > 0) {
089 for(int i = 0; i < _depth; ++i) {
090 super.writeCharacters(_indent);
091 }
092 }
093
094 }
095
096 @Override
097 public void writeStartDocument() throws XMLStreamException {
098 super.writeStartDocument();
099 super.writeCharacters(NEW_LINE);
100 }
101
102 @Override
103 public void writeStartDocument(final String version)
104 throws XMLStreamException
105 {
106 super.writeStartDocument(version);
107 super.writeCharacters(NEW_LINE);
108 }
109
110 @Override
111 public void writeStartDocument(final String encoding, final String version)
112 throws XMLStreamException
113 {
114 super.writeStartDocument(encoding, version);
115 super.writeCharacters(NEW_LINE);
116 }
117
118 @Override
119 public void writeStartElement(final String localName)
120 throws XMLStreamException
121 {
122 onStartElement();
123 super.writeStartElement(localName);
124 }
125
126 @Override
127 public void writeStartElement(
128 final String namespaceURI,
129 final String localName
130 )
131 throws XMLStreamException
132 {
133 onStartElement();
134 super.writeStartElement(namespaceURI, localName);
135 }
136
137 @Override
138 public void writeStartElement(
139 final String prefix,
140 final String localName,
141 final String namespaceURI
142 )
143 throws XMLStreamException
144 {
145 onStartElement();
146 super.writeStartElement(prefix, localName, namespaceURI);
147 }
148
149 @Override
150 public void writeEmptyElement(
151 final String namespaceURI,
152 final String localName
153 )
154 throws XMLStreamException
155 {
156 onEmptyElement();
157 super.writeEmptyElement(namespaceURI, localName);
158 }
159
160 @Override
161 public void writeEmptyElement(
162 final String prefix,
163 final String localName,
164 final String namespaceURI
165 )
166 throws XMLStreamException
167 {
168 onEmptyElement();
169 super.writeEmptyElement(prefix, localName, namespaceURI);
170 }
171
172 @Override
173 public void writeEmptyElement(final String localName)
174 throws XMLStreamException
175 {
176 onEmptyElement();
177 super.writeEmptyElement(localName);
178 }
179
180 @Override
181 public void writeEndElement() throws XMLStreamException {
182 onEndElement();
183 super.writeEndElement();
184 }
185
186 @Override
187 public void writeCharacters(final String text) throws XMLStreamException {
188 _state = State.SEEN_DATA;
189 super.writeCharacters(text);
190 }
191
192 @Override
193 public void writeCharacters(
194 final char[] text,
195 final int start,
196 final int len
197 )
198 throws XMLStreamException
199 {
200 _state = State.SEEN_DATA;
201 super.writeCharacters(text, start, len);
202 }
203
204 @Override
205 public void writeCData(final String data) throws XMLStreamException {
206 _state = State.SEEN_DATA;
207 super.writeCData(data);
208 }
209 }
|