001/*
002 * Copyright 2013-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2013-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) 2013-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.controls;
037
038
039
040import java.util.ArrayList;
041import java.util.LinkedHashMap;
042import java.util.List;
043import java.util.Map;
044
045import com.unboundid.asn1.ASN1Boolean;
046import com.unboundid.asn1.ASN1Element;
047import com.unboundid.asn1.ASN1Enumerated;
048import com.unboundid.asn1.ASN1Long;
049import com.unboundid.asn1.ASN1OctetString;
050import com.unboundid.asn1.ASN1Sequence;
051import com.unboundid.ldap.sdk.Control;
052import com.unboundid.ldap.sdk.JSONControlDecodeHelper;
053import com.unboundid.ldap.sdk.LDAPException;
054import com.unboundid.ldap.sdk.ResultCode;
055import com.unboundid.util.Debug;
056import com.unboundid.util.NotMutable;
057import com.unboundid.util.NotNull;
058import com.unboundid.util.Nullable;
059import com.unboundid.util.StaticUtils;
060import com.unboundid.util.ThreadSafety;
061import com.unboundid.util.ThreadSafetyLevel;
062import com.unboundid.util.json.JSONBoolean;
063import com.unboundid.util.json.JSONField;
064import com.unboundid.util.json.JSONNumber;
065import com.unboundid.util.json.JSONObject;
066import com.unboundid.util.json.JSONString;
067import com.unboundid.util.json.JSONValue;
068
069import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
070
071
072
073/**
074 * This class provides an implementation of an LDAP control that can be included
075 * in add, bind, modify, modify DN, and certain extended requests to indicate
076 * the level of replication assurance desired for the associated operation.
077 * <BR>
078 * <BLOCKQUOTE>
079 *   <B>NOTE:</B>  This class, and other classes within the
080 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
081 *   supported for use against Ping Identity, UnboundID, and
082 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
083 *   for proprietary functionality or for external specifications that are not
084 *   considered stable or mature enough to be guaranteed to work in an
085 *   interoperable way with other types of LDAP servers.
086 * </BLOCKQUOTE>
087 * <BR>
088 * The OID for this control is 1.3.6.1.4.1.30221.2.5.28, and it may have a
089 * criticality of either TRUE or FALSE.  It must have a value with the following
090 * encoding:
091 * <PRE>
092 *   AssuredReplicationRequest ::= SEQUENCE {
093 *        minimumLocalLevel           [0] LocalLevel OPTIONAL,
094 *        maximumLocalLevel           [1] LocalLevel OPTIONAL,
095 *        minimumRemoteLevel          [2] RemoteLevel OPTIONAL,
096 *        maximumRemoteLevel          [3] RemoteLevel OPTIONAL,
097 *        timeoutMillis               [4] INTEGER (1 .. 2147483647) OPTIONAL,
098 *        sendResponseImmediately     [5] BOOLEAN DEFAULT FALSE,
099 *        ... }
100 *
101 *   LocalLevel ::= ENUMERATED {
102 *        none                    (0),
103 *        receivedAnyServer       (1),
104 *        processedAllServers     (2),
105 *        ... }
106 *
107 *   RemoteLevel ::= ENUMERATED {
108 *        none                           (0),
109 *        receivedAnyRemoteLocation      (1),
110 *        receivedAllRemoteLocations     (2),
111 *        processedAllRemoteServers      (3),
112 *        ... }
113 * </PRE>
114 * <BR><BR>
115 * <H2>Example</H2>
116 * The following example demonstrates the use of the assured replication request
117 * control in conjunction with a delete operation to request that the server not
118 * return the delete result to the client until the delete has been applied to
119 * all available servers in the local data center and has also been replicated
120 * to at least one remote data center:
121 * <PRE>
122 * DeleteRequest deleteRequest = new DeleteRequest(
123 *      "uid=test.user,ou=People,dc=example,dc=com");
124 * deleteRequest.addControl(new AssuredReplicationRequestControl(
125 *      AssuredReplicationLocalLevel.PROCESSED_ALL_SERVERS,
126 *      AssuredReplicationRemoteLevel.RECEIVED_ANY_REMOTE_LOCATION,
127 *      5000L));
128 *  LDAPResult deleteResult = connection.delete(deleteRequest);
129 *
130 * if (deleteResult.getResultCode() == ResultCode.SUCCESS)
131 * {
132 *   AssuredReplicationResponseControl assuredReplicationResponse =
133 *        AssuredReplicationResponseControl.get(deleteResult);
134 *   if (assuredReplicationResponse == null)
135 *   {
136 *     // The entry was deleted, but its replication could not be confirmed in
137 *     // either the local or remote data centers.
138 *   }
139 *   else
140 *   {
141 *     if (assuredReplicationResponse.localAssuranceSatisfied())
142 *     {
143 *       if (assuredReplicationResponse.remoteAssuranceSatisfied())
144 *       {
145 *         // The entry was deleted.  The delete has been applied across all
146 *         // available local servers, and has been replicated to at least one
147 *         // remote data center.
148 *       }
149 *       else
150 *       {
151 *         // The entry was deleted.  The delete has been applied across all
152 *         // available local servers, but cannot be confirmed to have yet
153 *         // been replicated to any remote data centers.
154 *       }
155 *     }
156 *     else if (assuredReplicationResponse.remoteAssuranceSatisfied())
157 *     {
158 *       // The entry was deleted.  The delete has been confirmed to have been
159 *       // replicated to at least one remote data center, but cannot be
160 *       // confirmed to have yet been applied to all available local servers.
161 *     }
162 *     else
163 *     {
164 *       // The entry was deleted, but its replication could not be confirmed
165 *       // to either local servers or remote data centers.
166 *     }
167 *   }
168 * }
169 * else
170 * {
171 *   // The entry could not be deleted.
172 * }
173 * </PRE>
174 *
175 * @see  AssuredReplicationResponseControl
176 */
177@NotMutable()
178@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
179public final class AssuredReplicationRequestControl
180       extends Control
181{
182  /**
183   * The OID (1.3.6.1.4.1.30221.2.5.28) for the assured replication request
184   * control.
185   */
186  @NotNull public static final String ASSURED_REPLICATION_REQUEST_OID =
187       "1.3.6.1.4.1.30221.2.5.28";
188
189
190  /**
191   * The BER type for the minimum local assurance level.
192   */
193  private static final byte TYPE_MIN_LOCAL_LEVEL = (byte) 0x80;
194
195
196  /**
197   * The BER type for the maximum local assurance level.
198   */
199  private static final byte TYPE_MAX_LOCAL_LEVEL = (byte) 0x81;
200
201
202  /**
203   * The BER type for the minimum remote assurance level.
204   */
205  private static final byte TYPE_MIN_REMOTE_LEVEL = (byte) 0x82;
206
207
208  /**
209   * The BER type for the maximum remote assurance level.
210   */
211  private static final byte TYPE_MAX_REMOTE_LEVEL = (byte) 0x83;
212
213
214  /**
215   * The BER type for the maximum remote assurance level.
216   */
217  private static final byte TYPE_SEND_RESPONSE_IMMEDIATELY = (byte) 0x84;
218
219
220  /**
221   * The BER type for the timeout.
222   */
223  private static final byte TYPE_TIMEOUT = (byte) 0x85;
224
225
226
227  /**
228   * The name of the field used to specify the maximum replication assurance
229   * level in the JSON representation of this control.
230   */
231  @NotNull private static final String JSON_FIELD_MAXIMUM_LOCAL_LEVEL =
232       "maximum-local-level";
233
234
235
236  /**
237   * The name of the field used to specify the maximum remote assurance
238   * level in the JSON representation of this control.
239   */
240  @NotNull private static final String JSON_FIELD_MAXIMUM_REMOTE_LEVEL =
241       "maximum-remote-level";
242
243
244
245  /**
246   * The name of the field used to specify the minimum replication assurance
247   * level in the JSON representation of this control.
248   */
249  @NotNull private static final String JSON_FIELD_MINIMUM_LOCAL_LEVEL =
250       "minimum-local-level";
251
252
253
254  /**
255   * The name of the field used to specify the minimum remote assurance
256   * level in the JSON representation of this control.
257   */
258  @NotNull private static final String JSON_FIELD_MINIMUM_REMOTE_LEVEL =
259       "minimum-remote-level";
260
261
262
263  /**
264   * The name of the field used to indicate whether to send the operation
265   * response immediately in the JSON representation of this control.
266   */
267  @NotNull private static final String JSON_FIELD_SEND_RESPONSE_IMMEDIATELY =
268       "send-response-immediately";
269
270
271
272  /**
273   * The name of the field used to specify the assurance timeout in the JSON
274   * representation of this control.
275   */
276  @NotNull private static final String JSON_FIELD_TIMEOUT_MILLIS =
277       "timeout-millis";
278
279
280
281  /**
282   * The serial version UID for this serializable class.
283   */
284  private static final long serialVersionUID = -2013933506118879241L;
285
286
287
288  // The requested maximum local assurance level.
289  @Nullable private final AssuredReplicationLocalLevel maximumLocalLevel;
290
291  // The requested minimum local assurance level.
292  @Nullable private final AssuredReplicationLocalLevel minimumLocalLevel;
293
294  // The requested maximum remote assurance level.
295  @Nullable private final AssuredReplicationRemoteLevel maximumRemoteLevel;
296
297  // The requested minimum remote assurance level.
298  @Nullable private final AssuredReplicationRemoteLevel minimumRemoteLevel;
299
300  // Indicates whether the server should immediately send the operation response
301  // without waiting for assurance processing.
302  private final boolean sendResponseImmediately;
303
304  // The maximum length of time in milliseconds that the server should wait for
305  // the desired assurance level to be attained.
306  @Nullable private final Long timeoutMillis;
307
308
309
310  /**
311   * Creates a new assured replication request control with the provided
312   * information.  It will not be critical.
313   *
314   * @param  minimumLocalLevel   The minimum replication assurance level desired
315   *                             for servers in the same location as the server
316   *                             receiving the change.  This may be overridden
317   *                             by the server if the associated operation
318   *                             matches an assured replication criteria with a
319   *                             higher local assurance level.  If this is
320   *                             {@code null}, then the server will determine
321   *                             minimum local assurance level for the
322   *                             operation.
323   * @param  minimumRemoteLevel  The minimum replication assurance level desired
324   *                             for servers in different locations from the
325   *                             server receiving the change.  This may be
326   *                             overridden by the server if the associated
327   *                             operation matches an assured replication
328   *                             criteria with a higher remote assurance level.
329   *                             If this is {@code null}, then the server will
330   *                             determine the remote assurance level for the
331   *                             operation.
332   * @param  timeoutMillis       The maximum length of time in milliseconds to
333   *                             wait for the desired assurance to be satisfied.
334   *                             If this is {@code null}, then the server will
335   *                             determine the timeout to use.
336   */
337  public AssuredReplicationRequestControl(
338       @Nullable final AssuredReplicationLocalLevel minimumLocalLevel,
339       @Nullable final AssuredReplicationRemoteLevel minimumRemoteLevel,
340       @Nullable final Long timeoutMillis)
341  {
342    this(false, minimumLocalLevel, null, minimumRemoteLevel, null,
343         timeoutMillis, false);
344  }
345
346
347
348  /**
349   * Creates a new assured replication request control with the provided
350   * information.
351   *
352   * @param  isCritical               Indicates whether the control should be
353   *                                  marked critical.
354   * @param  minimumLocalLevel        The minimum replication assurance level
355   *                                  desired for servers in the same location
356   *                                  as the server receiving the change.  This
357   *                                  may be overridden by the server if the
358   *                                  associated operation matches an assured
359   *                                  replication criteria with a higher local
360   *                                  assurance level.  If this is {@code null},
361   *                                  then the server will determine the minimum
362   *                                  local assurance level for the operation.
363   * @param  maximumLocalLevel        The maximum replication assurance level
364   *                                  desired for servers in the same location
365   *                                  as the server receiving the change.  This
366   *                                  may override the server configuration if
367   *                                  the operation matches an assured
368   *                                  replication criteria that would have
369   *                                  otherwise used a higher local assurance
370   *                                  level.  If this is {@code null}, then the
371   *                                  server will determine the maximum local
372   *                                  assurance level for the operation.
373   * @param  minimumRemoteLevel       The minimum replication assurance level
374   *                                  desired for servers in different locations
375   *                                  from the server receiving the change.
376   *                                  This may be overridden by the server if
377   *                                  the associated operation matches an
378   *                                  assured replication criteria with a higher
379   *                                  remote assurance level.  If this is
380   *                                  {@code null}, then the server will
381   *                                  determine the minimum remote assurance
382   *                                  level for the operation.
383   * @param  maximumRemoteLevel       The maximum replication assurance level
384   *                                  desired for servers in different locations
385   *                                  from the server receiving the change.
386   *                                  This may override the server configuration
387   *                                  if the operation matches an assured
388   *                                  replication criteria that would have
389   *                                  otherwise used a higher remote assurance
390   *                                  level.  If this is {@code null}, then the
391   *                                  server will determine the maximum remote
392   *                                  assurance level for the operation.
393   * @param  timeoutMillis            The maximum length of time in milliseconds
394   *                                  to wait for the desired assurance to be
395   *                                  satisfied.  If this is {@code null}, then
396   *                                  the server will determine the timeout to
397   *                                  use.
398   * @param  sendResponseImmediately  Indicates whether the server should
399   *              send the response to the client immediately after the change
400   *              has been applied to the server receiving the change, without
401   *              waiting for the desired assurance to be satisfied.
402   */
403  public AssuredReplicationRequestControl(final boolean isCritical,
404              @Nullable final AssuredReplicationLocalLevel minimumLocalLevel,
405              @Nullable final AssuredReplicationLocalLevel maximumLocalLevel,
406              @Nullable final AssuredReplicationRemoteLevel minimumRemoteLevel,
407              @Nullable final AssuredReplicationRemoteLevel maximumRemoteLevel,
408              @Nullable final Long timeoutMillis,
409              final boolean sendResponseImmediately)
410  {
411    super(ASSURED_REPLICATION_REQUEST_OID, isCritical,
412         encodeValue(minimumLocalLevel, maximumLocalLevel, minimumRemoteLevel,
413              maximumRemoteLevel, sendResponseImmediately, timeoutMillis));
414
415    this.minimumLocalLevel       = minimumLocalLevel;
416    this.maximumLocalLevel       = maximumLocalLevel;
417    this.minimumRemoteLevel      = minimumRemoteLevel;
418    this.maximumRemoteLevel      = maximumRemoteLevel;
419    this.sendResponseImmediately = sendResponseImmediately;
420    this.timeoutMillis           = timeoutMillis;
421  }
422
423
424
425  /**
426   * Creates a new assured replication request control from the provided generic
427   * control.
428   *
429   * @param  c  The generic control to decode as an assured replication request
430   *            control.  It must not be {@code null}.
431   *
432   * @throws  LDAPException  If the provided generic control cannot be parsed as
433   *                         an assured replication request control.
434   */
435  public AssuredReplicationRequestControl(@NotNull final Control c)
436         throws LDAPException
437  {
438    super(c);
439
440    final ASN1OctetString value = c.getValue();
441    if (value == null)
442    {
443      throw new LDAPException(ResultCode.DECODING_ERROR,
444           ERR_ASSURED_REPLICATION_REQUEST_NO_VALUE.get());
445    }
446
447    AssuredReplicationLocalLevel  maxLocalLevel   = null;
448    AssuredReplicationLocalLevel  minLocalLevel   = null;
449    AssuredReplicationRemoteLevel maxRemoteLevel  = null;
450    AssuredReplicationRemoteLevel minRemoteLevel  = null;
451    boolean                       sendImmediately = false;
452    Long                          timeout         = null;
453
454    try
455    {
456      for (final ASN1Element e :
457           ASN1Sequence.decodeAsSequence(value.getValue()).elements())
458      {
459        switch (e.getType())
460        {
461          case TYPE_MIN_LOCAL_LEVEL:
462            int intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue();
463            minLocalLevel = AssuredReplicationLocalLevel.valueOf(intValue);
464            if (minLocalLevel == null)
465            {
466              throw new LDAPException(ResultCode.DECODING_ERROR,
467                   ERR_ASSURED_REPLICATION_REQUEST_INVALID_MIN_LOCAL_LEVEL.get(
468                        intValue));
469            }
470            break;
471
472          case TYPE_MAX_LOCAL_LEVEL:
473            intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue();
474            maxLocalLevel = AssuredReplicationLocalLevel.valueOf(intValue);
475            if (maxLocalLevel == null)
476            {
477              throw new LDAPException(ResultCode.DECODING_ERROR,
478                   ERR_ASSURED_REPLICATION_REQUEST_INVALID_MAX_LOCAL_LEVEL.get(
479                        intValue));
480            }
481            break;
482
483          case TYPE_MIN_REMOTE_LEVEL:
484            intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue();
485            minRemoteLevel = AssuredReplicationRemoteLevel.valueOf(intValue);
486            if (minRemoteLevel == null)
487            {
488              throw new LDAPException(ResultCode.DECODING_ERROR,
489                   ERR_ASSURED_REPLICATION_REQUEST_INVALID_MIN_REMOTE_LEVEL.get(
490                        intValue));
491            }
492            break;
493
494          case TYPE_MAX_REMOTE_LEVEL:
495            intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue();
496            maxRemoteLevel = AssuredReplicationRemoteLevel.valueOf(intValue);
497            if (maxRemoteLevel == null)
498            {
499              throw new LDAPException(ResultCode.DECODING_ERROR,
500                   ERR_ASSURED_REPLICATION_REQUEST_INVALID_MAX_REMOTE_LEVEL.get(
501                        intValue));
502            }
503            break;
504
505          case TYPE_SEND_RESPONSE_IMMEDIATELY:
506            sendImmediately = ASN1Boolean.decodeAsBoolean(e).booleanValue();
507            break;
508
509          case TYPE_TIMEOUT:
510            timeout = ASN1Long.decodeAsLong(e).longValue();
511            break;
512
513          default:
514            throw new LDAPException(ResultCode.DECODING_ERROR,
515                 ERR_ASSURED_REPLICATION_REQUEST_UNEXPECTED_ELEMENT_TYPE.get(
516                      StaticUtils.toHex(e.getType())));
517        }
518      }
519    }
520    catch (final LDAPException le)
521    {
522      Debug.debugException(le);
523      throw le;
524    }
525    catch (final Exception e)
526    {
527      Debug.debugException(e);
528      throw new LDAPException(ResultCode.DECODING_ERROR,
529           ERR_ASSURED_REPLICATION_REQUEST_ERROR_DECODING_VALUE.get(
530                StaticUtils.getExceptionMessage(e)),
531           e);
532    }
533
534    minimumLocalLevel       = minLocalLevel;
535    maximumLocalLevel       = maxLocalLevel;
536    minimumRemoteLevel      = minRemoteLevel;
537    maximumRemoteLevel      = maxRemoteLevel;
538    sendResponseImmediately = sendImmediately;
539    timeoutMillis           = timeout;
540  }
541
542
543
544  /**
545   * Encodes the provided information as needed for use as the value of this
546   * control.
547   *
548   * @param  minimumLocalLevel        The minimum replication assurance level
549   *                                  desired for servers in the same location
550   *                                  as the server receiving the change.  This
551   *                                  may be overridden by the server if the
552   *                                  associated operation matches an assured
553   *                                  replication criteria with a higher local
554   *                                  assurance level.  If this is {@code null},
555   *                                  then the server will determine the minimum
556   *                                  local assurance level for the operation.
557   * @param  maximumLocalLevel        The maximum replication assurance level
558   *                                  desired for servers in the same location
559   *                                  as the server receiving the change.  This
560   *                                  may override the server configuration if
561   *                                  the operation matches an assured
562   *                                  replication criteria that would have
563   *                                  otherwise used a higher local assurance
564   *                                  level.  If this is {@code null}, then the
565   *                                  server will determine the maximum local
566   *                                  assurance level for the operation.
567   * @param  minimumRemoteLevel       The minimum replication assurance level
568   *                                  desired for servers in different locations
569   *                                  from the server receiving the change.
570   *                                  This may be overridden by the server if
571   *                                  the associated operation matches an
572   *                                  assured replication criteria with a higher
573   *                                  remote assurance level.  If this is
574   *                                  {@code null}, then the server will
575   *                                  determine the minimum remote assurance
576   *                                  level for the operation.
577   * @param  maximumRemoteLevel       The maximum replication assurance level
578   *                                  desired for servers in different locations
579   *                                  from the server receiving the change.
580   *                                  This may override the server configuration
581   *                                  if the operation matches an assured
582   *                                  replication criteria that would have
583   *                                  otherwise used a higher remote assurance
584   *                                  level.  If this is {@code null}, then the
585   *                                  server will determine the maximum remote
586   *                                  assurance level for the operation.
587   * @param  timeoutMillis            The maximum length of time in milliseconds
588   *                                  to wait for the desired assurance to be
589   *                                  satisfied.  If this is {@code null}, then
590   *                                  the server will determine the timeout to
591   *                                  use.
592   * @param  sendResponseImmediately  Indicates whether the server should
593   *              send the response to the client immediately after the change
594   *              has been applied to the server receiving the change, without
595   *              waiting for the desired assurance to be satisfied.
596   *
597   * @return  The ASN.1 octet string containing the encoded value.
598   */
599  @NotNull()
600  private static ASN1OctetString encodeValue(
601               @Nullable final AssuredReplicationLocalLevel minimumLocalLevel,
602               @Nullable final AssuredReplicationLocalLevel maximumLocalLevel,
603               @Nullable final AssuredReplicationRemoteLevel minimumRemoteLevel,
604               @Nullable final AssuredReplicationRemoteLevel maximumRemoteLevel,
605               final boolean sendResponseImmediately,
606               @Nullable final Long timeoutMillis)
607  {
608    final ArrayList<ASN1Element> elements = new ArrayList<>(6);
609
610    if (minimumLocalLevel != null)
611    {
612      elements.add(new ASN1Enumerated(TYPE_MIN_LOCAL_LEVEL,
613           minimumLocalLevel.intValue()));
614    }
615
616    if (maximumLocalLevel != null)
617    {
618      elements.add(new ASN1Enumerated(TYPE_MAX_LOCAL_LEVEL,
619           maximumLocalLevel.intValue()));
620    }
621
622    if (minimumRemoteLevel != null)
623    {
624      elements.add(new ASN1Enumerated(TYPE_MIN_REMOTE_LEVEL,
625           minimumRemoteLevel.intValue()));
626    }
627
628    if (maximumRemoteLevel != null)
629    {
630      elements.add(new ASN1Enumerated(TYPE_MAX_REMOTE_LEVEL,
631           maximumRemoteLevel.intValue()));
632    }
633
634    if (sendResponseImmediately)
635    {
636      elements.add(new ASN1Boolean(TYPE_SEND_RESPONSE_IMMEDIATELY, true));
637    }
638
639    if (timeoutMillis != null)
640    {
641      elements.add(new ASN1Long(TYPE_TIMEOUT, timeoutMillis));
642    }
643
644    return new ASN1OctetString(new ASN1Sequence(elements).encode());
645  }
646
647
648
649  /**
650   * Retrieves the minimum desired replication level of assurance for local
651   * servers (i.e., servers in the same location as the server that originally
652   * received the change), if defined.  This may be overridden by the server if
653   * the associated operation matches an assured replication criteria with a
654   * higher local assurance level.
655   *
656   * @return  The minimum desired replication level of assurance for local
657   *          servers, or {@code null} if the server should determine the
658   *          minimum local assurance level for the operation.
659   */
660  @Nullable()
661  public AssuredReplicationLocalLevel getMinimumLocalLevel()
662  {
663    return minimumLocalLevel;
664  }
665
666
667
668  /**
669   * Retrieves the maximum desired replication level of assurance for local
670   * servers (i.e., servers in the same location as the server that originally
671   * received the change), if defined.  This may override the server
672   * configuration if the operation matches an assured replication criteria that
673   * would have otherwise used a higher local assurance level.
674   *
675   * @return  The maximum desired replication level of assurance for local
676   *          servers, or {@code null} if the server should determine the
677   *          maximum local assurance level for the operation.
678   */
679  @Nullable()
680  public AssuredReplicationLocalLevel getMaximumLocalLevel()
681  {
682    return maximumLocalLevel;
683  }
684
685
686
687  /**
688   * Retrieves the minimum desired replication level of assurance for remote
689   * servers (i.e., servers in locations different from the server that
690   * originally received the change), if defined.  This may be overridden by the
691   * server if the associated operation matches an assured replication
692   * criteria with a higher remote assurance level.
693   *
694   * @return  The minimum desired replication level of assurance for remote
695   *          servers, or {@code null} if the server should determine the
696   *          minimum remote assurance level for the operation.
697   */
698  @Nullable()
699  public AssuredReplicationRemoteLevel getMinimumRemoteLevel()
700  {
701    return minimumRemoteLevel;
702  }
703
704
705
706  /**
707   * Retrieves the maximum desired replication level of assurance for remote
708   * servers (i.e., servers in locations different from the server that
709   * originally received the change), if defined.  This may override the server
710   * configuration if the operation matches an assured replication criteria that
711   * would have otherwise used a higher remote assurance level.
712   *
713   * @return  The maximum desired replication level of assurance for remote
714   *          servers, or {@code null} if the server should determine the
715   *          maximum remote assurance level for the operation.
716   */
717  @Nullable()
718  public AssuredReplicationRemoteLevel getMaximumRemoteLevel()
719  {
720    return maximumRemoteLevel;
721  }
722
723
724
725  /**
726   * Indicates whether the server that originally received the change should
727   * return the operation result immediately, without waiting for the requested
728   * assurance processing to complete.
729   *
730   * @return  {@code false} if the server should wait to return the operation
731   *          result until the desired assurance has been attained or a timeout
732   *          has occurred, or {@code true} if the server should return the
733   *          result immediately.
734   */
735  public boolean sendResponseImmediately()
736  {
737    return sendResponseImmediately;
738  }
739
740
741
742  /**
743   * Retrieves the maximum length of time in milliseconds that the operation
744   * response should be delayed while waiting for the desired level of
745   * assurance to be attained.
746   *
747   * @return  The maximum length of time in milliseconds that the operation
748   *          response should be delayed while waiting for the desired level of
749   *          assurance to be attained.
750   */
751  @Nullable()
752  public Long getTimeoutMillis()
753  {
754    return timeoutMillis;
755  }
756
757
758
759  /**
760   * {@inheritDoc}
761   */
762  @Override()
763  @NotNull()
764  public String getControlName()
765  {
766    return INFO_CONTROL_NAME_ASSURED_REPLICATION_REQUEST.get();
767  }
768
769
770
771  /**
772   * Retrieves a representation of this assured replication request control as a
773   * JSON object.  The JSON object uses the following fields:
774   * <UL>
775   *   <LI>
776   *     {@code oid} -- A mandatory string field whose value is the object
777   *     identifier for this control.  For the assured replication request
778   *     control, the OID is "1.3.6.1.4.1.30221.2.5.28".
779   *   </LI>
780   *   <LI>
781   *     {@code control-name} -- An optional string field whose value is a
782   *     human-readable name for this control.  This field is only intended for
783   *     descriptive purposes, and when decoding a control, the {@code oid}
784   *     field should be used to identify the type of control.
785   *   </LI>
786   *   <LI>
787   *     {@code criticality} -- A mandatory Boolean field used to indicate
788   *     whether this control is considered critical.
789   *   </LI>
790   *   <LI>
791   *     {@code value-base64} -- An optional string field whose value is a
792   *     base64-encoded representation of the raw value for this assured
793   *     replication request control.  Exactly one of the {@code value-base64}
794   *     and {@code value-json} fields must be present.
795   *   </LI>
796   *   <LI>
797   *     {@code value-json} -- An optional JSON object field whose value is a
798   *     user-friendly representation of the value for this assured replication
799   *     request control.  Exactly one of the {@code value-base64} and
800   *     {@code value-json} fields must be present, and if the
801   *     {@code value-json} field is used, then it will use the following
802   *     fields:
803   *     <UL>
804   *       <LI>
805   *         {@code minimum-local-level} -- An optional string field whose
806   *         value is the name of the minimum assurance level desired for
807   *         replicas in the same location as the target server.  The value may
808   *         be one of "{@code none}", "{@code received-any-server}", or
809   *         "{@code processed-all-servers}".
810   *       </LI>
811   *       <LI>
812   *         {@code maximum-local-level} -- An optional string field whose
813   *         value is the name of the maximum assurance level desired for
814   *         replicas in the same location as the target server.  The value may
815   *         be one of "{@code none}", "{@code received-any-server}", or
816   *         "{@code processed-all-servers}".
817   *       </LI>
818   *       <LI>
819   *         {@code minimum-remote-level} -- An optional string field whose
820   *         value is the name of the minimum assurance level desired for
821   *         replicas in a different location from the target server.  The value
822   *         may be one of "{@code none}",
823   *         "{@code received-any-remote-location}",
824   *         "{@code received-all-remote-locations}", or
825   *         "{@code processed-all-remote-servers}".
826   *       </LI>
827   *       <LI>
828   *         {@code maximum-remote-level} -- An optional string field whose
829   *         value is the name of the maximum assurance level desired for
830   *         replicas in a different location from the target server.  The value
831   *         may be one of "{@code none}",
832   *         "{@code received-any-remote-location}",
833   *         "{@code received-all-remote-locations}", or
834   *         "{@code processed-all-remote-servers}".
835   *       </LI>
836   *       <LI>
837   *         {@code timeout-millis} -- An optional integer field whose value is
838   *         the maximum length of time in milliseconds that the server should
839   *         wait for assurance to be satisfied.
840   *       </LI>
841   *       <LI>
842   *         {@code send-response-immediately} -- A mandatory Boolean field that
843   *         indicates whether the server should return the response to the
844   *         client immediately after applying the change locally, even if it
845   *         has not yet been replicated.
846   *       </LI>
847   *     </UL>
848   *   </LI>
849   * </UL>
850   *
851   * @return  A JSON object that contains a representation of this control.
852   */
853  @Override()
854  @NotNull()
855  public JSONObject toJSONControl()
856  {
857    final Map<String,JSONValue> jsonValueFields = new LinkedHashMap<>();
858
859    if (minimumLocalLevel != null)
860    {
861      jsonValueFields.put(JSON_FIELD_MINIMUM_LOCAL_LEVEL,
862           new JSONString(minimumLocalLevel.getName()));
863    }
864
865    if (maximumLocalLevel != null)
866    {
867      jsonValueFields.put(JSON_FIELD_MAXIMUM_LOCAL_LEVEL,
868           new JSONString(maximumLocalLevel.getName()));
869    }
870
871    if (minimumRemoteLevel != null)
872    {
873      jsonValueFields.put(JSON_FIELD_MINIMUM_REMOTE_LEVEL,
874           new JSONString(minimumRemoteLevel.getName()));
875    }
876
877    if (maximumRemoteLevel != null)
878    {
879      jsonValueFields.put(JSON_FIELD_MAXIMUM_REMOTE_LEVEL,
880           new JSONString(maximumRemoteLevel.getName()));
881    }
882
883    if (timeoutMillis != null)
884    {
885      jsonValueFields.put(JSON_FIELD_TIMEOUT_MILLIS,
886           new JSONNumber(timeoutMillis));
887    }
888
889    jsonValueFields.put(JSON_FIELD_SEND_RESPONSE_IMMEDIATELY,
890         new JSONBoolean(sendResponseImmediately));
891
892    return new JSONObject(
893         new JSONField(JSONControlDecodeHelper.JSON_FIELD_OID,
894              ASSURED_REPLICATION_REQUEST_OID),
895         new JSONField(JSONControlDecodeHelper.JSON_FIELD_CONTROL_NAME,
896              INFO_CONTROL_NAME_ASSURED_REPLICATION_REQUEST.get()),
897         new JSONField(JSONControlDecodeHelper.JSON_FIELD_CRITICALITY,
898              isCritical()),
899         new JSONField(JSONControlDecodeHelper.JSON_FIELD_VALUE_JSON,
900              new JSONObject(jsonValueFields)));
901  }
902
903
904
905  /**
906   * Attempts to decode the provided object as a JSON representation of an
907   * assured replication request control.
908   *
909   * @param  controlObject  The JSON object to be decoded.  It must not be
910   *                        {@code null}.
911   * @param  strict         Indicates whether to use strict mode when decoding
912   *                        the provided JSON object.  If this is {@code true},
913   *                        then this method will throw an exception if the
914   *                        provided JSON object contains any unrecognized
915   *                        fields.  If this is {@code false}, then unrecognized
916   *                        fields will be ignored.
917   *
918   * @return  The assured replication control that was decoded from the provided
919   *          JSON object.
920   *
921   * @throws  LDAPException  If the provided JSON object cannot be parsed as a
922   *                         valid assured replication request control.
923   */
924  @NotNull()
925  public static AssuredReplicationRequestControl decodeJSONControl(
926              @NotNull final JSONObject controlObject,
927              final boolean strict)
928         throws LDAPException
929  {
930    final JSONControlDecodeHelper jsonControl = new JSONControlDecodeHelper(
931         controlObject, strict, true, true);
932
933    final ASN1OctetString rawValue = jsonControl.getRawValue();
934    if (rawValue != null)
935    {
936      return new AssuredReplicationRequestControl(new Control(
937           jsonControl.getOID(), jsonControl.getCriticality(), rawValue));
938    }
939
940
941    AssuredReplicationLocalLevel minimumLocalLevel = null;
942    AssuredReplicationLocalLevel maximumLocalLevel = null;
943    AssuredReplicationRemoteLevel minimumRemoteLevel = null;
944    AssuredReplicationRemoteLevel maximumRemoteLevel = null;
945    Long timeoutMillis = null;
946    Boolean sendImmediately = null;
947    final JSONObject valueObject = jsonControl.getValueObject();
948
949    final String minLocalLevelStr =
950         valueObject.getFieldAsString(JSON_FIELD_MINIMUM_LOCAL_LEVEL);
951    if (minLocalLevelStr != null)
952    {
953      minimumLocalLevel =
954           AssuredReplicationLocalLevel.forName(minLocalLevelStr);
955      if (minimumLocalLevel == null)
956      {
957        throw new LDAPException(ResultCode.DECODING_ERROR,
958             ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MIN_LOCAL_LEVEL.get(
959                  controlObject.toSingleLineString(),
960                  minLocalLevelStr));
961      }
962    }
963
964    final String maxLocalLevelStr =
965         valueObject.getFieldAsString(JSON_FIELD_MAXIMUM_LOCAL_LEVEL);
966    if (maxLocalLevelStr != null)
967    {
968      maximumLocalLevel =
969           AssuredReplicationLocalLevel.forName(maxLocalLevelStr);
970      if (maximumLocalLevel == null)
971      {
972        throw new LDAPException(ResultCode.DECODING_ERROR,
973             ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MAX_LOCAL_LEVEL.get(
974                  controlObject.toSingleLineString(),
975                  maxLocalLevelStr));
976      }
977    }
978
979    final String minRemoteLevelStr =
980         valueObject.getFieldAsString(JSON_FIELD_MINIMUM_REMOTE_LEVEL);
981    if (minRemoteLevelStr != null)
982    {
983      minimumRemoteLevel =
984           AssuredReplicationRemoteLevel.forName(minRemoteLevelStr);
985      if (minimumRemoteLevel == null)
986      {
987        throw new LDAPException(ResultCode.DECODING_ERROR,
988             ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MIN_REMOTE_LEVEL.get(
989                  controlObject.toSingleLineString(),
990                  minRemoteLevelStr));
991      }
992    }
993
994    final String maxRemoteLevelStr =
995         valueObject.getFieldAsString(JSON_FIELD_MAXIMUM_REMOTE_LEVEL);
996    if (maxRemoteLevelStr != null)
997    {
998      maximumRemoteLevel =
999           AssuredReplicationRemoteLevel.forName(maxRemoteLevelStr);
1000      if (maximumRemoteLevel == null)
1001      {
1002        throw new LDAPException(ResultCode.DECODING_ERROR,
1003             ERR_ASSURED_REPLICATION_REQUEST_JSON_INVALID_MAX_REMOTE_LEVEL.get(
1004                  controlObject.toSingleLineString(),
1005                  maxRemoteLevelStr));
1006      }
1007    }
1008
1009    timeoutMillis = valueObject.getFieldAsLong(JSON_FIELD_TIMEOUT_MILLIS);
1010
1011    sendImmediately =
1012         valueObject.getFieldAsBoolean(JSON_FIELD_SEND_RESPONSE_IMMEDIATELY);
1013    if (sendImmediately == null)
1014    {
1015      throw new LDAPException(ResultCode.DECODING_ERROR,
1016           ERR_ASSURED_REPLICATION_REQUEST_JSON_MISSING_FIELD.get(
1017                controlObject.toSingleLineString(),
1018                JSON_FIELD_SEND_RESPONSE_IMMEDIATELY));
1019    }
1020
1021
1022    if (strict)
1023    {
1024      final List<String> unrecognizedFields =
1025           JSONControlDecodeHelper.getControlObjectUnexpectedFields(
1026                valueObject, JSON_FIELD_MINIMUM_LOCAL_LEVEL,
1027                JSON_FIELD_MAXIMUM_LOCAL_LEVEL, JSON_FIELD_MINIMUM_REMOTE_LEVEL,
1028                JSON_FIELD_MAXIMUM_REMOTE_LEVEL, JSON_FIELD_TIMEOUT_MILLIS,
1029                JSON_FIELD_SEND_RESPONSE_IMMEDIATELY);
1030      if (! unrecognizedFields.isEmpty())
1031      {
1032        throw new LDAPException(ResultCode.DECODING_ERROR,
1033             ERR_ASSURED_REPLICATION_REQUEST_JSON_CONTROL_UNRECOGNIZED_FIELD
1034                  .get(controlObject.toSingleLineString(),
1035                       unrecognizedFields.get(0)));
1036      }
1037    }
1038
1039
1040    return new AssuredReplicationRequestControl(jsonControl.getCriticality(),
1041         minimumLocalLevel, maximumLocalLevel, minimumRemoteLevel,
1042         maximumRemoteLevel, timeoutMillis, sendImmediately);
1043  }
1044
1045
1046
1047  /**
1048   * {@inheritDoc}
1049   */
1050  @Override()
1051  public void toString(@NotNull final StringBuilder buffer)
1052  {
1053    buffer.append("AssuredReplicationRequestControl(isCritical=");
1054    buffer.append(isCritical());
1055
1056    if (minimumLocalLevel != null)
1057    {
1058      buffer.append(", minimumLocalLevel=");
1059      buffer.append(minimumLocalLevel.name());
1060    }
1061
1062    if (maximumLocalLevel != null)
1063    {
1064      buffer.append(", maximumLocalLevel=");
1065      buffer.append(maximumLocalLevel.name());
1066    }
1067
1068    if (minimumRemoteLevel != null)
1069    {
1070      buffer.append(", minimumRemoteLevel=");
1071      buffer.append(minimumRemoteLevel.name());
1072    }
1073
1074    if (maximumRemoteLevel != null)
1075    {
1076      buffer.append(", maximumRemoteLevel=");
1077      buffer.append(maximumRemoteLevel.name());
1078    }
1079
1080    buffer.append(", sendResponseImmediately=");
1081    buffer.append(sendResponseImmediately);
1082
1083    if (timeoutMillis != null)
1084    {
1085      buffer.append(", timeoutMillis=");
1086      buffer.append(timeoutMillis);
1087    }
1088
1089    buffer.append(')');
1090  }
1091}