Coverage Report - org.apache.commons.configuration.tree.MergeCombiner
 
Classes in this File Line Coverage Branch Coverage Complexity
MergeCombiner
100%
47/47
96%
27/28
6
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.configuration.tree;
 18  
 
 19  
 import java.util.ArrayList;
 20  
 import java.util.Iterator;
 21  
 import java.util.LinkedList;
 22  
 import java.util.List;
 23  
 
 24  
 /**
 25  
  * <p>
 26  
  * A specialized implementation of the {@code NodeCombiner} interface
 27  
  * that performs a merge from two passed in node hierarchies.
 28  
  * </p>
 29  
  * <p>
 30  
  * This combiner performs the merge using a few rules:
 31  
  * <ol>
 32  
  * <li>Nodes can be merged when attributes that appear in both have the same value.</li>
 33  
  * <li>Only a single node in the second file is considered a match to the node in the first file.</li>
 34  
  * <li>Attributes in nodes that match are merged.
 35  
  * <li>Nodes in both files that do not match are added to the result.</li>
 36  
  * </ol>
 37  
  * </p>
 38  
  *
 39  
  * @author <a
 40  
  * href="http://commons.apache.org/configuration/team-list.html">Commons
 41  
  * Configuration team</a>
 42  
  * @version $Id: MergeCombiner.java 1301991 2012-03-17 20:18:02Z sebb $
 43  
  * @since 1.7
 44  
  */
 45  37
 public class MergeCombiner extends NodeCombiner
 46  
 {
 47  
     /**
 48  
      * Combines the given nodes to a new union node.
 49  
      *
 50  
      * @param node1 the first source node
 51  
      * @param node2 the second source node
 52  
      * @return the union node
 53  
      */
 54  
 
 55  
     @Override
 56  
     public ConfigurationNode combine(ConfigurationNode node1, ConfigurationNode node2)
 57  
     {
 58  5849
         ViewNode result = createViewNode();
 59  5849
         result.setName(node1.getName());
 60  5851
         result.setValue(node1.getValue());
 61  5848
         addAttributes(result, node1, node2);
 62  
 
 63  
         // Check if nodes can be combined
 64  5842
         List<ConfigurationNode> children2 = new LinkedList<ConfigurationNode>(node2.getChildren());
 65  5849
         for (ConfigurationNode child1 : node1.getChildren())
 66  
         {
 67  5901
             ConfigurationNode child2 = canCombine(node1, node2, child1, children2);
 68  5901
             if (child2 != null)
 69  
             {
 70  3828
                 result.addChild(combine(child1, child2));
 71  3834
                 children2.remove(child2);
 72  
             }
 73  
             else
 74  
             {
 75  2070
                 result.addChild(child1);
 76  
             }
 77  5900
         }
 78  
 
 79  
         // Add remaining children of node 2
 80  5847
         for (ConfigurationNode c : children2)
 81  
         {
 82  4067
             result.addChild(c);
 83  4066
         }
 84  5850
         return result;
 85  
     }
 86  
 
 87  
     /**
 88  
      * Handles the attributes during a combination process. First all attributes
 89  
      * of the first node will be added to the result. Then all attributes of the
 90  
      * second node, which are not contained in the first node, will also be
 91  
      * added.
 92  
      *
 93  
      * @param result the resulting node
 94  
      * @param node1 the first node
 95  
      * @param node2 the second node
 96  
      */
 97  
     protected void addAttributes(ViewNode result, ConfigurationNode node1,
 98  
             ConfigurationNode node2)
 99  
     {
 100  5850
         result.appendAttributes(node1);
 101  5846
         for (ConfigurationNode attr : node2.getAttributes())
 102  
         {
 103  1762
             if (node1.getAttributeCount(attr.getName()) == 0)
 104  
             {
 105  485
                 result.addAttribute(attr);
 106  
             }
 107  1762
         }
 108  5843
     }
 109  
 
 110  
     /**
 111  
      * Tests if the first node can be combined with the second node. A node can
 112  
      * only be combined if its attributes are all present in the second node and
 113  
      * they all have the same value.
 114  
      *
 115  
      * @param node1 the first node
 116  
      * @param node2 the second node
 117  
      * @param child the child node (of the first node)
 118  
      * @return a child of the second node, with which a combination is possible
 119  
      */
 120  
     protected ConfigurationNode canCombine(ConfigurationNode node1,
 121  
             ConfigurationNode node2, ConfigurationNode child, List<ConfigurationNode> children2)
 122  
     {
 123  5899
         List<ConfigurationNode> attrs1 = child.getAttributes();
 124  5902
         List<ConfigurationNode> nodes = new ArrayList<ConfigurationNode>();
 125  
 
 126  5903
         List<ConfigurationNode> children = node2.getChildren(child.getName());
 127  5904
         Iterator<ConfigurationNode> it = children.iterator();
 128  10391
         while (it.hasNext())
 129  
         {
 130  4494
             ConfigurationNode node = it.next();
 131  4499
             Iterator<ConfigurationNode> iter = attrs1.iterator();
 132  5139
             while (iter.hasNext())
 133  
             {
 134  1300
                 ConfigurationNode attr1 = iter.next();
 135  1300
                 List<ConfigurationNode> list2 = node.getAttributes(attr1.getName());
 136  1300
                 if (list2.size() == 1
 137  
                     && !attr1.getValue().equals(list2.get(0).getValue()))
 138  
                 {
 139  653
                     node = null;
 140  653
                     break;
 141  
                 }
 142  646
             }
 143  4490
             if (node != null)
 144  
             {
 145  3839
                 nodes.add(node);
 146  
             }
 147  4499
         }
 148  
 
 149  5903
         if (nodes.size() == 1)
 150  
         {
 151  3832
             return nodes.get(0);
 152  
         }
 153  2070
         if (nodes.size() > 1 && !isListNode(child))
 154  
         {
 155  7
             Iterator<ConfigurationNode> iter = nodes.iterator();
 156  21
             while (iter.hasNext())
 157  
             {
 158  14
                 children2.remove(iter.next());
 159  
             }
 160  
         }
 161  
 
 162  2070
         return null;
 163  
     }
 164  
 }