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 */ 017package org.apache.commons.configuration2.tree; 018 019import java.util.Collections; 020import java.util.HashSet; 021import 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 * @version $Id: NodeCombiner.java 1790899 2017-04-10 21:56:46Z ggregory $ 048 * @since 1.3 049 */ 050public abstract class NodeCombiner 051{ 052 /** 053 * A default handler object for immutable nodes. This object can be used by 054 * derived classes for dealing with nodes. However, it provides only limited 055 * functionality; it supports only operations on child nodes, but no 056 * references to parent nodes. 057 */ 058 protected static final NodeHandler<ImmutableNode> HANDLER = 059 createNodeHandler(); 060 061 /** Stores a list with node names that are known to be list nodes. */ 062 private final Set<String> listNodes; 063 064 /** 065 * Creates a new instance of {@code NodeCombiner}. 066 */ 067 public NodeCombiner() 068 { 069 listNodes = new HashSet<>(); 070 } 071 072 /** 073 * Adds the name of a node to the list of known list nodes. This means that 074 * nodes with this name will never be combined. 075 * 076 * @param nodeName the name to be added 077 */ 078 public void addListNode(String nodeName) 079 { 080 listNodes.add(nodeName); 081 } 082 083 /** 084 * Returns a set with the names of nodes that are known to be list nodes. 085 * 086 * @return a set with the names of list nodes 087 */ 088 public Set<String> getListNodes() 089 { 090 return Collections.unmodifiableSet(listNodes); 091 } 092 093 /** 094 * Checks if a node is a list node. This implementation tests if the given 095 * node name is contained in the set of known list nodes. Derived classes 096 * which use different criteria may overload this method. 097 * 098 * @param node the node to be tested 099 * @return a flag whether this is a list node 100 */ 101 public boolean isListNode(ImmutableNode node) 102 { 103 return listNodes.contains(node.getNodeName()); 104 } 105 106 /** 107 * Combines the hierarchies represented by the given root nodes. This method 108 * must be defined in concrete sub classes with the implementation of a 109 * specific combination algorithm. 110 * 111 * @param node1 the first root node 112 * @param node2 the second root node 113 * @return the root node of the resulting combined node structure 114 */ 115 public abstract ImmutableNode combine(ImmutableNode node1, 116 ImmutableNode node2); 117 118 /** 119 * Creates a node handler object for immutable nodes which can be used by 120 * sub classes to perform advanced operations on nodes. 121 * 122 * @return the node handler implementation 123 */ 124 private static NodeHandler<ImmutableNode> createNodeHandler() 125 { 126 return new AbstractImmutableNodeHandler() 127 { 128 @Override 129 public ImmutableNode getParent(ImmutableNode node) 130 { 131 return null; 132 } 133 134 @Override 135 public ImmutableNode getRootNode() 136 { 137 return null; 138 } 139 }; 140 } 141}