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