1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.server.core.partition.tree;
21
22
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import javax.naming.NamingException;
27
28 import org.apache.directory.server.core.partition.Partition;
29 import org.apache.directory.shared.ldap.name.LdapDN;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33
34 /**
35 *
36 * The Partition Container holds entries which can be either Partitions or
37 * Containers.
38 *
39 * We can see them as directories, where Partitions are the files.
40 *
41 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
42 */
43 public class BranchNode implements Node
44 {
45 private static final Logger LOG = LoggerFactory.getLogger( BranchNode.class );
46
47 /** Stores the list of all the descendant partitions and containers */
48 private Map<String, Node> children;
49
50
51 /**
52 * Creates a new instance of a BranchNode.
53 */
54 public BranchNode()
55 {
56 children = new HashMap<String, Node>(3);
57 }
58
59
60 /**
61 * @see Node#isLeaf()
62 */
63 public boolean isLeaf()
64 {
65 return false;
66 }
67
68
69 /**
70 * Recursively adds new nodes to the partition lookup tree data structure.
71 * When called it will add a partition to the tree in the appropriate leaf
72 * node position based on the DN passed in as an argument.
73 *
74 * @param current The current node having a partition added to it
75 * @param dn The DN associated with the partition
76 * @param index The index of the current RDN being processed
77 * @param partition The associated partition to add as a tree node
78 * @return The modified tree structure.
79 */
80 public BranchNode recursivelyAddPartition( BranchNode current, LdapDN dn, int index, Partition partition ) throws NamingException
81 {
82 String rdnAtIndex = dn.getRdn( index ).toString();
83
84 if ( index == dn.size() - 1 )
85 {
86 return current.addNode( rdnAtIndex, new LeafNode( partition ) );
87 }
88 else
89 {
90 Node newNode = current.getChild( rdnAtIndex );
91
92 if ( newNode instanceof LeafNode )
93 {
94 String message = "Overlapping partitions are not allowed";
95 LOG.error( message );
96 throw new NamingException( message );
97 }
98
99 if ( newNode == null )
100 {
101 newNode = new BranchNode();
102 }
103
104 Node child = recursivelyAddPartition( (BranchNode)newNode, dn, index + 1, partition );
105 return current.addNode( rdnAtIndex, child );
106 }
107 }
108
109
110 /**
111 * Directly adds a new child Node to the current BranchNode.
112 *
113 * @param rdn The rdn of the child node to add
114 * @param child The child node to add
115 * @return The modified branch node after the insertion
116 */
117 public BranchNode addNode( String rdn, Node child )
118 {
119 children.put( rdn, child );
120 return this;
121 }
122
123
124 /**
125 * Tells if the current BranchNode contains another node associated
126 * with an rdn.
127 *
128 * @param rdn The name we are looking for
129 * @return <code>true</code> if the PartitionStructure instance contains this name
130 */
131 public boolean contains( String rdn )
132 {
133 return children.containsKey( rdn );
134 }
135
136
137 /**
138 * Get's a child using an rdn string.
139 *
140 * @param rdn the rdn to use as the node key
141 * @return the child node corresponding to the rdn.
142 */
143 public Node getChild( String rdn )
144 {
145 if ( children.containsKey( rdn ) )
146 {
147 return children.get( rdn );
148 }
149
150 return null;
151 }
152
153
154 /**
155 * @see Object#toString()
156 */
157 public String toString()
158 {
159 StringBuilder sb = new StringBuilder();
160 sb.append( "{" );
161 boolean isFirst = true;
162
163 for ( Node child:children.values() )
164 {
165 if ( isFirst )
166 {
167 isFirst = false;
168 }
169 else
170 {
171 sb.append( ", " );
172 }
173
174 if ( child instanceof BranchNode )
175 {
176 sb.append( "Branch: ").append( child.toString() );
177 }
178 else
179 {
180 sb.append( "Leaf: " ).append( "'" ).append( child.toString() ).append( "'" );
181 }
182 }
183
184 sb.append( "}" );
185 return sb.toString();
186 }
187 }