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