1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.doxia.site.inheritance;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.apache.maven.doxia.site.Banner;
28 import org.apache.maven.doxia.site.Body;
29 import org.apache.maven.doxia.site.LinkItem;
30 import org.apache.maven.doxia.site.Logo;
31 import org.apache.maven.doxia.site.Menu;
32 import org.apache.maven.doxia.site.MenuItem;
33 import org.apache.maven.doxia.site.SiteModel;
34 import org.codehaus.plexus.util.xml.Xpp3Dom;
35
36
37
38
39
40
41
42 @Singleton
43 @Named
44 public class DefaultSiteModelInheritanceAssembler implements SiteModelInheritanceAssembler {
45
46 public void assembleModelInheritance(
47 String name, SiteModel child, SiteModel parent, String childBaseUrl, String parentBaseUrl) {
48 if (parent == null || !child.isMergeParent()) {
49 return;
50 }
51
52 child.setCombineSelf(parent.getCombineSelf());
53
54 URLRebaser urlContainer = new URLRebaser(parentBaseUrl, childBaseUrl);
55
56 if (child.getBannerLeft() == null && parent.getBannerLeft() != null) {
57 child.setBannerLeft(parent.getBannerLeft().clone());
58 rebaseBannerPaths(child.getBannerLeft(), urlContainer);
59 }
60
61 if (child.getBannerRight() == null && parent.getBannerRight() != null) {
62 child.setBannerRight(parent.getBannerRight().clone());
63 rebaseBannerPaths(child.getBannerRight(), urlContainer);
64 }
65
66 if (child.isDefaultPublishDate() && parent.getPublishDate() != null) {
67 child.setPublishDate(parent.getPublishDate().clone());
68 }
69
70 if (child.isDefaultVersion() && parent.getVersion() != null) {
71 child.setVersion(parent.getVersion().clone());
72 }
73
74 if (child.getEdit() == null && parent.getEdit() != null) {
75 child.setEdit(parent.getEdit());
76 }
77
78 if (child.getSkin() == null && parent.getSkin() != null) {
79 child.setSkin(parent.getSkin().clone());
80 }
81
82 child.setPoweredBy(mergePoweredByLists(child.getPoweredBy(), parent.getPoweredBy(), urlContainer));
83
84 if (parent.getLastModified() > child.getLastModified()) {
85 child.setLastModified(parent.getLastModified());
86 }
87
88 assembleBodyInheritance(name, child, parent, urlContainer);
89
90 assembleCustomInheritance(child, parent);
91 }
92
93
94 public void resolvePaths(final SiteModel siteModel, final String baseUrl) {
95 if (baseUrl == null) {
96 return;
97 }
98
99 if (siteModel.getBannerLeft() != null) {
100 relativizeBannerPaths(siteModel.getBannerLeft(), baseUrl);
101 }
102
103 if (siteModel.getBannerRight() != null) {
104 relativizeBannerPaths(siteModel.getBannerRight(), baseUrl);
105 }
106
107 for (Logo logo : siteModel.getPoweredBy()) {
108 relativizeLogoPaths(logo, baseUrl);
109 }
110
111 if (siteModel.getBody() != null) {
112 for (LinkItem linkItem : siteModel.getBody().getLinks()) {
113 relativizeLinkItemPaths(linkItem, baseUrl);
114 }
115
116 for (LinkItem linkItem : siteModel.getBody().getBreadcrumbs()) {
117 relativizeLinkItemPaths(linkItem, baseUrl);
118 }
119
120 for (Menu menu : siteModel.getBody().getMenus()) {
121 relativizeMenuPaths(menu.getItems(), baseUrl);
122 }
123 }
124 }
125
126
127
128
129
130
131
132
133 private void relativizeBannerPaths(final Banner banner, final String baseUrl) {
134
135 banner.setHref(relativizeLink(banner.getHref(), baseUrl));
136 banner.setSrc(relativizeLink(banner.getSrc(), baseUrl));
137 }
138
139 private void rebaseBannerPaths(final Banner banner, final URLRebaser urlContainer) {
140 if (banner.getHref() != null)
141 {
142 banner.setHref(urlContainer.rebaseLink(banner.getHref()));
143 }
144
145 if (banner.getSrc() != null) {
146 banner.setSrc(urlContainer.rebaseLink(banner.getSrc()));
147 }
148 }
149
150 private void assembleCustomInheritance(final SiteModel child, final SiteModel parent) {
151 if (child.getCustom() == null) {
152 child.setCustom(parent.getCustom());
153 } else {
154 child.setCustom(Xpp3Dom.mergeXpp3Dom((Xpp3Dom) child.getCustom(), (Xpp3Dom) parent.getCustom()));
155 }
156 }
157
158 private void assembleBodyInheritance(
159 final String name, final SiteModel child, final SiteModel parent, final URLRebaser urlContainer) {
160 Body cBody = child.getBody();
161 Body pBody = parent.getBody();
162
163 if (cBody != null || pBody != null) {
164 if (cBody == null) {
165 cBody = new Body();
166 child.setBody(cBody);
167 }
168
169 if (pBody == null) {
170 pBody = new Body();
171 }
172
173 if (cBody.getHead() == null && pBody.getHead() != null) {
174 cBody.setHead(pBody.getHead());
175 }
176
177 cBody.setLinks(mergeLinkItemLists(cBody.getLinks(), pBody.getLinks(), urlContainer, false));
178
179 if (cBody.getBreadcrumbs().isEmpty() && !pBody.getBreadcrumbs().isEmpty()) {
180 LinkItem breadcrumb = new LinkItem();
181 breadcrumb.setName(name);
182 breadcrumb.setHref("index.html");
183 cBody.getBreadcrumbs().add(breadcrumb);
184 }
185 cBody.setBreadcrumbs(
186 mergeLinkItemLists(cBody.getBreadcrumbs(), pBody.getBreadcrumbs(), urlContainer, true));
187
188 cBody.setMenus(mergeMenus(cBody.getMenus(), pBody.getMenus(), urlContainer));
189
190 if (cBody.getFooter() == null && pBody.getFooter() != null) {
191 cBody.setFooter(pBody.getFooter());
192 }
193 }
194 }
195
196 private List<Menu> mergeMenus(
197 final List<Menu> childMenus, final List<Menu> parentMenus, final URLRebaser urlContainer) {
198 List<Menu> menus = new ArrayList<Menu>(childMenus.size() + parentMenus.size());
199
200 for (Menu menu : childMenus) {
201 menus.add(menu);
202 }
203
204 int topCounter = 0;
205 for (Menu menu : parentMenus) {
206 if ("top".equals(menu.getInherit())) {
207 final Menu clone = menu.clone();
208
209 rebaseMenuPaths(clone.getItems(), urlContainer);
210
211 menus.add(topCounter, clone);
212 topCounter++;
213 } else if ("bottom".equals(menu.getInherit())) {
214 final Menu clone = menu.clone();
215
216 rebaseMenuPaths(clone.getItems(), urlContainer);
217
218 menus.add(clone);
219 }
220 }
221
222 return menus;
223 }
224
225 private void relativizeMenuPaths(final List<MenuItem> items, final String baseUrl) {
226 for (MenuItem item : items) {
227 relativizeLinkItemPaths(item, baseUrl);
228 relativizeMenuPaths(item.getItems(), baseUrl);
229 }
230 }
231
232 private void rebaseMenuPaths(final List<MenuItem> items, final URLRebaser urlContainer) {
233 for (MenuItem item : items) {
234 rebaseLinkItemPaths(item, urlContainer);
235 rebaseMenuPaths(item.getItems(), urlContainer);
236 }
237 }
238
239 private void relativizeLinkItemPaths(final LinkItem item, final String baseUrl) {
240 item.setHref(relativizeLink(item.getHref(), baseUrl));
241 }
242
243 private void rebaseLinkItemPaths(final LinkItem item, final URLRebaser urlContainer) {
244 item.setHref(urlContainer.rebaseLink(item.getHref()));
245 }
246
247 private void relativizeLogoPaths(final Logo logo, final String baseUrl) {
248 logo.setImg(relativizeLink(logo.getImg(), baseUrl));
249 relativizeLinkItemPaths(logo, baseUrl);
250 }
251
252 private void rebaseLogoPaths(final Logo logo, final URLRebaser urlContainer) {
253 logo.setImg(urlContainer.rebaseLink(logo.getImg()));
254 rebaseLinkItemPaths(logo, urlContainer);
255 }
256
257 private List<LinkItem> mergeLinkItemLists(
258 final List<LinkItem> childList,
259 final List<LinkItem> parentList,
260 final URLRebaser urlContainer,
261 boolean cutParentAfterDuplicate) {
262 List<LinkItem> items = new ArrayList<LinkItem>(childList.size() + parentList.size());
263
264 for (LinkItem item : parentList) {
265 if (!items.contains(item) && !childList.contains(item)) {
266 final LinkItem clone = item.clone();
267
268 rebaseLinkItemPaths(clone, urlContainer);
269
270 items.add(clone);
271 } else if (cutParentAfterDuplicate) {
272
273
274
275 break;
276 }
277 }
278
279 for (LinkItem item : childList) {
280 if (!items.contains(item)) {
281 items.add(item);
282 }
283 }
284
285 return items;
286 }
287
288 private List<Logo> mergePoweredByLists(
289 final List<Logo> childList, final List<Logo> parentList, final URLRebaser urlContainer) {
290 List<Logo> logos = new ArrayList<Logo>(childList.size() + parentList.size());
291
292 for (Logo logo : parentList) {
293 if (!logos.contains(logo)) {
294 final Logo clone = logo.clone();
295
296 rebaseLogoPaths(clone, urlContainer);
297
298 logos.add(clone);
299 }
300 }
301
302 for (Logo logo : childList) {
303 if (!logos.contains(logo)) {
304 logos.add(logo);
305 }
306 }
307
308 return logos;
309 }
310
311
312
313 private String relativizeLink(final String link, final String baseUri) {
314 if (link == null || baseUri == null) {
315 return link;
316 }
317
318
319 try {
320 final URIPathDescriptor path = new URIPathDescriptor(baseUri, link);
321
322 return path.relativizeLink().toString();
323 } catch (IllegalArgumentException e) {
324 return link;
325 }
326 }
327
328
329
330
331
332 private static class URLRebaser {
333
334 private final String oldPath;
335
336 private final String newPath;
337
338
339
340
341
342
343
344 URLRebaser(final String oldPath, final String newPath) {
345 this.oldPath = oldPath;
346 this.newPath = newPath;
347 }
348
349
350
351
352
353
354 public String getNewPath() {
355 return this.newPath;
356 }
357
358
359
360
361
362
363 public String getOldPath() {
364 return this.oldPath;
365 }
366
367
368
369
370
371 public String rebaseLink(final String link) {
372 if (link == null || getOldPath() == null) {
373 return link;
374 }
375
376 if (link.contains("${project.")) {
377 throw new IllegalArgumentException("site.xml late interpolation ${project.*} expression found"
378 + " in link: '" + link + "'. Use early interpolation ${this.*}");
379 }
380
381 final URIPathDescriptor oldPath = new URIPathDescriptor(getOldPath(), link);
382
383 return oldPath.rebaseLink(getNewPath()).toString();
384 }
385 }
386 }