text: /* Copyright 2013-present MongoDB Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
  
  using System;
  using System.Threading;
  using System.Threading.Tasks;
  using MongoDB.Bson;
  using MongoDB.Bson.Serialization.Serializers;
  using MongoDB.Driver.Core.Bindings;
  using MongoDB.Driver.Core.Connections;
  using MongoDB.Driver.Core.Misc;
  using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
  
  namespace MongoDB.Driver.Core.Operations
  {
      /// <summary>
      /// Represents a rename collection operation.
      /// </summary>
      public class RenameCollectionOperation : IWriteOperation<BsonDocument>
      {
          // fields
          private readonly CollectionNamespace _collectionNamespace;
          private bool? _dropTarget;
          private readonly MessageEncoderSettings _messageEncoderSettings;
          private readonly CollectionNamespace _newCollectionNamespace;
          private WriteConcern _writeConcern;
  
          // constructors
          /// <summary>
          /// Initializes a new instance of the <see cref="RenameCollectionOperation"/> class.
          /// </summary>
          /// <param name="collectionNamespace">The collection namespace.</param>
          /// <param name="newCollectionNamespace">The new collection namespace.</param>
          /// <param name="messageEncoderSettings">The message encoder settings.</param>
          public RenameCollectionOperation(
              CollectionNamespace collectionNamespace,
              CollectionNamespace newCollectionNamespace,
              MessageEncoderSettings messageEncoderSettings)
          {
              _collectionNamespace = Ensure.IsNotNull(collectionNamespace, nameof(collectionNamespace));
              _newCollectionNamespace = Ensure.IsNotNull(newCollectionNamespace, nameof(newCollectionNamespace));
              _messageEncoderSettings = messageEncoderSettings;
          }
  
          // properties
          /// <summary>
          /// Gets the collection namespace.
          /// </summary>
          /// <value>
          /// The collection namespace.
          /// </value>
          public CollectionNamespace CollectionNamespace
          {
              get { return _collectionNamespace; }
          }
  
          /// <summary>
          /// Gets or sets a value indicating whether to drop the target collection first if it already exists.
          /// </summary>
          /// <value>
          ///   <c>true</c> if the target collection should be dropped first if it already exists.; otherwise, <c>false</c>.
          /// </value>
          public bool? DropTarget
          {
              get { return _dropTarget; }
              set { _dropTarget = value; }
          }
  
          /// <summary>
          /// Gets the message encoder settings.
          /// </summary>
          /// <value>
          /// The message encoder settings.
          /// </value>
          public MessageEncoderSettings MessageEncoderSettings
          {
              get { return _messageEncoderSettings; }
          }
  
          /// <summary>
          /// Gets the new collection namespace.
          /// </summary>
          /// <value>
          /// The new collection namespace.
          /// </value>
          public CollectionNamespace NewCollectionNamespace
          {
              get { return _newCollectionNamespace; }
          }
  
          /// <summary>
          /// Gets or sets the write concern.
          /// </summary>
          /// <value>
          /// The write concern.
          /// </value>
          public WriteConcern WriteConcern
          {
              get { return _writeConcern; }
              set { _writeConcern = value; }
          }
  
          // methods
          internal BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription)
          {
              var writeConcern = WriteConcernHelper.GetWriteConcernForCommandThatWrites(session, _writeConcern, connectionDescription.ServerVersion);
              return new BsonDocument
              {
                  { "renameCollection", _collectionNamespace.FullName },
                  { "to", _newCollectionNamespace.FullName },
                  { "dropTarget", () => _dropTarget.Value, _dropTarget.HasValue },
                  { "writeConcern", writeConcern, writeConcern != null }
              };
          }
  
          private WriteCommandOperation<BsonDocument> CreateOperation(ICoreSessionHandle session, ConnectionDescription connectionDescription)
          {
              var command = CreateCommand(session, connectionDescription);
              return new WriteCommandOperation<BsonDocument>(DatabaseNamespace.Admin, command, BsonDocumentSerializer.Instance, _messageEncoderSettings);
          }
  
          /// <inheritdoc/>
          public BsonDocument Execute(IWriteBinding binding, CancellationToken cancellationToken)
          {
              Ensure.IsNotNull(binding, nameof(binding));
  
              using (var channelSource = binding.GetWriteChannelSource(cancellationToken))
              using (var channel = channelSource.GetChannel(cancellationToken))
              using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork()))
              {
                  var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription);
                  return operation.Execute(channelBinding, cancellationToken);
              }
          }
  
          /// <inheritdoc/>
          public async Task<BsonDocument> ExecuteAsync(IWriteBinding binding, CancellationToken cancellationToken)
          {
              Ensure.IsNotNull(binding, nameof(binding));
  
              using (var channelSource = await binding.GetWriteChannelSourceAsync(cancellationToken).ConfigureAwait(false))
              using (var channel = await channelSource.GetChannelAsync(cancellationToken).ConfigureAwait(false))
              using (var channelBinding = new ChannelReadWriteBinding(channelSource.Server, channel, binding.Session.Fork()))
              {
                  var operation = CreateOperation(channelBinding.Session, channel.ConnectionDescription);
                  return await operation.ExecuteAsync(channelBinding, cancellationToken).ConfigureAwait(false);
              }
          }
      }
  }
  