Coverage Report - org.apache.maven.doxia.site.decoration.inheritance.DefaultDecorationModelInheritanceAssembler
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultDecorationModelInheritanceAssembler
97%
135/138
93%
90/96
3,7
DefaultDecorationModelInheritanceAssembler$URLContainer
100%
6/6
N/A
3,7
 
 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 1092010 2011-04-14 05:43:45Z ltheussl $
 41  
  * @plexus.component role="org.apache.maven.doxia.site.decoration.inheritance.DecorationModelInheritanceAssembler"
 42  
  */
 43  138
 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  198
         if ( parent == null )
 52  
         {
 53  12
             return;
 54  
         }
 55  
 
 56  186
         URLContainer urlContainer = new URLContainer( parentBaseUrl, childBaseUrl );
 57  
 
 58  186
         if ( child.getBannerLeft() == null && parent.getBannerLeft() != null )
 59  
         {
 60  108
             child.setBannerLeft( parent.getBannerLeft().clone());
 61  108
             rebaseBannerPaths( child.getBannerLeft(), urlContainer );
 62  
         }
 63  
 
 64  186
         if ( child.getBannerRight() == null && parent.getBannerRight() != null)
 65  
         {
 66  108
             child.setBannerRight( parent.getBannerRight().clone());
 67  108
             rebaseBannerPaths( child.getBannerRight(), urlContainer );
 68  
         }
 69  
 
 70  186
         if ( child.getPublishDate() == null && parent.getPublishDate() != null )
 71  
         {
 72  12
             child.setPublishDate( parent.getPublishDate().clone());
 73  
         }
 74  
 
 75  186
         if ( child.getVersion() == null && parent.getVersion() != null )
 76  
         {
 77  12
             child.setVersion( parent.getVersion().clone());
 78  
         }
 79  
 
 80  186
         if ( child.getSkin() == null && parent.getSkin() != null )
 81  
         {
 82  24
             child.setSkin( parent.getSkin().clone());
 83  
         }
 84  
 
 85  186
         child.setPoweredBy( mergePoweredByLists( child.getPoweredBy(), parent.getPoweredBy(), urlContainer ) );
 86  
 
 87  186
         if ( parent.getLastModified() > child.getLastModified() )
 88  
         {
 89  0
             child.setLastModified( parent.getLastModified() );
 90  
         }
 91  
 
 92  186
         assembleBodyInheritance( name, child, parent, urlContainer );
 93  
 
 94  186
         assembleCustomInheritance( child, parent );
 95  186
     }
 96  
 
 97  
     /** {@inheritDoc} */
 98  
     public void resolvePaths( final DecorationModel decoration, final String baseUrl )
 99  
     {
 100  72
         if ( baseUrl == null )
 101  
         {
 102  0
             return;
 103  
         }
 104  
 
 105  72
         if ( decoration.getBannerLeft() != null )
 106  
         {
 107  48
             relativizeBannerPaths( decoration.getBannerLeft(), baseUrl );
 108  
         }
 109  
 
 110  72
         if ( decoration.getBannerRight() != null )
 111  
         {
 112  42
             relativizeBannerPaths( decoration.getBannerRight(), baseUrl );
 113  
         }
 114  
 
 115  72
         for ( Logo logo : decoration.getPoweredBy() )
 116  
         {
 117  48
             relativizeLogoPaths( logo, baseUrl );
 118  
         }
 119  
 
 120  72
         if ( decoration.getBody() != null )
 121  
         {
 122  66
             for ( LinkItem linkItem : decoration.getBody().getLinks() )
 123  
             {
 124  42
                 relativizeLinkItemPaths( linkItem, baseUrl );
 125  
             }
 126  
 
 127  66
             for ( LinkItem linkItem : decoration.getBody().getBreadcrumbs() )
 128  
             {
 129  54
                 relativizeLinkItemPaths( linkItem, baseUrl );
 130  
             }
 131  
 
 132  66
             for ( Menu menu : decoration.getBody().getMenus() )
 133  
             {
 134  30
                 relativizeMenuPaths( menu.getItems(), baseUrl );
 135  
             }
 136  
         }
 137  72
     }
 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  90
         banner.setHref( relativizeLink( banner.getHref(), baseUrl ) );
 150  90
         banner.setSrc( relativizeLink( banner.getSrc(), baseUrl ) );
 151  90
     }
 152  
 
 153  
     private void rebaseBannerPaths( final Banner banner, final URLContainer urlContainer )
 154  
     {
 155  216
         if ( banner.getHref() != null ) // it may be empty
 156  
         {
 157  216
             banner.setHref( rebaseLink( banner.getHref(), urlContainer ) );
 158  
         }
 159  
 
 160  216
         if ( banner.getSrc() != null )
 161  
         {
 162  204
             banner.setSrc( rebaseLink( banner.getSrc(), urlContainer ) );
 163  
         }
 164  216
     }
 165  
 
 166  
     private void assembleCustomInheritance( final DecorationModel child, final DecorationModel parent )
 167  
     {
 168  186
         if ( child.getCustom() == null )
 169  
         {
 170  174
             child.setCustom( parent.getCustom() );
 171  
         }
 172  
         else
 173  
         {
 174  12
             child.setCustom( Xpp3Dom.mergeXpp3Dom( (Xpp3Dom) child.getCustom(), (Xpp3Dom) parent.getCustom() ) );
 175  
         }
 176  186
     }
 177  
 
 178  
     private void assembleBodyInheritance( final String name, final DecorationModel child, final DecorationModel parent,
 179  
                                           final URLContainer urlContainer )
 180  
     {
 181  186
         Body cBody = child.getBody();
 182  186
         Body pBody = parent.getBody();
 183  
 
 184  186
         if ( cBody != null || pBody != null )
 185  
         {
 186  174
             if ( cBody == null )
 187  
             {
 188  138
                 cBody = new Body();
 189  138
                 child.setBody( cBody );
 190  
             }
 191  
 
 192  174
             if ( pBody == null )
 193  
             {
 194  6
                 pBody = new Body();
 195  
             }
 196  
 
 197  174
             if ( cBody.getHead() == null )
 198  
             {
 199  162
                 cBody.setHead( pBody.getHead() );
 200  
             }
 201  
             else
 202  
             {
 203  12
                 cBody.setHead( Xpp3Dom.mergeXpp3Dom( (Xpp3Dom) cBody.getHead(), (Xpp3Dom) pBody.getHead() ) );
 204  
             }
 205  
 
 206  174
             cBody.setLinks( mergeLinkItemLists( cBody.getLinks(), pBody.getLinks(), urlContainer ) );
 207  
 
 208  174
             if ( cBody.getBreadcrumbs().isEmpty() && !pBody.getBreadcrumbs().isEmpty() )
 209  
             {
 210  132
                 LinkItem breadcrumb = new LinkItem();
 211  132
                 breadcrumb.setName( name );
 212  132
                 breadcrumb.setHref( "" );
 213  132
                 cBody.getBreadcrumbs().add( breadcrumb );
 214  
             }
 215  174
             cBody.setBreadcrumbs( mergeLinkItemLists( cBody.getBreadcrumbs(), pBody.getBreadcrumbs(), urlContainer ) );
 216  
 
 217  174
             cBody.setMenus( mergeMenus( cBody.getMenus(), pBody.getMenus(), urlContainer ) );
 218  
         }
 219  186
     }
 220  
 
 221  
     private List<Menu> mergeMenus( final List<Menu> childMenus, final List<Menu> parentMenus,
 222  
                                    final URLContainer urlContainer )
 223  
     {
 224  174
         List<Menu> menus = new ArrayList<Menu>( childMenus.size() + parentMenus.size() );
 225  
 
 226  174
         for ( Menu menu : childMenus )
 227  
         {
 228  24
             menus.add( menu );
 229  
         }
 230  
 
 231  174
         int topCounter = 0;
 232  174
         for ( Menu menu : parentMenus )
 233  
         {
 234  156
             if ( "top".equals( menu.getInherit() ) )
 235  
             {
 236  108
                 final Menu clone = menu.clone();
 237  
 
 238  108
                 rebaseMenuPaths( clone.getItems(), urlContainer );
 239  
 
 240  108
                 menus.add( topCounter, clone );
 241  108
                 topCounter++;
 242  108
             }
 243  48
             else if ( "bottom".equals( menu.getInherit() ) )
 244  
             {
 245  12
                 final Menu clone = menu.clone();
 246  
 
 247  12
                 rebaseMenuPaths( clone.getItems(), urlContainer );
 248  
 
 249  12
                 menus.add( clone );
 250  156
             }
 251  
         }
 252  
 
 253  174
         return menus;
 254  
     }
 255  
 
 256  
     private void relativizeMenuPaths( final List<MenuItem> items, final String baseUrl )
 257  
     {
 258  60
         for ( MenuItem item : items )
 259  
         {
 260  30
             relativizeLinkItemPaths( item, baseUrl );
 261  30
             relativizeMenuPaths( item.getItems(), baseUrl );
 262  
         }
 263  60
     }
 264  
 
 265  
     private void rebaseMenuPaths( final List<MenuItem> items, final URLContainer urlContainer )
 266  
     {
 267  240
         for ( MenuItem item : items )
 268  
         {
 269  120
             rebaseLinkItemPaths( item, urlContainer );
 270  120
             rebaseMenuPaths( item.getItems(), urlContainer );
 271  
         }
 272  240
     }
 273  
 
 274  
     private void relativizeLinkItemPaths( final LinkItem item, final String baseUrl )
 275  
     {
 276  174
         item.setHref( relativizeLink( item.getHref(), baseUrl ) );
 277  174
     }
 278  
 
 279  
     private void rebaseLinkItemPaths( final LinkItem item, final URLContainer urlContainer )
 280  
     {
 281  522
         item.setHref( rebaseLink( item.getHref(), urlContainer ) );
 282  522
     }
 283  
 
 284  
     private void relativizeLogoPaths( final Logo logo, final String baseUrl )
 285  
     {
 286  48
         logo.setImg( relativizeLink( logo.getImg(), baseUrl ) );
 287  48
         relativizeLinkItemPaths( logo, baseUrl );
 288  48
     }
 289  
 
 290  
     private void rebaseLogoPaths( final Logo logo, final URLContainer urlContainer )
 291  
     {
 292  126
         logo.setImg( rebaseLink( logo.getImg(), urlContainer ) );
 293  126
         rebaseLinkItemPaths( logo, urlContainer );
 294  126
     }
 295  
 
 296  
     private List<LinkItem> mergeLinkItemLists( final List<LinkItem> childList, final List<LinkItem> parentList,
 297  
                                                final URLContainer urlContainer )
 298  
     {
 299  348
         List<LinkItem> items = new ArrayList<LinkItem>( childList.size() + parentList.size() );
 300  
 
 301  348
         for ( LinkItem item : parentList )
 302  
         {
 303  282
             if ( !items.contains( item ) )
 304  
             {
 305  276
                 final LinkItem clone = item.clone();
 306  
 
 307  276
                 rebaseLinkItemPaths( clone, urlContainer );
 308  
 
 309  276
                 items.add( clone );
 310  282
             }
 311  
         }
 312  
 
 313  348
         for ( LinkItem item : childList )
 314  
         {
 315  174
             if ( !items.contains( item ) )
 316  
             {
 317  156
                 items.add( item );
 318  
             }
 319  
         }
 320  
 
 321  348
         return items;
 322  
     }
 323  
 
 324  
     private List<Logo> mergePoweredByLists( final List<Logo> childList, final List<Logo> parentList,
 325  
                                             final URLContainer urlContainer )
 326  
     {
 327  186
         List<Logo> logos = new ArrayList<Logo>( childList.size() + parentList.size() );
 328  
 
 329  186
         for ( Logo logo : parentList )
 330  
         {
 331  132
             if ( !logos.contains( logo ) )
 332  
             {
 333  126
                 final Logo clone = logo.clone();
 334  
 
 335  126
                 rebaseLogoPaths( clone, urlContainer );
 336  
 
 337  126
                 logos.add( clone );
 338  132
             }
 339  
         }
 340  
 
 341  186
         for ( Logo logo : childList )
 342  
         {
 343  24
             if ( !logos.contains( logo ) )
 344  
             {
 345  6
                 logos.add( logo );
 346  
             }
 347  
         }
 348  
 
 349  186
         return logos;
 350  
     }
 351  
 
 352  
     // rebase only affects relative links, a relative link wrt an old base gets translated,
 353  
     // so it points to the same location as viewed from a new base
 354  
     private String rebaseLink( final String link, final URLContainer urlContainer )
 355  
     {
 356  1068
         if ( link == null || urlContainer.getOldPath() == null )
 357  
         {
 358  0
             return link;
 359  
         }
 360  
 
 361  1068
         final URIPathDescriptor oldPath = new URIPathDescriptor( urlContainer.getOldPath(), link );
 362  
 
 363  1068
         return oldPath.rebaseLink( urlContainer.getNewPath() ).toString();
 364  
     }
 365  
 
 366  
     // relativize only affects absolute links, if the link has the same scheme, host and port
 367  
     // as the base, it is made into a relative link as viewed from the base
 368  
     private String relativizeLink( final String link, final String baseUri )
 369  
     {
 370  402
         if ( link == null || baseUri == null )
 371  
         {
 372  18
             return link;
 373  
         }
 374  
 
 375  
         // this shouldn't be necessary, just to swallow mal-formed hrefs
 376  
         try
 377  
         {
 378  384
             final URIPathDescriptor path = new URIPathDescriptor( baseUri, link );
 379  
 
 380  378
             return path.relativizeLink().toString();
 381  
         }
 382  6
         catch ( IllegalArgumentException e )
 383  
         {
 384  6
             return link;
 385  
         }
 386  
     }
 387  
 
 388  
     /**
 389  
      * Contains an old and a new path.
 390  
      */
 391  138
     public final class URLContainer
 392  
     {
 393  
 
 394  
         private final String oldPath;
 395  
 
 396  
         private final String newPath;
 397  
 
 398  
         /**
 399  
          * Construct a URLContainer.
 400  
          *
 401  
          * @param oldPath the old path.
 402  
          * @param newPath the new path.
 403  
          */
 404  
         public URLContainer( final String oldPath, final String newPath )
 405  186
         {
 406  186
             this.oldPath = oldPath;
 407  186
             this.newPath = newPath;
 408  186
         }
 409  
 
 410  
         /**
 411  
          * Get the new path.
 412  
          *
 413  
          * @return the new path.
 414  
          */
 415  
         public String getNewPath()
 416  
         {
 417  1068
             return this.newPath;
 418  
         }
 419  
 
 420  
         /**
 421  
          * Get the old path.
 422  
          *
 423  
          * @return the old path.
 424  
          */
 425  
         public String getOldPath()
 426  
         {
 427  2136
             return this.oldPath;
 428  
         }
 429  
     }
 430  
 }