<commit_before>#!/usr/bin/perl -w
#
# Copyright 2019, Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example adds complete campaigns including campaign budgets, campaigns,
# ad groups and keywords using MutateJobService.

use strict;
use warnings;
use utf8;

use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::V3::Resources::CampaignBudget;
use Google::Ads::GoogleAds::V3::Resources::Campaign;
use Google::Ads::GoogleAds::V3::Resources::CampaignCriterion;
use Google::Ads::GoogleAds::V3::Resources::AdGroup;
use Google::Ads::GoogleAds::V3::Resources::AdGroupCriterion;
use Google::Ads::GoogleAds::V3::Resources::AdGroupAd;
use Google::Ads::GoogleAds::V3::Resources::Ad;
use Google::Ads::GoogleAds::V3::Common::ManualCpc;
use Google::Ads::GoogleAds::V3::Common::KeywordInfo;
use Google::Ads::GoogleAds::V3::Common::ExpandedTextAdInfo;
use Google::Ads::GoogleAds::V3::Enums::BudgetDeliveryMethodEnum qw(STANDARD);
use Google::Ads::GoogleAds::V3::Enums::AdvertisingChannelTypeEnum qw(SEARCH);
use Google::Ads::GoogleAds::V3::Enums::CampaignStatusEnum;
use Google::Ads::GoogleAds::V3::Enums::KeywordMatchTypeEnum qw(BROAD);
use Google::Ads::GoogleAds::V3::Enums::AdGroupTypeEnum qw(SEARCH_STANDARD);
use Google::Ads::GoogleAds::V3::Enums::AdGroupCriterionStatusEnum;
use Google::Ads::GoogleAds::V3::Enums::AdGroupAdStatusEnum;
use Google::Ads::GoogleAds::V3::Services::GoogleAdsService::MutateOperation;
use
  Google::Ads::GoogleAds::V3::Services::CampaignBudgetService::CampaignBudgetOperation;
use Google::Ads::GoogleAds::V3::Services::CampaignService::CampaignOperation;
use
  Google::Ads::GoogleAds::V3::Services::CampaignCriterionService::CampaignCriterionOperation;
use Google::Ads::GoogleAds::V3::Services::AdGroupService::AdGroupOperation;
use
  Google::Ads::GoogleAds::V3::Services::AdGroupCriterionService::AdGroupCriterionOperation;
use Google::Ads::GoogleAds::V3::Services::AdGroupAdService::AdGroupAdOperation;
use Google::Ads::GoogleAds::V3::Utils::ResourceNames;

use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);

use constant NUMBER_OF_CAMPAIGNS_TO_ADD => 2;
use constant NUMBER_OF_AD_GROUPS_TO_ADD => 2;
use constant NUMBER_OF_KEYWORDS_TO_ADD  => 5;
use constant POLL_FREQUENCY_SECONDS     => 1;
use constant POLL_TIMEOUT_SECONDS       => 60;

use constant PAGE_SIZE => 1000;

# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my $customer_id = "INSERT_CUSTOMER_ID_HERE";

sub add_complete_campaigns_using_mutate_job {
  my ($api_client, $customer_id) = @_;

  my $mutate_job_service = $api_client->MutateJobService();
  my $operation_service  = $api_client->OperationService();

  my $mutate_job_resource_name =
    create_mutate_job($mutate_job_service, $customer_id);

  add_all_mutate_job_operations($mutate_job_service, $customer_id,
    $mutate_job_resource_name);

  my $mutate_job_lro =
    run_mutate_job($mutate_job_service, $mutate_job_resource_name);

  poll_mutate_job($operation_service, $mutate_job_lro);

  fetch_and_print_results($mutate_job_service, $mutate_job_resource_name);

  return 1;
}

# Creates a new mutate job for the specified customer ID.
sub create_mutate_job {
  my ($mutate_job_service, $customer_id) = @_;

  my $mutate_job_resource_name = $mutate_job_service->create({
      customerId => $customer_id
    })->{resourceName};

  printf
    "Created a mutate job with resource name: '%s'.\n",
    $mutate_job_resource_name;

  return $mutate_job_resource_name;
}

# Adds all mutate job operations to the mutate job. As this is the first time for
# this mutate job, pass null as a sequence token. The response will contain the
# next sequence token that you can use to upload more operations in the future.
sub add_all_mutate_job_operations {
  my ($mutate_job_service, $customer_id, $mutate_job_resource_name) = @_;

  my $add_mutate_job_operations_response = $mutate_job_service->add_operations({
      resourceName     => $mutate_job_resource_name,
      sequenceToken    => undef,
      mutateOperations => build_all_operations($customer_id)});

  printf
    "%d mutate operations have been added so far.\n",
    $add_mutate_job_operations_response->{totalOperations};

  # You can use this next sequence token for calling addMutateJobOperations() next time.
  printf
    "Next sequence token for adding next operations is '%s'.\n",
    $add_mutate_job_operations_response->{nextSequenceToken};
}

# Requests the API to run the mutate job for executing all uploaded mutate job
# operations.
sub run_mutate_job {
  my ($mutate_job_service, $mutate_job_resource_name) = @_;

  my $mutate_job_lro =
    $mutate_job_service->run({resourceName => $mutate_job_resource_name});

  printf
    "Mutate job with resource name '%s' has been executed.\n",
    $mutate_job_resource_name;

  return $mutate_job_lro;
}

# Polls the server until the mutate job execution finishes by setting the initial
# poll delay time and the total time to wait before time-out.
sub poll_mutate_job {
  my ($operation_service, $mutate_job_lro) = @_;

  $operation_service->poll_until_done({<commit_msg>Update a code example a little bit.<commit_after>#!/usr/bin/perl -w
#
# Copyright 2019, Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example adds complete campaigns including campaign budgets, campaigns,
# ad groups and keywords using MutateJobService.

use strict;
use warnings;
use utf8;

use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::V3::Resources::CampaignBudget;
use Google::Ads::GoogleAds::V3::Resources::Campaign;
use Google::Ads::GoogleAds::V3::Resources::CampaignCriterion;
use Google::Ads::GoogleAds::V3::Resources::AdGroup;
use Google::Ads::GoogleAds::V3::Resources::AdGroupCriterion;
use Google::Ads::GoogleAds::V3::Resources::AdGroupAd;
use Google::Ads::GoogleAds::V3::Resources::Ad;
use Google::Ads::GoogleAds::V3::Common::ManualCpc;
use Google::Ads::GoogleAds::V3::Common::KeywordInfo;
use Google::Ads::GoogleAds::V3::Common::ExpandedTextAdInfo;
use Google::Ads::GoogleAds::V3::Enums::BudgetDeliveryMethodEnum qw(STANDARD);
use Google::Ads::GoogleAds::V3::Enums::AdvertisingChannelTypeEnum qw(SEARCH);
use Google::Ads::GoogleAds::V3::Enums::CampaignStatusEnum;
use Google::Ads::GoogleAds::V3::Enums::KeywordMatchTypeEnum qw(BROAD);
use Google::Ads::GoogleAds::V3::Enums::AdGroupTypeEnum qw(SEARCH_STANDARD);
use Google::Ads::GoogleAds::V3::Enums::AdGroupCriterionStatusEnum;
use Google::Ads::GoogleAds::V3::Enums::AdGroupAdStatusEnum;
use Google::Ads::GoogleAds::V3::Services::GoogleAdsService::MutateOperation;
use
  Google::Ads::GoogleAds::V3::Services::CampaignBudgetService::CampaignBudgetOperation;
use Google::Ads::GoogleAds::V3::Services::CampaignService::CampaignOperation;
use
  Google::Ads::GoogleAds::V3::Services::CampaignCriterionService::CampaignCriterionOperation;
use Google::Ads::GoogleAds::V3::Services::AdGroupService::AdGroupOperation;
use
  Google::Ads::GoogleAds::V3::Services::AdGroupCriterionService::AdGroupCriterionOperation;
use Google::Ads::GoogleAds::V3::Services::AdGroupAdService::AdGroupAdOperation;
use Google::Ads::GoogleAds::V3::Utils::ResourceNames;

use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);

use constant NUMBER_OF_CAMPAIGNS_TO_ADD => 2;
use constant NUMBER_OF_AD_GROUPS_TO_ADD => 2;
use constant NUMBER_OF_KEYWORDS_TO_ADD  => 4;
use constant POLL_FREQUENCY_SECONDS     => 1;
use constant POLL_TIMEOUT_SECONDS       => 60;

use constant PAGE_SIZE => 1000;

# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my $customer_id = "INSERT_CUSTOMER_ID_HERE";

sub add_complete_campaigns_using_mutate_job {
  my ($api_client, $customer_id) = @_;

  my $mutate_job_service = $api_client->MutateJobService();
  my $operation_service  = $api_client->OperationService();

  my $mutate_job_resource_name =
    create_mutate_job($mutate_job_service, $customer_id);

  add_all_mutate_job_operations($mutate_job_service, $customer_id,
    $mutate_job_resource_name);

  my $mutate_job_lro =
    run_mutate_job($mutate_job_service, $mutate_job_resource_name);

  poll_mutate_job($operation_service, $mutate_job_lro);

  fetch_and_print_results($mutate_job_service, $mutate_job_resource_name);

  return 1;
}

# Creates a new mutate job for the specified customer ID.
sub create_mutate_job {
  my ($mutate_job_service, $customer_id) = @_;

  my $mutate_job_resource_name = $mutate_job_service->create({
      customerId => $customer_id
    })->{resourceName};

  printf
    "Created a mutate job with resource name: '%s'.\n",
    $mutate_job_resource_name;

  return $mutate_job_resource_name;
}

# Adds all mutate job operations to the mutate job. As this is the first time for
# this mutate job, pass null as a sequence token. The response will contain the
# next sequence token that you can use to upload more operations in the future.
sub add_all_mutate_job_operations {
  my ($mutate_job_service, $customer_id, $mutate_job_resource_name) = @_;

  my $add_mutate_job_operations_response = $mutate_job_service->add_operations({
      resourceName     => $mutate_job_resource_name,
      sequenceToken    => undef,
      mutateOperations => build_all_operations($customer_id)});

  printf
    "%d mutate operations have been added so far.\n",
    $add_mutate_job_operations_response->{totalOperations};

  # You can use this next sequence token for calling add_operations() next time.
  printf
    "Next sequence token for adding next operations is '%s'.\n",
    $add_mutate_job_operations_response->{nextSequenceToken};
}

# Requests the API to run the mutate job for executing all uploaded mutate job
# operations.
sub run_mutate_job {
  my ($mutate_job_service, $mutate_job_resource_name) = @_;

  my $mutate_job_lro =
    $mutate_job_service->run({resourceName => $mutate_job_resource_name});

  printf
    "Mutate job with resource name '%s' has been executed.\n",
    $mutate_job_resource_name;

  return $mutate_job_lro;
}

# Polls the server until the mutate job execution finishes by setting the initial
# poll delay time and the total time to wait before time-out.
sub poll_mutate_job {
  my ($operation_service, $mutate_job_lro) = @_;

  $operation_service->poll_until_done({
{'fraction_non_alphanumeric': 0.11230615307653827, 'fraction_numerical': 0.007503751875937969, 'mean_word_length': 6.6110406091370555, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2406008', 'n_tokens_mistral': 3987, 'n_tokens_neox': 3905, 'n_words': 961}