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