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 public <T> Set<T> asSetOf(final Function<ByteString, ? extends T, NeverThrowsException> f, 362 final T... defaultValues) { 363 return asSetOf(f, Arrays.asList(defaultValues)); 364 } 365 366 /** 367 * Returns the values decoded as a set of {@code AttributeDescription}s 368 * using the schema associated with this parser, or an empty set if the 369 * attribute does not contain any values. 370 * 371 * @return The values decoded as a set of {@code AttributeDescription}s. 372 */ 373 public Set<AttributeDescription> asSetOfAttributeDescription() { 374 return asSetOfAttributeDescription(Collections.<AttributeDescription> emptySet()); 375 } 376 377 /** 378 * Returns the values decoded as a set of {@code AttributeDescription}s 379 * using the schema associated with this parser, or {@code defaultValues} if 380 * the attribute does not contain any values. 381 * 382 * @param defaultValues 383 * The default values to return if the attribute is empty. 384 * @return The values decoded as a set of {@code AttributeDescription}s. 385 */ 386 public Set<AttributeDescription> asSetOfAttributeDescription( 387 final AttributeDescription... defaultValues) { 388 return asSetOfAttributeDescription(Arrays.asList(defaultValues)); 389 } 390 391 /** 392 * Returns the values decoded as a set of {@code AttributeDescription}s 393 * using the schema associated with this parser, or {@code defaultValues} if 394 * the attribute does not contain any values. 395 * 396 * @param defaultValues 397 * The default values to return if the attribute is empty. 398 * @return The values decoded as a set of {@code AttributeDescription}s. 399 */ 400 public Set<AttributeDescription> asSetOfAttributeDescription( 401 final Collection<AttributeDescription> defaultValues) { 402 return asSetOf(Functions.byteStringToAttributeDescription(), defaultValues); 403 } 404 405 /** 406 * Returns the values decoded as a set of {@code AttributeDescription}s 407 * using the schema associated with this parser, or {@code defaultValues} if 408 * the attribute does not contain any values. 409 * 410 * @param defaultValues 411 * The default values to return if the attribute is empty. 412 * @return The values decoded as a set of {@code AttributeDescription}s. 413 */ 414 public Set<AttributeDescription> asSetOfAttributeDescription(final String... defaultValues) { 415 return asSetOfAttributeDescription(transformedCollection(Arrays.asList(defaultValues), 416 Functions.stringToAttributeDescription(getSchema()), null)); 417 } 418 419 /** 420 * Returns the values decoded as a set of {@code Boolean}s, or 421 * {@code defaultValues} if the attribute does not contain any values. 422 * 423 * @param defaultValues 424 * The default values to return if the attribute is empty. 425 * @return The values decoded as a set of {@code Boolean}s. 426 */ 427 public Set<Boolean> asSetOfBoolean(final Boolean... defaultValues) { 428 return asSetOfBoolean(Arrays.asList(defaultValues)); 429 } 430 431 /** 432 * Returns the values decoded as a set of {@code Boolean}s, or 433 * {@code defaultValues} if the attribute does not contain any values. 434 * 435 * @param defaultValues 436 * The default values to return if the attribute is empty. 437 * @return The values decoded as a set of {@code Boolean}s. 438 */ 439 public Set<Boolean> asSetOfBoolean(final Collection<Boolean> defaultValues) { 440 return asSetOf(Functions.byteStringToBoolean(), defaultValues); 441 } 442 443 /** 444 * Returns the values contained in the attribute, or {@code defaultValues} 445 * if the attribute does not contain any values. 446 * 447 * @param defaultValues 448 * The default values to return if the attribute is empty. 449 * @return The values contained in the attribute. 450 */ 451 public Set<ByteString> asSetOfByteString(final ByteString... defaultValues) { 452 return asSetOfByteString(Arrays.asList(defaultValues)); 453 } 454 455 /** 456 * Returns the values contained in the attribute, or {@code defaultValues} 457 * if the attribute does not contain any values. 458 * 459 * @param defaultValues 460 * The default values to return if the attribute is empty. 461 * @return The values contained in the attribute. 462 */ 463 public Set<ByteString> asSetOfByteString(final Collection<ByteString> defaultValues) { 464 return asSetOf(Functions.<ByteString> identityFunction(), defaultValues); 465 } 466 467 /** 468 * Returns the values decoded as a set of {@code DN}s using the schema 469 * associated with this parser, or an empty set if the attribute does not 470 * contain any values. 471 * 472 * @return The values decoded as a set of {@code DN}s. 473 */ 474 public Set<DN> asSetOfDN() { 475 return asSetOfDN(Collections.<DN> emptySet()); 476 } 477 478 /** 479 * Returns the values decoded as a set of {@code DN}s using the schema 480 * associated with this parser, or {@code defaultValues} if the attribute 481 * does not contain any values. 482 * 483 * @param defaultValues 484 * The default values to return if the attribute is empty. 485 * @return The values decoded as a set of {@code DN}s. 486 */ 487 public Set<DN> asSetOfDN(final Collection<DN> defaultValues) { 488 return asSetOf(Functions.byteStringToDN(), defaultValues); 489 } 490 491 /** 492 * Returns the values decoded as a set of {@code DN}s using the schema 493 * associated with this parser, or {@code defaultValues} if the attribute 494 * does not contain any values. 495 * 496 * @param defaultValues 497 * The default values to return if the attribute is empty. 498 * @return The values decoded as a set of {@code DN}s. 499 */ 500 public Set<DN> asSetOfDN(final DN... defaultValues) { 501 return asSetOfDN(Arrays.asList(defaultValues)); 502 } 503 504 /** 505 * Returns the values decoded as a set of {@code DN}s using the schema 506 * associated with this parser, or {@code defaultValues} if the attribute 507 * does not contain any values. 508 * 509 * @param defaultValues 510 * The default values to return if the attribute is empty. 511 * @return The values decoded as a set of {@code DN}s. 512 */ 513 public Set<DN> asSetOfDN(final String... defaultValues) { 514 return asSetOfDN(transformedCollection(Arrays.asList(defaultValues), Functions 515 .stringToDN(getSchema()), null)); 516 } 517 518 /** 519 * Returns the values decoded as a set of {@code GeneralizedTime}s using the 520 * generalized time syntax, or {@code defaultValues} if the attribute does 521 * not contain any values. 522 * 523 * @param defaultValues 524 * The default values to return if the attribute is empty. 525 * @return The values decoded as a set of {@code GeneralizedTime}s. 526 */ 527 public Set<GeneralizedTime> asSetOfGeneralizedTime( 528 final Collection<GeneralizedTime> defaultValues) { 529 return asSetOf(Functions.byteStringToGeneralizedTime(), defaultValues); 530 } 531 532 /** 533 * Returns the values decoded as a set of {@code GeneralizedTime}s using the 534 * generalized time syntax, or {@code defaultValues} if the attribute does 535 * not contain any values. 536 * 537 * @param defaultValues 538 * The default values to return if the attribute is empty. 539 * @return The values decoded as a set of {@code GeneralizedTime}s. 540 */ 541 public Set<GeneralizedTime> asSetOfGeneralizedTime(final GeneralizedTime... defaultValues) { 542 return asSetOfGeneralizedTime(Arrays.asList(defaultValues)); 543 } 544 545 /** 546 * Returns the values decoded as a set of {@code Integer}s, or 547 * {@code defaultValues} if the attribute does not contain any values. 548 * 549 * @param defaultValues 550 * The default values to return if the attribute is empty. 551 * @return The values decoded as a set of {@code Integer}s. 552 */ 553 public Set<Integer> asSetOfInteger(final Collection<Integer> defaultValues) { 554 return asSetOf(Functions.byteStringToInteger(), defaultValues); 555 } 556 557 /** 558 * Returns the values decoded as a set of {@code Integer}s, or 559 * {@code defaultValues} if the attribute does not contain any values. 560 * 561 * @param defaultValues 562 * The default values to return if the attribute is empty. 563 * @return The values decoded as a set of {@code Integer}s. 564 */ 565 public Set<Integer> asSetOfInteger(final Integer... defaultValues) { 566 return asSetOfInteger(Arrays.asList(defaultValues)); 567 } 568 569 /** 570 * Returns the values decoded as a set of {@code Long}s, or 571 * {@code defaultValues} if the attribute does 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 Long}s. 576 */ 577 public Set<Long> asSetOfLong(final Collection<Long> defaultValues) { 578 return asSetOf(Functions.byteStringToLong(), defaultValues); 579 } 580 581 /** 582 * Returns the values decoded as a set of {@code Long}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 Long}s. 588 */ 589 public Set<Long> asSetOfLong(final Long... defaultValues) { 590 return asSetOfLong(Arrays.asList(defaultValues)); 591 } 592 593 /** 594 * Returns the values decoded as a set of {@code String}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 String}s. 600 */ 601 public Set<String> asSetOfString(final Collection<String> defaultValues) { 602 return asSetOf(Functions.byteStringToString(), defaultValues); 603 } 604 605 /** 606 * Returns the values decoded as a set of {@code String}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 String}s. 612 */ 613 public Set<String> asSetOfString(final String... defaultValues) { 614 return asSetOfString(Arrays.asList(defaultValues)); 615 } 616 617 /** 618 * Returns the first value decoded as a {@code String}, or {@code null} if 619 * the attribute does not contain any values. 620 * 621 * @return The first value decoded as a {@code String}. 622 */ 623 public String asString() { 624 return asString(null); 625 } 626 627 /** 628 * Returns the first value decoded as a {@code String}, or 629 * {@code defaultValue} if the attribute does not contain any values. 630 * 631 * @param defaultValue 632 * The default value to return if the attribute is empty. 633 * @return The first value decoded as a {@code String}. 634 */ 635 public String asString(final String defaultValue) { 636 return as(Functions.byteStringToString(), defaultValue); 637 } 638 639 /** 640 * Throws a {@code NoSuchElementException} if the attribute referenced by 641 * this parser is {@code null} or empty. 642 * 643 * @return A reference to this attribute parser. 644 * @throws NoSuchElementException 645 * If the attribute referenced by this parser is {@code null} or 646 * empty. 647 */ 648 public AttributeParser requireValue() { 649 if (isEmpty(attribute)) { 650 throw new NoSuchElementException(); 651 } else { 652 return this; 653 } 654 } 655 656 /** 657 * Sets the {@code Schema} which will be used when parsing schema sensitive 658 * values such as DNs and attribute descriptions. 659 * 660 * @param schema 661 * The {@code Schema} which will be used when parsing schema 662 * sensitive values. 663 * @return This attribute parser. 664 */ 665 public AttributeParser usingSchema(final Schema schema) { 666 // Avoid modifying the null instance: a schema will not be needed 667 // anyway. 668 if (this != NULL_INSTANCE) { 669 this.schema = schema; 670 } 671 return this; 672 } 673 674 private Schema getSchema() { 675 return schema == null ? Schema.getDefaultSchema() : schema; 676 } 677}