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