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}