001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.filter;
021
022
023 import java.util.ArrayList;
024 import java.util.List;
025 import java.util.regex.Pattern;
026
027 import org.apache.directory.shared.ldap.entry.StringValue;
028 import org.apache.directory.shared.ldap.exception.LdapException;
029 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
030 import org.apache.directory.shared.ldap.schema.Normalizer;
031 import org.apache.directory.shared.ldap.util.StringTools;
032
033
034 /**
035 * Filter expression tree node used to represent a substring assertion.
036 *
037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038 * @version $Revision: 928945 $
039 */
040 public class SubstringNode extends LeafNode
041 {
042 /** The initial fragment before any wildcard */
043 private String initialPattern;
044
045 /** The end fragment after wildcard */
046 private String finalPattern;
047
048 /** List of fragments between wildcard */
049 private List<String> anyPattern;
050
051 /**
052 * Creates a new SubstringNode object with only one wildcard and no internal
053 * any fragments between wildcards.
054 *
055 * @param attribute the name of the attribute to substring assert
056 * @param initialPattern the initial fragment
057 * @param finalPattern the final fragment
058 */
059 public SubstringNode( String attribute, String initialPattern, String finalPattern )
060 {
061 super( attribute, AssertionType.SUBSTRING );
062
063 anyPattern = new ArrayList<String>( 2 );
064 this.finalPattern = finalPattern;
065 this.initialPattern = initialPattern;
066 }
067
068
069 /**
070 * Clone the Node
071 */
072 @Override public ExprNode clone()
073 {
074 ExprNode clone = (ExprNode)super.clone();
075
076 if ( anyPattern != null )
077 {
078 ((SubstringNode)clone).anyPattern = new ArrayList<String>();
079
080 for ( String any:anyPattern )
081 {
082 ((SubstringNode)clone).anyPattern.add( any );
083 }
084 }
085
086 return clone;
087 }
088
089 /**
090 * Creates a new SubstringNode object without any value
091 *
092 * @param attribute the name of the attribute to substring assert
093 */
094 public SubstringNode( String attribute )
095 {
096 super( attribute, AssertionType.SUBSTRING );
097
098 anyPattern = new ArrayList<String>( 2 );
099 this.finalPattern = null;
100 this.initialPattern = null;
101 }
102
103
104 /**
105 * Creates a new SubstringNode object more than one wildcard and an any
106 * list.
107 *
108 * @param anyPattern list of internal fragments between wildcards
109 * @param attribute the name of the attribute to substring assert
110 * @param initialPattern the initial fragment
111 * @param finalPattern the final fragment
112 */
113 public SubstringNode( List<String> anyPattern, String attribute, String initialPattern, String finalPattern )
114 {
115 super( attribute, AssertionType.SUBSTRING );
116
117 this.anyPattern = anyPattern;
118 this.finalPattern = finalPattern;
119 this.initialPattern = initialPattern;
120 }
121
122
123 /**
124 * Gets the initial fragment.
125 *
126 * @return the initial prefix
127 */
128 public final String getInitial()
129 {
130 return initialPattern;
131 }
132
133 /**
134 * Set the initial pattern
135 * @param initialPattern The initial pattern
136 */
137 public void setInitial( String initialPattern )
138 {
139 this.initialPattern = initialPattern;
140 }
141
142 /**
143 * Gets the final fragment or suffix.
144 *
145 * @return the suffix
146 */
147 public final String getFinal()
148 {
149 return finalPattern;
150 }
151
152
153 /**
154 * Set the final pattern
155 * @param finalPattern The final pattern
156 */
157 public void setFinal( String finalPattern )
158 {
159 this.finalPattern = finalPattern;
160 }
161
162
163 /**
164 * Gets the list of wildcard surrounded any fragments.
165 *
166 * @return the any fragments
167 */
168 public final List<String> getAny()
169 {
170 return anyPattern;
171 }
172
173
174 /**
175 * Set the any patterns
176 * @param anyPattern The any patterns
177 */
178 public void setAny( List<String> anyPattern )
179 {
180 this.anyPattern = anyPattern;
181 }
182
183
184 /**
185 * Add an any pattern
186 * @param anyPattern The any pattern
187 */
188 public void addAny( String anyPattern )
189 {
190 this.anyPattern.add( anyPattern );
191 }
192
193
194 /**
195 * Gets the compiled regular expression for the substring expression.
196 *
197 * @param normalizer the normalizer to use for pattern component normalization
198 * @return the equivalent compiled regular expression
199 * @throws LdapInvalidDnException if there are problems while normalizing
200 */
201 public final Pattern getRegex( Normalizer normalizer ) throws LdapException
202 {
203 boolean isBinary = false;
204
205 if ( ( anyPattern != null ) && ( anyPattern.size() > 0 ) )
206 {
207 String[] any = new String[anyPattern.size()];
208
209 for ( int i = 0; i < any.length; i++ )
210 {
211 any[i] = ( String ) normalizer.normalize( anyPattern.get( i ) );
212
213 if ( any[i].length() == 0 )
214 {
215 any[i] = " ";
216 }
217 }
218
219 String initialStr = null;
220
221 if ( initialPattern != null )
222 {
223 initialStr = ( String ) normalizer.normalize( initialPattern );
224 }
225
226 String finalStr = null;
227
228 if ( finalPattern != null )
229 {
230 finalStr = ( String ) normalizer.normalize( finalPattern );
231 }
232
233 return StringTools.getRegex( initialStr, any, finalStr );
234 }
235
236 String initialStr = null;
237
238 if ( initialPattern != null )
239 {
240 initialStr = ( String ) normalizer.normalize( initialPattern );
241 }
242
243 String finalStr = null;
244
245 if ( finalPattern != null )
246 {
247 finalStr = ( String ) normalizer.normalize( finalPattern );
248 }
249
250 return StringTools.getRegex( initialStr, null, finalStr );
251 }
252
253
254 /**
255 * @see Object#hashCode()
256 * @return the instance's hash code
257 */
258 public int hashCode()
259 {
260 int h = 37;
261
262 h = h*17 + super.hashCode();
263 h = h*17 + ( initialPattern != null ? initialPattern.hashCode() : 0 );
264
265 if ( anyPattern != null )
266 {
267 for ( String pattern:anyPattern )
268 {
269 h = h*17 + pattern.hashCode();
270 }
271 }
272
273 h = h*17 + ( finalPattern != null ? finalPattern.hashCode() : 0 );
274
275 return h;
276 }
277
278
279 /**
280 * @see java.lang.Object#toString()
281 * @return A string representing the AndNode
282 */
283 public String toString()
284 {
285 StringBuilder buf = new StringBuilder();
286
287 buf.append( '(' ).append( getAttribute() ).append( '=' );
288
289 if ( null != initialPattern )
290 {
291 buf.append( AbstractExprNode.escapeFilterValue( new StringValue( initialPattern ) ) ).append( '*' );
292 }
293 else
294 {
295 buf.append( '*' );
296 }
297
298 if ( null != anyPattern )
299 {
300 for ( String any:anyPattern )
301 {
302 buf.append( AbstractExprNode.escapeFilterValue( new StringValue( any ) ) );
303 buf.append( '*' );
304 }
305 }
306
307 if ( null != finalPattern )
308 {
309 buf.append( AbstractExprNode.escapeFilterValue( new StringValue( finalPattern ) ) );
310 }
311
312 buf.append( super.toString() );
313
314 buf.append( ')' );
315
316 return buf.toString();
317 }
318 }