001/* 002 * Copyright 2017-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2017-2020 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-2020 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 * </UL> 105 */ 106@Mutable() 107@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 108public final class UniquenessRequestControlProperties 109 implements Serializable 110{ 111 /** 112 * The serial version UID for this serializable class. 113 */ 114 private static final long serialVersionUID = 4330352906527176309L; 115 116 117 118 // Indicates whether to prevent conflicts with soft-deleted entries. 119 private boolean preventConflictsWithSoftDeletedEntries = false; 120 121 // An optional filter that should be used in the course of identifying 122 // uniqueness conflicts. 123 @Nullable private Filter filter = null; 124 125 // A potentially-empty set of attribute types that should be checked for 126 // uniqueness conflicts. 127 @NotNull private Set<String> attributeTypes = Collections.emptySet(); 128 129 // An optional base DN to use when checking for conflicts. 130 @Nullable private String baseDN = null; 131 132 // The behavior that the server should exhibit if multiple attribute types 133 // are configured. 134 @NotNull private 135 UniquenessMultipleAttributeBehavior multipleAttributeBehavior = 136 UniquenessMultipleAttributeBehavior.UNIQUE_WITHIN_EACH_ATTRIBUTE; 137 138 // The level of validation that the server should perform before processing 139 // the associated change. 140 @NotNull private UniquenessValidationLevel postCommitValidationLevel = 141 UniquenessValidationLevel.ALL_SUBTREE_VIEWS; 142 143 // The level of validation that the server should perform after processing the 144 // associated change. 145 @NotNull private UniquenessValidationLevel preCommitValidationLevel = 146 UniquenessValidationLevel.ALL_SUBTREE_VIEWS; 147 148 149 150 /** 151 * Creates a new instance of this uniqueness request control properties object 152 * with no attribute types and all default values. This is primarily intended 153 * for supporting deserialization, since it will not include any . 154 */ 155 private UniquenessRequestControlProperties() 156 { 157 // No implementation is required. 158 } 159 160 161 162 /** 163 * Creates a new instance of this uniqueness request control properties object 164 * with the provided set of attribute types and default values for all other 165 * properties as specified in the class-level javadoc documentation. 166 * 167 * @param attributeTypes The set of attribute types that the server will 168 * check for uniqueness conflicts. It must not be 169 * {@code null} or empty. The server should be 170 * configured with equality indexes for each of these 171 * attribute types. 172 */ 173 public UniquenessRequestControlProperties( 174 @NotNull final String... attributeTypes) 175 { 176 this(); 177 178 Validator.ensureTrue( 179 ((attributeTypes != null) && (attributeTypes.length > 0)), 180 "The set of attribute types must not be null or empty."); 181 this.attributeTypes = Collections.unmodifiableSet(new LinkedHashSet<>( 182 StaticUtils.toList(attributeTypes))); 183 } 184 185 186 187 /** 188 * Creates a new instance of this uniqueness request control properties object 189 * with the provided set of attribute types and default values for all other 190 * properties as specified in the class-level javadoc documentation. 191 * 192 * @param attributeTypes The set of attribute types that the server will 193 * check for uniqueness conflicts. It must not be 194 * {@code null} or empty. The server should be 195 * configured with equality indexes for each of these 196 * attribute types. 197 */ 198 public UniquenessRequestControlProperties( 199 @NotNull final Collection<String> attributeTypes) 200 { 201 this(); 202 203 Validator.ensureTrue( 204 ((attributeTypes != null) && (! attributeTypes.isEmpty())), 205 "The set of attribute types must not be null or empty."); 206 this.attributeTypes = 207 Collections.unmodifiableSet(new LinkedHashSet<>(attributeTypes)); 208 } 209 210 211 212 /** 213 * Creates a new instance of this uniqueness request control properties object 214 * with the provided filter and default values for all other properties as 215 * specified in the class-level javadoc documentation. 216 * 217 * @param filter The filter that the server will use to check for uniqueness 218 * conflicts. It must not be {@code null}. 219 */ 220 public UniquenessRequestControlProperties(@NotNull final Filter filter) 221 { 222 this(); 223 224 Validator.ensureNotNull(filter); 225 this.filter = filter; 226 } 227 228 229 230 /** 231 * Retrieves the set of attribute types that the server will check for 232 * uniqueness conflicts. 233 * 234 * @return The set of attribute types that the server will check for 235 * uniqueness conflicts, or an empty set if only a filter should be 236 * used to identify conflicts. 237 */ 238 @NotNull() 239 public Set<String> getAttributeTypes() 240 { 241 return attributeTypes; 242 } 243 244 245 246 /** 247 * Specifies the set of attribute types that the server will check for 248 * uniqueness conflicts. 249 * 250 * @param attributeTypes The set of attribute types that the server will 251 * check for uniqueness conflicts. It must not be 252 * {@code null} or empty if no filter is configured. 253 * It may optionally be {@code null} or empty if 254 * a filter is provided. The server should be 255 * configured with an equality index for each of the 256 * provided attribute types. 257 */ 258 public void setAttributeTypes(@Nullable final String... attributeTypes) 259 { 260 if (attributeTypes == null) 261 { 262 this.attributeTypes = Collections.emptySet(); 263 } 264 else 265 { 266 this.attributeTypes = Collections.unmodifiableSet(new LinkedHashSet<>( 267 StaticUtils.toList(attributeTypes))); 268 } 269 } 270 271 272 273 /** 274 * Specifies the set of attribute types that the server will check for 275 * uniqueness conflicts. 276 * 277 * @param attributeTypes The set of attribute types that the server will 278 * check for uniqueness conflicts. It must not be 279 * {@code null} or empty if no filter is configured. 280 * It may optionally be {@code null} or empty if 281 * a filter is provided. The server should be 282 * configured with an equality index for each of the 283 * provided attribute types. 284 */ 285 public void setAttributeTypes( 286 @Nullable final Collection<String> attributeTypes) 287 { 288 if (attributeTypes == null) 289 { 290 this.attributeTypes = Collections.emptySet(); 291 } 292 else 293 { 294 this.attributeTypes = 295 Collections.unmodifiableSet(new LinkedHashSet<>(attributeTypes)); 296 } 297 } 298 299 300 301 /** 302 * Retrieves the behavior that the server should exhibit if multiple attribute 303 * types are configured. 304 * 305 * @return The behavior that the server should exhibit if multiple attribute 306 * types are configured. 307 */ 308 @NotNull() 309 public UniquenessMultipleAttributeBehavior getMultipleAttributeBehavior() 310 { 311 return multipleAttributeBehavior; 312 } 313 314 315 316 /** 317 * Specifies the behavior that the server should exhibit if multiple attribute 318 * types are configured. 319 * 320 * @param multipleAttributeBehavior The behavior that the server should 321 * exhibit if multiple attribute types are 322 * configured. This must not be 323 * {@code null}. 324 */ 325 public void setMultipleAttributeBehavior( 326 @NotNull 327 final UniquenessMultipleAttributeBehavior multipleAttributeBehavior) 328 { 329 Validator.ensureNotNull(multipleAttributeBehavior); 330 this.multipleAttributeBehavior = multipleAttributeBehavior; 331 } 332 333 334 335 /** 336 * Retrieves the base DN that will be used for searches used to identify 337 * uniqueness conflicts, if defined. 338 * 339 * @return The base DN that will be used for searches used to identify 340 * uniqueness conflicts, or {@code null} if the server should search 341 * below all public naming contexts. 342 */ 343 @Nullable() 344 public String getBaseDN() 345 { 346 return baseDN; 347 } 348 349 350 351 /** 352 * Specifies the base DN that will be used for searches used to identify 353 * uniqueness conflicts. 354 * 355 * @param baseDN The base DN that will be used for searches used to identify 356 * uniqueness conflicts. It may be {@code null} to indicate 357 * that the server should search below all public naming 358 * contexts. 359 */ 360 public void setBaseDN(@Nullable final String baseDN) 361 { 362 this.baseDN = baseDN; 363 } 364 365 366 367 /** 368 * Retrieves a filter that will be used to identify uniqueness conflicts, if 369 * defined. 370 * 371 * @return A filter that will be used to identify uniqueness conflicts, or 372 * {@code null} if no filter has been defined. 373 */ 374 @Nullable() 375 public Filter getFilter() 376 { 377 return filter; 378 } 379 380 381 382 /** 383 * Specifies a filter that will be used to identify uniqueness conflicts. 384 * 385 * @param filter A filter that will be used to identify uniqueness 386 * conflicts. It must not be {@code null} if no set of 387 * attribute types has been configured. It may optionally be 388 * {@code null} if a set of attribute types has been 389 * configured. If no attribute types are provided, then this 390 * filter should be indexed within the server. 391 */ 392 public void setFilter(@Nullable final Filter filter) 393 { 394 this.filter = filter; 395 } 396 397 398 399 /** 400 * Indicates whether the server should attempt to identify conflicts with 401 * soft-deleted entries. 402 * 403 * @return {@code true} if the server should identify conflicts with both 404 * regular entries and soft-deleted entries, or {@code false} if the 405 * server should only identify conflicts with regular entries. 406 */ 407 public boolean preventConflictsWithSoftDeletedEntries() 408 { 409 return preventConflictsWithSoftDeletedEntries; 410 } 411 412 413 414 /** 415 * Specifies whether the server should attempt to identify conflicts with 416 * soft-deleted entries. 417 * 418 * @param preventConflictsWithSoftDeletedEntries Indicates whether the 419 * server should attempt to 420 * identify conflicts with 421 * soft-deleted entries. 422 */ 423 public void setPreventConflictsWithSoftDeletedEntries( 424 final boolean preventConflictsWithSoftDeletedEntries) 425 { 426 this.preventConflictsWithSoftDeletedEntries = 427 preventConflictsWithSoftDeletedEntries; 428 } 429 430 431 432 /** 433 * Retrieves the pre-commit validation level, which will be used to identify 434 * any conflicts before the associated request is processed. 435 * 436 * @return The pre-commit validation level. 437 */ 438 @NotNull() 439 public UniquenessValidationLevel getPreCommitValidationLevel() 440 { 441 return preCommitValidationLevel; 442 } 443 444 445 446 /** 447 * Specifies the pre-commit validation level, which will be used to identify 448 * any conflicts before the associated request is processed. 449 * 450 * @param preCommitValidationLevel The pre-commit validation level. It must 451 * not be {@code null}. 452 */ 453 public void setPreCommitValidationLevel( 454 @NotNull final UniquenessValidationLevel preCommitValidationLevel) 455 { 456 Validator.ensureNotNull(preCommitValidationLevel); 457 this.preCommitValidationLevel = preCommitValidationLevel; 458 } 459 460 461 462 /** 463 * Retrieves the post-commit validation level, which will be used to identify 464 * any conflicts that were introduced by the request with which the control is 465 * associated, or by some other concurrent changed processed in the server. 466 * 467 * @return The post-commit validation level. 468 */ 469 @NotNull() 470 public UniquenessValidationLevel getPostCommitValidationLevel() 471 { 472 return postCommitValidationLevel; 473 } 474 475 476 477 /** 478 * Specifies 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 * @param postCommitValidationLevel The post-commit validation level. It 483 * must not be {@code null}. 484 */ 485 public void setPostCommitValidationLevel( 486 @NotNull final UniquenessValidationLevel postCommitValidationLevel) 487 { 488 Validator.ensureNotNull(postCommitValidationLevel); 489 this.postCommitValidationLevel = postCommitValidationLevel; 490 } 491 492 493 494 /** 495 * Retrieves a string representation of this uniqueness request control 496 * properties object. 497 * 498 * @return A string representation of this uniqueness request control 499 * properties object. 500 */ 501 @Override() 502 @NotNull() 503 public String toString() 504 { 505 final StringBuilder buffer = new StringBuilder(); 506 toString(buffer); 507 return buffer.toString(); 508 } 509 510 511 512 /** 513 * Appends a string representation of this uniqueness request control 514 * properties object to the provided buffer. 515 * 516 * @param buffer The buffer to which the information should be appended. 517 */ 518 public void toString(@NotNull final StringBuilder buffer) 519 { 520 buffer.append("UniquenessRequestControlProperties(attributeTypes={"); 521 522 final Iterator<String> attributeTypesIterator = attributeTypes.iterator(); 523 while (attributeTypesIterator.hasNext()) 524 { 525 buffer.append('\''); 526 buffer.append(attributeTypesIterator.next()); 527 buffer.append('\''); 528 529 if (attributeTypesIterator.hasNext()) 530 { 531 buffer.append(", "); 532 } 533 } 534 535 buffer.append("}, multipleAttributeBehavior="); 536 buffer.append(multipleAttributeBehavior); 537 538 if (baseDN != null) 539 { 540 buffer.append(", baseDN='"); 541 buffer.append(baseDN); 542 buffer.append('\''); 543 } 544 545 if (filter != null) 546 { 547 buffer.append(", filter='"); 548 buffer.append(filter); 549 buffer.append('\''); 550 } 551 552 buffer.append(", preventConflictsWithSoftDeletedEntries="); 553 buffer.append(preventConflictsWithSoftDeletedEntries); 554 buffer.append(", preCommitValidationLevel="); 555 buffer.append(preCommitValidationLevel); 556 buffer.append(", postCommitValidationLevel="); 557 buffer.append(postCommitValidationLevel); 558 buffer.append(')'); 559 } 560}