001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2009-2010 Sun Microsystems, Inc. 015 * Portions copyright 2012-2016 ForgeRock AS. 016 */ 017package org.forgerock.opendj.ldap; 018 019import org.forgerock.i18n.LocalizableMessage; 020import org.forgerock.i18n.LocalizedIllegalArgumentException; 021import org.forgerock.opendj.ldap.schema.Schema; 022import org.forgerock.util.Function; 023import org.forgerock.util.promise.NeverThrowsException; 024 025import com.forgerock.opendj.util.StaticUtils; 026 027import static org.forgerock.opendj.ldap.schema.Schema.*; 028 029import static com.forgerock.opendj.ldap.CoreMessages.*; 030 031/** 032 * Common {@link Function} implementations which may be used when parsing 033 * attributes. 034 * 035 * @see Entry#parseAttribute 036 * @see Attribute#parse 037 * @see AttributeParser 038 */ 039public final class Functions { 040 041 private static final Function<ByteString, String, NeverThrowsException> BYTESTRING_TO_STRING = 042 new Function<ByteString, String, NeverThrowsException>() { 043 @Override 044 public String apply(final ByteString value) { 045 return value.toString(); 046 } 047 }; 048 049 private static final Function<Object, Object, NeverThrowsException> IDENTITY = 050 new Function<Object, Object, NeverThrowsException>() { 051 @Override 052 public Object apply(final Object value) { 053 return value; 054 } 055 }; 056 057 private static final Function<String, String, NeverThrowsException> NORMALIZE_STRING = 058 new Function<String, String, NeverThrowsException>() { 059 @Override 060 public String apply(final String value) { 061 return StaticUtils.toLowerCase(value).trim(); 062 } 063 }; 064 065 private static final Function<Object, ByteString, NeverThrowsException> OBJECT_TO_BYTESTRING = 066 new Function<Object, ByteString, NeverThrowsException>() { 067 @Override 068 public ByteString apply(final Object value) { 069 return ByteString.valueOfObject(value); 070 } 071 }; 072 073 private static final Function<String, Boolean, NeverThrowsException> STRING_TO_BOOLEAN = 074 new Function<String, Boolean, NeverThrowsException>() { 075 @Override 076 public Boolean apply(final String value) { 077 final String valueString = StaticUtils.toLowerCase(value); 078 if ("true".equals(valueString) || "yes".equals(valueString) 079 || "on".equals(valueString) || "1".equals(valueString)) { 080 return Boolean.TRUE; 081 } else if ("false".equals(valueString) || "no".equals(valueString) 082 || "off".equals(valueString) || "0".equals(valueString)) { 083 return Boolean.FALSE; 084 } else { 085 throw new LocalizedIllegalArgumentException( 086 WARN_ATTR_SYNTAX_ILLEGAL_BOOLEAN.get(valueString)); 087 } 088 } 089 }; 090 091 private static final Function<String, GeneralizedTime, NeverThrowsException> STRING_TO_GENERALIZED_TIME = 092 new Function<String, GeneralizedTime, NeverThrowsException>() { 093 @Override 094 public GeneralizedTime apply(final String value) { 095 return GeneralizedTime.valueOf(value); 096 } 097 }; 098 099 private static final Function<String, Integer, NeverThrowsException> STRING_TO_INTEGER = 100 new Function<String, Integer, NeverThrowsException>() { 101 @Override 102 public Integer apply(final String value) { 103 try { 104 return Integer.valueOf(value); 105 } catch (final NumberFormatException e) { 106 final LocalizableMessage message = FUNCTIONS_TO_INTEGER_FAIL.get(value); 107 throw new LocalizedIllegalArgumentException(message); 108 } 109 } 110 }; 111 112 private static final Function<String, Long, NeverThrowsException> STRING_TO_LONG = 113 new Function<String, Long, NeverThrowsException>() { 114 @Override 115 public Long apply(final String value) { 116 try { 117 return Long.valueOf(value); 118 } catch (final NumberFormatException e) { 119 final LocalizableMessage message = FUNCTIONS_TO_LONG_FAIL.get(value); 120 throw new LocalizedIllegalArgumentException(message); 121 } 122 } 123 }; 124 125 private static final Function<ByteString, Boolean, NeverThrowsException> BYTESTRING_TO_BOOLEAN = compose( 126 byteStringToString(), STRING_TO_BOOLEAN); 127 128 private static final Function<ByteString, GeneralizedTime, NeverThrowsException> BYTESTRING_TO_GENERALIZED_TIME = 129 compose(byteStringToString(), STRING_TO_GENERALIZED_TIME); 130 131 private static final Function<ByteString, Integer, NeverThrowsException> BYTESTRING_TO_INTEGER = compose( 132 byteStringToString(), STRING_TO_INTEGER); 133 134 private static final Function<ByteString, Long, NeverThrowsException> BYTESTRING_TO_LONG = compose( 135 byteStringToString(), STRING_TO_LONG); 136 137 /** 138 * Creates a function that returns constant value for any input. 139 * 140 * @param <M> 141 * The type of input values transformed by this function. 142 * @param <N> 143 * The type of output values returned by this function. 144 * @param constant 145 * The constant value for the function to return 146 * @return A function that always returns constant value. 147 */ 148 public static <M, N> Function<M, N, NeverThrowsException> returns(final N constant) { 149 return new Function<M, N, NeverThrowsException>() { 150 @Override 151 public N apply(M value) { 152 return constant; 153 } 154 }; 155 } 156 157 /** 158 * Returns the composition of two functions. The result of the first 159 * function will be passed to the second. 160 * 161 * @param <M> 162 * The type of input values transformed by this function. 163 * @param <N> 164 * The type of output values returned by this function. 165 * @param <X> 166 * The type of intermediate values passed between the two 167 * functions. 168 * @param first 169 * The first function which will consume the input. 170 * @param second 171 * The second function which will produce the result. 172 * @return The composition. 173 */ 174 public static <M, X, N> Function<M, N, NeverThrowsException> compose( 175 final Function<M, X, NeverThrowsException> first, final Function<X, N, NeverThrowsException> second) { 176 return new Function<M, N, NeverThrowsException>() { 177 @Override 178 public N apply(final M value) { 179 return second.apply(first.apply(value)); 180 } 181 }; 182 } 183 184 /** 185 * Returns a function which always returns the value that it was provided 186 * with. 187 * 188 * @param <M> 189 * The type of values transformed by this function. 190 * @return A function which always returns the value that it was provided 191 * with. 192 */ 193 @SuppressWarnings("unchecked") 194 public static <M> Function<M, M, NeverThrowsException> identityFunction() { 195 return (Function<M, M, NeverThrowsException>) IDENTITY; 196 } 197 198 /** 199 * Returns a function which converts a {@code String} to lower case using 200 * {@link StaticUtils#toLowerCase} and then trims it. 201 * 202 * @return A function which converts a {@code String} to lower case using 203 * {@link StaticUtils#toLowerCase} and then trims it. 204 */ 205 public static Function<String, String, NeverThrowsException> normalizeString() { 206 return NORMALIZE_STRING; 207 } 208 209 /** 210 * Returns a function which converts an {@code Object} to a 211 * {@code ByteString} using the {@link ByteString#valueOfObject(Object)} method. 212 * 213 * @return A function which converts an {@code Object} to a 214 * {@code ByteString} . 215 */ 216 public static Function<Object, ByteString, NeverThrowsException> objectToByteString() { 217 return OBJECT_TO_BYTESTRING; 218 } 219 220 /** 221 * Returns a function which parses {@code AttributeDescription}s using the 222 * default schema. Invalid values will result in a 223 * {@code LocalizedIllegalArgumentException}. 224 * 225 * @return A function which parses {@code AttributeDescription}s. 226 */ 227 public static Function<String, AttributeDescription, NeverThrowsException> stringToAttributeDescription() { 228 return stringToAttributeDescription(getDefaultSchema()); 229 } 230 231 /** 232 * Returns a function which parses {@code AttributeDescription}s using the 233 * provided schema. Invalid values will result in a 234 * {@code LocalizedIllegalArgumentException}. 235 * 236 * @param schema 237 * The schema to use for decoding attribute descriptions. 238 * @return A function which parses {@code AttributeDescription}s. 239 */ 240 public static Function<String, AttributeDescription, NeverThrowsException> stringToAttributeDescription( 241 final Schema schema) { 242 return new Function<String, AttributeDescription, NeverThrowsException>() { 243 @Override 244 public AttributeDescription apply(final String value) { 245 return AttributeDescription.valueOf(value, schema); 246 } 247 }; 248 } 249 250 /** 251 * Returns a function which parses {@code Boolean} values. The function will 252 * accept the values {@code 0}, {@code false}, {@code no}, {@code off}, 253 * {@code 1}, {@code true}, {@code yes}, {@code on}. All other values will 254 * result in a {@code NumberFormatException}. 255 * 256 * @return A function which parses {@code Boolean} values. 257 */ 258 public static Function<String, Boolean, NeverThrowsException> stringToBoolean() { 259 return STRING_TO_BOOLEAN; 260 } 261 262 /** 263 * Returns a function which parses {@code DN}s using the default schema. 264 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 265 * . 266 * 267 * @return A function which parses {@code DN}s. 268 */ 269 public static Function<String, DN, NeverThrowsException> stringToDN() { 270 return stringToDN(getDefaultSchema()); 271 } 272 273 /** 274 * Returns a function which parses {@code DN}s using the provided schema. 275 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 276 * . 277 * 278 * @param schema 279 * The schema to use for decoding DNs. 280 * @return A function which parses {@code DN}s. 281 */ 282 public static Function<String, DN, NeverThrowsException> stringToDN(final Schema schema) { 283 return new Function<String, DN, NeverThrowsException>() { 284 @Override 285 public DN apply(final String value) { 286 return DN.valueOf(value, schema); 287 } 288 }; 289 } 290 291 /** 292 * Returns a function which parses generalized time strings. Invalid values 293 * will result in a {@code LocalizedIllegalArgumentException}. 294 * 295 * @return A function which parses generalized time strings. 296 */ 297 public static Function<String, GeneralizedTime, NeverThrowsException> stringToGeneralizedTime() { 298 return STRING_TO_GENERALIZED_TIME; 299 } 300 301 /** 302 * Returns a function which parses {@code Integer} string values. Invalid 303 * values will result in a {@code LocalizedIllegalArgumentException}. 304 * 305 * @return A function which parses {@code Integer} string values. 306 */ 307 public static Function<String, Integer, NeverThrowsException> stringToInteger() { 308 return STRING_TO_INTEGER; 309 } 310 311 /** 312 * Returns a function which parses {@code Long} string values. Invalid 313 * values will result in a {@code LocalizedIllegalArgumentException}. 314 * 315 * @return A function which parses {@code Long} string values. 316 */ 317 public static Function<String, Long, NeverThrowsException> stringToLong() { 318 return STRING_TO_LONG; 319 } 320 321 /** 322 * Returns a function which parses {@code AttributeDescription}s using the 323 * default schema. Invalid values will result in a 324 * {@code LocalizedIllegalArgumentException}. 325 * 326 * @return A function which parses {@code AttributeDescription}s. 327 */ 328 public static Function<ByteString, AttributeDescription, NeverThrowsException> byteStringToAttributeDescription() { 329 return byteStringToAttributeDescription(getDefaultSchema()); 330 } 331 332 /** 333 * Returns a function which parses {@code AttributeDescription}s using the 334 * provided schema. Invalid values will result in a 335 * {@code LocalizedIllegalArgumentException}. 336 * 337 * @param schema 338 * The schema to use for decoding attribute descriptions. 339 * @return A function which parses {@code AttributeDescription}s. 340 */ 341 public static Function<ByteString, AttributeDescription, NeverThrowsException> byteStringToAttributeDescription( 342 final Schema schema) { 343 return compose(byteStringToString(), new Function<String, AttributeDescription, NeverThrowsException>() { 344 @Override 345 public AttributeDescription apply(final String value) { 346 return AttributeDescription.valueOf(value, schema); 347 } 348 }); 349 } 350 351 /** 352 * Returns a function which parses {@code Boolean} values. The function will 353 * accept the values {@code 0}, {@code false}, {@code no}, {@code off}, 354 * {@code 1}, {@code true}, {@code yes}, {@code on}. All other values will 355 * result in a {@code NumberFormatException}. 356 * 357 * @return A function which parses {@code Boolean} values. 358 */ 359 public static Function<ByteString, Boolean, NeverThrowsException> byteStringToBoolean() { 360 return BYTESTRING_TO_BOOLEAN; 361 } 362 363 /** 364 * Returns a function which parses {@code DN}s using the default schema. 365 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 366 * . 367 * 368 * @return A function which parses {@code DN}s. 369 */ 370 public static Function<ByteString, DN, NeverThrowsException> byteStringToDN() { 371 return byteStringToDN(getDefaultSchema()); 372 } 373 374 /** 375 * Returns a function which parses {@code DN}s using the provided schema. 376 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 377 * . 378 * 379 * @param schema 380 * The schema to use for decoding DNs. 381 * @return A function which parses {@code DN}s. 382 */ 383 public static Function<ByteString, DN, NeverThrowsException> byteStringToDN(final Schema schema) { 384 return compose(byteStringToString(), new Function<String, DN, NeverThrowsException>() { 385 @Override 386 public DN apply(final String value) { 387 return DN.valueOf(value, schema); 388 } 389 }); 390 } 391 392 /** 393 * Returns a function which parses generalized time strings. Invalid values 394 * will result in a {@code LocalizedIllegalArgumentException}. 395 * 396 * @return A function which parses generalized time strings. 397 */ 398 public static Function<ByteString, GeneralizedTime, NeverThrowsException> byteStringToGeneralizedTime() { 399 return BYTESTRING_TO_GENERALIZED_TIME; 400 } 401 402 /** 403 * Returns a function which parses {@code Integer} string values. Invalid 404 * values will result in a {@code LocalizedIllegalArgumentException}. 405 * 406 * @return A function which parses {@code Integer} string values. 407 */ 408 public static Function<ByteString, Integer, NeverThrowsException> byteStringToInteger() { 409 return BYTESTRING_TO_INTEGER; 410 } 411 412 /** 413 * Returns a function which parses {@code Long} string values. Invalid 414 * values will result in a {@code LocalizedIllegalArgumentException}. 415 * 416 * @return A function which parses {@code Long} string values. 417 */ 418 public static Function<ByteString, Long, NeverThrowsException> byteStringToLong() { 419 return BYTESTRING_TO_LONG; 420 } 421 422 /** 423 * Returns a function which parses a {@code ByteString} as a UTF-8 encoded 424 * {@code String}. 425 * 426 * @return A function which parses the string representation of a 427 * {@code ByteString} as a UTF-8 encoded {@code String}. 428 */ 429 public static Function<ByteString, String, NeverThrowsException> byteStringToString() { 430 return BYTESTRING_TO_STRING; 431 } 432 433 /** Prevent instantiation. */ 434 private Functions() { 435 // Do nothing. 436 } 437 438}