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 @Override
70 protected void printElement(final Writer out, final FormatStack fstack,
71 final NamespaceStack nstack, final Element element) throws IOException {
72
73 nstack.push(element);
74 try {
75 final List<Content> content = element.getContent();
76
77
78
79 write(out, "<");
80
81 write(out, element.getQualifiedName());
82
83
84 List<Namespace> definedNamespaces = new ArrayList<>();
85 for (final Namespace ns : nstack.addedForward()) {
86 definedNamespaces.add(ns);
87 }
88 for (String prefix : namespacePrefixes) {
89 for (int i = 0; i < definedNamespaces.size(); i++) {
90 Namespace ns = definedNamespaces.get(i);
91 if (StringUtils.equals(prefix, ns.getPrefix())) {
92 if (namespacePrefixesActuallyUsed.contains(ns.getPrefix())) {
93 printNamespace(out, fstack, ns);
94 }
95 definedNamespaces.remove(i);
96 break;
97 }
98 }
99 }
100 for (Namespace ns : definedNamespaces) {
101 if (namespacePrefixesActuallyUsed.contains(ns.getPrefix())) {
102 printNamespace(out, fstack, ns);
103 }
104 }
105
106
107 if (element.hasAttributes()) {
108 boolean printMultiLine = element.getAttributes().size() > 1
109 || nstack.addedForward().iterator().hasNext();
110 for (final Attribute attribute : element.getAttributes()) {
111 printAttribute(out, fstack, attribute, printMultiLine);
112 }
113 }
114
115 if (content.isEmpty()) {
116
117 if (fstack.isExpandEmptyElements()) {
118 write(out, "></");
119 write(out, element.getQualifiedName());
120 write(out, ">");
121 }
122 else {
123 write(out, "/>");
124 }
125
126 return;
127 }
128
129
130 fstack.push();
131 try {
132
133
134 final String space = element.getAttributeValue("space",
135 Namespace.XML_NAMESPACE);
136
137 if ("default".equals(space)) {
138 fstack.setTextMode(fstack.getDefaultMode());
139 }
140 else if ("preserve".equals(space)) {
141 fstack.setTextMode(TextMode.PRESERVE);
142 }
143
144
145 Walker walker = buildWalker(fstack, content, true);
146
147 if (!walker.hasNext()) {
148
149 if (fstack.isExpandEmptyElements()) {
150 write(out, "></");
151 write(out, element.getQualifiedName());
152 write(out, ">");
153 }
154 else {
155 write(out, "/>");
156 }
157
158 return;
159 }
160
161 write(out, ">");
162 if (!walker.isAllText()) {
163
164 textRaw(out, fstack.getPadBetween());
165 }
166
167 printContent(out, fstack, nstack, walker);
168
169 if (!walker.isAllText()) {
170
171 textRaw(out, fstack.getPadLast());
172 }
173 write(out, "</");
174 write(out, element.getQualifiedName());
175 write(out, ">");
176
177 }
178 finally {
179 fstack.pop();
180 }
181 }
182 finally {
183 nstack.pop();
184 }
185
186 }
187
188 private void printAttribute(Writer out, FormatStack fstack, Attribute attribute, boolean printMultiLine) throws IOException {
189 if (!attribute.isSpecified() && fstack.isSpecifiedAttributesOnly()) {
190 return;
191 }
192
193 if (printMultiLine) {
194 write(out, StringUtils.defaultString(fstack.getLineSeparator()));
195 write(out, StringUtils.defaultString(fstack.getLevelIndent()));
196 write(out, StringUtils.defaultString(fstack.getIndent()));
197 }
198 else {
199 write(out, " ");
200 }
201
202 write(out, attribute.getQualifiedName());
203 write(out, "=");
204
205 write(out, "\"");
206 attributeEscapedEntitiesFilter(out, fstack, attribute.getValue());
207 write(out, "\"");
208 }
209
210 }