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.xdbm;
21  
22  
23  import java.io.Externalizable;
24  import java.io.IOException;
25  import java.io.ObjectInput;
26  import java.io.ObjectOutput;
27  import java.util.Arrays;
28  import java.util.List;
29  
30  import org.apache.directory.api.ldap.model.name.Rdn;
31  
32  
33  /**
34   * A wrapper for the tuple of parentId and Rdn, used for the Rdn index.
35   * 
36   * If the refered entry is a ContextEntry, we may have more than one Rdn stored
37   *
38   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39   */
40  public class ParentIdAndRdn implements Externalizable, Comparable<ParentIdAndRdn>
41  {
42      /** The entry ID */
43      protected String parentId;
44  
45      /** The list of Rdn for this instance */
46      protected Rdn[] rdns;
47  
48      /** Number of direct children */
49      protected int nbChildren;
50  
51      /** Number of global descendant */
52      protected int nbDescendants;
53  
54  
55      /**
56       * Serializable constructor.
57       */
58      public ParentIdAndRdn()
59      {
60      }
61  
62  
63      /**
64       * Creates a new instance of ParentIdAndRdn.
65       *
66       * @param parentId the parent ID
67       * @param rdns the RDNs
68       */
69      public ParentIdAndRdn( String parentId, Rdn... rdns )
70      {
71          this.parentId = parentId;
72          this.rdns = rdns;
73      }
74  
75  
76      /**
77       * Creates a new instance of ParentIdAndRdn.
78       *
79       * @param parentId the parent ID
80       * @param rdns the RDNs
81       */
82      public ParentIdAndRdn( String parentId, List<Rdn> rdns )
83      {
84          this.parentId = parentId;
85          this.rdns = rdns.toArray( new Rdn[rdns.size()] );
86          nbChildren = 0;
87          nbDescendants = 0;
88      }
89  
90  
91      /**
92       * Gets the parent ID.
93       * 
94       * @return the parent ID
95       */
96      public String getParentId()
97      {
98          return parentId;
99      }
100 
101 
102     /**
103      * Sets the parent ID.
104      * 
105      * @param parentId the new parent ID
106      */
107     public void setParentId( String parentId )
108     {
109         this.parentId = parentId;
110     }
111 
112 
113     /**
114      * Gets the RDNs.
115      * 
116      * @return the RDNs
117      */
118     public Rdn[] getRdns()
119     {
120         return rdns;
121     }
122 
123 
124     /**
125      * Sets the Rdn.
126      * 
127      * @param rdns the new Rdn
128      */
129     public void setRdns( Rdn... rdns )
130     {
131         this.rdns = rdns;
132     }
133 
134 
135     @Override
136     public int hashCode()
137     {
138         int h = 37;
139         h = h * 17 + ( ( parentId == null ) ? 0 : parentId.hashCode() );
140         h = h * 17 + Arrays.hashCode( rdns );
141 
142         return h;
143     }
144 
145 
146     @Override
147     @SuppressWarnings("unchecked")
148     public boolean equals( Object obj )
149     {
150         // Shortcut
151         if ( this == obj )
152         {
153             return true;
154         }
155 
156         if ( !( obj instanceof ParentIdAndRdn ) )
157         {
158             return false;
159         }
160 
161         ParentIdAndRdn./../../org/apache/directory/server/xdbm/ParentIdAndRdn.html#ParentIdAndRdn">ParentIdAndRdn that = ( ParentIdAndRdn ) obj;
162 
163         if ( rdns == null )
164         {
165             return that.rdns == null;
166         }
167         else if ( that.rdns == null )
168         {
169             return false;
170         }
171 
172         if ( rdns.length != that.rdns.length )
173         {
174             return false;
175         }
176 
177         for ( int i = 0; i < rdns.length; i++ )
178         {
179             if ( !rdns[i].equals( that.rdns[i] ) )
180             {
181                 return false;
182             }
183         }
184 
185         return true;
186     }
187 
188 
189     /**
190      * {@inheritDoc}
191      */
192     @Override
193     public int compareTo( ParentIdAndRdn that )
194     {
195         // Special case when that.rdns = null : we are searching for oneLevel or subLevel scope
196         if ( that.rdns == null )
197         {
198             int val = parentId.compareTo( that.parentId );
199 
200             if ( val != 0 )
201             {
202                 return val;
203             }
204             else
205             {
206                 // The current value is necessarily superior
207                 return 1;
208             }
209         }
210 
211         if ( rdns == null )
212         {
213             int res = parentId.compareTo( that.parentId );
214 
215             if ( res == 0 )
216             {
217                 return -1;
218             }
219             else
220             {
221                 return res;
222             }
223         }
224 
225         int val = parentId.compareTo( that.getParentId() );
226 
227         if ( val != 0 )
228         {
229             return val;
230         }
231 
232         // The ID is the same, check the RDNs now
233         val = rdns.length - that.rdns.length;
234 
235         if ( val != 0 )
236         {
237             return val;
238         }
239 
240         if ( rdns.length == 1 )
241         {
242             // Special case : we only have one rdn.
243             // first try with the normalized name
244             if ( rdns[0].getNormName() != null )
245             {
246                 return rdns[0].getNormName().compareTo( that.rdns[0].getNormName() );
247             }
248 
249             val = rdns[0].compareTo( that.rdns[0] );
250 
251             return val;
252         }
253         else
254         {
255             // We need to compare the Rdns in the order they are given.
256             // Actually, this is a Dn, not a Rdn.
257             for ( int i = 0; i < rdns.length; i++ )
258             {
259                 // first try with the normalized name
260                 if ( rdns[i].getNormName() != null )
261                 {
262                     return rdns[i].getNormName().compareTo( that.rdns[i].getNormName() );
263                 }
264 
265                 val = rdns[i].compareTo( that.rdns[i] );
266 
267                 if ( val != 0 )
268                 {
269                     return val;
270                 }
271             }
272 
273             return 0;
274         }
275     }
276 
277 
278     /**
279      * {@inheritDoc}
280      */
281     @Override
282     public void writeExternal( ObjectOutput out ) throws IOException
283     {
284         out.writeUTF( parentId );
285         out.writeInt( nbChildren );
286         out.writeInt( nbDescendants );
287         out.writeInt( rdns.length );
288 
289         for ( Rdn rdn : rdns )
290         {
291             rdn.writeExternal( out );
292         }
293     }
294 
295 
296     /**
297      * {@inheritDoc}
298      */
299     @SuppressWarnings("unchecked")
300     @Override
301     public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
302     {
303         parentId = in.readUTF();
304         nbChildren = in.readInt();
305         nbDescendants = in.readInt();
306         int size = in.readInt();
307         rdns = new Rdn[size];
308 
309         for ( int i = 0; i < size; i++ )
310         {
311             Rdn rdn = new Rdn();
312             rdn.readExternal( in );
313             rdns[i] = rdn;
314         }
315     }
316 
317 
318     /**
319      * @return The number of children this entry has
320      */
321     public int getNbChildren()
322     {
323         return nbChildren;
324     }
325 
326 
327     /**
328      * Sets the number of children this entry has
329      * @param nbChildren The number of children
330      */
331     public void setNbChildren( int nbChildren )
332     {
333         this.nbChildren = nbChildren;
334     }
335 
336 
337     /**
338      * @return The number of descendants this entry has
339      */
340     public int getNbDescendants()
341     {
342         return nbDescendants;
343     }
344 
345 
346     /**
347      * Sets the number of descendants this entry has
348      * 
349      * @param nbDescendants The number of descendants
350      */
351     public void setNbDescendants( int nbDescendants )
352     {
353         this.nbDescendants = nbDescendants;
354     }
355 
356 
357     /**
358      * {@inheritDoc}
359      */
360     @Override
361     public String toString()
362     {
363         StringBuilder sb = new StringBuilder();
364 
365         sb.append( "ParentIdAndRdn<" );
366         sb.append( parentId ).append( ", '" );
367 
368         if ( rdns == null )
369         {
370             sb.append( "*'>" );
371         }
372         else
373         {
374             boolean isFirst = true;
375 
376             for ( Rdn rdn : rdns )
377             {
378                 if ( isFirst )
379                 {
380                     isFirst = false;
381                 }
382                 else
383                 {
384                     sb.append( "," );
385                 }
386 
387                 sb.append( rdn );
388             }
389 
390             sb.append( "'>" );
391 
392             sb.append( "[nbC:" ).append( nbChildren ).append( ", nbD:" ).append( nbDescendants ).append( "]" );
393         }
394 
395         return sb.toString();
396     }
397 }