示例#1
0
        /// <summary>
        /// Creates a new <see cref="AdGroupCriterion"/> configured for an
        /// <code>ADD</code> operation.
        /// </summary>
        /// <param name="node">The node whose criterion should be added.</param>
        /// <param name="adGroupId">The ad group ID of the criterion.</param>
        /// <param name="idGenerator">The temporary ID generator for new nodes.</param>
        /// <returns>An <see cref="AdGroupCriterion"/> object for <code>ADD</code>
        /// operation.</returns>
        internal static AdGroupCriterion CreateCriterionForAdd(ProductPartitionNode node,
                                                               long adGroupId, TemporaryIdGenerator idGenerator)
        {
            PreconditionUtilities.CheckNotNull(node, ShoppingMessages.NodeCannotBeNull);

            AdGroupCriterion adGroupCriterion;

            if (node.IsExcludedUnit)
            {
                adGroupCriterion = new NegativeAdGroupCriterion();
            }
            else
            {
                adGroupCriterion = new BiddableAdGroupCriterion()
                {
                    biddingStrategyConfiguration = node.GetBiddingConfig()
                };
            }
            adGroupCriterion.adGroupId = adGroupId;
            adGroupCriterion.criterion = node.GetCriterion();

            adGroupCriterion.criterion.id = node.ProductPartitionId;
            if (node.Parent != null)
            {
                (adGroupCriterion.criterion as ProductPartition).parentCriterionId =
                    node.Parent.ProductPartitionId;
            }

            return(adGroupCriterion);
        }
示例#2
0
        public void TestNextWithDefaultValues()
        {
            TemporaryIdGenerator generator = new TemporaryIdGenerator();

            Assert.That(generator.Next == Int32.MinValue);
            Assert.That(generator.Next == Int32.MinValue + 1);
        }
        /// <summary>
        /// Creates ADD operations for the node and ALL of its children.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="idGenerator">The temporary ID generator for new nodes.</param>
        /// <returns>A list of operation pair for the specified operation and nodes.
        /// </returns>
        private List <OperationPair> CreateAddOperations(ProductPartitionNode node,
                                                         TemporaryIdGenerator idGenerator)
        {
            AdGroupCriterionOperation addOp = new AdGroupCriterionOperation();

            addOp.@operator = Operator.ADD;

            // Overwrite the ID set by the user when doing ADD operations. This
            // minimizes the chances of a malformed tree.
            node.ProductPartitionId = idGenerator.Next;

            addOp.operand = ProductPartitionNodeAdapter.CreateCriterionForAdd(node, adGroupId,
                                                                              idGenerator);

            List <OperationPair> operationsList = new List <OperationPair>();

            operationsList.Add(new OperationPair(node, addOp));

            // Recursively add all of this node's children to the operations list.
            foreach (ProductPartitionNode child in node.Children)
            {
                operationsList.AddRange(CreateAddOperations(child, idGenerator));
            }
            return(operationsList);
        }
        /// <summary>
        /// Creates and returns the pairs of node/operation that will apply the
        /// changes made to this tree.
        /// </summary>
        /// <returns>The list of operation pairs.</returns>
        internal List <OperationPair> CreateMutateOperationPairs()
        {
            TemporaryIdGenerator idGenerator = new TemporaryIdGenerator();
            List <OperationPair> ops         = new List <OperationPair>();

            AddMutateOperations(this.originalRoot, this.root, ops, idGenerator);
            return(ops);
        }
示例#5
0
        public void TestNextWithStartId()
        {
            int startId = -20;
            TemporaryIdGenerator generator = new TemporaryIdGenerator(startId);

            Assert.That(generator.Next == startId);
            Assert.That(generator.Next == startId + 1);
        }
示例#6
0
        public void TestDoesNotGeneratePositiveId()
        {
            int startId = -1;
            TemporaryIdGenerator generator = new TemporaryIdGenerator(startId);

            Assert.Throws <ApplicationException>(delegate() {
                long next = generator.Next;
            });
        }
示例#7
0
        public void TestThrowsExceptionWithPositiveStartId()
        {
            int startId = 20;

            Assert.Throws <ArgumentException>(delegate() {
                TemporaryIdGenerator generator = new TemporaryIdGenerator(startId);
            });

            startId = 0;
            Assert.Throws <ArgumentException>(delegate() {
                TemporaryIdGenerator generator = new TemporaryIdGenerator(startId);
            });
        }
        /// <summary>
        /// Adds to the operations list all operations required to mutate
        /// <paramref name="originalNode"/> to the state* of
        /// <paramref name="newNode"/>.
        /// </summary>
        /// <param name="originalNode">The original node.</param>
        /// <param name="newNode">The new node.</param>
        /// <param name="ops">The operations list to add to.</param>
        /// <param name="idGenerator">The temporary ID generator for ADD operations.</param>
        /// <returns>The set of child product dimensions that require further
        /// processing.</returns>
        private void AddMutateOperations(ProductPartitionNode originalNode,
                                         ProductPartitionNode newNode, List <OperationPair> ops, TemporaryIdGenerator idGenerator)
        {
            NodeDifference nodeDifference = Diff(originalNode, newNode, dimensionComparator);
            bool           isProcessChildren;

            switch (nodeDifference)
            {
            case NodeDifference.NEW_NODE:
                ops.AddRange(CreateAddOperations(newNode, idGenerator));
                // No need to further process children. The ADD operations above will include operations
                // for all children of newNode.
                isProcessChildren = false;
                break;

            case NodeDifference.REMOVED_NODE:
                ops.Add(CreateRemoveOperation(originalNode));
                // No need to further process children. The REMOVE operation above will perform a
                // cascading delete of all children of newNode.
                isProcessChildren = false;
                break;

            case NodeDifference.PARTITION_TYPE_CHANGE:
            case NodeDifference.EXCLUDED_UNIT_CHANGE:
                ops.Add(CreateRemoveOperation(originalNode));
                ops.AddRange(CreateAddOperations(newNode, idGenerator));
                // No need to further process children. The ADD operations above will include operations
                // for all children of newNode.
                isProcessChildren = false;
                break;

            case NodeDifference.BID_CHANGE:
                // Ensure that the new node has the proper ID (this may have been lost if the node
                // was removed and then re-added).
                newNode.ProductPartitionId = originalNode.ProductPartitionId;
                ops.Add(CreateSetBidOperation(newNode));
                // Process the children of newNode. The SET operation above will only handle changes
                // made to newNode, not its children.
                isProcessChildren = true;
                break;

            case NodeDifference.NONE:
                // Ensure that the new node has the proper ID (this may have been lost if the node
                // was removed and then re-added).
                newNode.ProductPartitionId = originalNode.ProductPartitionId;
                // This node does not have changes, but its children may.
                isProcessChildren = true;
                break;

            default:
                throw new InvalidOperationException("Unrecognized difference: " + nodeDifference);
            }

            if (isProcessChildren)
            {
                // Try to match the children in new and original trees to identify the
                // matching dimensions.

                foreach (ProductPartitionNode newChild in newNode.Children)
                {
                    if (originalNode.HasChild(newChild.Dimension))
                    {
                        // this is probably an edit.
                        AddMutateOperations(originalNode.GetChild(newChild.Dimension), newChild, ops,
                                            idGenerator);
                    }
                    else
                    {
                        // this is a new node.
                        AddMutateOperations(null, newChild, ops, idGenerator);
                    }
                }

                foreach (ProductPartitionNode originalChild in originalNode.Children)
                {
                    if (newNode.HasChild(originalChild.Dimension))
                    {
                        // this is probably an edit. We dealt with it before
                        continue;
                    }
                    else
                    {
                        // this is a removed node.
                        AddMutateOperations(originalChild, null, ops, idGenerator);
                    }
                }
            }
        }