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