IndentingXMLWriter.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-7.0.0).
003  * Copyright (c) 2007-2022 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.xml.stream;
021 
022 import java.util.Deque;
023 import java.util.LinkedList;
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 3.9
033  @since 3.9
034  */
035 final class IndentingXMLWriter extends XMLWriterProxy {
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 final String _indent;
046 
047     private State _state;
048     private final Deque<State> _states = new LinkedList<>();
049     private int _depth;
050 
051     IndentingXMLWriter(final XMLStreamWriter writer, final String indent) {
052         super(writer);
053         _state = State.SEEN_NOTHING;
054         _indent = indent;
055         _depth = 0;
056     }
057 
058     private void onStartElement() throws XMLStreamException {
059         _states.push(State.SEEN_ELEMENT);
060         _state = State.SEEN_NOTHING;
061         if (_depth > 0) {
062             super.writeCharacters(NEW_LINE);
063         }
064 
065         doIndent();
066         ++_depth;
067     }
068 
069     private void onEndElement() throws XMLStreamException {
070         --_depth;
071         if (_state == State.SEEN_ELEMENT) {
072             super.writeCharacters(NEW_LINE);
073             doIndent();
074         }
075 
076         _state = _states.pop();
077     }
078 
079     private void onEmptyElement() throws XMLStreamException {
080         _state = State.SEEN_ELEMENT;
081         if(_depth > 0) {
082             super.writeCharacters(NEW_LINE);
083         }
084 
085         doIndent();
086     }
087 
088     private void doIndent() throws XMLStreamException {
089         if (_depth > 0) {
090             for(int i = 0; i < _depth; ++i) {
091                 super.writeCharacters(_indent);
092             }
093         }
094 
095     }
096 
097     @Override
098     public void writeStartDocument() throws XMLStreamException {
099         super.writeStartDocument();
100         super.writeCharacters(NEW_LINE);
101     }
102 
103     @Override
104     public void writeStartDocument(final String version)
105         throws XMLStreamException
106     {
107         super.writeStartDocument(version);
108         super.writeCharacters(NEW_LINE);
109     }
110 
111     @Override
112     public void writeStartDocument(final String encoding, final String version)
113         throws XMLStreamException
114     {
115         super.writeStartDocument(encoding, version);
116         super.writeCharacters(NEW_LINE);
117     }
118 
119     @Override
120     public void writeStartElement(final String localName)
121         throws XMLStreamException
122     {
123         onStartElement();
124         super.writeStartElement(localName);
125     }
126 
127     @Override
128     public void writeStartElement(
129         final String namespaceURI,
130         final String localName
131     )
132         throws XMLStreamException
133     {
134         onStartElement();
135         super.writeStartElement(namespaceURI, localName);
136     }
137 
138     @Override
139     public void writeStartElement(
140         final String prefix,
141         final String localName,
142         final String namespaceURI
143     )
144         throws XMLStreamException
145     {
146         onStartElement();
147         super.writeStartElement(prefix, localName, namespaceURI);
148     }
149 
150     @Override
151     public void writeEmptyElement(
152         final String namespaceURI,
153         final String localName
154     )
155         throws XMLStreamException
156     {
157         onEmptyElement();
158         super.writeEmptyElement(namespaceURI, localName);
159     }
160 
161     @Override
162     public void writeEmptyElement(
163         final String prefix,
164         final String localName,
165         final String namespaceURI
166     )
167         throws XMLStreamException
168     {
169         onEmptyElement();
170         super.writeEmptyElement(prefix, localName, namespaceURI);
171     }
172 
173     @Override
174     public void writeEmptyElement(final String localName)
175         throws XMLStreamException
176     {
177         onEmptyElement();
178         super.writeEmptyElement(localName);
179     }
180 
181     @Override
182     public void writeEndElement() throws XMLStreamException {
183         onEndElement();
184         super.writeEndElement();
185     }
186 
187     @Override
188     public void writeCharacters(final String textthrows XMLStreamException {
189         _state = State.SEEN_DATA;
190         super.writeCharacters(text);
191     }
192 
193     @Override
194     public void writeCharacters(
195         final char[] text,
196         final int start,
197         final int len
198     )
199         throws XMLStreamException
200     {
201         _state = State.SEEN_DATA;
202         super.writeCharacters(text, start, len);
203     }
204 
205     @Override
206     public void writeCData(final String datathrows XMLStreamException {
207         _state = State.SEEN_DATA;
208         super.writeCData(data);
209     }
210 }