Coverage Report - org.codehaus.plexus.metadata.merge.support.AbstractMergeableElement
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractMergeableElement
85 %
35/41
87 %
28/32
4,333
 
 1  
 package org.codehaus.plexus.metadata.merge.support;
 2  
 
 3  
 /*
 4  
  * The MIT License
 5  
  *
 6  
  * Copyright (c) 2006, The Codehaus
 7  
  *
 8  
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
 9  
  * this software and associated documentation files (the "Software"), to deal in
 10  
  * the Software without restriction, including without limitation the rights to
 11  
  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 12  
  * of the Software, and to permit persons to whom the Software is furnished to do
 13  
  * so, subject to the following conditions:
 14  
  *
 15  
  * The above copyright notice and this permission notice shall be included in all
 16  
  * copies or substantial portions of the Software.
 17  
  *
 18  
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 24  
  * SOFTWARE.
 25  
  */
 26  
 
 27  
 import java.util.ArrayList;
 28  
 import java.util.HashSet;
 29  
 import java.util.Iterator;
 30  
 import java.util.List;
 31  
 import java.util.Set;
 32  
 
 33  
 import org.codehaus.plexus.metadata.merge.MergeException;
 34  
 import org.codehaus.plexus.metadata.merge.MergeStrategy;
 35  
 import org.jdom.Content;
 36  
 import org.jdom.Element;
 37  
 
 38  
 /**
 39  
  * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 40  
  * @version $Id$
 41  
  */
 42  
 public abstract class AbstractMergeableElement
 43  
     extends AbstractMergeableSupport
 44  
 {
 45  
     public AbstractMergeableElement( Element element )
 46  
     {
 47  21
         super( element );
 48  21
     }
 49  
 
 50  
     /**
 51  
      * Detects if there was a conflict, that is the specified element was
 52  
      * present in both dominant and recessive element-sets.
 53  
      * <p/>
 54  
      * This delegates to
 55  
      * {@link #isRecessiveElementInConflict(AbstractMergeableElement,List)}.
 56  
      *
 57  
      * @param re      Recessive element.
 58  
      * @param eltName Element name to test for.
 59  
      * @return <code>true</code> if there was a conflict of element.
 60  
      * @deprecated <em>use {@link #isRecessiveElementInConflict(AbstractMergeableElement,List)} instead.</em>
 61  
      */
 62  
     protected boolean isRecessiveElementInConflict( AbstractMergeableElement re, String eltName )
 63  
     {
 64  
         // return (null != getChild (eltName) && null != re.getChild (eltName));
 65  0
         List l = new ArrayList();
 66  0
         l.add( eltName );
 67  0
         return isRecessiveElementInConflict( re, l );
 68  
     }
 69  
 
 70  
     /**
 71  
      * Detects if there was a conflict, that is the specified element was
 72  
      * present in both dominant and recessive element-sets.
 73  
      * <p/>
 74  
      * Use this to determine conflicts when the Dominant and Recessive element
 75  
      * sets are keyed with Composite keys.<br>
 76  
      * For instance: <code>&lt;component&gt;</code> is keyed on
 77  
      * <code>&lt;role&gt;</code> and <code>&lt;role-hint&gt;</code>.
 78  
      *
 79  
      * @param re
 80  
      * @param eltNameList List of elements that will be checked for values in both dominant and recessive sets.
 81  
      * @return
 82  
      */
 83  
     protected boolean isRecessiveElementInConflict( AbstractMergeableElement re, List eltNameList )
 84  
     {
 85  
         // give opportunity to subclasses to provide any custom Composite keys
 86  
         // for conflict checks.
 87  30
         eltNameList = getElementNamesForConflictResolution( eltNameList );
 88  
 
 89  30
         if ( null == eltNameList || eltNameList.size() == 0 )
 90  
         {
 91  0
             return false;
 92  
         }
 93  
 
 94  
         // assuming the elements will conflict.
 95  30
         for (Object anEltNameList : eltNameList) {
 96  30
             String eltName = (String) anEltNameList;
 97  30
             String dEltValue = getChildTextTrim(eltName);
 98  30
             String rEltValue = re.getChildTextTrim(eltName);
 99  30
             if (null == dEltValue || null == rEltValue || !dEltValue.equals(rEltValue)) {
 100  18
                 return false;
 101  
             }
 102  12
         }
 103  12
         return true;
 104  
     }
 105  
 
 106  
     /**
 107  
      * Determines if the Element to be merged is to be sourced from Recessive
 108  
      * Element set.
 109  
      *
 110  
      * @param re      Recessive element.
 111  
      * @param eltName Element name to test for.
 112  
      * @return
 113  
      */
 114  
     protected boolean mergeableElementComesFromRecessive( AbstractMergeableElement re, String eltName )
 115  
     {
 116  18
         return null == getChildText( eltName ) && null != re.getChildText( eltName );
 117  
     }
 118  
 
 119  
     /**
 120  
      * Simply delegate to
 121  
      *
 122  
      * @see Mergeable#merge(Mergeable,org.codehaus.plexus.metadata.merge.MergeStrategy)
 123  
      */
 124  
     public void merge( Mergeable me, MergeStrategy strategy )
 125  
         throws MergeException
 126  
     {
 127  
         // TODO set up a unit test for this!
 128  3
         strategy.apply( this, me );
 129  3
     }
 130  
 
 131  
     public void merge( Mergeable me )
 132  
         throws MergeException
 133  
     {
 134  6
         if ( !isExpectedElementType( me ) )
 135  
         {
 136  
             // if (getLogger().isErrorEnabled)
 137  
             //     getLogger().error ("Cannot Merge dissimilar elements. (Expected : '" + getClass ().getName () + "', found '" + me.getClass ().getName () + "')");
 138  1
             throw new MergeException( "Cannot Merge dissimilar elements. " + "(Expected : '" + getClass().getName() +
 139  
                 "', found '" + me.getClass().getName() + "')" );
 140  
         }
 141  
         // recessive Component Element.
 142  5
         AbstractMergeableElement rce = (AbstractMergeableElement) me;
 143  
 
 144  5
         Set allowedTags = new HashSet();
 145  
 
 146  32
         for ( int i = 0; i < getAllowedTags().length; i++ )
 147  
         {
 148  27
             String tagName = getAllowedTags()[i].getTagName();
 149  
 
 150  27
             allowedTags.add( tagName );
 151  
 
 152  27
             List defaultConflictChecklist = new ArrayList();
 153  27
             defaultConflictChecklist.add( tagName );
 154  
 
 155  27
             if ( !isRecessiveElementInConflict( rce, defaultConflictChecklist ) &&
 156  
                 mergeableElementComesFromRecessive( rce, tagName ) )
 157  
             {
 158  3
                 this.addContent( (Element) rce.getChild( tagName ).clone() );
 159  
                 // else dominant wins in anycase!
 160  
             }
 161  
             else
 162  24
             if ( getAllowedTags()[i].isMergeable() && isRecessiveElementInConflict( rce, defaultConflictChecklist ) )
 163  
             {
 164  
                 // this allows for merging multiple/list of elements.
 165  
                 try
 166  
                 {
 167  3
                     getAllowedTags()[i].createMergeable( this.getChild( tagName ) )
 168  
                         .merge( getAllowedTags()[i].createMergeable( rce.getChild( tagName ) ),
 169  
                                 getDefaultMergeStrategy() );
 170  
                 }
 171  0
                 catch ( Exception e )
 172  
                 {
 173  
                     // TODO log to error
 174  0
                     throw new MergeException(
 175  
                         "Unable to create Mergeable instance for tag " + "'" + getAllowedTags()[i] + "'.", e );
 176  3
                 }
 177  
             }
 178  
         }
 179  
 
 180  5
         for (Object o : me.getElement().getChildren()) {
 181  16
             Element child = (Element) o;
 182  
 
 183  16
             if (!allowedTags.contains(child.getName())) {
 184  
                 // not yet merged, copy over
 185  1
                 element.addContent((Content) child.clone());
 186  
             }
 187  16
         }
 188  
 
 189  5
     }
 190  
 
 191  
 }