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}