/// <summary>
        /// Creates a SET operation for the specified node.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <returns>An operation pair for the specified operation and node.
        /// </returns>
        private OperationPair CreateSetBidOperation(ProductPartitionNode node)
        {
            // TODO(Anash): This check is dangerous, since we should only depend on parent-child
            // relationships, not ID relationships.
            PreconditionUtilities.CheckArgument(node.ProductPartitionId >= NEW_ROOT_ID,
                                                string.Format(ShoppingMessages.NodeForSetCannotHaveNegativeId, node));
            AdGroupCriterionOperation setOp = new AdGroupCriterionOperation();

            setOp.@operator = Operator.SET;
            setOp.operand   = ProductPartitionNodeAdapter.CreateCriterionForSetBid(node, adGroupId);

            return(new OperationPair(node, setOp));
        }
        /// <summary>
        /// Creates a REMOVE operation for the specified node.
        /// </summary>
        /// <param name="node">The node to be removed.</param>
        /// <returns>An operation pair for the node and the REMOVE operation.
        /// </returns>
        private OperationPair CreateRemoveOperation(ProductPartitionNode node)
        {
            PreconditionUtilities.CheckArgument(node.ProductPartitionId >= NEW_ROOT_ID,
                                                string.Format(ShoppingMessages.NodeForRemoveCannotHaveNegativeId,
                                                              node.ProductPartitionId));

            AdGroupCriterionOperation removeOp = new AdGroupCriterionOperation();

            removeOp.@operator = Operator.REMOVE;
            removeOp.operand   = ProductPartitionNodeAdapter.CreateCriterionForRemove(node, adGroupId);

            return(new OperationPair(node, removeOp));
        }
        /// <summary>
        /// Creates a new AdGroupCriterion configured for a SET operation that will
        /// set the criterion's bid.
        /// </summary>
        /// <param name="node">The node whose criterion should be updated.</param>
        /// <param name="adGroupId">The ad group ID of the criterion.</param>
        /// <param name="biddingConfig">The bidding strategy configuration of the
        /// criterion.</param>
        /// <returns>The AdGroupCriterion for SET operation.</returns>
        internal static AdGroupCriterion CreateCriterionForSetBid(ProductPartitionNode node,
                                                                  long adGroupId)
        {
            PreconditionUtilities.CheckNotNull(node, ShoppingMessages.NodeCannotBeNull);
            PreconditionUtilities.CheckArgument(node.IsBiddableUnit,
                                                string.Format(ShoppingMessages.NodeForBidUpdateIsNotBiddable, node.ProductPartitionId));

            return(new BiddableAdGroupCriterion()
            {
                adGroupId = adGroupId,
                criterion = node.GetCriterion(),
                biddingStrategyConfiguration = node.GetBiddingConfig()
            });
        }