Coverage Report - org.apache.maven.doxia.site.decoration.inheritance.DefaultDecorationModelInheritanceAssembler
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultDecorationModelInheritanceAssembler
97%
139/142
93%
97/104
3,9
DefaultDecorationModelInheritanceAssembler$URLContainer
100%
6/6
N/A
3,9
 
 1  
 package org.apache.maven.doxia.site.decoration.inheritance;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 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.util.xml.Xpp3Dom;
 34  
 
 35  
 /**
 36  
  * Manage inheritance of the decoration model.
 37  
  *
 38  
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 39  
  * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
 40  
  * @version $Id: DefaultDecorationModelInheritanceAssembler.java 1310075 2012-04-05 21:25:03Z dennisl $
 41  
  * @plexus.component role="org.apache.maven.doxia.site.decoration.inheritance.DecorationModelInheritanceAssembler"
 42  
  */
 43  48
 public class DefaultDecorationModelInheritanceAssembler
 44  
     implements DecorationModelInheritanceAssembler
 45  
 {
 46  
     /** {@inheritDoc} */
 47  
     public void assembleModelInheritance( String name, DecorationModel child, DecorationModel parent,
 48  
                                           String childBaseUrl, String parentBaseUrl )
 49  
     {
 50  
         // cannot inherit from null parent.
 51  68
         if ( parent == null )
 52  
         {
 53  4
             return;
 54  
         }
 55  
 
 56  64
         URLContainer urlContainer = new URLContainer( parentBaseUrl, childBaseUrl );
 57  
 
 58  64
         if ( child.getBannerLeft() == null && parent.getBannerLeft() != null )
 59  
         {
 60  36
             child.setBannerLeft( parent.getBannerLeft().clone());
 61  36
             rebaseBannerPaths( child.getBannerLeft(), urlContainer );
 62  
         }
 63  
 
 64  64
         if ( child.getBannerRight() == null && parent.getBannerRight() != null)
 65  
         {
 66  36
             child.setBannerRight( parent.getBannerRight().clone());
 67  36
             rebaseBannerPaths( child.getBannerRight(), urlContainer );
 68  
         }
 69  
 
 70  64
         if ( child.getPublishDate() == null && parent.getPublishDate() != null )
 71  
         {
 72  4
             child.setPublishDate( parent.getPublishDate().clone());
 73  
         }
 74  
 
 75  64
         if ( child.getVersion() == null && parent.getVersion() != null )
 76  
         {
 77  4
             child.setVersion( parent.getVersion().clone());
 78  
         }
 79  
 
 80  64
         if ( child.getSkin() == null && parent.getSkin() != null )
 81  
         {
 82  8
             child.setSkin( parent.getSkin().clone());
 83  
         }
 84  
 
 85  64
         child.setPoweredBy( mergePoweredByLists( child.getPoweredBy(), parent.getPoweredBy(), urlContainer ) );
 86  
 
 87  64
         if ( parent.getLastModified() > child.getLastModified() )
 88  
         {
 89  0
             child.setLastModified( parent.getLastModified() );
 90  
         }
 91  
 
 92  64
         assembleBodyInheritance( name, child, parent, urlContainer );
 93  
 
 94  64
         assembleCustomInheritance( child, parent );
 95  64
     }
 96  
 
 97  
     /** {@inheritDoc} */
 98  
     public void resolvePaths( final DecorationModel decoration, final String baseUrl )
 99  
     {
 100  24
         if ( baseUrl == null )
 101  
         {
 102  0
             return;
 103  
         }
 104  
 
 105  24
         if ( decoration.getBannerLeft() != null )
 106  
         {
 107  16
             relativizeBannerPaths( decoration.getBannerLeft(), baseUrl );
 108  
         }
 109  
 
 110  24
         if ( decoration.getBannerRight() != null )
 111  
         {
 112  14
             relativizeBannerPaths( decoration.getBannerRight(), baseUrl );
 113  
         }
 114  
 
 115  24
         for ( Logo logo : decoration.getPoweredBy() )
 116  
         {
 117  16
             relativizeLogoPaths( logo, baseUrl );
 118  
         }
 119  
 
 120  24
         if ( decoration.getBody() != null )
 121  
         {
 122  22
             for ( LinkItem linkItem : decoration.getBody().getLinks() )
 123  
             {
 124  14
                 relativizeLinkItemPaths( linkItem, baseUrl );
 125  
             }
 126  
 
 127  22
             for ( LinkItem linkItem : decoration.getBody().getBreadcrumbs() )
 128  
             {
 129  18
                 relativizeLinkItemPaths( linkItem, baseUrl );
 130  
             }
 131  
 
 132  22
             for ( Menu menu : decoration.getBody().getMenus() )
 133  
             {
 134  10
                 relativizeMenuPaths( menu.getItems(), baseUrl );
 135  
             }
 136  
         }
 137  24
     }
 138  
 
 139  
     /**
 140  
      * Resolves all relative paths between the elements in a banner. The banner element might contain relative paths
 141  
      * to the oldBaseUrl, these are changed to the newBannerUrl.
 142  
      *
 143  
      * @param banner
 144  
      * @param baseUrl
 145  
      */
 146  
     private void relativizeBannerPaths( final Banner banner, final String baseUrl )
 147  
     {
 148  
         // banner has been checked to be not null, both href and src may be empty or null
 149  30
         banner.setHref( relativizeLink( banner.getHref(), baseUrl ) );
 150  30
         banner.setSrc( relativizeLink( banner.getSrc(), baseUrl ) );
 151  30
     }
 152  
 
 153  
     private void rebaseBannerPaths( final Banner banner, final URLContainer urlContainer )
 154  
     {
 155  72
         if ( banner.getHref() != null ) // it may be empty
 156  
         {
 157  72
             banner.setHref( rebaseLink( banner.getHref(), urlContainer ) );
 158  
         }
 159  
 
 160  72
         if ( banner.getSrc() != null )
 161  
         {
 162  68
             banner.setSrc( rebaseLink( banner.getSrc(), urlContainer ) );
 163  
         }
 164  72
     }
 165  
 
 166  
     private void assembleCustomInheritance( final DecorationModel child, final DecorationModel parent )
 167  
     {
 168  64
         if ( child.getCustom() == null )
 169  
         {
 170  60
             child.setCustom( parent.getCustom() );
 171  
         }
 172  
         else
 173  
         {
 174  4
             child.setCustom( Xpp3Dom.mergeXpp3Dom( (Xpp3Dom) child.getCustom(), (Xpp3Dom) parent.getCustom() ) );
 175  
         }
 176  64
     }
 177  
 
 178  
     private void assembleBodyInheritance( final String name, final DecorationModel child, final DecorationModel parent,
 179  
                                           final URLContainer urlContainer )
 180  
     {
 181  64
         Body cBody = child.getBody();
 182  64
         Body pBody = parent.getBody();
 183  
 
 184  64
         if ( cBody != null || pBody != null )
 185  
         {
 186  60
             if ( cBody == null )
 187  
             {
 188  46
                 cBody = new Body();
 189  46
                 child.setBody( cBody );
 190  
             }
 191  
 
 192  60
             if ( pBody == null )
 193  
             {
 194  2
                 pBody = new Body();
 195  
             }
 196  
 
 197  60
             if ( cBody.getHead() == null )
 198  
             {
 199  56
                 cBody.setHead( pBody.getHead() );
 200  
             }
 201  
             else
 202  
             {
 203  4
                 cBody.setHead( Xpp3Dom.mergeXpp3Dom( (Xpp3Dom) cBody.getHead(), (Xpp3Dom) pBody.getHead() ) );
 204  
             }
 205  
 
 206  60
             cBody.setLinks( mergeLinkItemLists( cBody.getLinks(), pBody.getLinks(), urlContainer, false ) );
 207  
 
 208  60
             if ( cBody.getBreadcrumbs().isEmpty() && !pBody.getBreadcrumbs().isEmpty() )
 209  
             {
 210  44
                 LinkItem breadcrumb = new LinkItem();
 211  44
                 breadcrumb.setName( name );
 212  44
                 breadcrumb.setHref( "" );
 213  44
                 cBody.getBreadcrumbs().add( breadcrumb );
 214  
             }
 215  60
             cBody.setBreadcrumbs( mergeLinkItemLists( cBody.getBreadcrumbs(), pBody.getBreadcrumbs(), urlContainer,
 216  
                                                       true ) );
 217  
 
 218  60
             cBody.setMenus( mergeMenus( cBody.getMenus(), pBody.getMenus(), urlContainer ) );
 219  
 
 220  60
             if ( cBody.getFooter() == null && pBody.getFooter() != null )
 221  
             {
 222  0
                 cBody.setFooter( pBody.getFooter() );
 223  
             }
 224  
         }
 225  64
     }
 226  
 
 227  
     private List<Menu> mergeMenus( final List<Menu> childMenus, final List<Menu> parentMenus,
 228  
                                    final URLContainer urlContainer )
 229  
     {
 230  60
         List<Menu> menus = new ArrayList<Menu>( childMenus.size() + parentMenus.size() );
 231  
 
 232  60
         for ( Menu menu : childMenus )
 233  
         {
 234  8
             menus.add( menu );
 235  
         }
 236  
 
 237  60
         int topCounter = 0;
 238  60
         for ( Menu menu : parentMenus )
 239  
         {
 240  52
             if ( "top".equals( menu.getInherit() ) )
 241  
             {
 242  36
                 final Menu clone = menu.clone();
 243  
 
 244  36
                 rebaseMenuPaths( clone.getItems(), urlContainer );
 245  
 
 246  36
                 menus.add( topCounter, clone );
 247  36
                 topCounter++;
 248  36
             }
 249  16
             else if ( "bottom".equals( menu.getInherit() ) )
 250  
             {
 251  4
                 final Menu clone = menu.clone();
 252  
 
 253  4
                 rebaseMenuPaths( clone.getItems(), urlContainer );
 254  
 
 255  4
                 menus.add( clone );
 256  52
             }
 257  
         }
 258  
 
 259  60
         return menus;
 260  
     }
 261  
 
 262  
     private void relativizeMenuPaths( final List<MenuItem> items, final String baseUrl )
 263  
     {
 264  20
         for ( MenuItem item : items )
 265  
         {
 266  10
             relativizeLinkItemPaths( item, baseUrl );
 267  10
             relativizeMenuPaths( item.getItems(), baseUrl );
 268  
         }
 269  20
     }
 270  
 
 271  
     private void rebaseMenuPaths( final List<MenuItem> items, final URLContainer urlContainer )
 272  
     {
 273  80
         for ( MenuItem item : items )
 274  
         {
 275  40
             rebaseLinkItemPaths( item, urlContainer );
 276  40
             rebaseMenuPaths( item.getItems(), urlContainer );
 277  
         }
 278  80
     }
 279  
 
 280  
     private void relativizeLinkItemPaths( final LinkItem item, final String baseUrl )
 281  
     {
 282  58
         item.setHref( relativizeLink( item.getHref(), baseUrl ) );
 283  58
     }
 284  
 
 285  
     private void rebaseLinkItemPaths( final LinkItem item, final URLContainer urlContainer )
 286  
     {
 287  172
         item.setHref( rebaseLink( item.getHref(), urlContainer ) );
 288  172
     }
 289  
 
 290  
     private void relativizeLogoPaths( final Logo logo, final String baseUrl )
 291  
     {
 292  16
         logo.setImg( relativizeLink( logo.getImg(), baseUrl ) );
 293  16
         relativizeLinkItemPaths( logo, baseUrl );
 294  16
     }
 295  
 
 296  
     private void rebaseLogoPaths( final Logo logo, final URLContainer urlContainer )
 297  
     {
 298  42
         logo.setImg( rebaseLink( logo.getImg(), urlContainer ) );
 299  42
         rebaseLinkItemPaths( logo, urlContainer );
 300  42
     }
 301  
 
 302  
     private List<LinkItem> mergeLinkItemLists( final List<LinkItem> childList, final List<LinkItem> parentList,
 303  
                                                final URLContainer urlContainer, boolean cutParentAfterDuplicate )
 304  
     {
 305  120
         List<LinkItem> items = new ArrayList<LinkItem>( childList.size() + parentList.size() );
 306  
 
 307  120
         for ( LinkItem item : parentList )
 308  
         {
 309  98
             if ( !items.contains( item ) && !childList.contains( item ) )
 310  
             {
 311  90
                 final LinkItem clone = item.clone();
 312  
 
 313  90
                 rebaseLinkItemPaths( clone, urlContainer );
 314  
 
 315  90
                 items.add( clone );
 316  90
             }
 317  8
             else if ( cutParentAfterDuplicate )
 318  
             {
 319  
                 // if a parent item is found in child, ignore next items (case for breadcrumbs)
 320  
                 // merge ( "B > E", "A > B > C > D" ) -> "A > B > E" (notice missing "C > D")
 321  
                 // see http://jira.codehaus.org/browse/DOXIASITETOOLS-62
 322  2
                 break;
 323  
             }
 324  
         }
 325  
 
 326  120
         for ( LinkItem item : childList )
 327  
         {
 328  62
             if ( !items.contains( item ) )
 329  
             {
 330  60
                 items.add( item );
 331  
             }
 332  
         }
 333  
 
 334  120
         return items;
 335  
     }
 336  
 
 337  
     private List<Logo> mergePoweredByLists( final List<Logo> childList, final List<Logo> parentList,
 338  
                                             final URLContainer urlContainer )
 339  
     {
 340  64
         List<Logo> logos = new ArrayList<Logo>( childList.size() + parentList.size() );
 341  
 
 342  64
         for ( Logo logo : parentList )
 343  
         {
 344  44
             if ( !logos.contains( logo ) )
 345  
             {
 346  42
                 final Logo clone = logo.clone();
 347  
 
 348  42
                 rebaseLogoPaths( clone, urlContainer );
 349  
 
 350  42
                 logos.add( clone );
 351  44
             }
 352  
         }
 353  
 
 354  64
         for ( Logo logo : childList )
 355  
         {
 356  8
             if ( !logos.contains( logo ) )
 357  
             {
 358  2
                 logos.add( logo );
 359  
             }
 360  
         }
 361  
 
 362  64
         return logos;
 363  
     }
 364  
 
 365  
     // rebase only affects relative links, a relative link wrt an old base gets translated,
 366  
     // so it points to the same location as viewed from a new base
 367  
     private String rebaseLink( final String link, final URLContainer urlContainer )
 368  
     {
 369  354
         if ( link == null || urlContainer.getOldPath() == null )
 370  
         {
 371  2
             return link;
 372  
         }
 373  
 
 374  352
         final URIPathDescriptor oldPath = new URIPathDescriptor( urlContainer.getOldPath(), link );
 375  
 
 376  352
         return oldPath.rebaseLink( urlContainer.getNewPath() ).toString();
 377  
     }
 378  
 
 379  
     // relativize only affects absolute links, if the link has the same scheme, host and port
 380  
     // as the base, it is made into a relative link as viewed from the base
 381  
     private String relativizeLink( final String link, final String baseUri )
 382  
     {
 383  134
         if ( link == null || baseUri == null )
 384  
         {
 385  6
             return link;
 386  
         }
 387  
 
 388  
         // this shouldn't be necessary, just to swallow mal-formed hrefs
 389  
         try
 390  
         {
 391  128
             final URIPathDescriptor path = new URIPathDescriptor( baseUri, link );
 392  
 
 393  126
             return path.relativizeLink().toString();
 394  
         }
 395  2
         catch ( IllegalArgumentException e )
 396  
         {
 397  2
             return link;
 398  
         }
 399  
     }
 400  
 
 401  
     /**
 402  
      * Contains an old and a new path.
 403  
      */
 404  48
     public final class URLContainer
 405  
     {
 406  
 
 407  
         private final String oldPath;
 408  
 
 409  
         private final String newPath;
 410  
 
 411  
         /**
 412  
          * Construct a URLContainer.
 413  
          *
 414  
          * @param oldPath the old path.
 415  
          * @param newPath the new path.
 416  
          */
 417  
         public URLContainer( final String oldPath, final String newPath )
 418  64
         {
 419  64
             this.oldPath = oldPath;
 420  64
             this.newPath = newPath;
 421  64
         }
 422  
 
 423  
         /**
 424  
          * Get the new path.
 425  
          *
 426  
          * @return the new path.
 427  
          */
 428  
         public String getNewPath()
 429  
         {
 430  352
             return this.newPath;
 431  
         }
 432  
 
 433  
         /**
 434  
          * Get the old path.
 435  
          *
 436  
          * @return the old path.
 437  
          */
 438  
         public String getOldPath()
 439  
         {
 440  704
             return this.oldPath;
 441  
         }
 442  
     }
 443  
 }