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 }