public void TestAddChildToUnitFails()
 {
     Assert.True(rootNode.IsUnit, "Root should be a unit by default.");
     Assert.Throws <ArgumentException>(delegate() {
         rootNode.AddChild(ProductDimensions.CreateBrand("google"));
     });
 }
        private void RebuildMultiNodeTree()
        {
            // Clear out the tree.
            ProductPartitionNode rootNode = tree.Root.RemoveAllChildren().AsSubdivision();

            long[] bids = new long[]
            {
                2500000L,
                1500000L,
                1000000L
            };
            String[] productTypeValues = new String[]
            {
                "shoes",
                "clothing",
                null
            };
            for (int i = 0; i < productTypeValues.Length; i++)
            {
                rootNode.AddChild(ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L1,
                                                               productTypeValues[i])).AsBiddableUnit().CpcBid = bids[i];
            }

            Assert.DoesNotThrow(delegate() { tree = ExecuteTreeOperations(); });
        }
Exemplo n.º 3
0
        public void TestChildNodeBasicFunctionality()
        {
            rootNode = rootNode.AsSubdivision();
            Assert.False(rootNode.IsUnit, "Parent should not be a unit.");
            Assert.True(rootNode.IsSubdivision, "Parent should be a subdivision.");
            ProductBrand         childDimension = ProductDimensions.CreateBrand("google");
            ProductPartitionNode childNode      = rootNode.AddChild(childDimension);

            Assert.AreSame(childDimension, childNode.Dimension,
                           "Child node merely wraps the " + "underlying dimension node.");
            Assert.AreSame(rootNode, childNode.Parent, "child.GetParent should return parentNode.");
            Assert.That(childNode.ProductPartitionId == 0, "Partition ID is incorrect.");

            Assert.That(childNode.Children.Count() == 0, "ChildNode should not have any children.");
            Assert.True(childNode.IsUnit, "New node should be a unit node by default.");
            Assert.True(childNode.IsBiddableUnit,
                        "New node should be a biddable unit node by default.");

            Assert.That(rootNode.HasChild(childDimension),
                        "rootNode.HasChild should return true when " +
                        "passed the dimension of the added child");
            Assert.False(rootNode.HasChild(ProductDimensions.CreateBrand("xyz")),
                         "rootNode.HasChild " +
                         "should return false when passed a dimension for a nonexistent child");
            Assert.False(rootNode.HasChild(null),
                         "rootNode.HasChild should return false when passed " +
                         "a dimension for a nonexistent child");
        }
 /// <summary>
 /// Takes a tree with product type L1 "shoes" SUBDIVISION and collapses that node to a UNIT.
 /// </summary>
 private void CollapseShoes()
 {
     tree.Root.GetChild(
         ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L1, "shoes"))
     .AsBiddableUnit().CpcBid = (1500000L);
     Assert.DoesNotThrow(delegate() { tree = ExecuteTreeOperations(); });
 }
        /// <summary>
        /// Takes a tree with product type L1 "clothing" and sets its bid.
        /// </summary>
        /// <param name="bid">The bid.</param>
        private void UpdateClothingBid(long bid)
        {
            tree.Root.GetChild(ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L1,
                                                            "clothing")).AsBiddableUnit().CpcBid = bid;

            Assert.DoesNotThrow(delegate() { tree = ExecuteTreeOperations(); });
        }
 public void TestRemoveChildThatDoesNotExistFails()
 {
     rootNode = rootNode.AsSubdivision();
     Assert.Throws <ArgumentException>(delegate() {
         rootNode.RemoveChild(ProductDimensions.CreateBrand("google"));
     });
 }
        /// <summary>
        /// Uses obsolete category Hardware > Flooring (5264193646140135688). This is expected to
        /// fail with the error {@code CriterionError.INVALID_PRODUCT_BIDDING_CATEGORY}.
        /// </summary>
        private void UseObsoleteCategory()
        {
            tree.Root.RemoveAllChildren();
            ProductPartitionNode hardwareLevel1 = tree.Root.AsSubdivision()
                                                  .AddChild(ProductDimensions.CreateBiddingCategory(
                                                                ProductDimensionType.BIDDING_CATEGORY_L1, 1689639310991627077L))
                                                  .AsSubdivision();

            hardwareLevel1
            .AddChild(ProductDimensions.CreateBiddingCategory(
                          ProductDimensionType.BIDDING_CATEGORY_L2, 5264193646140135688L)).CpcBid =
                1000000L;
            hardwareLevel1
            .AddChild(
                ProductDimensions.CreateBiddingCategory(
                    ProductDimensionType.BIDDING_CATEGORY_L2)).AsExcludedUnit();
            tree.Root.AddChild(
                ProductDimensions.CreateBiddingCategory(
                    ProductDimensionType.BIDDING_CATEGORY_L1))
            .AsExcludedUnit();
            try
            {
                tree = ExecuteTreeOperations();
                Assert.Fail("Did not throw CriterionError.INVALID_PRODUCT_BIDDING_CATEGORY");
            }
            catch (AdWordsApiException e)
            {
                ApiError[] errors = (e.ApiException as ApiException).errors;
                Assert.That(errors != null && errors.Length == 1);
                Assert.That(errors[0] is CriterionError);
                Assert.That((errors[0] as CriterionError).reason ==
                            CriterionErrorReason.INVALID_PRODUCT_BIDDING_CATEGORY);
            }
        }
        /// <summary>
        /// Removes product type L1 "shoes".
        /// </summary>
        private void RemoveShoes()
        {
            tree.Root.RemoveChild(
                ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L1, "shoes"));

            Assert.DoesNotThrow(delegate() { tree = ExecuteTreeOperations(); });
        }
    public void TestNavigation() {
      rootNode = rootNode.AsSubdivision();
      ProductBrand brandGoogle = ProductDimensions.CreateBrand("google");
      ProductBrand brandOther = ProductDimensions.CreateBrand(null);
      ProductCanonicalCondition conditionNew =
          ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition.NEW);
      ProductCanonicalCondition conditionUsed =
          ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition.USED);
      ProductCanonicalCondition conditionOther = ProductDimensions.CreateCanonicalCondition();

      // Build up the brand = Google node under the root.
      ProductPartitionNode brandGoogleNode = rootNode.AddChild(brandGoogle).AsSubdivision();
      brandGoogleNode.AddChild(conditionNew);
      brandGoogleNode.AddChild(conditionUsed);
      brandGoogleNode.AddChild(conditionOther);

      Assert.True(brandGoogleNode.HasChild(conditionNew),
          "HasChild should return true for existing child dimension.");
      Assert.AreSame(brandGoogleNode, brandGoogleNode.GetChild(conditionNew).Parent,
          "parent->GetChild->getParent should return parent.");
      Assert.True(brandGoogleNode.HasChild(conditionUsed),
          "HasChild should return true for existing child dimension.");
      Assert.AreSame(brandGoogleNode, brandGoogleNode.GetChild(conditionUsed).Parent,
          "parent->GetChild->getParent should return parent.");
      Assert.True(brandGoogleNode.HasChild(conditionOther),
          "HasChild should return true for existing child dimension.");
      Assert.AreSame(brandGoogleNode, brandGoogleNode.GetChild(conditionOther).Parent,
          "parent->GetChild->getParent should return parent.");

      // Build up the brand = null (other) node under the root.
      ProductPartitionNode brandOtherNode = rootNode.AddChild(brandOther).AsSubdivision();
      brandOtherNode.AddChild(conditionNew);
      Assert.True(brandOtherNode.HasChild(conditionNew),
          "HasChild should return true for existing child dimension.");
      Assert.AreSame(brandOtherNode, brandOtherNode.GetChild(conditionNew).Parent,
          "parent->GetChild->getParent should return parent.");
      Assert.False(brandOtherNode.HasChild(conditionUsed),
          "HasChild should return false for nonexistent child dimension.");
      Assert.False(brandOtherNode.HasChild(conditionOther),
          "HasChild should return false for nonexistent child dimension.");
      brandOtherNode.AddChild(conditionOther);
      Assert.True(brandOtherNode.HasChild(conditionOther),
          "HasChild should return true for existing child dimension.");
      Assert.AreSame(brandOtherNode, brandOtherNode.GetChild(conditionOther).Parent,
          "parent->GetChild->getParent should return parent.");

      // Remove one of the children of brand = null.
      brandOtherNode.RemoveChild(conditionOther);
      Assert.False(brandOtherNode.HasChild(conditionOther),
          "HasChild should return false for a removed child dimension.");

      // Remove the rest of the children of brand = null.
      brandOtherNode.RemoveAllChildren();
      Assert.False(brandOtherNode.HasChild(conditionNew),
          "HasChild should return false for any removed child dimension.");
      Assert.False(brandOtherNode.HasChild(conditionUsed),
          "HasChild should return false for any removed child dimension.");
    }
Exemplo n.º 10
0
        /// <summary>
        /// Creates a product partition tree.
        /// </summary>
        /// <param name="user">The AdWords user for which the product partition is created.</param>
        /// <param name="adGroupId">Ad group ID.</param>
        /// <returns>The product partition.</returns>
        private static ProductPartitionTree CreateProductPartition(AdWordsUser user, long adGroupId)
        {
            using (AdGroupCriterionService adGroupCriterionService =
                       (AdGroupCriterionService)user.GetService(AdWordsService.v201809
                                                                .AdGroupCriterionService))
            {
                // Build a new ProductPartitionTree using the ad group's current set of criteria.
                ProductPartitionTree partitionTree =
                    ProductPartitionTree.DownloadAdGroupTree(user, adGroupId);

                Console.WriteLine("Original tree: {0}", partitionTree);

                // Clear out any existing criteria.
                ProductPartitionNode rootNode = partitionTree.Root.RemoveAllChildren();

                // Make the root node a subdivision.
                rootNode = rootNode.AsSubdivision();

                // Add a unit node for condition = NEW to include it.
                rootNode.AddChild(
                    ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition
                                                               .NEW));

                // Add a unit node for condition = USED to include it.
                rootNode.AddChild(
                    ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition
                                                               .USED));

                // Exclude everything else.
                rootNode.AddChild(ProductDimensions.CreateCanonicalCondition()).AsExcludedUnit();

                // Make the mutate request, using the operations returned by the
                // ProductPartitionTree.
                AdGroupCriterionOperation[] mutateOperations = partitionTree.GetMutateOperations();

                if (mutateOperations.Length == 0)
                {
                    Console.WriteLine(
                        "Skipping the mutate call because the original tree and the current " +
                        "tree are logically identical.");
                }
                else
                {
                    adGroupCriterionService.mutate(mutateOperations);
                }

                // The request was successful, so create a new ProductPartitionTree based on the
                // updated state of the ad group.
                partitionTree = ProductPartitionTree.DownloadAdGroupTree(user, adGroupId);
                return(partitionTree);
            }
        }
        /// <summary>
        /// Takes a tree with:
        ///
        /// <pre>
        /// ROOT
        ///  ...
        ///  shoes
        ///    new
        ///      offerId=1 $1.00
        ///      offerId=2 $2.00
        ///      ...
        ///      offerId=20 $20.00
        ///    other - excluded
        /// </pre>
        ///
        ///  and changes it to:
        ///
        ///  <pre>
        /// ROOT
        ///  ...
        ///  shoes
        ///    new $1.25
        ///    other $0.50
        /// </pre>
        /// </summary>
        private void CollapseNewShoes()
        {
            ProductPartitionNode shoesLevel1 = tree.Root.GetChild(ProductDimensions.CreateType(
                                                                      ProductDimensionType.PRODUCT_TYPE_L1, "shoes"));

            shoesLevel1.GetChild(ProductDimensions.CreateCanonicalCondition(
                                     ProductCanonicalConditionCondition.NEW)).AsBiddableUnit().CpcBid = 1250000L;
            shoesLevel1.GetChild(ProductDimensions.CreateCanonicalCondition()).AsBiddableUnit()
            .CpcBid = 500000L;

            Assert.DoesNotThrow(delegate() {
                tree = ExecuteTreeOperations();
            });
        }
    public void TestAddChildThatExistsFails() {
      rootNode = rootNode.AsSubdivision();
      rootNode.AddChild(ProductDimensions.CreateBrand("google"));

      // Add the same child again. The call should fail.
      Assert.Throws<ArgumentException>(delegate() {
        rootNode.AddChild(ProductDimensions.CreateBrand("google"));
      });

      // Add the same child again, this time with a different case.
      // The call should fail.
      Assert.Throws<ArgumentException>(delegate() {
        rootNode.AddChild(ProductDimensions.CreateBrand("GOOGLE"));
      });
    }
        public void TestCreateMultiNodeTreeFromScratch()
        {
            ProductPartitionTree tree =
                ProductPartitionTree.CreateAdGroupTree(new List <AdGroupCriterion>());

            ProductPartitionNode rootNode = tree.Root.AsSubdivision();
            ProductPartitionNode brand1   = rootNode.AddChild(ProductDimensions.CreateBrand("google"))
                                            .AsSubdivision();
            ProductPartitionNode brand1Offer1 =
                brand1.AddChild(ProductDimensions.CreateOfferId("A"));

            brand1Offer1.AsBiddableUnit().CpcBid = 1000000L;
            ProductPartitionNode brand1Offer2    =
                brand1.AddChild(ProductDimensions.CreateOfferId()).AsExcludedUnit();
            ProductPartitionNode brand2 =
                rootNode.AddChild(ProductDimensions.CreateBrand()).AsExcludedUnit();

            ProductPartitionNode[] nodes = new ProductPartitionNode[]
            {
                rootNode,
                brand1,
                brand1Offer1,
                brand1Offer2,
                brand2
            };

            AdGroupCriterionOperation[] mutateOperations = tree.GetMutateOperations();

            for (int i = 0; i < nodes.Length; i++)
            {
                List <AdGroupCriterionOperation> nodeOperations =
                    shoppingTestUtils.GetOperationsForNode(nodes[i], mutateOperations);
                Assert.That(nodeOperations.Count == 1);
                Assert.That(nodeOperations[0].@operator == Operator.ADD);
                ProductPartition partition = (ProductPartition)nodeOperations[0].operand.criterion;
                Assert.That(partition.id == nodes[i].ProductPartitionId);
                if (nodes[i].Parent == null)
                {
                    Assert.That(partition.parentCriterionIdSpecified == false);
                }
                else
                {
                    Assert.That(partition.parentCriterionId == nodes[i].Parent.ProductPartitionId);
                }

                Assert.That(partition.caseValue == nodes[i].Dimension);
            }
        }
    public void TestCreateOfferId() {
      ProductOfferId productOfferIdA = new ProductOfferId() {
        value = "google"
      };

      ProductOfferId productOfferIdB = ProductDimensions.CreateOfferId("google");

      Assert.True(comparer.Equals(productOfferIdA, productOfferIdB));

      ProductOfferId productOfferIdC = new ProductOfferId() {
      };

      ProductOfferId productOfferIdD = ProductDimensions.CreateOfferId();

      Assert.True(comparer.Equals(productOfferIdC, productOfferIdD));
    }
    public void TestCreateBrand() {
      ProductBrand brandA = new ProductBrand() {
        value = "google"
      };

      ProductBrand brandB = ProductDimensions.CreateBrand("google");

      Assert.True(comparer.Equals(brandA, brandB));

      ProductBrand brandC = new ProductBrand() {
      };

      ProductBrand brandD = ProductDimensions.CreateBrand();

      Assert.True(comparer.Equals(brandC, brandD));
    }
        /// <summary>
        /// Takes a tree with product type L1 "shoes" UNIT and subdivides that node into UNITs:
        ///
        /// <pre>
        /// shoes
        ///   new $1.00
        ///   refurbished $1.50
        ///   other - excluded
        /// </pre>
        /// </summary>
        private void SubdivideShoes()
        {
            ProductPartitionNode shoesLevel1 = tree.Root.GetChild(ProductDimensions.CreateType(
                                                                      ProductDimensionType.PRODUCT_TYPE_L1, "shoes"))
                                               .AsSubdivision();

            shoesLevel1.AddChild(ProductDimensions.CreateCanonicalCondition(
                                     ProductCanonicalConditionCondition.NEW)).AsBiddableUnit().CpcBid = 1000000L;
            shoesLevel1.AddChild(ProductDimensions.CreateCanonicalCondition(
                                     ProductCanonicalConditionCondition.REFURBISHED)).AsBiddableUnit().CpcBid = 1500000L;
            shoesLevel1.AddChild(ProductDimensions.CreateCanonicalCondition()).AsExcludedUnit();

            Assert.DoesNotThrow(delegate() {
                tree = ExecuteTreeOperations();
            });
        }
    public void TestCreateCanonicalCondition() {
      ProductCanonicalCondition conditionA = new ProductCanonicalCondition() {
        condition = ProductCanonicalConditionCondition.NEW
      };

      ProductCanonicalCondition conditionB =
          ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition.NEW);

      Assert.True(comparer.Equals(conditionA, conditionB));

      ProductCanonicalCondition conditionC = new ProductCanonicalCondition() {
      };

      ProductCanonicalCondition conditionD = ProductDimensions.CreateCanonicalCondition();

      Assert.True(comparer.Equals(conditionC, conditionD));
    }
    public void TestProductChannelExclusivityEquals() {
      ProductChannelExclusivity channelExclusivityA = new ProductChannelExclusivity() {
        channelExclusivity = ShoppingProductChannelExclusivity.MULTI_CHANNEL
      };

      ProductChannelExclusivity channelExclusivityB =
          ProductDimensions.CreateChannelExclusivity(
              ShoppingProductChannelExclusivity.MULTI_CHANNEL);

      Assert.True(comparer.Equals(channelExclusivityA, channelExclusivityB));

      ProductChannelExclusivity channelExclusivityC = new ProductChannelExclusivity() {
      };

      ProductChannelExclusivity channelExclusivityD = ProductDimensions.CreateChannelExclusivity();

      Assert.True(comparer.Equals(channelExclusivityC, channelExclusivityD));
    }
    public void TestProductTypeEquals() {
      ProductType productTypeA = new ProductType() {
        type = ProductDimensionType.BRAND,
        value = "google",
      };

      ProductType productTypeB = ProductDimensions.CreateType(ProductDimensionType.BRAND,
          "google");

      Assert.True(comparer.Equals(productTypeA, productTypeB));

      ProductType productTypeC = new ProductType() {
        type = ProductDimensionType.BRAND,
      };

      ProductType productTypeD = ProductDimensions.CreateType(ProductDimensionType.BRAND);

      Assert.True(comparer.Equals(productTypeC, productTypeD));
    }
    public void TestCreateBiddingCategory() {
      ProductBiddingCategory categoryA = new ProductBiddingCategory() {
        type = ProductDimensionType.BIDDING_CATEGORY_L1,
        value = 2L
      };

      ProductBiddingCategory categoryB = ProductDimensions.CreateBiddingCategory(
          ProductDimensionType.BIDDING_CATEGORY_L1, 2L);

      Assert.True(comparer.Equals(categoryA, categoryB));

      ProductBiddingCategory categoryC = new ProductBiddingCategory() {
        type = ProductDimensionType.BIDDING_CATEGORY_L1,
      };

      ProductBiddingCategory categoryD = ProductDimensions.CreateBiddingCategory(
          ProductDimensionType.BIDDING_CATEGORY_L1);

      Assert.True(comparer.Equals(categoryC, categoryD));
    }
    public void TestCreateCustomAttribute() {
      ProductCustomAttribute customAttributeA = new ProductCustomAttribute() {
        type = ProductDimensionType.BIDDING_CATEGORY_L1,
        value = "google"
      };

      ProductCustomAttribute customAttributeB = ProductDimensions.CreateCustomAttribute(
          ProductDimensionType.BIDDING_CATEGORY_L1, "google");

      Assert.True(comparer.Equals(customAttributeA, customAttributeB));

      ProductCustomAttribute customAttributeC = new ProductCustomAttribute() {
        type = ProductDimensionType.BIDDING_CATEGORY_L1,
      };

      ProductCustomAttribute customAttributeD = ProductDimensions.CreateCustomAttribute(
          ProductDimensionType.BIDDING_CATEGORY_L1);

      Assert.True(comparer.Equals(customAttributeC, customAttributeD));
    }
    public void TestSetBidOnUnit() {
      rootNode = rootNode.AsSubdivision();
      ProductBrand childDimension = ProductDimensions.CreateBrand("google");
      ProductPartitionNode childNode = rootNode.AddChild(childDimension);

      Assert.That(childNode.CpcBidSpecified == false, "Bid should be null by default.");

      childNode.CpcBid = 1L;

      Assert.AreEqual(1L, childNode.CpcBid, "Bid does not reflect setBid.");
      Assert.True(childNode.IsBiddableUnit, "Node should be a biddable unit.");

      childNode = childNode.AsExcludedUnit();
      Assert.True(childNode.IsExcludedUnit, "Node should be an excluded unit.");
      Assert.False(childNode.IsBiddableUnit, "Node should not be a biddable unit.");
      Assert.False(childNode.CpcBidSpecified, "Excluded unit should have a null bid");

      // Set back to biddable.
      childNode = childNode.AsBiddableUnit();
      Assert.True(childNode.IsBiddableUnit, "Node should be a biddable unit.");
    }
        public void TestRemovedCriteriaIgnored()
        {
            AdGroupCriterion rootCriterion = ShoppingTestUtils.CreateCriterionForProductPartition(
                1L, 0L, null, true, false);
            List <AdGroupCriterion> criteria = new List <AdGroupCriterion>();

            criteria.Add(rootCriterion);

            // Create a criteria for a child node and set its UserStatus to REMOVED.
            ProductBrand     brandGoogle      = ProductDimensions.CreateBrand("google");
            AdGroupCriterion removedCriterion = ShoppingTestUtils.CreateCriterionForProductPartition(
                2L, 1L, brandGoogle, true, false);

            ((BiddableAdGroupCriterion)removedCriterion).userStatus = UserStatus.REMOVED;
            criteria.Add(removedCriterion);

            ProductPartitionTree tree =
                ProductPartitionTree.CreateAdGroupTree(criteria);

            Assert.False(tree.Root.HasChild(brandGoogle),
                         "Brand = google criteria had status removed, but it is in the tree.");
        }
        public void TestCreateUltimatelyEmptyTree()
        {
            ProductPartitionTree tree =
                ProductPartitionTree.CreateAdGroupTree(new List <AdGroupCriterion>());

            ProductPartitionNode rootNode = tree.Root.AsSubdivision();
            ProductPartitionNode brand1   = rootNode.AddChild(ProductDimensions.CreateBrand("google"))
                                            .AsSubdivision();
            ProductPartitionNode offerNode = brand1.AddChild(ProductDimensions.CreateOfferId("A"));

            offerNode.AsBiddableUnit().CpcBid = 1000000L;

            brand1.AddChild(ProductDimensions.CreateOfferId()).AsExcludedUnit();
            ProductPartitionNode brand2 =
                rootNode.AddChild(ProductDimensions.CreateBrand()).AsExcludedUnit();

            // Now remove the two child nodes under the root and set the root back
            // to a UNIT. This should result in operations that simply create the
            // root node.
            rootNode.RemoveChild(brand1.Dimension);
            rootNode.RemoveChild(brand2.Dimension);
            rootNode = rootNode.AsBiddableUnit();

            AdGroupCriterionOperation[] mutateOperations = tree.GetMutateOperations();

            Assert.AreEqual(mutateOperations.Count(), 1, "Number of operations is incorrect.");
            AdGroupCriterionOperation operation = mutateOperations[0];

            Assert.AreEqual(Operator.ADD, operation.@operator,
                            "Should have a single operation to ADD the root node.");
            BiddableAdGroupCriterion adGroupCriterion =
                (BiddableAdGroupCriterion)operation.operand;

            Assert.Null(((ProductPartition)adGroupCriterion.criterion).caseValue,
                        "Product dimension of operation's operand should be null.");
            Assert.True(adGroupCriterion.criterion.id < 0L,
                        "Partition ID of the operand should be negative.");
        }
        /// <summary>
        /// Subdivides the new shoes.
        /// </summary>
        /// Takes a tree with:
        /// <pre>
        /// ROOT
        ///   ...
        ///   shoes
        ///     new some bid
        /// </pre>
        ///
        /// and changes it to:
        ///
        /// <pre>
        ///   ROOT
        ///     ...
        ///     shoes
        ///       new
        ///       other offerId $1.00
        ///       offerId=2 $2.00
        ///       ...
        ///       offerId=20 $20.00
        /// </pre>
        private void SubdivideNewShoes()
        {
            ProductPartitionNode shoesLevel1 = tree.Root.GetChild(ProductDimensions.CreateType(
                                                                      ProductDimensionType.PRODUCT_TYPE_L1, "shoes")).AsSubdivision();
            ProductPartitionNode newShoesLevel2 = shoesLevel1.GetChild(
                ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition.NEW))
                                                  .AsSubdivision();

            for (int i = 1; i <= 20; i++)
            {
                ProductOfferId offerId = ProductDimensions.CreateOfferId();
                if (i > 1)
                {
                    offerId.value = i.ToString();
                }

                newShoesLevel2.AddChild(offerId).AsBiddableUnit().CpcBid = i * 1000000L;
            }

            Assert.DoesNotThrow(delegate() {
                tree = ExecuteTreeOperations();
            });
        }
        public void Init()
        {
            CAMPAIGN_ID = utils.CreateShoppingCampaign(user, BiddingStrategyType.MANUAL_CPC);
            ADGROUP_ID  = utils.CreateAdGroup(user, CAMPAIGN_ID);

            tree = ProductPartitionTree.CreateAdGroupTree(ADGROUP_ID,
                                                          new List <AdGroupCriterion>());
            ProductPartitionNode root = tree.Root.AsSubdivision();

            ProductPartitionNode clothing = root.AddChild(ProductDimensions.CreateType(
                                                              ProductDimensionType.PRODUCT_TYPE_L1, "clothing"));

            clothing.AsBiddableUnit().CpcBid = 200000;
            ProductPartitionNode shoes       = root.AddChild(ProductDimensions.CreateType(
                                                                 ProductDimensionType.PRODUCT_TYPE_L1, "shoes"));

            shoes.AsBiddableUnit().CpcBid  = 400000;
            ProductPartitionNode otherNode = root.AddChild(ProductDimensions.CreateType(
                                                               ProductDimensionType.PRODUCT_TYPE_L1));

            otherNode.AsBiddableUnit().CpcBid = 300000;

            tree = ExecuteTreeOperations();
        }
        /// <summary>
        /// Creates a tree of the form:
        ///
        /// <pre>
        /// ROOT
        ///   ProductType Level1 shoes
        ///     ProductType Level2 athletic shoes
        ///       Condition new $2.50
        ///       Condition used $1.00
        ///       Other - exclude from bidding
        ///     ProductType Level2 walking shoes
        ///       Condition new $3.50
        ///       Condition used $1.25
        ///       Other $1.00
        ///     ProductType Level2 null (everything else) - exclude from bidding
        ///   ProductType Level1 clothing
        ///     ProductType Level2 winter clothing
        ///       Condition new $1.00
        ///       Condition used $1.25
        ///       Other $1.50
        ///     ProductType Level2 summer clothing
        ///       Condition new $1.10
        ///       Condition used $1.00
        ///       Other $1.25
        ///     ProductType Level2 null (everything else)
        ///       Condition new $0.90
        ///       Condition used $0.85
        ///       Other $0.75
        ///   ProductType Level1 null (everything else) - exclude from bidding
        /// </pre>
        /// </summary>
        private void RebuildComplexTree()
        {
            // Clear out the tree.
            ProductPartitionNode rootNode = tree.Root.RemoveAllChildren().AsSubdivision();

            ProductPartitionNode shoesLevel1 = rootNode.AddChild(ProductDimensions.CreateType(
                                                                     ProductDimensionType.PRODUCT_TYPE_L1, "shoes")).AsSubdivision();

            ProductPartitionNode athleticShoesLevel2 = shoesLevel1.AddChild(
                ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L2, "athletic shoes"))
                                                       .AsSubdivision();

            athleticShoesLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                             ProductCanonicalConditionCondition.NEW)).AsBiddableUnit().CpcBid = 2500000L;
            athleticShoesLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                             ProductCanonicalConditionCondition.USED)).AsBiddableUnit().CpcBid = 1000000L;
            athleticShoesLevel2.AddChild(ProductDimensions.CreateCanonicalCondition()).AsExcludedUnit();

            ProductPartitionNode walkingShoesLevel2 = shoesLevel1.AddChild(
                ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L2, "walking shoes"))
                                                      .AsSubdivision();

            walkingShoesLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                            ProductCanonicalConditionCondition.NEW)).AsBiddableUnit().CpcBid = 3500000L;
            walkingShoesLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                            ProductCanonicalConditionCondition.USED)).AsBiddableUnit().CpcBid = 1250000L;
            walkingShoesLevel2.AddChild(ProductDimensions.CreateCanonicalCondition()).AsBiddableUnit()
            .CpcBid = 1000000L;

            shoesLevel1.AddChild(ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L2))
            .AsExcludedUnit();

            ProductPartitionNode clothingLevel1 = rootNode.AddChild(ProductDimensions.CreateType(
                                                                        ProductDimensionType.PRODUCT_TYPE_L1, "clothing")).AsSubdivision();

            ProductPartitionNode winterClothingLevel2 = clothingLevel1.AddChild(
                ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L2, "winter clothing"))
                                                        .AsSubdivision();

            winterClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                              ProductCanonicalConditionCondition.NEW)).AsBiddableUnit().CpcBid = 1000000L;
            winterClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                              ProductCanonicalConditionCondition.USED)).AsBiddableUnit().CpcBid = 1250000L;
            winterClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition()).AsBiddableUnit()
            .CpcBid = 1500000L;

            ProductPartitionNode summerClothingLevel2 = clothingLevel1.AddChild(
                ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L2, "summer clothing"))
                                                        .AsSubdivision();

            summerClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                              ProductCanonicalConditionCondition.NEW)).AsBiddableUnit().CpcBid = 1100000L;
            summerClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                              ProductCanonicalConditionCondition.USED)).AsBiddableUnit().CpcBid = 1000000L;
            summerClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition()).AsBiddableUnit()
            .CpcBid = 1250000L;

            ProductPartitionNode otherClothingLevel2 = clothingLevel1.AddChild(
                ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L2, null))
                                                       .AsSubdivision();

            otherClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                             ProductCanonicalConditionCondition.NEW)).AsBiddableUnit().CpcBid = 900000L;
            otherClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition(
                                             ProductCanonicalConditionCondition.USED)).AsBiddableUnit().CpcBid = 850000L;
            otherClothingLevel2.AddChild(ProductDimensions.CreateCanonicalCondition()).AsBiddableUnit()
            .CpcBid = 750000L;

            rootNode.AddChild(ProductDimensions.CreateType(ProductDimensionType.PRODUCT_TYPE_L1, null))
            .AsExcludedUnit();

            Assert.DoesNotThrow(delegate() {
                tree = ExecuteTreeOperations();
            });
        }
        /// <summary>
        /// Runs the code example.
        /// </summary>
        /// <param name="user">The AdWords user.</param>
        /// <param name="adGroupId">The ad group to which product partition is
        /// added.</param>
        public void Run(AdWordsUser user, long adGroupId)
        {
            using (AdGroupCriterionService adGroupCriterionService =
                       (AdGroupCriterionService)user.GetService(
                           AdWordsService.v201802.AdGroupCriterionService)) {
                // Build a new ProductPartitionTree using the ad group's current set of criteria.
                ProductPartitionTree partitionTree =
                    ProductPartitionTree.DownloadAdGroupTree(user, adGroupId);

                Console.WriteLine("Original tree: {0}", partitionTree);

                // Clear out any existing criteria.
                ProductPartitionNode rootNode = partitionTree.Root.RemoveAllChildren();

                // Make the root node a subdivision.
                rootNode = rootNode.AsSubdivision();

                // Add a unit node for condition = NEW.
                ProductPartitionNode newConditionNode = rootNode.AddChild(
                    ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition.NEW));
                newConditionNode.AsBiddableUnit().CpcBid = 200000;

                ProductPartitionNode usedConditionNode = rootNode.AddChild(
                    ProductDimensions.CreateCanonicalCondition(ProductCanonicalConditionCondition.USED));
                usedConditionNode.AsBiddableUnit().CpcBid = 100000;

                // Add a subdivision node for condition = null (everything else).
                ProductPartitionNode otherConditionNode =
                    rootNode.AddChild(ProductDimensions.CreateCanonicalCondition()).AsSubdivision();

                // Add a unit node under condition = null for brand = "CoolBrand".
                ProductPartitionNode coolBrandNode = otherConditionNode.AddChild(
                    ProductDimensions.CreateBrand("CoolBrand"));
                coolBrandNode.AsBiddableUnit().CpcBid = 900000L;

                // Add a unit node under condition = null for brand = "CheapBrand".
                ProductPartitionNode cheapBrandNode = otherConditionNode.AddChild(
                    ProductDimensions.CreateBrand("CheapBrand"));
                cheapBrandNode.AsBiddableUnit().CpcBid = 10000L;

                // Add a subdivision node under condition = null for brand = null (everything else).
                ProductPartitionNode otherBrandNode = otherConditionNode.AddChild(
                    ProductDimensions.CreateBrand(null)).AsSubdivision();

                // Add unit nodes under condition = null/brand = null.
                // The value for each bidding category is a fixed ID for a specific
                // category. You can retrieve IDs for categories from the ConstantDataService.
                // See the 'GetProductCategoryTaxonomy' example for more details.

                // Add a unit node under condition = null/brand = null for product type
                // level 1 = 'Luggage & Bags'.
                ProductPartitionNode luggageAndBagNode = otherBrandNode.AddChild(
                    ProductDimensions.CreateBiddingCategory(ProductDimensionType.BIDDING_CATEGORY_L1,
                                                            -5914235892932915235L));
                luggageAndBagNode.AsBiddableUnit().CpcBid = 750000L;

                // Add a unit node under condition = null/brand = null for product type
                // level 1 = null (everything else).
                ProductPartitionNode everythingElseNode = otherBrandNode.AddChild(
                    ProductDimensions.CreateBiddingCategory(ProductDimensionType.BIDDING_CATEGORY_L1));
                everythingElseNode.AsBiddableUnit().CpcBid = 110000L;

                try {
                    // Make the mutate request, using the operations returned by the ProductPartitionTree.
                    AdGroupCriterionOperation[] mutateOperations = partitionTree.GetMutateOperations();

                    if (mutateOperations.Length == 0)
                    {
                        Console.WriteLine("Skipping the mutate call because the original tree and the " +
                                          "current tree are logically identical.");
                    }
                    else
                    {
                        adGroupCriterionService.mutate(mutateOperations);
                    }

                    // The request was successful, so create a new ProductPartitionTree based on the updated
                    // state of the ad group.
                    partitionTree = ProductPartitionTree.DownloadAdGroupTree(user, adGroupId);

                    Console.WriteLine("Final tree: {0}", partitionTree);
                } catch (Exception e) {
                    throw new System.ApplicationException("Failed to set shopping product partition.", e);
                }
            }
        }