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