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
049 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
050 *   for proprietary functionality or for external specifications that are not
051 *   considered stable or mature enough to be guaranteed to work in an
052 *   interoperable way with 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}