1 package ca.uhn.fhir.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import javax.xml.namespace.NamespaceContext;
27 import javax.xml.stream.XMLStreamException;
28 import javax.xml.stream.XMLStreamWriter;
29
30 import org.apache.commons.lang3.StringUtils;
31
32 public class PrettyPrintWriterWrapper implements XMLStreamWriter {
33
34 private static final String INDENT_CHAR = " ";
35 private static final String LINEFEED_CHAR = "\n";
36 private static final String PRE = "pre";
37 private int depth = 0;
38 private Map<Integer, Boolean> hasChildElement = new HashMap<Integer, Boolean>();
39
40 private int myInsidePre = 0;
41 private XMLStreamWriter myTarget;
42 private boolean myFirstIndent=true;
43
44 public PrettyPrintWriterWrapper(XMLStreamWriter target) {
45 myTarget = target;
46 }
47
48 @Override
49 public void close() throws XMLStreamException {
50 myTarget.close();
51 }
52
53 @Override
54 public void flush() throws XMLStreamException {
55 myTarget.flush();
56 }
57
58 @Override
59 public NamespaceContext getNamespaceContext() {
60 return myTarget.getNamespaceContext();
61 }
62
63 @Override
64 public String getPrefix(String theUri) throws XMLStreamException {
65 return myTarget.getPrefix(theUri);
66 }
67
68 @Override
69 public Object getProperty(String theName) throws IllegalArgumentException {
70 return myTarget.getProperty(theName);
71 }
72
73 @Override
74 public void setDefaultNamespace(String theUri) throws XMLStreamException {
75 myTarget.setDefaultNamespace(theUri);
76 }
77
78 @Override
79 public void setNamespaceContext(NamespaceContext theContext) throws XMLStreamException {
80 myTarget.setNamespaceContext(theContext);
81 }
82
83 @Override
84 public void setPrefix(String thePrefix, String theUri) throws XMLStreamException {
85 myTarget.setPrefix(thePrefix, theUri);
86 }
87
88 @Override
89 public void writeAttribute(String theLocalName, String theValue) throws XMLStreamException {
90 myTarget.writeAttribute(theLocalName, theValue);
91 }
92
93 @Override
94 public void writeAttribute(String theNamespaceURI, String theLocalName, String theValue) throws XMLStreamException {
95 myTarget.writeAttribute(theNamespaceURI, theLocalName, theValue);
96 }
97
98 @Override
99 public void writeAttribute(String thePrefix, String theNamespaceURI, String theLocalName, String theValue) throws XMLStreamException {
100 myTarget.writeAttribute(thePrefix, theNamespaceURI, theLocalName, theValue);
101 }
102
103 @Override
104 public void writeCData(String theData) throws XMLStreamException {
105 myTarget.writeCData(theData);
106 }
107
108 @Override
109 public void writeCharacters(char[] theText, int theStart, int theLen) throws XMLStreamException {
110 NonPrettyPrintWriterWrapper.writeCharacters(theText, theStart, theLen, myTarget, myInsidePre);
111 }
112
113 @Override
114 public void writeCharacters(String theText) throws XMLStreamException {
115 if (myInsidePre > 0) {
116 myTarget.writeCharacters(theText);
117 } else {
118 writeCharacters(theText.toCharArray(), 0, theText.length());
119 }
120 }
121
122 @Override
123 public void writeComment(String theData) throws XMLStreamException {
124 myTarget.writeComment(theData);
125 }
126
127 @Override
128 public void writeDefaultNamespace(String theNamespaceURI) throws XMLStreamException {
129 myTarget.writeDefaultNamespace(theNamespaceURI);
130 }
131
132 @Override
133 public void writeDTD(String theDtd) throws XMLStreamException {
134 myTarget.writeDTD(theDtd);
135 }
136
137 @Override
138 public void writeEmptyElement(String theLocalName) throws XMLStreamException {
139 indent();
140 myTarget.writeEmptyElement(theLocalName);
141 }
142
143 @Override
144 public void writeEmptyElement(String theNamespaceURI, String theLocalName) throws XMLStreamException {
145 indent();
146 myTarget.writeEmptyElement(theNamespaceURI, theLocalName);
147 }
148
149 @Override
150 public void writeEmptyElement(String thePrefix, String theLocalName, String theNamespaceURI) throws XMLStreamException {
151 indent();
152 myTarget.writeEmptyElement(thePrefix, theLocalName, theNamespaceURI);
153 }
154
155 @Override
156 public void writeEndDocument() throws XMLStreamException {
157 decrementAndIndent();
158 myTarget.writeEndDocument();
159 }
160
161 @Override
162 public void writeEndElement() throws XMLStreamException {
163 if (myInsidePre > 0) {
164 myInsidePre--;
165 }
166 decrementAndIndent();
167
168 myTarget.writeEndElement();
169
170 }
171
172 @Override
173 public void writeEntityRef(String theName) throws XMLStreamException {
174 myTarget.writeEntityRef(theName);
175 }
176
177 @Override
178 public void writeNamespace(String thePrefix, String theNamespaceURI) throws XMLStreamException {
179 myTarget.writeNamespace(thePrefix, theNamespaceURI);
180 }
181
182 @Override
183 public void writeProcessingInstruction(String theTarget) throws XMLStreamException {
184 myTarget.writeProcessingInstruction(theTarget);
185 }
186
187 @Override
188 public void writeProcessingInstruction(String theTarget, String theData) throws XMLStreamException {
189 myTarget.writeProcessingInstruction(theTarget, theData);
190 }
191
192 @Override
193 public void writeStartDocument() throws XMLStreamException {
194 myFirstIndent=true;
195 myTarget.writeStartDocument();
196 }
197
198 @Override
199 public void writeStartDocument(String theVersion) throws XMLStreamException {
200 myFirstIndent=true;
201 myTarget.writeStartDocument(theVersion);
202 }
203
204 @Override
205 public void writeStartDocument(String theEncoding, String theVersion) throws XMLStreamException {
206 myFirstIndent=true;
207 myTarget.writeStartDocument(theEncoding, theVersion);
208 }
209
210 @Override
211 public void writeStartElement(String theLocalName) throws XMLStreamException {
212 indentAndAdd();
213 myTarget.writeStartElement(theLocalName);
214 if (PRE.equals(theLocalName) || myInsidePre > 0) {
215 myInsidePre++;
216 }
217 }
218
219 @Override
220 public void writeStartElement(String theNamespaceURI, String theLocalName) throws XMLStreamException {
221 indentAndAdd();
222 myTarget.writeStartElement(theNamespaceURI, theLocalName);
223 if (PRE.equals(theLocalName) || myInsidePre > 0) {
224 myInsidePre++;
225 }
226 }
227
228 @Override
229 public void writeStartElement(String thePrefix, String theLocalName, String theNamespaceURI) throws XMLStreamException {
230 indentAndAdd();
231 myTarget.writeStartElement(thePrefix, theLocalName, theNamespaceURI);
232 if (PRE.equals(theLocalName) || myInsidePre > 0) {
233 myInsidePre++;
234 }
235 }
236
237 private void decrementAndIndent() throws XMLStreamException {
238 if (myInsidePre > 0) {
239 return;
240 }
241 depth--;
242
243 if (hasChildElement.get(depth) == true) {
244
245 myTarget.writeCharacters(LINEFEED_CHAR + repeat(depth, INDENT_CHAR));
246 }
247 }
248
249 private void indent() throws XMLStreamException {
250 if (myFirstIndent) {
251 myFirstIndent = false;
252 return;
253 }
254 myTarget.writeCharacters(LINEFEED_CHAR + repeat(depth, INDENT_CHAR));
255 }
256
257 private void indentAndAdd() throws XMLStreamException {
258 if (myInsidePre > 0) {
259 return;
260 }
261 indent();
262
263
264 if (depth > 0) {
265 hasChildElement.put(depth - 1, true);
266 }
267
268
269 hasChildElement.put(depth, false);
270
271 depth++;
272 }
273
274 private String repeat(int d, String s) {
275 return StringUtils.repeat(s, d * 3);
276 }
277
278 }