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-2014 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.valueOf(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 * Returns the composition of two functions. The result of the first 141 * function will be passed to the second. 142 * 143 * @param <M> 144 * The type of input values transformed by this function. 145 * @param <N> 146 * The type of output values returned by this function. 147 * @param <X> 148 * The type of intermediate values passed between the two 149 * functions. 150 * @param first 151 * The first function which will consume the input. 152 * @param second 153 * The second function which will produce the result. 154 * @return The composition. 155 */ 156 public static <M, X, N> Function<M, N, NeverThrowsException> compose( 157 final Function<M, X, NeverThrowsException> first, final Function<X, N, NeverThrowsException> second) { 158 return new Function<M, N, NeverThrowsException>() { 159 public N apply(final M value) { 160 return second.apply(first.apply(value)); 161 } 162 }; 163 } 164 165 /** 166 * Returns a function which always returns the value that it was provided 167 * with. 168 * 169 * @param <M> 170 * The type of values transformed by this function. 171 * @return A function which always returns the value that it was provided 172 * with. 173 */ 174 @SuppressWarnings("unchecked") 175 public static <M> Function<M, M, NeverThrowsException> identityFunction() { 176 return (Function<M, M, NeverThrowsException>) IDENTITY; 177 } 178 179 /** 180 * Returns a function which converts a {@code String} to lower case using 181 * {@link StaticUtils#toLowerCase} and then trims it. 182 * 183 * @return A function which converts a {@code String} to lower case using 184 * {@link StaticUtils#toLowerCase} and then trims it. 185 */ 186 public static Function<String, String, NeverThrowsException> normalizeString() { 187 return NORMALIZE_STRING; 188 } 189 190 /** 191 * Returns a function which converts an {@code Object} to a 192 * {@code ByteString} using the {@link ByteString#valueOf(Object)} method. 193 * 194 * @return A function which converts an {@code Object} to a 195 * {@code ByteString} . 196 */ 197 public static Function<Object, ByteString, NeverThrowsException> objectToByteString() { 198 return OBJECT_TO_BYTESTRING; 199 } 200 201 /** 202 * Returns a function which parses {@code AttributeDescription}s using the 203 * default schema. Invalid values will result in a 204 * {@code LocalizedIllegalArgumentException}. 205 * 206 * @return A function which parses {@code AttributeDescription}s. 207 */ 208 public static Function<String, AttributeDescription, NeverThrowsException> stringToAttributeDescription() { 209 return stringToAttributeDescription(getDefaultSchema()); 210 } 211 212 /** 213 * Returns a function which parses {@code AttributeDescription}s using the 214 * provided schema. Invalid values will result in a 215 * {@code LocalizedIllegalArgumentException}. 216 * 217 * @param schema 218 * The schema to use for decoding attribute descriptions. 219 * @return A function which parses {@code AttributeDescription}s. 220 */ 221 public static Function<String, AttributeDescription, NeverThrowsException> stringToAttributeDescription( 222 final Schema schema) { 223 return new Function<String, AttributeDescription, NeverThrowsException>() { 224 public AttributeDescription apply(final String value) { 225 return AttributeDescription.valueOf(value, schema); 226 } 227 }; 228 } 229 230 /** 231 * Returns a function which parses {@code Boolean} values. The function will 232 * accept the values {@code 0}, {@code false}, {@code no}, {@code off}, 233 * {@code 1}, {@code true}, {@code yes}, {@code on}. All other values will 234 * result in a {@code NumberFormatException}. 235 * 236 * @return A function which parses {@code Boolean} values. 237 */ 238 public static Function<String, Boolean, NeverThrowsException> stringToBoolean() { 239 return STRING_TO_BOOLEAN; 240 } 241 242 /** 243 * Returns a function which parses {@code DN}s using the default schema. 244 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 245 * . 246 * 247 * @return A function which parses {@code DN}s. 248 */ 249 public static Function<String, DN, NeverThrowsException> stringToDN() { 250 return stringToDN(getDefaultSchema()); 251 } 252 253 /** 254 * Returns a function which parses {@code DN}s using the provided schema. 255 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 256 * . 257 * 258 * @param schema 259 * The schema to use for decoding DNs. 260 * @return A function which parses {@code DN}s. 261 */ 262 public static Function<String, DN, NeverThrowsException> stringToDN(final Schema schema) { 263 return new Function<String, DN, NeverThrowsException>() { 264 public DN apply(final String value) { 265 return DN.valueOf(value, schema); 266 } 267 }; 268 } 269 270 /** 271 * Returns a function which parses generalized time strings. Invalid values 272 * will result in a {@code LocalizedIllegalArgumentException}. 273 * 274 * @return A function which parses generalized time strings. 275 */ 276 public static Function<String, GeneralizedTime, NeverThrowsException> stringToGeneralizedTime() { 277 return STRING_TO_GENERALIZED_TIME; 278 } 279 280 /** 281 * Returns a function which parses {@code Integer} string values. Invalid 282 * values will result in a {@code LocalizedIllegalArgumentException}. 283 * 284 * @return A function which parses {@code Integer} string values. 285 */ 286 public static Function<String, Integer, NeverThrowsException> stringToInteger() { 287 return STRING_TO_INTEGER; 288 } 289 290 /** 291 * Returns a function which parses {@code Long} string values. Invalid 292 * values will result in a {@code LocalizedIllegalArgumentException}. 293 * 294 * @return A function which parses {@code Long} string values. 295 */ 296 public static Function<String, Long, NeverThrowsException> stringToLong() { 297 return STRING_TO_LONG; 298 } 299 300 /** 301 * Returns a function which parses {@code AttributeDescription}s using the 302 * default schema. Invalid values will result in a 303 * {@code LocalizedIllegalArgumentException}. 304 * 305 * @return A function which parses {@code AttributeDescription}s. 306 */ 307 public static Function<ByteString, AttributeDescription, NeverThrowsException> byteStringToAttributeDescription() { 308 return byteStringToAttributeDescription(getDefaultSchema()); 309 } 310 311 /** 312 * Returns a function which parses {@code AttributeDescription}s using the 313 * provided schema. Invalid values will result in a 314 * {@code LocalizedIllegalArgumentException}. 315 * 316 * @param schema 317 * The schema to use for decoding attribute descriptions. 318 * @return A function which parses {@code AttributeDescription}s. 319 */ 320 public static Function<ByteString, AttributeDescription, NeverThrowsException> byteStringToAttributeDescription( 321 final Schema schema) { 322 return compose(byteStringToString(), new Function<String, AttributeDescription, NeverThrowsException>() { 323 public AttributeDescription apply(final String value) { 324 return AttributeDescription.valueOf(value, schema); 325 } 326 }); 327 } 328 329 /** 330 * Returns a function which parses {@code Boolean} values. The function will 331 * accept the values {@code 0}, {@code false}, {@code no}, {@code off}, 332 * {@code 1}, {@code true}, {@code yes}, {@code on}. All other values will 333 * result in a {@code NumberFormatException}. 334 * 335 * @return A function which parses {@code Boolean} values. 336 */ 337 public static Function<ByteString, Boolean, NeverThrowsException> byteStringToBoolean() { 338 return BYTESTRING_TO_BOOLEAN; 339 } 340 341 /** 342 * Returns a function which parses {@code DN}s using the default schema. 343 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 344 * . 345 * 346 * @return A function which parses {@code DN}s. 347 */ 348 public static Function<ByteString, DN, NeverThrowsException> byteStringToDN() { 349 return byteStringToDN(getDefaultSchema()); 350 } 351 352 /** 353 * Returns a function which parses {@code DN}s using the provided schema. 354 * Invalid values will result in a {@code LocalizedIllegalArgumentException} 355 * . 356 * 357 * @param schema 358 * The schema to use for decoding DNs. 359 * @return A function which parses {@code DN}s. 360 */ 361 public static Function<ByteString, DN, NeverThrowsException> byteStringToDN(final Schema schema) { 362 return compose(byteStringToString(), new Function<String, DN, NeverThrowsException>() { 363 public DN apply(final String value) { 364 return DN.valueOf(value, schema); 365 } 366 }); 367 } 368 369 /** 370 * Returns a function which parses generalized time strings. Invalid values 371 * will result in a {@code LocalizedIllegalArgumentException}. 372 * 373 * @return A function which parses generalized time strings. 374 */ 375 public static Function<ByteString, GeneralizedTime, NeverThrowsException> byteStringToGeneralizedTime() { 376 return BYTESTRING_TO_GENERALIZED_TIME; 377 } 378 379 /** 380 * Returns a function which parses {@code Integer} string values. Invalid 381 * values will result in a {@code LocalizedIllegalArgumentException}. 382 * 383 * @return A function which parses {@code Integer} string values. 384 */ 385 public static Function<ByteString, Integer, NeverThrowsException> byteStringToInteger() { 386 return BYTESTRING_TO_INTEGER; 387 } 388 389 /** 390 * Returns a function which parses {@code Long} string values. Invalid 391 * values will result in a {@code LocalizedIllegalArgumentException}. 392 * 393 * @return A function which parses {@code Long} string values. 394 */ 395 public static Function<ByteString, Long, NeverThrowsException> byteStringToLong() { 396 return BYTESTRING_TO_LONG; 397 } 398 399 /** 400 * Returns a function which parses a {@code ByteString} as a UTF-8 encoded 401 * {@code String}. 402 * 403 * @return A function which parses the string representation of a 404 * {@code ByteString} as a UTF-8 encoded {@code String}. 405 */ 406 public static Function<ByteString, String, NeverThrowsException> byteStringToString() { 407 return BYTESTRING_TO_STRING; 408 } 409 410 /** Prevent instantiation. */ 411 private Functions() { 412 // Do nothing. 413 } 414 415}