1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.jackrabbit;
35
36 import static java.util.Collections.emptyList;
37
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.OutputStream;
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.List;
44 import java.util.Optional;
45 import java.util.function.Consumer;
46 import java.util.function.Predicate;
47
48 import javax.xml.parsers.DocumentBuilder;
49 import javax.xml.parsers.DocumentBuilderFactory;
50 import javax.xml.parsers.ParserConfigurationException;
51 import javax.xml.transform.OutputKeys;
52 import javax.xml.transform.Transformer;
53 import javax.xml.transform.TransformerException;
54 import javax.xml.transform.TransformerFactory;
55 import javax.xml.transform.dom.DOMSource;
56 import javax.xml.transform.stream.StreamResult;
57
58 import org.w3c.dom.Document;
59 import org.w3c.dom.Element;
60 import org.w3c.dom.Node;
61 import org.w3c.dom.NodeList;
62 import org.xml.sax.SAXException;
63
64
65
66
67
68 public class WorkspaceConfigurationMerger {
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public static void merge(InputStream repositoryXml, InputStream workspaceStubXml, OutputStream workspaceXml)
98 throws ParserConfigurationException, IOException, SAXException, TransformerException {
99
100 DocumentBuilder xmlParser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
101 Document repositoryConfig = xmlParser.parse(repositoryXml);
102 Document workspaceConfig = xmlParser.parse(workspaceStubXml);
103
104 getElement(workspaceConfig, "Workspace")
105
106
107 .ifPresent(workspaceElement -> {
108
109
110
111 getWorkspaceChildren(repositoryConfig).stream()
112 .filter(notChildOf(workspaceElement))
113 .forEach(addChild(workspaceConfig, workspaceElement));
114
115
116 removeEmptyElements(workspaceElement);
117 });
118
119 Transformer transformer = TransformerFactory.newInstance().newTransformer();
120 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
121 transformer.transform(new DOMSource(workspaceConfig), new StreamResult(workspaceXml));
122 }
123
124 private static Predicate<Node> notChildOf(Element parent) {
125 return node -> !getElement(parent, node.getNodeName()).isPresent();
126 }
127
128 private static Consumer<Node> addChild(Document document, Element parent) {
129 return node -> parent.appendChild(document.importNode(node, true));
130 }
131
132 private static Collection<Node> getWorkspaceChildren(Document repositoryConfig) {
133 return getElement(repositoryConfig, "Repository")
134 .flatMap(repository -> getElement(repository, "Workspace"))
135 .map(WorkspaceConfigurationMerger::getChildNodes)
136 .orElse(emptyList());
137 }
138
139 private static void removeEmptyElements(Node parent) {
140 getChildNodes(parent).stream()
141 .filter(WorkspaceConfigurationMerger::emptyElement)
142 .forEach(parent::removeChild);
143 }
144
145 private static boolean emptyElement(Node node) {
146 return node.getNodeType() == Node.ELEMENT_NODE && !node.hasAttributes() && !node.hasChildNodes();
147 }
148
149 private static Optional<Element> getElement(Node parent, String childName) {
150 return getChildNodes(parent).stream()
151 .filter(elementWithName(childName))
152 .findFirst()
153 .map(Element.class::cast);
154 }
155
156 private static Predicate<Node> elementWithName(String childName) {
157 return node -> node.getNodeType() == Node.ELEMENT_NODE && childName.equals(node.getNodeName());
158 }
159
160 private static Collection<Node> getChildNodes(Node parent) {
161 List<Node> nodes = new ArrayList<>();
162 NodeList children = parent.getChildNodes();
163 for (int i = 0; i < children.getLength(); i++) {
164 nodes.add(children.item(i));
165 }
166 return nodes;
167 }
168
169 }