001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.configuration.tree;
018    
019    import java.util.Collections;
020    import java.util.HashSet;
021    import java.util.Set;
022    
023    /**
024     * <p>
025     * A base class for node combiner implementations.
026     * </p>
027     * <p>
028     * A <em>node combiner</em> is an object that knows how two hierarchical node
029     * structures can be combined into a single one. Of course, there are many
030     * possible ways of implementing such a combination, e.g. constructing a union,
031     * an intersection, or an "override" structure (were nodes in the first
032     * hierarchy take precedence over nodes in the second hierarchy). This abstract
033     * base class only provides some helper methods and defines the common interface
034     * for node combiners. Concrete sub classes will implement the diverse
035     * combination algorithms.
036     * </p>
037     * <p>
038     * For some concrete combiner implementations it is important to distinguish
039     * whether a node is a single node or whether it belongs to a list structure.
040     * Alone from the input structures, the combiner will not always be able to make
041     * this decision. So sometimes it may be necessary for the developer to
042     * configure the combiner and tell it, which nodes should be treated as list
043     * nodes. For this purpose the {@code addListNode()} method exists. It
044     * can be passed the name of a node, which should be considered a list node.
045     * </p>
046     *
047     * @author <a
048     * href="http://commons.apache.org/configuration/team-list.html">Commons
049     * Configuration team</a>
050     * @version $Id: NodeCombiner.java 1206476 2011-11-26 16:19:53Z oheger $
051     * @since 1.3
052     */
053    public abstract class NodeCombiner
054    {
055        /** Stores a list with node names that are known to be list nodes. */
056        protected Set<String> listNodes;
057    
058        /**
059         * Creates a new instance of {@code NodeCombiner}.
060         */
061        public NodeCombiner()
062        {
063            listNodes = new HashSet<String>();
064        }
065    
066        /**
067         * Adds the name of a node to the list of known list nodes. This means that
068         * nodes with this name will never be combined.
069         *
070         * @param nodeName the name to be added
071         */
072        public void addListNode(String nodeName)
073        {
074            listNodes.add(nodeName);
075        }
076    
077        /**
078         * Returns a set with the names of nodes that are known to be list nodes.
079         *
080         * @return a set with the names of list nodes
081         */
082        public Set<String> getListNodes()
083        {
084            return Collections.unmodifiableSet(listNodes);
085        }
086    
087        /**
088         * Checks if a node is a list node. This implementation tests if the given
089         * node name is contained in the set of known list nodes. Derived classes
090         * which use different criteria may overload this method.
091         *
092         * @param node the node to be tested
093         * @return a flag whether this is a list node
094         */
095        public boolean isListNode(ConfigurationNode node)
096        {
097            return listNodes.contains(node.getName());
098        }
099    
100        /**
101         * Combines the hierarchies represented by the given root nodes. This method
102         * must be defined in concrete sub classes with the implementation of a
103         * specific combination algorithm.
104         *
105         * @param node1 the first root node
106         * @param node2 the second root node
107         * @return the resulting combined node structure
108         */
109        public abstract ConfigurationNode combine(ConfigurationNode node1,
110                ConfigurationNode node2);
111    
112        /**
113         * Creates a new view node. This method will be called whenever a new view
114         * node is to be created. It can be overridden to create special view nodes.
115         * This base implementation returns a new instance of
116         * {@link ViewNode}.
117         *
118         * @return the new view node
119         */
120        protected ViewNode createViewNode()
121        {
122            return new ViewNode();
123        }
124    }