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