##### Coverage Report - org.apache.commons.configuration.tree.OverrideCombiner

Classes in this File | Line Coverage | Branch Coverage | Complexity

OverrideCombiner

100% | 25/25

100% | 8/8

3.6666666666666665;3,667

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.Iterator;

20

21

     /**

22

      * <p>

23

      * A concrete combiner implementation that is able to construct an override

24

      * combination.

25

      * </p>

26

      * <p>

27

      * An <em>override combination</em> means that nodes in the first node

28

      * structure take precedence over nodes in the second, or - in other words -

29

      * nodes of the second structure are only added to the resulting structure if

30

      * they do not occure in the first one. This is especially suitable for dealing

31

      * with the properties of configurations that are defined in an

32

      * <code>override</code> section of a configuration definition file (hence the

33

      * name).

34

      * </p>

35

      * <p>

36

      * This combiner will iterate over the second node hierarchy and find all nodes

37

      * that are not contained in the first hierarchy; these are added to the result.

38

      * If a node can be found in both structures, it is checked whether a

39

      * combination (in a recursive way) can be constructed for the two, which will

40

      * then be added. Per default, nodes are combined, which occur only once in both

41

      * structures. This test is implemented in the <code>canCombine()</code>

42

      * method.

43

      * </p>

44

      * <p>

45

      * As is true for the <code>{@link UnionCombiner}</code>, for this combiner

46

      * list nodes are important. The <code>addListNode()</code> can be called to

47

      * declare certain nodes as list nodes. This has the effect that these nodes

48

      * will never be combined.

49

      * </p>

50

      *

51

      * @author <a

52

      * href="http://jakarta.apache.org/commons/configuration/team-list.html">Commons

53

      * Configuration team</a>

54

      * @version $Id: OverrideCombiner.java 439648 2006-09-02 20:42:10Z oheger $

55

      * @since 1.3

56

      */

57

25

     public class OverrideCombiner extends NodeCombiner

58

     {

59

         /**

60

          * Constructs an override combination for the passed in node structures.

61

          *

62

          * @param node1 the first node

63

          * @param node2 the second node

64

          * @return the resulting combined node structure

65

          */

66

         public ConfigurationNode combine(ConfigurationNode node1,

67

                 ConfigurationNode node2)

68

         {

69

157

             ViewNode result = createViewNode();

70

157

             result.setName(node1.getName());

71

72

             // Process nodes from the first structure, which override the second

73

882

             for (Iterator it = node1.getChildren().iterator(); it.hasNext();)

74

             {

75

568

                 ConfigurationNode child = (ConfigurationNode) it.next();

76

568

                 ConfigurationNode child2 = canCombine(node1, node2, child);

77

568

                 if (child2 != null)

78

                 {

79

122

                     result.addChild(combine(child, child2));

80

                 }

81

                 else

82

                 {

83

446

                     result.addChild(child);

84

                 }

85

             }

86

87

             // Process nodes from the second structure, which are not contained

88

             // in the first structure

89

699

             for (Iterator it = node2.getChildren().iterator(); it.hasNext();)

90

             {

91

385

                 ConfigurationNode child = (ConfigurationNode) it.next();

92

385

                 if (node1.getChildrenCount(child.getName()) < 1)

93

                 {

94

216

                     result.addChild(child);

95

                 }

96

             }

97

98

             // Handle attributes and value

99

157

             addAttributes(result, node1, node2);

100

157

             result.setValue((node1.getValue() != null) ? node1.getValue() : node2

101

                     .getValue());

102

103

157

             return result;

104

         }

105

106

         /**

107

          * Handles the attributes during a combination process. First all attributes

108

          * of the first node will be added to the result. Then all attributes of the

109

          * second node, which are not contained in the first node, will also be

110

          * added.

111

          *

112

          * @param result the resulting node

113

          * @param node1 the first node

114

          * @param node2 the second node

115

          */

116

         protected void addAttributes(ViewNode result, ConfigurationNode node1,

117

                 ConfigurationNode node2)

118

         {

119

157

             result.appendAttributes(node1);

120

334

             for (Iterator it = node2.getAttributes().iterator(); it.hasNext();)

121

             {

122

20

                 ConfigurationNode attr = (ConfigurationNode) it.next();

123

20

                 if (node1.getAttributeCount(attr.getName()) == 0)

124

                 {

125

14

                     result.addAttribute(attr);

126

                 }

127

             }

128

157

         }

129

130

         /**

131

          * Tests if a child node of the second node can be combined with the given

132

          * child node of the first node. If this is the case, the corresponding node

133

          * will be returned, otherwise <b>null</b>. This implementation checks

134

          * whether the child node occurs only once in both hierarchies and is no

135

          * known list node.

136

          *

137

          * @param node1 the first node

138

          * @param node2 the second node

139

          * @param child the child node (of the first node)

140

          * @return a child of the second node, with which a combination is possible

141

          */

142

         protected ConfigurationNode canCombine(ConfigurationNode node1,

143

                 ConfigurationNode node2, ConfigurationNode child)

144

         {

145

568

             if (node2.getChildrenCount(child.getName()) == 1

146

                     && node1.getChildrenCount(child.getName()) == 1

147

                     && !isListNode(child))

148

             {

149

122

                 return (ConfigurationNode) node2.getChildren(child.getName())

150

                         .get(0);

151

             }

152

             else

153

             {

154

446

                 return null;

155

             }

156

         }

157

     }