/// <summary>
      /// Creates a subdivision node.
      /// </summary>
      /// <param name="parent">The node that should be this node's parent.
      /// </param>
      /// <param name="value">The value being paritioned on.</param>
      /// <returns>A new subdivision node.</returns>
      public ProductPartition CreateSubdivision(ProductPartition parent, ProductDimension value) {
        ProductPartition division = new ProductPartition();
        division.partitionType = ProductPartitionType.SUBDIVISION;
        division.id = this.nextId--;

        // The root node has neither a parent nor a value.
        if (parent != null) {
          division.parentCriterionId = parent.id;
          division.caseValue = value;
        }

        BiddableAdGroupCriterion criterion = new BiddableAdGroupCriterion();
        criterion.adGroupId = this.adGroupId;
        criterion.criterion = division;

        this.CreateAddOperation(criterion);
        return division;
      }
            /// <summary>
            /// Creates the unit.
            /// </summary>
            /// <param name="parent">The node that should be this node's parent.
            /// </param>
            /// <param name="value">The value being paritioned on.</param>
            /// <param name="bidAmount">The amount to bid for matching products,
            /// in micros.</param>
            /// <param name="isNegative">True, if this is negative criterion, false
            /// otherwise.</param>
            /// <returns>A new unit node.</returns>
            public ProductPartition CreateUnit(ProductPartition parent, ProductDimension value,
          long bidAmount, bool isNegative)
            {
                ProductPartition unit = new ProductPartition();
                unit.partitionType = ProductPartitionType.UNIT;

                // The root node has neither a parent nor a value.
                if (parent != null) {
                  unit.parentCriterionId = parent.id;
                  unit.caseValue = value;
                }

                AdGroupCriterion criterion;

                if (isNegative) {
                  criterion = new NegativeAdGroupCriterion();
                } else {
                  BiddingStrategyConfiguration biddingStrategyConfiguration =
                  new BiddingStrategyConfiguration();

                  CpcBid cpcBid = new CpcBid();
                  cpcBid.bid = new Money();
                  cpcBid.bid.microAmount = bidAmount;
                  biddingStrategyConfiguration.bids = new Bids[] { cpcBid };

                  criterion = new BiddableAdGroupCriterion();
                  (criterion as BiddableAdGroupCriterion).biddingStrategyConfiguration =
                  biddingStrategyConfiguration;
                }

                criterion.adGroupId = this.adGroupId;
                criterion.criterion = unit;

                this.CreateAddOperation(criterion);

                return unit;
            }
        /// <summary>
        /// Displays the product partition tree.
        /// </summary>
        /// <param name="node">The root node.</param>
        /// <param name="children">The child node.</param>
        /// <param name="level">The tree level.</param>
        /// <param name="writer">The stream to write output to.</param>
        private void DisplayTree(ProductPartition node, Dictionary<long,
        List<ProductPartition>> children, int level, StringWriter writer)
        {
            // Recursively display a node and each of its children.
              object value = null;
              string type = "";

              if (node.caseValue != null) {
            type = node.caseValue.ProductDimensionType;
            switch (type) {
              case "ProductCanonicalCondition":
            value = (node.caseValue as ProductCanonicalCondition).condition.ToString();
            break;

              case "ProductBiddingCategory":
            value = (node.caseValue as ProductBiddingCategory).type.ToString() + "(" +
                (node.caseValue as ProductBiddingCategory).value + ")";
            break;

              default:
            value = node.caseValue.GetType().GetProperty("value").GetValue(node.caseValue, null);
            break;
            }
              }

              writer.WriteLine("{0}id: {1}, type: {2}, value: {3}", "".PadLeft(level, ' '), node.id,
              type, value);
              foreach (ProductPartition childNode in children[node.id]) {
            DisplayTree(childNode, children, level + 1, writer);
              }
        }