/// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="campaignId">The campaign id to add product scope.</param>
    public void Run(AdWordsUser user, long campaignId) {
      // Get the CampaignCriterionService.
      CampaignCriterionService campaignCriterionService =
          (CampaignCriterionService) user.GetService(
              AdWordsService.v201502.CampaignCriterionService);

      ProductScope productScope = new ProductScope();
      // This set of dimensions is for demonstration purposes only. It would be
      // extremely unlikely that you want to include so many dimensions in your
      // product scope.
      ProductBrand nexusBrand = new ProductBrand();
      nexusBrand.value = "Nexus";

      ProductCanonicalCondition newProducts = new ProductCanonicalCondition();
      newProducts.condition = ProductCanonicalConditionCondition.NEW;

      ProductCustomAttribute customAttribute = new ProductCustomAttribute();
      customAttribute.type = ProductDimensionType.CUSTOM_ATTRIBUTE_0;
      customAttribute.value = "my attribute value";

      ProductOfferId bookOffer = new ProductOfferId();
      bookOffer.value = "book1";

      ProductType mediaProducts = new ProductType();
      mediaProducts.type = ProductDimensionType.PRODUCT_TYPE_L1;
      mediaProducts.value = "Media";

      ProductType bookProducts = new ProductType();
      bookProducts.type = ProductDimensionType.PRODUCT_TYPE_L2;
      bookProducts.value = "Books";

      // The value for the bidding category is a fixed ID for the
      // 'Luggage & Bags' category. You can retrieve IDs for categories from
      // the ConstantDataService. See the 'GetProductCategoryTaxonomy' example
      // for more details.
      ProductBiddingCategory luggageBiddingCategory = new ProductBiddingCategory();
      luggageBiddingCategory.type = ProductDimensionType.BIDDING_CATEGORY_L1;
      luggageBiddingCategory.value = -5914235892932915235;

      productScope.dimensions = new ProductDimension[] {nexusBrand, newProducts, bookOffer,
          mediaProducts, luggageBiddingCategory};

      CampaignCriterion campaignCriterion = new CampaignCriterion();
      campaignCriterion.campaignId = campaignId;
      campaignCriterion.criterion = productScope;

      // Create operation.
      CampaignCriterionOperation operation = new CampaignCriterionOperation();
      operation.operand = campaignCriterion;
      operation.@operator = Operator.ADD;

      try {
        // Make the mutate request.
        CampaignCriterionReturnValue result = campaignCriterionService.mutate(
            new CampaignCriterionOperation[] { operation });

        Console.WriteLine("Created a ProductScope criterion with ID '{0}'",
              result.value[0].criterion.id);
      } catch (Exception ex) {
        throw new System.ApplicationException("Failed to set shopping product scope.", ex);
      }
    }
        /// <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)
        {
            // Get the AdGroupCriterionService.
              AdGroupCriterionService adGroupCriterionService =
              (AdGroupCriterionService) user.GetService(
              AdWordsService.v201502.AdGroupCriterionService);

              ProductPartitionHelper helper = new ProductPartitionHelper(adGroupId);

              // The most trivial partition tree has only a unit node as the root:
              //   helper.createUnit(null, null, 100000);

              ProductPartition root = helper.CreateSubdivision(null, null);

              ProductCanonicalCondition newCondition = new ProductCanonicalCondition();
              newCondition.condition = ProductCanonicalConditionCondition.NEW;
              ProductPartition newPartition = helper.CreateUnit(root, newCondition, 200000, false);

              ProductCanonicalCondition usedCondition = new ProductCanonicalCondition();
              usedCondition.condition = ProductCanonicalConditionCondition.USED;
              ProductPartition usedPartition = helper.CreateUnit(root, usedCondition, 100000, false);

              ProductPartition otherCondition = helper.CreateSubdivision(root,
              new ProductCanonicalCondition());

              ProductBrand coolBrand = new ProductBrand();
              coolBrand.value = "CoolBrand";
              helper.CreateUnit(otherCondition, coolBrand, 900000, false);

              ProductBrand cheapBrand = new ProductBrand();
              cheapBrand.value = "CheapBrand";
              helper.CreateUnit(otherCondition, cheapBrand, 10000, false);

              ProductPartition otherBrand =
              helper.CreateSubdivision(otherCondition, new ProductBrand());

              // The value for the bidding category is a fixed ID for the 'Luggage & Bags'
              // category. You can retrieve IDs for categories from the ConstantDataService.
              // See the 'GetProductCategoryTaxonomy' example for more details.

              ProductBiddingCategory luggageAndBags = new ProductBiddingCategory();
              luggageAndBags.type = ProductDimensionType.BIDDING_CATEGORY_L1;
              luggageAndBags.value = -5914235892932915235;
              helper.CreateUnit(otherBrand, luggageAndBags, 750000, false);

              ProductBiddingCategory everythingElse = new ProductBiddingCategory();
              everythingElse.type = ProductDimensionType.BIDDING_CATEGORY_L1;

              helper.CreateUnit(otherBrand, everythingElse, 110000, false);

              try {
            // Make the mutate request.
            AdGroupCriterionReturnValue retval = adGroupCriterionService.mutate(helper.Operations);

            Dictionary<long, List<ProductPartition>> children =
            new Dictionary<long, List<ProductPartition>>();
            ProductPartition rootNode = null;
            // For each criterion, make an array containing each of its children
            // We always create the parent before the child, so we can rely on that here.
            foreach (AdGroupCriterion adGroupCriterion in retval.value) {
              ProductPartition newCriterion = (ProductPartition) adGroupCriterion.criterion;
              children[newCriterion.id] = new List<ProductPartition>();

              if (newCriterion.parentCriterionIdSpecified) {
            children[newCriterion.parentCriterionId].Add(newCriterion);
              } else {
            rootNode = (ProductPartition) adGroupCriterion.criterion;
              }
            }

            // Show the tree
            StringWriter writer = new StringWriter();
            DisplayTree(rootNode, children, 0, writer);
            Console.WriteLine(writer.ToString());

              } catch (Exception e) {
            throw new System.ApplicationException("Failed to set shopping product partition.", e);
              }
        }