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