1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.tooling.commons.packmgr.unpack;
21
22 import java.io.IOException;
23 import java.io.Writer;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.apache.commons.lang3.StringUtils;
29 import org.jdom2.Attribute;
30 import org.jdom2.Content;
31 import org.jdom2.Element;
32 import org.jdom2.Namespace;
33 import org.jdom2.output.Format.TextMode;
34 import org.jdom2.output.support.AbstractXMLOutputProcessor;
35 import org.jdom2.output.support.FormatStack;
36 import org.jdom2.output.support.Walker;
37 import org.jdom2.util.NamespaceStack;
38
39
40
41
42 class OneAttributePerLineXmlProcessor extends AbstractXMLOutputProcessor {
43
44 private final Set<String> namespacePrefixes;
45 private final Set<String> namespacePrefixesActuallyUsed;
46
47 OneAttributePerLineXmlProcessor(Set<String> namespacePrefixes, Set<String> namespacePrefixesActuallyUsed) {
48 this.namespacePrefixes = namespacePrefixes;
49 this.namespacePrefixesActuallyUsed = namespacePrefixesActuallyUsed;
50 }
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 @Override
71 protected void printElement(final Writer out, final FormatStack fstack,
72 final NamespaceStack nstack, final Element element) throws IOException {
73
74 nstack.push(element);
75 try {
76 final List<Content> content = element.getContent();
77
78
79
80 write(out, "<");
81
82 write(out, element.getQualifiedName());
83
84
85 List<Namespace> definedNamespaces = new ArrayList<>();
86 for (final Namespace ns : nstack.addedForward()) {
87 definedNamespaces.add(ns);
88 }
89 for (String prefix : namespacePrefixes) {
90 for (int i = 0; i < definedNamespaces.size(); i++) {
91 Namespace ns = definedNamespaces.get(i);
92 if (StringUtils.equals(prefix, ns.getPrefix())) {
93 if (namespacePrefixesActuallyUsed.contains(ns.getPrefix())) {
94 printNamespace(out, fstack, ns);
95 }
96 definedNamespaces.remove(i);
97 break;
98 }
99 }
100 }
101 for (Namespace ns : definedNamespaces) {
102 if (namespacePrefixesActuallyUsed.contains(ns.getPrefix())) {
103 printNamespace(out, fstack, ns);
104 }
105 }
106
107
108 if (element.hasAttributes()) {
109 boolean printMultiLine = element.getAttributes().size() > 1
110 || nstack.addedForward().iterator().hasNext();
111 for (final Attribute attribute : element.getAttributes()) {
112 printAttribute(out, fstack, attribute, printMultiLine);
113 }
114 }
115
116 if (content.isEmpty()) {
117
118 if (fstack.isExpandEmptyElements()) {
119 write(out, "></");
120 write(out, element.getQualifiedName());
121 write(out, ">");
122 }
123 else {
124 write(out, "/>");
125 }
126
127 return;
128 }
129
130
131 fstack.push();
132 try {
133
134
135 final String space = element.getAttributeValue("space",
136 Namespace.XML_NAMESPACE);
137
138 if ("default".equals(space)) {
139 fstack.setTextMode(fstack.getDefaultMode());
140 }
141 else if ("preserve".equals(space)) {
142 fstack.setTextMode(TextMode.PRESERVE);
143 }
144
145
146 Walker walker = buildWalker(fstack, content, true);
147
148 if (!walker.hasNext()) {
149
150 if (fstack.isExpandEmptyElements()) {
151 write(out, "></");
152 write(out, element.getQualifiedName());
153 write(out, ">");
154 }
155 else {
156 write(out, "/>");
157 }
158
159 return;
160 }
161
162 write(out, ">");
163 if (!walker.isAllText()) {
164
165 textRaw(out, fstack.getPadBetween());
166 }
167
168 printContent(out, fstack, nstack, walker);
169
170 if (!walker.isAllText()) {
171
172 textRaw(out, fstack.getPadLast());
173 }
174 write(out, "</");
175 write(out, element.getQualifiedName());
176 write(out, ">");
177
178 }
179 finally {
180 fstack.pop();
181 }
182 }
183 finally {
184 nstack.pop();
185 }
186
187 }
188
189 private void printAttribute(Writer out, FormatStack fstack, Attribute attribute, boolean printMultiLine) throws IOException {
190 if (!attribute.isSpecified() && fstack.isSpecifiedAttributesOnly()) {
191 return;
192 }
193
194 if (printMultiLine) {
195 write(out, StringUtils.defaultString(fstack.getLineSeparator()));
196 write(out, StringUtils.defaultString(fstack.getLevelIndent()));
197 write(out, StringUtils.defaultString(fstack.getIndent()));
198 }
199 else {
200 write(out, " ");
201 }
202
203 write(out, attribute.getQualifiedName());
204 write(out, "=");
205
206 write(out, "\"");
207 attributeEscapedEntitiesFilter(out, fstack, attribute.getValue());
208 write(out, "\"");
209 }
210
211 }