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.ldap.client.api.search;
21  
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.directory.api.ldap.model.filter.FilterEncoder;
27  import org.apache.directory.api.util.Strings;
28  
29  
30  /**
31   * A class used to manage Substring Filters.
32   *
33   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
34   */
35  final class SubstringFilter extends AbstractFilter
36  {
37      /** The AttributeType for this filter */
38      private String attribute;
39  
40      /** The initial substring string. It may be null */
41      private String initial;
42  
43      /** The array of any substring strings. It may be null */
44      private String[] any;
45  
46      /** The final substring string. It may be null */
47      private String end;
48  
49  
50      /**
51       * A private constructor that builds a SubstringFilter 
52       */
53      private SubstringFilter( String attribute, String initial, String[] any, String end )
54      {
55          this.attribute = attribute;
56          this.initial = initial;
57  
58          // We have to filter the 'any' and remove every empty strings
59          if ( ( any != null ) && ( any.length != 0 ) )
60          {
61              List<String> anyList = new ArrayList<>();
62  
63              for ( String string : any )
64              {
65                  if ( !Strings.isEmpty( string ) )
66                  {
67                      anyList.add( string );
68                  }
69              }
70  
71              if ( !anyList.isEmpty() )
72              {
73                  this.any = anyList.toArray( new String[]
74                      {} );
75              }
76          }
77  
78          this.end = end;
79      }
80  
81  
82      /**
83       * Create a SubstringFilter based on the filter elements. Such a filter
84       * has a form like <b>Attribute=initial*([any]*)*</b>. We don't expect any
85       * <em>final</em> String.
86       *
87       * @param attribute The AttributeType for this filter
88       * @param parts The parts that are the initial string and zero to N any strings
89       * @return An instance of a SubstringFilter
90       */
91      public static SubstringFilter startsWith( String attribute, String... parts )
92      {
93          if ( ( parts != null ) && ( parts.length > 0 ) )
94          {
95              if ( parts.length > 1 )
96              {
97                  String[] any = new String[parts.length - 1];
98                  System.arraycopy( parts, 1, any, 0, any.length );
99  
100                 return new SubstringFilter( attribute, parts[0], any, null );
101             }
102             else
103             {
104                 return new SubstringFilter( attribute, parts[0], null, null );
105             }
106         }
107         else
108         {
109             // This is a presence filter, kind of
110             return new SubstringFilter( attribute, null, null, null );
111         }
112     }
113 
114 
115     /**
116      * Create a SubstringFilter based on the filter elements. Such a filter
117      * has a form like <b>Attribute=*([any]*)*final</b>. We don't expect any
118      * <em>initial</em> String.
119      *
120      * @param attribute The AttributeType for this filter
121      * @param parts The parts that are zero to N any strings followed by a final string
122      * @return An instance of a SubstringFilter
123      */
124     public static SubstringFilter endsWith( String attribute, String... parts )
125     {
126         if ( ( parts != null ) && ( parts.length > 0 ) )
127         {
128             if ( parts.length > 1 )
129             {
130                 String[] any = new String[parts.length - 1];
131                 System.arraycopy( parts, 0, any, 0, any.length );
132 
133                 return new SubstringFilter( attribute, null, any, parts[parts.length - 1] );
134             }
135             else
136             {
137                 return new SubstringFilter( attribute, null, null, parts[0] );
138             }
139         }
140         else
141         {
142             // This is a presence filter, kind of
143             return new SubstringFilter( attribute, null, null, null );
144         }
145     }
146 
147 
148     /**
149      * Create a SubstringFilter based on the filter elements. Such a filter
150      * has a form like <b>Attribute=*([any]*)*</b>. We don't expect any
151      * <em>initial</em>or <em>final</em> Strings.
152      *
153      * @param attribute The AttributeType for this filter
154      * @param parts The parts that are zero to N any strings with no initial nor final Strings
155      * @return An instance of a SubstringFilter
156      */
157     public static SubstringFilter contains( String attribute, String... parts )
158     {
159         if ( ( parts != null ) && ( parts.length > 0 ) )
160         {
161             if ( parts.length > 1 )
162             {
163                 String[] any = new String[parts.length];
164                 System.arraycopy( parts, 0, any, 0, any.length );
165 
166                 return new SubstringFilter( attribute, null, any, null );
167             }
168             else
169             {
170                 return new SubstringFilter( attribute, null, parts, null );
171             }
172         }
173         else
174         {
175             // This is a presence filter, kind of
176             return new SubstringFilter( attribute, null, null, null );
177         }
178     }
179 
180 
181     /**
182      * Create a SubstringFilter based on the filter elements. Such a filter
183      * has a form like <b>Attribute=initial*([any]*)*final</b>.
184      *
185      * @param attribute The AttributeType for this filter
186      * @param parts The parts that are zero to N any strings starting with an initial String and 
187      * followed by a final string
188      * @return An instance of a SubstringFilter
189      */
190     public static SubstringFilter substring( String attribute, String... parts )
191     {
192         if ( ( parts != null ) && ( parts.length > 0 ) )
193         {
194             if ( parts.length > 2 )
195             {
196                 // We have initial, any and final
197                 String[] any = new String[parts.length - 2];
198                 System.arraycopy( parts, 1, any, 0, any.length );
199 
200                 return new SubstringFilter( attribute, parts[0], any, parts[parts.length - 1] );
201             }
202             else if ( parts.length > 1 )
203             {
204                 // we only have initial and final
205                 return new SubstringFilter( attribute, parts[0], null, parts[1] );
206             }
207             else
208             {
209                 // We don't have any or final
210                 return new SubstringFilter( attribute, parts[0], null, null );
211             }
212         }
213         else
214         {
215             // This is a presence filter, kind of
216             return new SubstringFilter( attribute, null, null, null );
217         }
218     }
219 
220 
221     /**
222      * {@inheritDoc}
223      */
224     @Override
225     public StringBuilder build( StringBuilder builder )
226     {
227         builder.append( "(" ).append( attribute ).append( '=' );
228 
229         if ( !Strings.isEmpty( initial ) )
230         {
231             builder.append( FilterEncoder.encodeFilterValue( initial ) );
232         }
233 
234         if ( any != null )
235         {
236             for ( String string : any )
237             {
238                 builder.append( '*' ).append( FilterEncoder.encodeFilterValue( string ) );
239             }
240         }
241 
242         builder.append( '*' );
243 
244         if ( !Strings.isEmpty( end ) )
245         {
246             builder.append( FilterEncoder.encodeFilterValue( end ) );
247         }
248 
249         builder.append( ")" );
250 
251         return builder;
252     }
253 }