/// <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);
       }
 }
        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>
        /// 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();
              });
        }
        /// <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();
              });
        }
        /// <summary>
        /// Removes the root of the tree.
        /// </summary>
        private void SetRootToEmpty()
        {
            ProductPartitionNode root = tree.Root;
              if (root != null && root.ProductPartitionId >= 0L) {
            AdGroupCriterion rootCriterion = new AdGroupCriterion() {
              adGroupId = ADGROUP_ID,
              criterion = new Criterion() {
            id = root.ProductPartitionId
              }
            };

            AdGroupCriterionOperation removeOp = new AdGroupCriterionOperation() {
              @operator = Operator.REMOVE,
              operand = rootCriterion
            };

            AdGroupCriterionService adGroupCriterionService = (AdGroupCriterionService)
            user.GetService(AdWordsService.v201601.AdGroupCriterionService);
            adGroupCriterionService.mutate(new AdGroupCriterionOperation[] { removeOp });
              }

              Assert.DoesNotThrow(delegate() {
            tree = ProductPartitionTree.DownloadAdGroupTree(user, ADGROUP_ID);
              });
        }
        /// <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();
              });
        }
 /// <summary>
 /// Creates a tree of the form:
 ///
 /// <pre>
 ///   ROOT $2.50
 /// </pre>
 /// </summary>
 private void RebuildSingleNodeTree()
 {
     // Clear out the tree and set the root bid.
       tree.Root.RemoveAllChildren().AsBiddableUnit().CpcBid = 2500000L;
       Assert.DoesNotThrow(delegate() {
     tree = ExecuteTreeOperations();
       });
 }
        /// <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();
              });
        }
        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();
              });
        }
        /// <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>
        /// Creates a tree from criteria passed into the factory method.
        /// </summary>
        private void CreateTreeFromCriteria()
        {
            AdGroupCriterionService service = (AdGroupCriterionService) user.GetService(
              AdWordsService.v201601.AdGroupCriterionService);

              string[] REQUIRED_SELECTOR_FIELD_ENUMS = new string[] {
              AdGroupCriterion.Fields.AdGroupId,
              Criterion.Fields.Id,
              ProductPartition.Fields.ParentCriterionId,
              ProductPartition.Fields.PartitionType,
              ProductPartition.Fields.CriteriaType,
              ProductPartition.Fields.CaseValue,
              CpcBid.Fields.CpcBid,
              CpcBid.Fields.CpcBidSource,
              BiddableAdGroupCriterion.Fields.Status
              };

              Selector selector = new Selector() {
            fields = REQUIRED_SELECTOR_FIELD_ENUMS,
            predicates = new Predicate[] {
            Predicate.Equals(AdGroupCriterion.Fields.AdGroupId, ADGROUP_ID)
              }
              };

              AdGroupCriterionPage retval = service.get(selector);

              tree = ProductPartitionTree.CreateAdGroupTree(ADGROUP_ID,
              new List<AdGroupCriterion>(retval.entries));
        }
 /// <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:
        ///
        /// <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();
              });
        }