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