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