001/*
002 * Copyright 2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2024 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) 2024 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;
037
038
039
040import com.unboundid.ldap.sdk.DN;
041import com.unboundid.ldap.sdk.LDAPException;
042import com.unboundid.ldap.sdk.unboundidds.controls.
043            OperationPurposeRequestControl;
044import com.unboundid.ldap.sdk.unboundidds.extensions.SubtreeAccessibilityState;
045import com.unboundid.util.Mutable;
046import com.unboundid.util.NotNull;
047import com.unboundid.util.Nullable;
048import com.unboundid.util.ThreadSafety;
049import com.unboundid.util.ThreadSafetyLevel;
050import com.unboundid.util.Validator;
051
052
053
054/**
055 * This class defines a number of properties that can be used when attempting to
056 * move a subtree from one Ping Identity Directory Server instance to another
057 * Ping Identity Directory Server instance using restricted subtree
058 * accessibility.
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 */
070@Mutable()
071@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
072public final class MoveSubtreeProperties
073{
074  // Indicates whether to suppress referential integrity processing on the
075  // source server.
076  private boolean suppressReferentialIntegrityUpdates;
077
078  // Indicates whether to use the to-be-deleted subtree accessibility state
079  // (rather than the hidden state) when beginning to remove entries from the
080  // source server.
081  private boolean useToBeDeletedAccessibilityState;
082
083  // The base DN for the subtree to move.
084  @NotNull private DN baseDN;
085
086  // The maximum number of entries allowed in the subtree to move.
087  private int maximumAllowedSubtreeSize;
088
089  // An optional listener that may be invoked during the course of moving
090  // entries from the source server to the target server.
091  @Nullable private MoveSubtreeListener listener;
092
093  // An optional operation purpose request control to include in all requests
094  // sent to the source and target servers.
095  @Nullable private OperationPurposeRequestControl
096       operationPurposeRequestControl;
097
098
099
100  /**
101   * Creates a new set of properties that can be used when moving the specified
102   * subtree from one server to another.
103   *
104   * @param  baseDN  The base DN for the subtree to be moved.  It must not be
105   *                 {@code null}, and it must represent a valid DN with one or
106   *                 more RDN components.
107   *
108   * @throws  LDAPException  If the provided string cannot be parsed as a valid
109   *                         DN.
110   */
111  public MoveSubtreeProperties(@NotNull final String baseDN)
112         throws LDAPException
113  {
114    this(new DN(baseDN));
115  }
116
117
118
119  /**
120   * Creates a new set of properties that can be used when moving the specified
121   * subtree from one server to another.
122   *
123   * @param  baseDN  The base DN for the subtree to be moved.  It must not be
124   *                 {@code null}, and it must have one or more RDN components.
125   */
126  public MoveSubtreeProperties(@NotNull final DN baseDN)
127  {
128    setBaseDN(baseDN);
129
130    suppressReferentialIntegrityUpdates = false;
131    useToBeDeletedAccessibilityState = false;
132    maximumAllowedSubtreeSize = 0;
133    listener = null;
134    operationPurposeRequestControl = null;
135  }
136
137
138
139  /**
140   * Creates a new set of properties that is a copy of the provided properties
141   * object.
142   *
143   * @param  properties  The properties object to use to create the new
144   *                     properties.
145   */
146  public MoveSubtreeProperties(@NotNull final MoveSubtreeProperties properties)
147  {
148    baseDN = properties.baseDN;
149    suppressReferentialIntegrityUpdates =
150         properties.suppressReferentialIntegrityUpdates;
151    useToBeDeletedAccessibilityState =
152         properties.useToBeDeletedAccessibilityState;
153    maximumAllowedSubtreeSize = properties.maximumAllowedSubtreeSize;
154    listener = properties.listener;
155    operationPurposeRequestControl = properties.operationPurposeRequestControl;
156  }
157
158
159
160  /**
161   * Retrieves the base DN of the subtree to move.
162   *
163   * @return  The base DN of the subtree to move.
164   */
165  @NotNull()
166  public DN getBaseDN()
167  {
168    return baseDN;
169  }
170
171
172
173  /**
174   * Specifies the base DN of the subtree to move.
175   *
176   * @param  baseDN  The base DN for the subtree to be moved.  It must not be
177   *                 {@code null}, and it must represent a valid DN with one or
178   *                 more RDN components.
179   *
180   * @throws  LDAPException  If the provided string cannot be parsed as a valid
181   *                         DN.
182   */
183  public void setBaseDN(@NotNull final String baseDN)
184         throws LDAPException
185  {
186    setBaseDN(new DN(baseDN));
187  }
188
189
190
191  /**
192   * Specifies the base DN of the subtree to move.
193   *
194   * @param  baseDN  The base DN for the subtree to be moved.  It must not be
195   *                 {@code null}, and it must have one or more RDN components.
196   */
197  public void setBaseDN(@NotNull final DN baseDN)
198  {
199    Validator.ensureNotNullWithMessage(baseDN,
200         "MoveSubtreeProperties.baseDN must not be null.");
201    Validator.ensureTrue((baseDN.getRDNs().length > 0),
202         "MoveSubtreeProperties.baseDN must include one or more RDN " +
203              "components.");
204
205    this.baseDN = baseDN;
206  }
207
208
209
210  /**
211   * Retrieves the maximum number of entries that the target subtree may contain
212   * for it to be moved from one server to another.
213   *
214   * @return  The maximum number of entries that the target subtree may contain
215   *          for it to be moved from one server to another, or zero if no
216   *          client-side size limit should be enforced (although the server may
217   *          still impose its own size limit).
218   */
219  public int getMaximumAllowedSubtreeSize()
220  {
221    return maximumAllowedSubtreeSize;
222  }
223
224
225
226  /**
227   * Specifies the maximum number of entries that the target subtree may contain
228   * for it to be moved from one server to another.  If the subtree contains
229   * more than the maximum number of entries, then the attempt to move it will
230   * be aborted before any changes are applied to the data in either server.
231   *
232   * @param  sizeLimit  The maximum number of entries tht the target subtree may
233   *                    contain for it to be moved from one server to another.
234   *                    A value that is less than or equal to zero indicates
235   *                    that no client-side size limit should be imposed.  Note
236   *                    that the server may also impose a size limit, and the
237   *                    smaller of the client-side and server-side limits will
238   *                    be in effect.
239   */
240  public void setMaximumAllowedSubtreeSize(final int sizeLimit)
241  {
242    if (sizeLimit > 0)
243    {
244      maximumAllowedSubtreeSize = sizeLimit;
245    }
246    else
247    {
248      maximumAllowedSubtreeSize = 0;
249    }
250  }
251
252
253
254  /**
255   * Indicates whether to use the
256   * {@link SubtreeAccessibilityState#TO_BE_DELETED} subtree accessibility state
257   * (as opposed to the {@code HIDDEN} state) for the target subtree on the
258   * source server before beginning to remove entries from it.
259   *
260   * @return  {@code true} if the {@code TO_BE_DELETED} subtree accessibility
261   *          state should be used, or {@code false} if the {@code HIDDEN} state
262   *          should be used.
263   */
264  public boolean useToBeDeletedAccessibilityState()
265  {
266    return useToBeDeletedAccessibilityState;
267  }
268
269
270
271  /**
272   * Specifies whether to use the
273   * {@link SubtreeAccessibilityState#TO_BE_DELETED} subtree accessibility state
274   * (as opposed to the {@code HIDDEN} state) for the target subtree on the
275   * source server before beginning to remove entries from it.  Both the
276   * {@code TO_BE_DELETED} and {@code HIDDEN} subtree accessibility states will
277   * completely hide the target subtree from all clients expect those
278   * authenticated as a designated bypass-user account, but the key differences
279   * between these states include:
280   * <UL>
281   *   <LI>
282   *     In some cases, the server may be able to process delete requests for
283   *     entries in {@code TO_BE_DELETED} subtrees than for entries in subtrees
284   *     with other accessibility states, including the {@code HIDDEN} state.
285   *   </LI>
286   *   <LI>
287   *     Support for the {@code TO_BE_DELETED} subtree accessibility state was
288   *     added to the Directory Server more recently than support for the
289   *     {@code HIDDEN} state.  Older Directory Server instances may not support
290   *     the {@code TO_BE_DELETED} state.
291   *   </LI>
292   *   <LI>
293   *     A {@code HIDDEN} subtree can be updated to give it a different
294   *     accessibility state, but once a subtree has been placed in a
295   *     {@code TO_BE_DELETED} accessibility state, its state cannot be manually
296   *     updated.
297   *   </LI>
298   *   <LI>
299   *     The {@code TO_BE_DELETED} accessibility state will automatically be
300   *     removed from a subtree once all entries have been removed from that
301   *     subtree, while the {@code HIDDEN} state needs to be manually removed
302   *     if it is no longer desired.
303   *   </LI>
304   * </UL>
305   *
306   * @param  useToBeDeletedState  Indicates whether to use the
307   *                              {@code TO_BE_DELETED} subtree accessibility
308   *                              state instead of the {@code HIDDEN} state for
309   *                              the target subtree on the source server before
310   *                              beginning to remove entries from it.
311   */
312  public void setUseToBeDeletedAccessibilityState(
313                   final boolean useToBeDeletedState)
314  {
315    useToBeDeletedAccessibilityState = useToBeDeletedState;
316  }
317
318
319
320  /**
321   * Indicates whether to suppress referential integrity updates when removing
322   * entries from the source server.
323   *
324   * @return  {@code true} if referential integrity updates should be suppressed
325   *          when removing entries from the source server, or {@code false} if
326   *          not.
327   */
328  public boolean suppressReferentialIntegrityUpdates()
329  {
330    return suppressReferentialIntegrityUpdates;
331  }
332
333
334
335  /**
336   * Specifies whether to suppress referential integrity updates when removing
337   * entries from the source server.  By default, if the referential integrity
338   * plugin is enabled, then removing a user entry will automatically remove
339   * references to it from other entries, including things like static group
340   * membership.  However, when moving entries from one server to another, and
341   * especially in cases where the associated references are in other entries
342   * that are also being moved, it may be desirable to suppress those
343   * referential integrity updates.
344   *
345   * @param  suppressUpdates  Indicates whether to suppress referential
346   *                          integrity updates when removing entries from the
347   *                          source server.
348   */
349  public void setSuppressReferentialIntegrityUpdates(
350                   final boolean suppressUpdates)
351  {
352    suppressReferentialIntegrityUpdates = suppressUpdates;
353  }
354
355
356
357  /**
358   * Retrieves an operation purpose request control that should be included in
359   * all requests sent to the source and target servers, if any.
360   *
361   * @return  An operation purpose request control that should be included in
362   *          all requests sent ot the source and target servers, or
363   *          {@code null} if no operation purpose request control should be
364   *          used.
365   */
366  @Nullable()
367  public OperationPurposeRequestControl getOperationPurposeRequestControl()
368  {
369    return operationPurposeRequestControl;
370  }
371
372
373
374  /**
375   * Specifies an operation purpose request control that should be included in
376   * all requests sent to the source and target servers.
377   *
378   * @param  control  An operation purpose request control that should be
379   *                  included in all requests sent to the source and target
380   *                  servers.  It may be {@code null} if no operation purpose
381   *                  request control should be used.
382   */
383  public void setOperationPurposeRequestControl(
384                   @Nullable final OperationPurposeRequestControl control)
385  {
386    operationPurposeRequestControl = control;
387  }
388
389
390
391
392  /**
393   * Retrieves the listener that may be invoked during the course of moving
394   * entries from the source server to the target server, if any.
395   *
396   * @return  The listener that may be invoked during the course of moving
397   *          entries from the source server to the target server, or
398   *          {@code null} if no move subtree listener has been configured.
399   */
400  @Nullable()
401  public MoveSubtreeListener getMoveSubtreeListener()
402  {
403    return listener;
404  }
405
406
407
408
409  /**
410   * Specifies a listener that may be invoked during the course of moving
411   * entries from the source server to the target server.  The listener will be
412   * invoked before and after adding an entry to the target server, and it will
413   * be invoked before and after removing an entry from the source server.
414   *
415   * @param  listener  A listener that may be invoked during the course of
416   *                   moving entries from the source server to the target
417   *                   server.  It may be {@code null} if no listener is needed.
418   */
419  public void setMoveSubtreeListener(
420                   @Nullable final MoveSubtreeListener listener)
421  {
422    this.listener = listener;
423  }
424
425
426
427  /**
428   * Retrieves a string representation of the properties.
429   *
430   * @return  A string representation of the proprties.
431   */
432  @Override()
433  @NotNull()
434  public String toString()
435  {
436    final StringBuilder buffer = new StringBuilder();
437    toString(buffer);
438    return buffer.toString();
439  }
440
441
442
443  /**
444   * Appends a string representation of the properties to the provided buffer.
445   *
446   * @param  buffer  The buffer to which the information should be appended.  It
447   *                 must not be {@code null}.
448   */
449  public void toString(@NotNull final StringBuilder buffer)
450  {
451    buffer.append("MoveSubtreeProperties(baseDN='");
452    buffer.append(baseDN);
453    buffer.append("', maximumAllowedSubtreeSize=");
454    buffer.append(maximumAllowedSubtreeSize);
455    buffer.append(", useToBeDeletedAccessibilityState=");
456    buffer.append(useToBeDeletedAccessibilityState);
457    buffer.append(", suppressReferentialIntegrityUpdates=");
458    buffer.append(suppressReferentialIntegrityUpdates);
459    buffer.append(", operationPurposeRequestControl=");
460    buffer.append(operationPurposeRequestControl);
461    buffer.append(", moveSubtreeListener=");
462    buffer.append(listener);
463    buffer.append(')');
464  }
465}