View Javadoc

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 }