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 2012-2015 ForgeRock AS. 025 */ 026package org.forgerock.opendj.ldap; 027 028import java.util.Arrays; 029import java.util.Collection; 030import java.util.Collections; 031import java.util.LinkedHashSet; 032import java.util.NoSuchElementException; 033import java.util.Set; 034 035import org.forgerock.opendj.ldap.schema.Schema; 036import org.forgerock.util.Function; 037import org.forgerock.util.promise.NeverThrowsException; 038 039import static com.forgerock.opendj.util.Collections2.*; 040 041/** 042 * A fluent API for parsing attributes as different types of object. An 043 * attribute parser is obtained from an entry using the method 044 * {@link Entry#parseAttribute} or from an attribute using 045 * {@link Attribute#parse}. 046 * <p> 047 * Methods throw an {@code IllegalArgumentException} when a value cannot be 048 * parsed (e.g. because its syntax is invalid). Methods which return a 049 * {@code Set} always return a modifiable non-{@code null} result, even if the 050 * attribute is {@code null} or empty. 051 * <p> 052 * Examples: 053 * 054 * <pre> 055 * Entry entry = ...; 056 * 057 * Calendar timestamp = entry.parseAttribute("createTimestamp").asCalendar(); 058 * boolean isEnabled = entry.parseAttribute("enabled").asBoolean(false); 059 * 060 * Entry group = ...; 061 * Schema schema = ...; 062 * 063 * Set<DN> members = group.parseAttribute("member").usingSchema(schema).asSetOfDN(); 064 * </pre> 065 * 066 * @see Entry#parseAttribute 067 * @see Attribute#parse 068 */ 069public final class AttributeParser { 070 // TODO: enums, filters, rdns? 071 072 private static final AttributeParser NULL_INSTANCE = new AttributeParser(null); 073 074 /** 075 * Returns an attribute parser for the provided attribute. {@code null} 076 * attributes are permitted and will be treated as if an empty attribute was 077 * provided. 078 * 079 * @param attribute 080 * The attribute to be parsed, which may be {@code null}. 081 * @return The attribute parser. 082 */ 083 public static AttributeParser parseAttribute(final Attribute attribute) { 084 return isEmpty(attribute) ? NULL_INSTANCE : new AttributeParser(attribute); 085 } 086 087 private static boolean isEmpty(final Attribute attribute) { 088 return attribute == null || attribute.isEmpty(); 089 } 090 091 private final Attribute attribute; 092 private Schema schema; 093 094 private AttributeParser(final Attribute attribute) { 095 this.attribute = attribute; 096 } 097 098 /** 099 * Returns the first value decoded as a {@code T} using the provided 100 * {@link Function}, or {@code null} if the attribute does not contain any 101 * values. 102 * 103 * @param <T> 104 * The type of the value to be decoded. 105 * @param f 106 * The function which should be used to decode the value. 107 * @return The first value decoded as a {@code T}. 108 */ 109 public <T> T as(final Function<ByteString, ? extends T, NeverThrowsException> f) { 110 return as(f, null); 111 } 112 113 /** 114 * Returns the first value decoded as a {@code T} using the provided 115 * {@link Function}, or {@code defaultValue} if the attribute does not 116 * contain any values. 117 * 118 * @param <T> 119 * The type of the value to be decoded. 120 * @param f 121 * The function which should be used to decode the value. 122 * @param defaultValue 123 * The default value to return if the attribute is empty. 124 * @return The first value decoded as a {@code T}. 125 */ 126 public <T> T as(final Function<ByteString, ? extends T, NeverThrowsException> f, final T defaultValue) { 127 if (!isEmpty(attribute)) { 128 return f.apply(attribute.firstValue()); 129 } else { 130 return defaultValue; 131 } 132 } 133 134 /** 135 * Returns the first value decoded as an {@code AttributeDescription} using 136 * the schema associated with this parser, or {@code null} if the attribute 137 * does not contain any values. 138 * 139 * @return The first value decoded as an {@code AttributeDescription}. 140 */ 141 public AttributeDescription asAttributeDescription() { 142 return asAttributeDescription((AttributeDescription) null); 143 } 144 145 /** 146 * Returns the first value decoded as an {@code AttributeDescription} using 147 * the schema associated with this parser, or {@code defaultValue} if the 148 * attribute does not contain any values. 149 * 150 * @param defaultValue 151 * The default value to return if the attribute is empty. 152 * @return The first value decoded as an {@code AttributeDescription}. 153 */ 154 public AttributeDescription asAttributeDescription(final AttributeDescription defaultValue) { 155 return as(Functions.byteStringToAttributeDescription(getSchema()), defaultValue); 156 } 157 158 /** 159 * Returns the first value decoded as an {@code AttributeDescription} using 160 * the schema associated with this parser, or {@code defaultValue} if the 161 * attribute does not contain any values. 162 * 163 * @param defaultValue 164 * The default value to return if the attribute is empty. 165 * @return The first value decoded as an {@code AttributeDescription}. 166 */ 167 public AttributeDescription asAttributeDescription(final String defaultValue) { 168 return asAttributeDescription(AttributeDescription.valueOf(defaultValue, getSchema())); 169 } 170 171 /** 172 * Returns the first value decoded as a boolean, or {@code null} if the 173 * attribute does not contain any values. 174 * 175 * @return The first value decoded as a boolean. 176 */ 177 public Boolean asBoolean() { 178 return isEmpty(attribute) ? null : asBoolean(false /* ignored */); 179 } 180 181 /** 182 * Returns the first value decoded as an {@code Boolean}, or 183 * {@code defaultValue} if the attribute does not contain any values. 184 * 185 * @param defaultValue 186 * The default value to return if the attribute is empty. 187 * @return The first value decoded as an {@code Boolean}. 188 */ 189 public boolean asBoolean(final boolean defaultValue) { 190 return as(Functions.byteStringToBoolean(), defaultValue); 191 } 192 193 /** 194 * Returns the first value, or {@code null} if the attribute does not 195 * contain any values. 196 * 197 * @return The first value. 198 */ 199 public ByteString asByteString() { 200 return asByteString(null); 201 } 202 203 /** 204 * Returns the first value, or {@code defaultValue} if the attribute does 205 * not contain any values. 206 * 207 * @param defaultValue 208 * The default value to return if the attribute is empty. 209 * @return The first value. 210 */ 211 public ByteString asByteString(final ByteString defaultValue) { 212 return as(Functions.<ByteString> identityFunction(), defaultValue); 213 } 214 215 /** 216 * Returns the first value decoded as a {@code DN} using the schema 217 * associated with this parser, or {@code null} if the attribute does not 218 * contain any values. 219 * 220 * @return The first value decoded as a {@code DN}. 221 */ 222 public DN asDN() { 223 return asDN((DN) null); 224 } 225 226 /** 227 * Returns the first value decoded as a {@code DN} using the schema 228 * associated with this parser, or {@code defaultValue} if the attribute 229 * does not contain any values. 230 * 231 * @param defaultValue 232 * The default value to return if the attribute is empty. 233 * @return The first value decoded as a {@code DN}. 234 */ 235 public DN asDN(final DN defaultValue) { 236 return as(Functions.byteStringToDN(getSchema()), defaultValue); 237 } 238 239 /** 240 * Returns the first value decoded as a {@code DN} using the schema 241 * associated with this parser, or {@code defaultValue} if the attribute 242 * does not contain any values. 243 * 244 * @param defaultValue 245 * The default value to return if the attribute is empty. 246 * @return The first value decoded as a {@code DN}. 247 */ 248 public DN asDN(final String defaultValue) { 249 return asDN(DN.valueOf(defaultValue, getSchema())); 250 } 251 252 /** 253 * Returns the first value decoded as a {@code GeneralizedTime} using the 254 * generalized time syntax, or {@code null} if the attribute does not 255 * contain any values. 256 * 257 * @return The first value decoded as a {@code GeneralizedTime}. 258 */ 259 public GeneralizedTime asGeneralizedTime() { 260 return asGeneralizedTime(null); 261 } 262 263 /** 264 * Returns the first value decoded as an {@code GeneralizedTime} using the 265 * generalized time syntax, or {@code defaultValue} if the attribute does 266 * not contain any values. 267 * 268 * @param defaultValue 269 * The default value to return if the attribute is empty. 270 * @return The first value decoded as an {@code GeneralizedTime}. 271 */ 272 public GeneralizedTime asGeneralizedTime(final GeneralizedTime defaultValue) { 273 return as(Functions.byteStringToGeneralizedTime(), defaultValue); 274 } 275 276 /** 277 * Returns the first value decoded as an {@code Integer}, or {@code null} if 278 * the attribute does not contain any values. 279 * 280 * @return The first value decoded as an {@code Integer}. 281 */ 282 public Integer asInteger() { 283 return isEmpty(attribute) ? null : asInteger(0 /* ignored */); 284 } 285 286 /** 287 * Returns the first value decoded as an {@code Integer}, or 288 * {@code defaultValue} if the attribute does not contain any values. 289 * 290 * @param defaultValue 291 * The default value to return if the attribute is empty. 292 * @return The first value decoded as an {@code Integer}. 293 */ 294 public int asInteger(final int defaultValue) { 295 return as(Functions.byteStringToInteger(), defaultValue); 296 } 297 298 /** 299 * Returns the first value decoded as a {@code Long}, or {@code null} if the 300 * attribute does not contain any values. 301 * 302 * @return The first value decoded as a {@code Long}. 303 */ 304 public Long asLong() { 305 return isEmpty(attribute) ? null : asLong(0L /* ignored */); 306 } 307 308 /** 309 * Returns the first value decoded as a {@code Long}, or 310 * {@code defaultValue} if the attribute does not contain any values. 311 * 312 * @param defaultValue 313 * The default value to return if the attribute is empty. 314 * @return The first value decoded as a {@code Long}. 315 */ 316 public long asLong(final long defaultValue) { 317 return as(Functions.byteStringToLong(), defaultValue); 318 } 319 320 /** 321 * Returns the values decoded as a set of {@code T}s using the provided 322 * {@link Function}, or {@code defaultValues} if the attribute does not 323 * contain any values. 324 * 325 * @param <T> 326 * The type of the values to be decoded. 327 * @param f 328 * The function which should be used to decode values. 329 * @param defaultValues 330 * The default values to return if the attribute is empty. 331 * @return The values decoded as a set of {@code T}s. 332 */ 333 public <T> Set<T> asSetOf(final Function<ByteString, ? extends T, NeverThrowsException> f, 334 final Collection<? extends T> defaultValues) { 335 if (!isEmpty(attribute)) { 336 final LinkedHashSet<T> result = new LinkedHashSet<>(attribute.size()); 337 for (final ByteString b : attribute) { 338 result.add(f.apply(b)); 339 } 340 return result; 341 } else if (defaultValues != null) { 342 return new LinkedHashSet<>(defaultValues); 343 } else { 344 return new LinkedHashSet<>(0); 345 } 346 } 347 348 /** 349 * Returns the values decoded as a set of {@code T}s using the provided 350 * {@link Function}, or {@code defaultValues} if the attribute does not 351 * contain any values. 352 * 353 * @param <T> 354 * The type of the values to be decoded. 355 * @param f 356 * The function which should be used to decode values. 357 * @param defaultValues 358 * The default values to return if the attribute is empty. 359 * @return The values decoded as a set of {@code T}s. 360 */ 361 @SafeVarargs 362 @SuppressWarnings("varargs") 363 public final <T> Set<T> asSetOf(final Function<ByteString, ? extends T, NeverThrowsException> f, 364 final T... defaultValues) { 365 return asSetOf(f, Arrays.asList(defaultValues)); 366 } 367 368 /** 369 * Returns the values decoded as a set of {@code AttributeDescription}s 370 * using the schema associated with this parser, or an empty set if the 371 * attribute does not contain any values. 372 * 373 * @return The values decoded as a set of {@code AttributeDescription}s. 374 */ 375 public Set<AttributeDescription> asSetOfAttributeDescription() { 376 return asSetOfAttributeDescription(Collections.<AttributeDescription> emptySet()); 377 } 378 379 /** 380 * Returns the values decoded as a set of {@code AttributeDescription}s 381 * using the schema associated with this parser, or {@code defaultValues} if 382 * the attribute does not contain any values. 383 * 384 * @param defaultValues 385 * The default values to return if the attribute is empty. 386 * @return The values decoded as a set of {@code AttributeDescription}s. 387 */ 388 public Set<AttributeDescription> asSetOfAttributeDescription( 389 final AttributeDescription... defaultValues) { 390 return asSetOfAttributeDescription(Arrays.asList(defaultValues)); 391 } 392 393 /** 394 * Returns the values decoded as a set of {@code AttributeDescription}s 395 * using the schema associated with this parser, or {@code defaultValues} if 396 * the attribute does not contain any values. 397 * 398 * @param defaultValues 399 * The default values to return if the attribute is empty. 400 * @return The values decoded as a set of {@code AttributeDescription}s. 401 */ 402 public Set<AttributeDescription> asSetOfAttributeDescription( 403 final Collection<AttributeDescription> defaultValues) { 404 return asSetOf(Functions.byteStringToAttributeDescription(), defaultValues); 405 } 406 407 /** 408 * Returns the values decoded as a set of {@code AttributeDescription}s 409 * using the schema associated with this parser, or {@code defaultValues} if 410 * the attribute does not contain any values. 411 * 412 * @param defaultValues 413 * The default values to return if the attribute is empty. 414 * @return The values decoded as a set of {@code AttributeDescription}s. 415 */ 416 public Set<AttributeDescription> asSetOfAttributeDescription(final String... defaultValues) { 417 return asSetOfAttributeDescription(transformedCollection(Arrays.asList(defaultValues), 418 Functions.stringToAttributeDescription(getSchema()), null)); 419 } 420 421 /** 422 * Returns the values decoded as a set of {@code Boolean}s, or 423 * {@code defaultValues} if the attribute does not contain any values. 424 * 425 * @param defaultValues 426 * The default values to return if the attribute is empty. 427 * @return The values decoded as a set of {@code Boolean}s. 428 */ 429 public Set<Boolean> asSetOfBoolean(final Boolean... defaultValues) { 430 return asSetOfBoolean(Arrays.asList(defaultValues)); 431 } 432 433 /** 434 * Returns the values decoded as a set of {@code Boolean}s, or 435 * {@code defaultValues} if the attribute does not contain any values. 436 * 437 * @param defaultValues 438 * The default values to return if the attribute is empty. 439 * @return The values decoded as a set of {@code Boolean}s. 440 */ 441 public Set<Boolean> asSetOfBoolean(final Collection<Boolean> defaultValues) { 442 return asSetOf(Functions.byteStringToBoolean(), defaultValues); 443 } 444 445 /** 446 * Returns the values contained in the attribute, or {@code defaultValues} 447 * if the attribute does not contain any values. 448 * 449 * @param defaultValues 450 * The default values to return if the attribute is empty. 451 * @return The values contained in the attribute. 452 */ 453 public Set<ByteString> asSetOfByteString(final ByteString... defaultValues) { 454 return asSetOfByteString(Arrays.asList(defaultValues)); 455 } 456 457 /** 458 * Returns the values contained in the attribute, or {@code defaultValues} 459 * if the attribute does not contain any values. 460 * 461 * @param defaultValues 462 * The default values to return if the attribute is empty. 463 * @return The values contained in the attribute. 464 */ 465 public Set<ByteString> asSetOfByteString(final Collection<ByteString> defaultValues) { 466 return asSetOf(Functions.<ByteString> identityFunction(), defaultValues); 467 } 468 469 /** 470 * Returns the values decoded as a set of {@code DN}s using the schema 471 * associated with this parser, or an empty set if the attribute does not 472 * contain any values. 473 * 474 * @return The values decoded as a set of {@code DN}s. 475 */ 476 public Set<DN> asSetOfDN() { 477 return asSetOfDN(Collections.<DN> emptySet()); 478 } 479 480 /** 481 * Returns the values decoded as a set of {@code DN}s using the schema 482 * associated with this parser, or {@code defaultValues} if the attribute 483 * does not contain any values. 484 * 485 * @param defaultValues 486 * The default values to return if the attribute is empty. 487 * @return The values decoded as a set of {@code DN}s. 488 */ 489 public Set<DN> asSetOfDN(final Collection<DN> defaultValues) { 490 return asSetOf(Functions.byteStringToDN(), defaultValues); 491 } 492 493 /** 494 * Returns the values decoded as a set of {@code DN}s using the schema 495 * associated with this parser, or {@code defaultValues} if the attribute 496 * does not contain any values. 497 * 498 * @param defaultValues 499 * The default values to return if the attribute is empty. 500 * @return The values decoded as a set of {@code DN}s. 501 */ 502 public Set<DN> asSetOfDN(final DN... defaultValues) { 503 return asSetOfDN(Arrays.asList(defaultValues)); 504 } 505 506 /** 507 * Returns the values decoded as a set of {@code DN}s using the schema 508 * associated with this parser, or {@code defaultValues} if the attribute 509 * does not contain any values. 510 * 511 * @param defaultValues 512 * The default values to return if the attribute is empty. 513 * @return The values decoded as a set of {@code DN}s. 514 */ 515 public Set<DN> asSetOfDN(final String... defaultValues) { 516 return asSetOfDN(transformedCollection(Arrays.asList(defaultValues), Functions 517 .stringToDN(getSchema()), null)); 518 } 519 520 /** 521 * Returns the values decoded as a set of {@code GeneralizedTime}s using the 522 * generalized time syntax, or {@code defaultValues} if the attribute does 523 * not contain any values. 524 * 525 * @param defaultValues 526 * The default values to return if the attribute is empty. 527 * @return The values decoded as a set of {@code GeneralizedTime}s. 528 */ 529 public Set<GeneralizedTime> asSetOfGeneralizedTime( 530 final Collection<GeneralizedTime> defaultValues) { 531 return asSetOf(Functions.byteStringToGeneralizedTime(), defaultValues); 532 } 533 534 /** 535 * Returns the values decoded as a set of {@code GeneralizedTime}s using the 536 * generalized time syntax, or {@code defaultValues} if the attribute does 537 * not contain any values. 538 * 539 * @param defaultValues 540 * The default values to return if the attribute is empty. 541 * @return The values decoded as a set of {@code GeneralizedTime}s. 542 */ 543 public Set<GeneralizedTime> asSetOfGeneralizedTime(final GeneralizedTime... defaultValues) { 544 return asSetOfGeneralizedTime(Arrays.asList(defaultValues)); 545 } 546 547 /** 548 * Returns the values decoded as a set of {@code Integer}s, or 549 * {@code defaultValues} if the attribute does not contain any values. 550 * 551 * @param defaultValues 552 * The default values to return if the attribute is empty. 553 * @return The values decoded as a set of {@code Integer}s. 554 */ 555 public Set<Integer> asSetOfInteger(final Collection<Integer> defaultValues) { 556 return asSetOf(Functions.byteStringToInteger(), defaultValues); 557 } 558 559 /** 560 * Returns the values decoded as a set of {@code Integer}s, or 561 * {@code defaultValues} if the attribute does not contain any values. 562 * 563 * @param defaultValues 564 * The default values to return if the attribute is empty. 565 * @return The values decoded as a set of {@code Integer}s. 566 */ 567 public Set<Integer> asSetOfInteger(final Integer... defaultValues) { 568 return asSetOfInteger(Arrays.asList(defaultValues)); 569 } 570 571 /** 572 * Returns the values decoded as a set of {@code Long}s, or 573 * {@code defaultValues} if the attribute does not contain any values. 574 * 575 * @param defaultValues 576 * The default values to return if the attribute is empty. 577 * @return The values decoded as a set of {@code Long}s. 578 */ 579 public Set<Long> asSetOfLong(final Collection<Long> defaultValues) { 580 return asSetOf(Functions.byteStringToLong(), defaultValues); 581 } 582 583 /** 584 * Returns the values decoded as a set of {@code Long}s, or 585 * {@code defaultValues} if the attribute does not contain any values. 586 * 587 * @param defaultValues 588 * The default values to return if the attribute is empty. 589 * @return The values decoded as a set of {@code Long}s. 590 */ 591 public Set<Long> asSetOfLong(final Long... defaultValues) { 592 return asSetOfLong(Arrays.asList(defaultValues)); 593 } 594 595 /** 596 * Returns the values decoded as a set of {@code String}s, or 597 * {@code defaultValues} if the attribute does not contain any values. 598 * 599 * @param defaultValues 600 * The default values to return if the attribute is empty. 601 * @return The values decoded as a set of {@code String}s. 602 */ 603 public Set<String> asSetOfString(final Collection<String> defaultValues) { 604 return asSetOf(Functions.byteStringToString(), defaultValues); 605 } 606 607 /** 608 * Returns the values decoded as a set of {@code String}s, or 609 * {@code defaultValues} if the attribute does not contain any values. 610 * 611 * @param defaultValues 612 * The default values to return if the attribute is empty. 613 * @return The values decoded as a set of {@code String}s. 614 */ 615 public Set<String> asSetOfString(final String... defaultValues) { 616 return asSetOfString(Arrays.asList(defaultValues)); 617 } 618 619 /** 620 * Returns the first value decoded as a {@code String}, or {@code null} if 621 * the attribute does not contain any values. 622 * 623 * @return The first value decoded as a {@code String}. 624 */ 625 public String asString() { 626 return asString(null); 627 } 628 629 /** 630 * Returns the first value decoded as a {@code String}, or 631 * {@code defaultValue} if the attribute does not contain any values. 632 * 633 * @param defaultValue 634 * The default value to return if the attribute is empty. 635 * @return The first value decoded as a {@code String}. 636 */ 637 public String asString(final String defaultValue) { 638 return as(Functions.byteStringToString(), defaultValue); 639 } 640 641 /** 642 * Throws a {@code NoSuchElementException} if the attribute referenced by 643 * this parser is {@code null} or empty. 644 * 645 * @return A reference to this attribute parser. 646 * @throws NoSuchElementException 647 * If the attribute referenced by this parser is {@code null} or 648 * empty. 649 */ 650 public AttributeParser requireValue() { 651 if (isEmpty(attribute)) { 652 throw new NoSuchElementException(); 653 } else { 654 return this; 655 } 656 } 657 658 /** 659 * Sets the {@code Schema} which will be used when parsing schema sensitive 660 * values such as DNs and attribute descriptions. 661 * 662 * @param schema 663 * The {@code Schema} which will be used when parsing schema 664 * sensitive values. 665 * @return This attribute parser. 666 */ 667 public AttributeParser usingSchema(final Schema schema) { 668 // Avoid modifying the null instance: a schema will not be needed 669 // anyway. 670 if (this != NULL_INSTANCE) { 671 this.schema = schema; 672 } 673 return this; 674 } 675 676 private Schema getSchema() { 677 return schema == null ? Schema.getDefaultSchema() : schema; 678 } 679}