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