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     @Override
181     public Dn getBase()
182     {
183         return this.base;
184     }
185 
186 
187     /**
188      * @return The set of ChopBefore exclusions
189      */
190     @Override
191     public Set<Dn> getChopBeforeExclusions()
192     {
193         return this.chopBefore;
194     }
195 
196 
197     /**
198      * @return The set of ChopAfter exclusions
199      */
200     @Override
201     public Set<Dn> getChopAfterExclusions()
202     {
203         return this.chopAfter;
204     }
205 
206 
207     /**
208      * @return The mimimum distance from the base
209      */
210     @Override
211     public int getMinBaseDistance()
212     {
213         return this.minBaseDistance;
214     }
215 
216 
217     /**
218      * @return The maximum distance from the base
219      */
220     @Override
221     public int getMaxBaseDistance()
222     {
223         return this.maxBaseDistance;
224     }
225 
226 
227     /**
228      * @return The refinement
229      */
230     @Override
231     public ExprNode getRefinement()
232     {
233         return this.refinement;
234     }
235 
236 
237     /**
238      * Converts this item into its string representation as stored
239      * in directory.
240      *
241      * @param buffer the string buffer
242      */
243     @Override
244     public void toString( StringBuilder buffer )
245     {
246         buffer.append( toString() );
247     }
248 
249 
250     /**
251      * @see Object#toString()
252      */
253     @Override
254     public String toString()
255     {
256         StringBuilder buffer = new StringBuilder();
257         boolean isFirst = true;
258         buffer.append( '{' );
259 
260         // The base
261         if ( !base.isEmpty() )
262         {
263             buffer.append( " base \"" );
264             buffer.append( base.getName() );
265             buffer.append( '"' );
266             isFirst = false;
267         }
268 
269         // The minimum
270         if ( minBaseDistance > 0 )
271         {
272             if ( isFirst )
273             {
274                 isFirst = false;
275                 buffer.append( " " );
276             }
277             else
278             {
279                 buffer.append( ", " );
280             }
281 
282             buffer.append( "minimum " );
283             buffer.append( minBaseDistance );
284         }
285 
286         // The maximum
287         if ( maxBaseDistance > UNBOUNDED_MAX )
288         {
289             if ( isFirst )
290             {
291                 isFirst = false;
292                 buffer.append( " " );
293             }
294             else
295             {
296                 buffer.append( ", " );
297             }
298 
299             buffer.append( "maximum " );
300             buffer.append( maxBaseDistance );
301         }
302 
303         // The chopBefore exclusions
304         if ( ( ( chopBefore != null ) && !chopBefore.isEmpty() ) || ( ( chopAfter != null ) && !chopAfter.isEmpty() ) )
305         {
306             if ( isFirst )
307             {
308                 isFirst = false;
309                 buffer.append( " " );
310             }
311             else
312             {
313                 buffer.append( ", " );
314             }
315 
316             buffer.append( "specificExclusions { " );
317 
318             boolean isFirstExclusion = true;
319 
320             if ( chopBefore != null )
321             {
322                 for ( Dn exclusion : chopBefore )
323                 {
324                     if ( isFirstExclusion )
325                     {
326                         isFirstExclusion = false;
327                     }
328                     else
329                     {
330                         buffer.append( ", " );
331                     }
332 
333                     buffer.append( "chopBefore: \"" );
334                     buffer.append( exclusion.getName() );
335                     buffer.append( '"' );
336                 }
337             }
338 
339             if ( chopAfter != null )
340             {
341                 for ( Dn exclusion : chopAfter )
342                 {
343                     if ( isFirstExclusion )
344                     {
345                         isFirstExclusion = false;
346                     }
347                     else
348                     {
349                         buffer.append( ", " );
350                     }
351 
352                     buffer.append( "chopAfter: \"" );
353                     buffer.append( exclusion.getName() );
354                     buffer.append( '"' );
355                 }
356             }
357 
358             buffer.append( " }" );
359         }
360 
361         if ( refinement != null )
362         {
363             if ( isFirst )
364             {
365                 buffer.append( " " );
366             }
367             else
368             {
369                 buffer.append( ", " );
370             }
371 
372             buffer.append( "specificationFilter " );
373             buffer.append( refinement.toString() );
374         }
375 
376         buffer.append( " }" );
377 
378         return buffer.toString();
379     }
380 }