/**
   * Returns a new AdGroupCriterion configured for a SET operation that will set the criterion's
   * bid.
   *
   * @param node the node whose criterion should be updated
   * @param adGroupId the ad group ID of the criterion
   * @param biddingConfig the bidding strategy configuration of the criterion
   */
  static AdGroupCriterion createCriterionForSetBid(
      ProductPartitionNode node, long adGroupId, BiddingStrategyConfiguration biddingConfig) {
    Preconditions.checkNotNull(node, "Null node");
    Preconditions.checkNotNull(biddingConfig, "Null bidding configuration");
    Preconditions.checkArgument(node.isBiddableUnit(), "Node is not a biddable unit");

    BiddableAdGroupCriterion biddableCriterion = new BiddableAdGroupCriterion();
    biddableCriterion.setAdGroupId(adGroupId);

    ProductPartition partition = new ProductPartition();
    partition.setId(node.getProductPartitionId());
    if (node.getParent() != null) {
      partition.setParentCriterionId(node.getParent().getProductPartitionId());
    }
    partition.setCaseValue(node.getDimension());
    partition.setPartitionType(ProductPartitionType.UNIT);

    biddableCriterion.setCriterion(partition);

    if (node.getBid() != null) {
      Money bidMoney = new Money();
      bidMoney.setMicroAmount(node.getBid());
      CpcBid cpcBid = new CpcBid();
      cpcBid.setBid(bidMoney);
      biddingConfig.setBids(new Bids[] {cpcBid});
    } else {
      biddingConfig.setBids(new Bids[0]);
    }
    biddableCriterion.setBiddingStrategyConfiguration(biddingConfig);
    return biddableCriterion;
  }
  private static List<AdGroupCriterionOperation> buildAdGroupCriterionOperations(
      List<AdGroupOperation> adGroupOperations) {
    List<AdGroupCriterionOperation> adGroupCriteriaOperations = Lists.newArrayList();

    // Create AdGroupCriterionOperations to add keywords.
    for (AdGroupOperation adGroupOperation : adGroupOperations) {
      long newAdGroupId = adGroupOperation.getOperand().getId();
      for (int i = 0; i < NUMBER_OF_KEYWORDS_TO_ADD; i++) {
        // Create Keyword.
        String text = String.format("mars%d", i);

        // Make 50% of keywords invalid to demonstrate error handling.
        if (i % 2 == 0) {
          text = text + "!!!";
        }
        Keyword keyword = new Keyword();
        keyword.setText(text);
        keyword.setMatchType(KeywordMatchType.BROAD);

        // Create BiddableAdGroupCriterion.
        BiddableAdGroupCriterion biddableAdGroupCriterion = new BiddableAdGroupCriterion();
        biddableAdGroupCriterion.setAdGroupId(newAdGroupId);
        biddableAdGroupCriterion.setCriterion(keyword);

        // Create AdGroupCriterionOperation.
        AdGroupCriterionOperation operation = new AdGroupCriterionOperation();
        operation.setOperand(biddableAdGroupCriterion);
        operation.setOperator(Operator.ADD);

        // Add to list.
        adGroupCriteriaOperations.add(operation);
      }
    }
    return adGroupCriteriaOperations;
  }
  /**
   * Returns a new AdGroupCriterion configured for an ADD operation.
   *
   * @param node the node whose criterion should be added
   * @param adGroupId the ad group ID of the criterion
   * @param biddingConfig the bidding strategy configuration of the criterion
   */
  static AdGroupCriterion createCriterionForAdd(
      ProductPartitionNode node, long adGroupId, BiddingStrategyConfiguration biddingConfig) {
    Preconditions.checkNotNull(node, "Null node");
    Preconditions.checkNotNull(biddingConfig, "Null bidding configuration");

    AdGroupCriterion adGroupCriterion;
    if (node.isExcludedUnit()) {
      adGroupCriterion = new NegativeAdGroupCriterion();
    } else {
      adGroupCriterion = new BiddableAdGroupCriterion();
      if (node.isUnit() && node.getBid() != null) {
        Money bidMoney = new Money();
        bidMoney.setMicroAmount(node.getBid());
        CpcBid cpcBid = new CpcBid();
        cpcBid.setBid(bidMoney);
        cpcBid.setCpcBidSource(BidSource.CRITERION);
        biddingConfig.setBids(new Bids[] {cpcBid});
        ((BiddableAdGroupCriterion) adGroupCriterion)
            .setBiddingStrategyConfiguration(biddingConfig);
      }
    }
    adGroupCriterion.setAdGroupId(adGroupId);

    ProductPartition partition = new ProductPartition();
    partition.setId(node.getProductPartitionId());
    if (node.getParent() != null) {
      partition.setParentCriterionId(node.getParent().getProductPartitionId());
    }
    partition.setCaseValue(node.getDimension());
    partition.setPartitionType(
        node.isUnit() ? ProductPartitionType.UNIT : ProductPartitionType.SUBDIVISION);
    adGroupCriterion.setCriterion(partition);
    return adGroupCriterion;
  }