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