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.api.ldap.model.subtree;
21  
22  
23  import java.util.Collections;
24  import java.util.Set;
25  
26  import org.apache.directory.api.ldap.model.filter.ExprNode;
27  import org.apache.directory.api.ldap.model.name.Dn;
28  
29  
30  /**
31   * A simple implementation of the SubtreeSpecification interface.
32   *
33   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
34   */
35  public class BaseSubtreeSpecification implements SubtreeSpecification
36  {
37      /** the subtree base relative to the administration point */
38      private final Dn base;
39  
40      /** the set of subordinates entries and their subordinates to exclude */
41      private final Set<Dn> chopBefore;
42  
43      /** the set of subordinates entries whose subordinates are to be excluded */
44      private final Set<Dn> chopAfter;
45  
46      /** the minimum distance below base to start including entries */
47      private final int minBaseDistance;
48  
49      /** the maximum distance from base past which entries are excluded */
50      private final int maxBaseDistance;
51  
52      /**
53       * a filter using only assertions on objectClass attributes for subtree
54       * refinement
55       */
56      private final ExprNode refinement;
57  
58  
59      // -----------------------------------------------------------------------
60      // C O N S T R U C T O R S
61      // -----------------------------------------------------------------------
62  
63      /**
64       * Creates a simple subtree whose administrative point is necessarily the
65       * base and all subordinates underneath (excluding those that are part of
66       * inner areas) are part of the the subtree.
67       */
68      @SuppressWarnings("unchecked")
69      public BaseSubtreeSpecification()
70      {
71          this.base = new Dn();
72          this.minBaseDistance = 0;
73          this.maxBaseDistance = UNBOUNDED_MAX;
74          this.chopAfter = Collections.EMPTY_SET;
75          this.chopBefore = Collections.EMPTY_SET;
76          this.refinement = null;
77      }
78  
79  
80      /**
81       * Creates a simple subtree refinement whose administrative point is
82       * necessarily the base and only those subordinates selected by the
83       * refinement filter are included.
84       *
85       * @param refinement the filter expression only composed of objectClass attribute
86       *  value assertions
87       */
88      @SuppressWarnings("unchecked")
89      public BaseSubtreeSpecification( ExprNode refinement )
90      {
91          this.base = new Dn();
92          this.minBaseDistance = 0;
93          this.maxBaseDistance = UNBOUNDED_MAX;
94          this.chopAfter = Collections.EMPTY_SET;
95          this.chopBefore = Collections.EMPTY_SET;
96          this.refinement = refinement;
97      }
98  
99  
100     /**
101      * Creates a simple subtree whose administrative point above the base and
102      * all subordinates underneath the base (excluding those that are part of
103      * inner areas) are part of the the subtree.
104      *
105      * @param base the base of the subtree relative to the administrative point
106      */
107     @SuppressWarnings("unchecked")
108     public BaseSubtreeSpecification( Dn base )
109     {
110         this.base = base;
111         this.minBaseDistance = 0;
112         this.maxBaseDistance = UNBOUNDED_MAX;
113         this.chopAfter = Collections.EMPTY_SET;
114         this.chopBefore = Collections.EMPTY_SET;
115         this.refinement = null;
116     }
117 
118 
119     /**
120      * Creates a subtree without a refinement filter where all other aspects can
121      * be varied.
122      *
123      * @param base the base of the subtree relative to the administrative point
124      * @param minBaseDistance the minimum distance below base to start including entries
125      * @param maxBaseDistance the maximum distance from base past which entries are excluded
126      * @param chopAfter the set of subordinates entries whose subordinates are to be
127      *  excluded
128      * @param chopBefore the set of subordinates entries and their subordinates to
129      * exclude
130      */
131     public BaseSubtreeSpecification( Dn base, int minBaseDistance, int maxBaseDistance,
132         Set<Dn> chopAfter, Set<Dn> chopBefore )
133     {
134         this( base, minBaseDistance, maxBaseDistance, chopAfter, chopBefore, null );
135     }
136 
137 
138     /**
139      * Creates a subtree which may be a refinement filter where all aspects of
140      * the specification can be set. If the refinement filter is null this
141      * defaults to {@link #BaseSubtreeSpecification(org.apache.directory.api.ldap.model.name.Dn, int, int, Set, Set)}.
142      *
143      * @param base the base of the subtree relative to the administrative point
144      * @param minBaseDistance the minimum distance below base to start including entries
145      * @param maxBaseDistance the maximum distance from base past which entries are excluded
146      * @param chopAfter the set of subordinates entries whose subordinates are to be
147      * excluded
148      * @param chopBefore the set of subordinates entries and their subordinates to
149      * exclude
150      * @param refinement the filter expression only composed of objectClass attribute
151      * value assertions
152      */
153     public BaseSubtreeSpecification( Dn base, int minBaseDistance, int maxBaseDistance,
154         Set<Dn> chopAfter, Set<Dn> chopBefore, ExprNode refinement )
155     {
156         this.base = base;
157         this.minBaseDistance = minBaseDistance;
158 
159         if ( maxBaseDistance < 0 )
160         {
161             this.maxBaseDistance = UNBOUNDED_MAX;
162         }
163         else
164         {
165             this.maxBaseDistance = maxBaseDistance;
166         }
167 
168         this.chopAfter = chopAfter;
169         this.chopBefore = chopBefore;
170         this.refinement = refinement;
171     }
172 
173 
174     // -----------------------------------------------------------------------
175     // A C C E S S O R S
176     // -----------------------------------------------------------------------
177     /**
178      * @return The base
179      */
180     public Dn getBase()
181     {
182         return this.base;
183     }
184 
185 
186     /**
187      * @return The set of ChopBefore exclusions
188      */
189     public Set<Dn> getChopBeforeExclusions()
190     {
191         return this.chopBefore;
192     }
193 
194 
195     /**
196      * @return The set of ChopAfter exclusions
197      */
198     public Set<Dn> getChopAfterExclusions()
199     {
200         return this.chopAfter;
201     }
202 
203 
204     /**
205      * @return The mimimum distance from the base
206      */
207     public int getMinBaseDistance()
208     {
209         return this.minBaseDistance;
210     }
211 
212 
213     /**
214      * @return The maximum distance from the base
215      */
216     public int getMaxBaseDistance()
217     {
218         return this.maxBaseDistance;
219     }
220 
221 
222     /**
223      * @return The refinement
224      */
225     public ExprNode getRefinement()
226     {
227         return this.refinement;
228     }
229 
230 
231     /**
232      * Converts this item into its string representation as stored
233      * in directory.
234      *
235      * @param buffer the string buffer
236      */
237     public void toString( StringBuilder buffer )
238     {
239         buffer.append( toString() );
240     }
241 
242 
243     /**
244      * @see Object#toString()
245      */
246     public String toString()
247     {
248         StringBuilder buffer = new StringBuilder();
249         boolean isFirst = true;
250         buffer.append( '{' );
251 
252         // The base
253         if ( !base.isEmpty() )
254         {
255             buffer.append( " base \"" );
256             buffer.append( base.getName() );
257             buffer.append( '"' );
258             isFirst = false;
259         }
260 
261         // The minimum
262         if ( minBaseDistance > 0 )
263         {
264             if ( isFirst )
265             {
266                 isFirst = false;
267                 buffer.append( " " );
268             }
269             else
270             {
271                 buffer.append( ", " );
272             }
273 
274             buffer.append( "minimum " );
275             buffer.append( minBaseDistance );
276         }
277 
278         // The maximum
279         if ( maxBaseDistance > UNBOUNDED_MAX )
280         {
281             if ( isFirst )
282             {
283                 isFirst = false;
284                 buffer.append( " " );
285             }
286             else
287             {
288                 buffer.append( ", " );
289             }
290 
291             buffer.append( "maximum " );
292             buffer.append( maxBaseDistance );
293         }
294 
295         // The chopBefore exclusions
296         if ( !chopBefore.isEmpty() || !chopAfter.isEmpty() )
297         {
298             if ( isFirst )
299             {
300                 isFirst = false;
301                 buffer.append( " " );
302             }
303             else
304             {
305                 buffer.append( ", " );
306             }
307 
308             buffer.append( "specificExclusions { " );
309 
310             boolean isFirstExclusion = true;
311 
312             if ( chopBefore != null )
313             {
314                 for ( Dn exclusion : chopBefore )
315                 {
316                     if ( isFirstExclusion )
317                     {
318                         isFirstExclusion = false;
319                     }
320                     else
321                     {
322                         buffer.append( ", " );
323                     }
324 
325                     buffer.append( "chopBefore: \"" );
326                     buffer.append( exclusion.getName() );
327                     buffer.append( '"' );
328                 }
329             }
330 
331             if ( chopAfter != null )
332             {
333                 for ( Dn exclusion : chopAfter )
334                 {
335                     if ( isFirstExclusion )
336                     {
337                         isFirstExclusion = false;
338                     }
339                     else
340                     {
341                         buffer.append( ", " );
342                     }
343 
344                     buffer.append( "chopAfter: \"" );
345                     buffer.append( exclusion.getName() );
346                     buffer.append( '"' );
347                 }
348             }
349 
350             buffer.append( " }" );
351         }
352 
353         if ( refinement != null )
354         {
355             if ( isFirst )
356             {
357                 isFirst = false;
358                 buffer.append( " " );
359             }
360             else
361             {
362                 buffer.append( ", " );
363             }
364 
365             buffer.append( "specificationFilter " );
366             buffer.append( refinement.toString() );
367         }
368 
369         buffer.append( " }" );
370 
371         return buffer.toString();
372     }
373 }