001/* 002 * Copyright 2017-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2017-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2017-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.unboundidds.controls; 037 038 039 040import java.io.Serializable; 041import java.util.Collection; 042import java.util.Collections; 043import java.util.Iterator; 044import java.util.LinkedHashSet; 045import java.util.Set; 046 047import com.unboundid.ldap.sdk.Filter; 048import com.unboundid.util.Mutable; 049import com.unboundid.util.NotNull; 050import com.unboundid.util.Nullable; 051import com.unboundid.util.StaticUtils; 052import com.unboundid.util.ThreadSafety; 053import com.unboundid.util.ThreadSafetyLevel; 054import com.unboundid.util.Validator; 055 056 057 058/** 059 * This class provides a data structure that holds a set of properties for use 060 * in conjunction with the {@link UniquenessRequestControl}. 061 * <BR> 062 * <BLOCKQUOTE> 063 * <B>NOTE:</B> This class, and other classes within the 064 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 065 * supported for use against Ping Identity, UnboundID, and 066 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 067 * for proprietary functionality or for external specifications that are not 068 * considered stable or mature enough to be guaranteed to work in an 069 * interoperable way with other types of LDAP servers. 070 * </BLOCKQUOTE> 071 * <BR> 072 * The control must be created with either a set of attribute types or a filter 073 * (or both). See the {@link UniquenessRequestControl} class-level 074 * documentation for details about how the server will behave if either or both 075 * of these values are provided. 076 * <BR><BR> 077 * The following default values will be used for properties that are not 078 * specified: 079 * <UL> 080 * <LI> 081 * An empty set of attribute types. 082 * </LI> 083 * <LI> 084 * A multiple attribute behavior of 085 * {@link UniquenessMultipleAttributeBehavior#UNIQUE_WITHIN_EACH_ATTRIBUTE}. 086 * </LI> 087 * <LI> 088 * No base DN. 089 * </LI> 090 * <LI> 091 * No filter. 092 * </LI> 093 * <LI> 094 * The control will not prevent conflicts with soft-deleted entries. 095 * </LI> 096 * <LI> 097 * A pre-commit validation level of 098 * {@link UniquenessValidationLevel#ALL_SUBTREE_VIEWS}. 099 * </LI> 100 * <LI> 101 * A post-commit validation level of 102 * {@link UniquenessValidationLevel#ALL_SUBTREE_VIEWS}. 103 * </LI> 104 * <LI> 105 * Do alert on conflicts detected during post-commit validation. 106 * </LI> 107 * <LI> 108 * Do not create a conflict prevention details entry. 109 * </LI> 110 * </UL> 111 */ 112@Mutable() 113@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 114public final class UniquenessRequestControlProperties 115 implements Serializable 116{ 117 /** 118 * The serial version UID for this serializable class. 119 */ 120 private static final long serialVersionUID = 4330352906527176309L; 121 122 123 124 // Indicates whether the server should raise an administrative alert if a 125 // conflict is detected during post-commit validation. 126 private boolean alertOnPostCommitConflictDetection = true; 127 128 // Indicates whether the server should create a conflict prevention details 129 // entry before pre-commit validation as a means of helping to avoid 130 // conflicts. 131 private boolean createConflictPreventionDetailsEntry = false; 132 133 // Indicates whether to prevent conflicts with soft-deleted entries. 134 private boolean preventConflictsWithSoftDeletedEntries = false; 135 136 // An optional filter that should be used in the course of identifying 137 // uniqueness conflicts. 138 @Nullable private Filter filter = null; 139 140 // A potentially-empty set of attribute types that should be checked for 141 // uniqueness conflicts. 142 @NotNull private Set<String> attributeTypes = Collections.emptySet(); 143 144 // An optional base DN to use when checking for conflicts. 145 @Nullable private String baseDN = null; 146 147 // The behavior that the server should exhibit if multiple attribute types 148 // are configured. 149 @NotNull private 150 UniquenessMultipleAttributeBehavior multipleAttributeBehavior = 151 UniquenessMultipleAttributeBehavior.UNIQUE_WITHIN_EACH_ATTRIBUTE; 152 153 // The level of validation that the server should perform before processing 154 // the associated change. 155 @NotNull private UniquenessValidationLevel postCommitValidationLevel = 156 UniquenessValidationLevel.ALL_SUBTREE_VIEWS; 157 158 // The level of validation that the server should perform after processing the 159 // associated change. 160 @NotNull private UniquenessValidationLevel preCommitValidationLevel = 161 UniquenessValidationLevel.ALL_SUBTREE_VIEWS; 162 163 164 165 /** 166 * Creates a new instance of this uniqueness request control properties object 167 * with no attribute types and all default values. This is primarily intended 168 * for supporting deserialization, since it will not include any . 169 */ 170 private UniquenessRequestControlProperties() 171 { 172 // No implementation is required. 173 } 174 175 176 177 /** 178 * Creates a new instance of this uniqueness request control properties object 179 * with the provided set of attribute types and default values for all other 180 * properties as specified in the class-level javadoc documentation. 181 * 182 * @param attributeTypes The set of attribute types that the server will 183 * check for uniqueness conflicts. It must not be 184 * {@code null} or empty. The server should be 185 * configured with equality indexes for each of these 186 * attribute types. 187 */ 188 public UniquenessRequestControlProperties( 189 @NotNull final String... attributeTypes) 190 { 191 this(); 192 193 Validator.ensureTrue( 194 ((attributeTypes != null) && (attributeTypes.length > 0)), 195 "The set of attribute types must not be null or empty."); 196 this.attributeTypes = Collections.unmodifiableSet(new LinkedHashSet<>( 197 StaticUtils.toList(attributeTypes))); 198 } 199 200 201 202 /** 203 * Creates a new instance of this uniqueness request control properties object 204 * with the provided set of attribute types and default values for all other 205 * properties as specified in the class-level javadoc documentation. 206 * 207 * @param attributeTypes The set of attribute types that the server will 208 * check for uniqueness conflicts. It must not be 209 * {@code null} or empty. The server should be 210 * configured with equality indexes for each of these 211 * attribute types. 212 */ 213 public UniquenessRequestControlProperties( 214 @NotNull final Collection<String> attributeTypes) 215 { 216 this(); 217 218 Validator.ensureTrue( 219 ((attributeTypes != null) && (! attributeTypes.isEmpty())), 220 "The set of attribute types must not be null or empty."); 221 this.attributeTypes = 222 Collections.unmodifiableSet(new LinkedHashSet<>(attributeTypes)); 223 } 224 225 226 227 /** 228 * Creates a new instance of this uniqueness request control properties object 229 * with the provided filter and default values for all other properties as 230 * specified in the class-level javadoc documentation. 231 * 232 * @param filter The filter that the server will use to check for uniqueness 233 * conflicts. It must not be {@code null}. 234 */ 235 public UniquenessRequestControlProperties(@NotNull final Filter filter) 236 { 237 this(); 238 239 Validator.ensureNotNull(filter); 240 this.filter = filter; 241 } 242 243 244 245 /** 246 * Retrieves the set of attribute types that the server will check for 247 * uniqueness conflicts. 248 * 249 * @return The set of attribute types that the server will check for 250 * uniqueness conflicts, or an empty set if only a filter should be 251 * used to identify conflicts. 252 */ 253 @NotNull() 254 public Set<String> getAttributeTypes() 255 { 256 return attributeTypes; 257 } 258 259 260 261 /** 262 * Specifies the set of attribute types that the server will check for 263 * uniqueness conflicts. 264 * 265 * @param attributeTypes The set of attribute types that the server will 266 * check for uniqueness conflicts. It must not be 267 * {@code null} or empty if no filter is configured. 268 * It may optionally be {@code null} or empty if 269 * a filter is provided. The server should be 270 * configured with an equality index for each of the 271 * provided attribute types. 272 */ 273 public void setAttributeTypes(@Nullable final String... attributeTypes) 274 { 275 if (attributeTypes == null) 276 { 277 this.attributeTypes = Collections.emptySet(); 278 } 279 else 280 { 281 this.attributeTypes = Collections.unmodifiableSet(new LinkedHashSet<>( 282 StaticUtils.toList(attributeTypes))); 283 } 284 } 285 286 287 288 /** 289 * Specifies the set of attribute types that the server will check for 290 * uniqueness conflicts. 291 * 292 * @param attributeTypes The set of attribute types that the server will 293 * check for uniqueness conflicts. It must not be 294 * {@code null} or empty if no filter is configured. 295 * It may optionally be {@code null} or empty if 296 * a filter is provided. The server should be 297 * configured with an equality index for each of the 298 * provided attribute types. 299 */ 300 public void setAttributeTypes( 301 @Nullable final Collection<String> attributeTypes) 302 { 303 if (attributeTypes == null) 304 { 305 this.attributeTypes = Collections.emptySet(); 306 } 307 else 308 { 309 this.attributeTypes = 310 Collections.unmodifiableSet(new LinkedHashSet<>(attributeTypes)); 311 } 312 } 313 314 315 316 /** 317 * Retrieves the behavior that the server should exhibit if multiple attribute 318 * types are configured. 319 * 320 * @return The behavior that the server should exhibit if multiple attribute 321 * types are configured. 322 */ 323 @NotNull() 324 public UniquenessMultipleAttributeBehavior getMultipleAttributeBehavior() 325 { 326 return multipleAttributeBehavior; 327 } 328 329 330 331 /** 332 * Specifies the behavior that the server should exhibit if multiple attribute 333 * types are configured. 334 * 335 * @param multipleAttributeBehavior The behavior that the server should 336 * exhibit if multiple attribute types are 337 * configured. This must not be 338 * {@code null}. 339 */ 340 public void setMultipleAttributeBehavior( 341 @NotNull 342 final UniquenessMultipleAttributeBehavior multipleAttributeBehavior) 343 { 344 Validator.ensureNotNull(multipleAttributeBehavior); 345 this.multipleAttributeBehavior = multipleAttributeBehavior; 346 } 347 348 349 350 /** 351 * Retrieves the base DN that will be used for searches used to identify 352 * uniqueness conflicts, if defined. 353 * 354 * @return The base DN that will be used for searches used to identify 355 * uniqueness conflicts, or {@code null} if the server should search 356 * below all public naming contexts. 357 */ 358 @Nullable() 359 public String getBaseDN() 360 { 361 return baseDN; 362 } 363 364 365 366 /** 367 * Specifies the base DN that will be used for searches used to identify 368 * uniqueness conflicts. 369 * 370 * @param baseDN The base DN that will be used for searches used to identify 371 * uniqueness conflicts. It may be {@code null} to indicate 372 * that the server should search below all public naming 373 * contexts. 374 */ 375 public void setBaseDN(@Nullable final String baseDN) 376 { 377 this.baseDN = baseDN; 378 } 379 380 381 382 /** 383 * Retrieves a filter that will be used to identify uniqueness conflicts, if 384 * defined. 385 * 386 * @return A filter that will be used to identify uniqueness conflicts, or 387 * {@code null} if no filter has been defined. 388 */ 389 @Nullable() 390 public Filter getFilter() 391 { 392 return filter; 393 } 394 395 396 397 /** 398 * Specifies a filter that will be used to identify uniqueness conflicts. 399 * 400 * @param filter A filter that will be used to identify uniqueness 401 * conflicts. It must not be {@code null} if no set of 402 * attribute types has been configured. It may optionally be 403 * {@code null} if a set of attribute types has been 404 * configured. If no attribute types are provided, then this 405 * filter should be indexed within the server. 406 */ 407 public void setFilter(@Nullable final Filter filter) 408 { 409 this.filter = filter; 410 } 411 412 413 414 /** 415 * Indicates whether the server should attempt to identify conflicts with 416 * soft-deleted entries. 417 * 418 * @return {@code true} if the server should identify conflicts with both 419 * regular entries and soft-deleted entries, or {@code false} if the 420 * server should only identify conflicts with regular entries. 421 */ 422 public boolean preventConflictsWithSoftDeletedEntries() 423 { 424 return preventConflictsWithSoftDeletedEntries; 425 } 426 427 428 429 /** 430 * Specifies whether the server should attempt to identify conflicts with 431 * soft-deleted entries. 432 * 433 * @param preventConflictsWithSoftDeletedEntries Indicates whether the 434 * server should attempt to 435 * identify conflicts with 436 * soft-deleted entries. 437 */ 438 public void setPreventConflictsWithSoftDeletedEntries( 439 final boolean preventConflictsWithSoftDeletedEntries) 440 { 441 this.preventConflictsWithSoftDeletedEntries = 442 preventConflictsWithSoftDeletedEntries; 443 } 444 445 446 447 /** 448 * Retrieves the pre-commit validation level, which will be used to identify 449 * any conflicts before the associated request is processed. 450 * 451 * @return The pre-commit validation level. 452 */ 453 @NotNull() 454 public UniquenessValidationLevel getPreCommitValidationLevel() 455 { 456 return preCommitValidationLevel; 457 } 458 459 460 461 /** 462 * Specifies the pre-commit validation level, which will be used to identify 463 * any conflicts before the associated request is processed. 464 * 465 * @param preCommitValidationLevel The pre-commit validation level. It must 466 * not be {@code null}. 467 */ 468 public void setPreCommitValidationLevel( 469 @NotNull final UniquenessValidationLevel preCommitValidationLevel) 470 { 471 Validator.ensureNotNull(preCommitValidationLevel); 472 this.preCommitValidationLevel = preCommitValidationLevel; 473 } 474 475 476 477 /** 478 * Retrieves the post-commit validation level, which will be used to identify 479 * any conflicts that were introduced by the request with which the control is 480 * associated, or by some other concurrent changed processed in the server. 481 * 482 * @return The post-commit validation level. 483 */ 484 @NotNull() 485 public UniquenessValidationLevel getPostCommitValidationLevel() 486 { 487 return postCommitValidationLevel; 488 } 489 490 491 492 /** 493 * Specifies the post-commit validation level, which will be used to identify 494 * any conflicts that were introduced by the request with which the control is 495 * associated, or by some other concurrent changed processed in the server. 496 * 497 * @param postCommitValidationLevel The post-commit validation level. It 498 * must not be {@code null}. 499 */ 500 public void setPostCommitValidationLevel( 501 @NotNull final UniquenessValidationLevel postCommitValidationLevel) 502 { 503 Validator.ensureNotNull(postCommitValidationLevel); 504 this.postCommitValidationLevel = postCommitValidationLevel; 505 } 506 507 508 509 /** 510 * Indicates whether the server should raise an administrative alert if a 511 * conflict is detected during post-commit validation processing. 512 * 513 * @return {@code true} if the server should raise an administrative alert if 514 * a conflict is detected during post-commit validation processing, 515 * or {@code false} if not. 516 */ 517 public boolean alertOnPostCommitConflictDetection() 518 { 519 return alertOnPostCommitConflictDetection; 520 } 521 522 523 524 /** 525 * Specifies whether the server should raise an administrative alert if a 526 * conflict is detected during post-commit validation processing. 527 * 528 * @param alertOnPostCommitConflictDetection Indicates whether the server 529 * should raise an administrative 530 * alert if a conflict is detected 531 * during post-commit validation 532 * processing. 533 */ 534 public void setAlertOnPostCommitConflictDetection( 535 final boolean alertOnPostCommitConflictDetection) 536 { 537 this.alertOnPostCommitConflictDetection = 538 alertOnPostCommitConflictDetection; 539 } 540 541 542 543 /** 544 * Indicates whether the server should create a temporary conflict prevention 545 * details entry before beginning pre-commit validation to provide better 546 * support for preventing conflicts. If created, the entry will be removed 547 * after post-commit validation processing has completed. 548 * 549 * @return {@code true} if the server should create a temporary conflict 550 * prevention details entry before beginning pre-commit validation, 551 * or {@code false} if not. 552 */ 553 public boolean createConflictPreventionDetailsEntry() 554 { 555 return createConflictPreventionDetailsEntry; 556 } 557 558 559 560 /** 561 * Specifies whether the server should create a temporary conflict prevention 562 * details entry before beginning pre-commit validation to provide better 563 * support for preventing conflicts. If created, the entry will be removed 564 * after post-commit validation processing has completed. 565 * 566 * @param createConflictPreventionDetailsEntry Indicates whether the server 567 * should create a temporary 568 * conflict prevention details 569 * entry before beginning 570 * pre-commit validation. 571 */ 572 public void setCreateConflictPreventionDetailsEntry( 573 final boolean createConflictPreventionDetailsEntry) 574 { 575 this.createConflictPreventionDetailsEntry = 576 createConflictPreventionDetailsEntry; 577 } 578 579 580 581 /** 582 * Retrieves a string representation of this uniqueness request control 583 * properties object. 584 * 585 * @return A string representation of this uniqueness request control 586 * properties object. 587 */ 588 @Override() 589 @NotNull() 590 public String toString() 591 { 592 final StringBuilder buffer = new StringBuilder(); 593 toString(buffer); 594 return buffer.toString(); 595 } 596 597 598 599 /** 600 * Appends a string representation of this uniqueness request control 601 * properties object to the provided buffer. 602 * 603 * @param buffer The buffer to which the information should be appended. 604 */ 605 public void toString(@NotNull final StringBuilder buffer) 606 { 607 buffer.append("UniquenessRequestControlProperties(attributeTypes={"); 608 609 final Iterator<String> attributeTypesIterator = attributeTypes.iterator(); 610 while (attributeTypesIterator.hasNext()) 611 { 612 buffer.append('\''); 613 buffer.append(attributeTypesIterator.next()); 614 buffer.append('\''); 615 616 if (attributeTypesIterator.hasNext()) 617 { 618 buffer.append(", "); 619 } 620 } 621 622 buffer.append("}, multipleAttributeBehavior="); 623 buffer.append(multipleAttributeBehavior); 624 625 if (baseDN != null) 626 { 627 buffer.append(", baseDN='"); 628 buffer.append(baseDN); 629 buffer.append('\''); 630 } 631 632 if (filter != null) 633 { 634 buffer.append(", filter='"); 635 buffer.append(filter); 636 buffer.append('\''); 637 } 638 639 buffer.append(", preventConflictsWithSoftDeletedEntries="); 640 buffer.append(preventConflictsWithSoftDeletedEntries); 641 buffer.append(", preCommitValidationLevel="); 642 buffer.append(preCommitValidationLevel); 643 buffer.append(", postCommitValidationLevel="); 644 buffer.append(postCommitValidationLevel); 645 buffer.append(", alertOnPostCommitConflictDetection="); 646 buffer.append(alertOnPostCommitConflictDetection); 647 buffer.append(", createConflictPreventionDetailsEntry="); 648 buffer.append(createConflictPreventionDetailsEntry); 649 buffer.append(')'); 650 } 651}