From 57f715a36a004fdae02cc60b7a570a754faa6155 Mon Sep 17 00:00:00 2001 From: devchas Date: Fri, 3 Apr 2020 14:45:43 -0400 Subject: [PATCH 01/14] Add GetAccountHierarchy example --- .../GetAccountHierarchy.java | 260 ++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java new file mode 100644 index 0000000000..b00da6b242 --- /dev/null +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -0,0 +1,260 @@ +// Copyright 2020 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 +// +// https://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. + +package com.google.ads.googleads.examples.accountmanagement; + +import com.beust.jcommander.Parameter; +import com.google.ads.googleads.examples.utils.ArgumentNames; +import com.google.ads.googleads.examples.utils.CodeSampleParams; +import com.google.ads.googleads.lib.GoogleAdsClient; +import com.google.ads.googleads.v3.services.CustomerServiceClient; +import com.google.ads.googleads.v3.errors.GoogleAdsError; +import com.google.ads.googleads.v3.errors.GoogleAdsException; +import com.google.ads.googleads.v3.resources.CustomerClient; +import com.google.ads.googleads.v3.services.GoogleAdsRow; +import com.google.ads.googleads.v3.services.GoogleAdsServiceClient; +import com.google.ads.googleads.v3.services.GoogleAdsServiceClient.SearchPagedResponse; +import com.google.ads.googleads.v3.services.ListAccessibleCustomersRequest; +import com.google.ads.googleads.v3.services.ListAccessibleCustomersResponse; +import com.google.ads.googleads.v3.services.SearchGoogleAdsRequest; +import com.google.common.base.Strings; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Gets the account hierarchy of the specified manager account. If you don't specify manager + * customer ID, the example will instead print the hierarchies of all accessible customer accounts + * for your authenticated Google account. Note that if the list of accessible customers for your + * authenticated Google account includes accounts within the same hierarchy, this example will + * retrieve and print the overlapping portions of the hierarchy for each accessible customer. + */ +public class GetAccountHierarchy { + + private static final int PAGE_SIZE = 1_000; + + private static class GetAccountHierarchyParams extends CodeSampleParams { + + @Parameter(names = ArgumentNames.MANAGER_ID) + private Long managerId; + } + + public static void main(String[] args) { + GetAccountHierarchyParams params = new GetAccountHierarchyParams(); + if (!params.parseArguments(args)) { + + // Optional: You may pass the managerId on the command line or specify a managerId here. If + // neither are set, a null value will be passed to the run example method, and the example + // will print the hierarchies of all accessible customer IDs. + // params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); + } + + GoogleAdsClient googleAdsClient; + try { + googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build(); + } catch (FileNotFoundException fnfe) { + System.err.printf( + "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe); + return; + } catch (IOException ioe) { + System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe); + return; + } + + try { + new GetAccountHierarchy().runExample(googleAdsClient, params.managerId); + } catch (GoogleAdsException gae) { + // GoogleAdsException is the base class for most exceptions thrown by an API request. + // Instances of this exception have a message and a GoogleAdsFailure that contains a + // collection of GoogleAdsErrors that indicate the underlying causes of the + // GoogleAdsException. + System.err.printf( + "Request ID %s failed due to GoogleAdsException. Underlying errors:%n", + gae.getRequestId()); + int i = 0; + for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) { + System.err.printf(" Error %d: %s%n", i++, googleAdsError); + } + } + } + + /** + * Runs the examples. + * + * @param googleAdsClient the Google Ads API client. + * @param managerId managerCustomerId the customer ID. + */ + private void runExample(GoogleAdsClient googleAdsClient, Long managerId) { + List seedCustomerIds = new ArrayList<>(); + if (!(managerId == null)) { + seedCustomerIds.add(managerId); + } else { + // Issues a request for listing all accessible customers by this authenticated Google account. + try (CustomerServiceClient customerServiceClient = + googleAdsClient.getLatestVersion().createCustomerServiceClient()) { + ListAccessibleCustomersResponse accessibleCustomers = + customerServiceClient.listAccessibleCustomers( + ListAccessibleCustomersRequest.newBuilder().build()); + System.out.println( + "No manager customer ID is specified. The example will print the " + + "hierarchies of all accessible customer IDs:"); + + for (String customerResourceName : accessibleCustomers.getResourceNamesList()) { + long customer = + customerServiceClient.getCustomer(customerResourceName).getId().getValue(); + System.out.println(customer); + seedCustomerIds.add(customer); + } + } + } + + List unprocessedCustomerIds = new ArrayList<>(); + for (long seedCustomerId : seedCustomerIds) { + // Instantiates several variables used later. + Map> customerIdsToChildAccounts = new HashMap<>(); + CustomerClient rootCustomerClient = null; + int depth = 0; + // Adds the seed customer ID to the list of IDs to be processed. + unprocessedCustomerIds.add(seedCustomerId); + + // Creates the Google Ads Service client. + try (GoogleAdsServiceClient googleAdsServiceClient = + googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { + // Creates a query that retrieves all child accounts of the manager specified in search + // calls below. + String query = + "SELECT customer_client.client_customer, customer_client.level, " + + "customer_client.manager, customer_client.descriptive_name, " + + "customer_client.currency_code, customer_client.time_zone, " + + "customer_client.id " + + "FROM customer_client " + + "WHERE customer_client.level <= 1"; + + // Performs a breadth-first search algorithm to build a mapping of managers to their + // child accounts. The map keys are manager IDs, and the values are lists of those + // managers' direct child accounts, as represented by CustomerClient objects. + while (!unprocessedCustomerIds.isEmpty()) { + long customerId = unprocessedCustomerIds.get(0); + unprocessedCustomerIds.remove(0); + // Issues a search request by specifying page size. + SearchPagedResponse response = + googleAdsServiceClient.search( + SearchGoogleAdsRequest.newBuilder() + .setQuery(query) + .setCustomerId(Long.toString(customerId)) + .setPageSize(PAGE_SIZE) + .build()); + + // Iterates over all rows in all pages to get all customer clients under the specified + // customer's hierarchy. + for (GoogleAdsRow googleAdsRow : response.iterateAll()) { + CustomerClient customerClient = googleAdsRow.getCustomerClient(); + // The customer client making the request will be returned in the + // search result with a level of 0. + if (customerClient.getLevel().getValue() == 0) { + // Store the root customer client, which is the first encountered customer client + // that has level of 0. + if (rootCustomerClient == null) { + rootCustomerClient = customerClient; + } + // The steps below map parent and children accounts. Continue here so that managers + // accounts exclude themselves from the list of their children accounts. + continue; + } + + // For all level-1 (direct child) accounts that are manager accounts, the above + // query will be run against them to create a map of managers to their + // child accounts for printing the hierarchy afterwards. + List customerClientChildren = new ArrayList<>(); + // Updates the customerClientChildren with the list of children accounts if there + // exists an entry in the map for the given manager. + if (customerIdsToChildAccounts.containsKey(customerId)) { + customerClientChildren = customerIdsToChildAccounts.get(customerId); + } + // Adds the current child account to the list of the given manager's child accounts, + // which will be empty if the manager has not yet been added to the map. + customerClientChildren.add(customerClient); + // Inserts or updates the map for the given manager with the new list of child accounts. + customerIdsToChildAccounts.put(customerId, customerClientChildren); + // Checks is the child account is a manager itself so that it can later be processed + // and added to the map if it hasn't been already. + if (customerClient.getManager().getValue()) { + // A customer can be managed by multiple managers, so to prevent visiting the same + // customer multiple times, we need to check if it's already in the map. + boolean alreadyVisited = + customerIdsToChildAccounts.containsKey(customerClient.getId().getValue()); + if (!alreadyVisited && customerClient.getLevel().getValue() == 1) { + unprocessedCustomerIds.add(customerClient.getId().getValue()); + } + } + } + } + + if (!(rootCustomerClient == null)) { + System.out.printf( + "The hierarchy of customer ID %d is printed below.%n", + rootCustomerClient.getId().getValue()); + printAccountHierarchy(rootCustomerClient, customerIdsToChildAccounts, depth); + } else { + System.out.println( + "Customer ID is likely a test account, so its customer client " + + "information cannot be retrieved"); + } + } + } + } + + /** + * Prints the specified account's hierarchy using recursion. + * + * @param customerClient the customer client whose info will be printed and its child accounts + * will be processed if it's a manager. + * @param customerIdsToChildAccounts a map containing the account hierarchy information. The keys + * are manager account IDs, and the values are lists ofthe children for given manager + * accounts. + * @param depth the current depth we are printing from in the account hierarchy. + */ + private void printAccountHierarchy( + CustomerClient customerClient, + Map> customerIdsToChildAccounts, + int depth) { + String leadingSpace = " "; + if (depth == 0) { + System.out.println("Customer ID (Descriptive Name, Currency Code, Time Zone"); + leadingSpace = ""; + } else { + System.out.println("|"); + } + System.out.print(Strings.repeat("-", depth * 2)); + long customerId = customerClient.getId().getValue(); + System.out.printf( + leadingSpace + "%d ('%s', '%s', '%s')%n", + customerId, + customerClient.getDescriptiveName().getValue(), + customerClient.getCurrencyCode().getValue(), + customerClient.getTimeZone().getValue()); + + // Recursively calls this function for all child accounts of customerClient if the current + // customer is a manager account. + if (customerIdsToChildAccounts.containsKey(customerId)) { + for (CustomerClient childCustomer : customerIdsToChildAccounts.get(customerId)) { + printAccountHierarchy(childCustomer, customerIdsToChildAccounts, depth + 1); + } + } + } +} From cbf69340d98b159aeb09d985b7dab45bb50a3a7b Mon Sep 17 00:00:00 2001 From: devchas Date: Mon, 6 Apr 2020 16:58:10 -0400 Subject: [PATCH 02/14] Address comments and make managerId required --- .../GetAccountHierarchy.java | 219 +++++++----------- 1 file changed, 83 insertions(+), 136 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index b00da6b242..fcf1d5826f 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -18,39 +18,27 @@ import com.google.ads.googleads.examples.utils.ArgumentNames; import com.google.ads.googleads.examples.utils.CodeSampleParams; import com.google.ads.googleads.lib.GoogleAdsClient; -import com.google.ads.googleads.v3.services.CustomerServiceClient; import com.google.ads.googleads.v3.errors.GoogleAdsError; import com.google.ads.googleads.v3.errors.GoogleAdsException; import com.google.ads.googleads.v3.resources.CustomerClient; import com.google.ads.googleads.v3.services.GoogleAdsRow; import com.google.ads.googleads.v3.services.GoogleAdsServiceClient; import com.google.ads.googleads.v3.services.GoogleAdsServiceClient.SearchPagedResponse; -import com.google.ads.googleads.v3.services.ListAccessibleCustomersRequest; -import com.google.ads.googleads.v3.services.ListAccessibleCustomersResponse; import com.google.ads.googleads.v3.services.SearchGoogleAdsRequest; import com.google.common.base.Strings; - +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; import java.io.FileNotFoundException; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.HashSet; +import java.util.Set; -/** - * Gets the account hierarchy of the specified manager account. If you don't specify manager - * customer ID, the example will instead print the hierarchies of all accessible customer accounts - * for your authenticated Google account. Note that if the list of accessible customers for your - * authenticated Google account includes accounts within the same hierarchy, this example will - * retrieve and print the overlapping portions of the hierarchy for each accessible customer. - */ +/** Gets the account hierarchy of the specified manager account. */ public class GetAccountHierarchy { - private static final int PAGE_SIZE = 1_000; - private static class GetAccountHierarchyParams extends CodeSampleParams { - @Parameter(names = ArgumentNames.MANAGER_ID) + @Parameter(names = ArgumentNames.MANAGER_ID, required = true) private Long managerId; } @@ -58,10 +46,9 @@ public static void main(String[] args) { GetAccountHierarchyParams params = new GetAccountHierarchyParams(); if (!params.parseArguments(args)) { - // Optional: You may pass the managerId on the command line or specify a managerId here. If - // neither are set, a null value will be passed to the run example method, and the example - // will print the hierarchies of all accessible customer IDs. - // params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); + // Either pass the required parameters for this example on the command line, or insert them + // into the code here. See the parameter class definition above for descriptions. + params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); } GoogleAdsClient googleAdsClient; @@ -94,127 +81,89 @@ public static void main(String[] args) { } /** - * Runs the examples. + * Runs the example. * * @param googleAdsClient the Google Ads API client. - * @param managerId managerCustomerId the customer ID. + * @param managerId the root customer ID from which to begin the search. */ - private void runExample(GoogleAdsClient googleAdsClient, Long managerId) { - List seedCustomerIds = new ArrayList<>(); - if (!(managerId == null)) { - seedCustomerIds.add(managerId); - } else { - // Issues a request for listing all accessible customers by this authenticated Google account. - try (CustomerServiceClient customerServiceClient = - googleAdsClient.getLatestVersion().createCustomerServiceClient()) { - ListAccessibleCustomersResponse accessibleCustomers = - customerServiceClient.listAccessibleCustomers( - ListAccessibleCustomersRequest.newBuilder().build()); - System.out.println( - "No manager customer ID is specified. The example will print the " - + "hierarchies of all accessible customer IDs:"); - - for (String customerResourceName : accessibleCustomers.getResourceNamesList()) { - long customer = - customerServiceClient.getCustomer(customerResourceName).getId().getValue(); - System.out.println(customer); - seedCustomerIds.add(customer); - } - } - } + private void runExample(GoogleAdsClient googleAdsClient, long managerId) { + Set managerAccountsToSearch = new HashSet<>(); + CustomerClient rootCustomerClient = null; + int depth = 0; + + // Creates the Google Ads Service client. + try (GoogleAdsServiceClient googleAdsServiceClient = + googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { + // Creates a query that retrieves all child accounts of the manager specified in search + // calls below. + String query = + "SELECT customer_client.client_customer, customer_client.level, " + + "customer_client.manager, customer_client.descriptive_name, " + + "customer_client.currency_code, customer_client.time_zone, " + + "customer_client.id " + + "FROM customer_client " + + "WHERE customer_client.level <= 1"; - List unprocessedCustomerIds = new ArrayList<>(); - for (long seedCustomerId : seedCustomerIds) { - // Instantiates several variables used later. - Map> customerIdsToChildAccounts = new HashMap<>(); - CustomerClient rootCustomerClient = null; - int depth = 0; // Adds the seed customer ID to the list of IDs to be processed. - unprocessedCustomerIds.add(seedCustomerId); - - // Creates the Google Ads Service client. - try (GoogleAdsServiceClient googleAdsServiceClient = - googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { - // Creates a query that retrieves all child accounts of the manager specified in search - // calls below. - String query = - "SELECT customer_client.client_customer, customer_client.level, " - + "customer_client.manager, customer_client.descriptive_name, " - + "customer_client.currency_code, customer_client.time_zone, " - + "customer_client.id " - + "FROM customer_client " - + "WHERE customer_client.level <= 1"; - - // Performs a breadth-first search algorithm to build a mapping of managers to their - // child accounts. The map keys are manager IDs, and the values are lists of those - // managers' direct child accounts, as represented by CustomerClient objects. - while (!unprocessedCustomerIds.isEmpty()) { - long customerId = unprocessedCustomerIds.get(0); - unprocessedCustomerIds.remove(0); - // Issues a search request by specifying page size. - SearchPagedResponse response = - googleAdsServiceClient.search( - SearchGoogleAdsRequest.newBuilder() - .setQuery(query) - .setCustomerId(Long.toString(customerId)) - .setPageSize(PAGE_SIZE) - .build()); - - // Iterates over all rows in all pages to get all customer clients under the specified - // customer's hierarchy. - for (GoogleAdsRow googleAdsRow : response.iterateAll()) { - CustomerClient customerClient = googleAdsRow.getCustomerClient(); - // The customer client making the request will be returned in the - // search result with a level of 0. - if (customerClient.getLevel().getValue() == 0) { - // Store the root customer client, which is the first encountered customer client - // that has level of 0. - if (rootCustomerClient == null) { - rootCustomerClient = customerClient; - } - // The steps below map parent and children accounts. Continue here so that managers - // accounts exclude themselves from the list of their children accounts. - continue; + managerAccountsToSearch.add(managerId); + // Performs a breadth-first search algorithm to build a mapping of managers to their + // child accounts. + Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); + while (!managerAccountsToSearch.isEmpty()) { + long customerId = managerAccountsToSearch.iterator().next(); + managerAccountsToSearch.remove(customerId); + // Issues a search request by specifying page size. + SearchPagedResponse response = + googleAdsServiceClient.search( + SearchGoogleAdsRequest.newBuilder() + .setQuery(query) + .setCustomerId(Long.toString(customerId)) + .build()); + + // Iterates over all rows in all pages to get all customer clients under the specified + // customer's hierarchy. + for (GoogleAdsRow googleAdsRow : response.iterateAll()) { + CustomerClient customerClient = googleAdsRow.getCustomerClient(); + // The customer client making the request will be returned in the + // search result with a level of 0. + if (customerClient.getLevel().getValue() == 0) { + // Store the root customer client, which is the first encountered customer client + // that has level of 0. + if (rootCustomerClient == null) { + rootCustomerClient = customerClient; } + // The steps below map parent and children accounts. Continue here so that managers + // accounts exclude themselves from the list of their children accounts. + continue; + } - // For all level-1 (direct child) accounts that are manager accounts, the above - // query will be run against them to create a map of managers to their - // child accounts for printing the hierarchy afterwards. - List customerClientChildren = new ArrayList<>(); - // Updates the customerClientChildren with the list of children accounts if there - // exists an entry in the map for the given manager. - if (customerIdsToChildAccounts.containsKey(customerId)) { - customerClientChildren = customerIdsToChildAccounts.get(customerId); - } - // Adds the current child account to the list of the given manager's child accounts, - // which will be empty if the manager has not yet been added to the map. - customerClientChildren.add(customerClient); - // Inserts or updates the map for the given manager with the new list of child accounts. - customerIdsToChildAccounts.put(customerId, customerClientChildren); - // Checks is the child account is a manager itself so that it can later be processed - // and added to the map if it hasn't been already. - if (customerClient.getManager().getValue()) { - // A customer can be managed by multiple managers, so to prevent visiting the same - // customer multiple times, we need to check if it's already in the map. - boolean alreadyVisited = - customerIdsToChildAccounts.containsKey(customerClient.getId().getValue()); - if (!alreadyVisited && customerClient.getLevel().getValue() == 1) { - unprocessedCustomerIds.add(customerClient.getId().getValue()); - } + // For all level-1 (direct child) accounts that are manager accounts, the above + // query will be run against them to create a map of managers to their + // child accounts for printing the hierarchy afterwards. + customerIdsToChildAccounts.put(customerId, customerClient); + // Checks is the child account is a manager itself so that it can later be processed + // and added to the map if it hasn't been already. + if (customerClient.getManager().getValue()) { + // A customer can be managed by multiple managers, so to prevent visiting the same + // customer multiple times, we need to check if it's already in the map. + boolean alreadyVisited = + customerIdsToChildAccounts.containsKey(customerClient.getId().getValue()); + if (!alreadyVisited && customerClient.getLevel().getValue() == 1) { + managerAccountsToSearch.add(customerClient.getId().getValue()); } } } + } - if (!(rootCustomerClient == null)) { - System.out.printf( - "The hierarchy of customer ID %d is printed below.%n", - rootCustomerClient.getId().getValue()); - printAccountHierarchy(rootCustomerClient, customerIdsToChildAccounts, depth); - } else { - System.out.println( - "Customer ID is likely a test account, so its customer client " - + "information cannot be retrieved"); - } + if (!(rootCustomerClient == null)) { + System.out.printf( + "The hierarchy of customer ID %d is printed below.%n", + rootCustomerClient.getId().getValue()); + printAccountHierarchy(rootCustomerClient, customerIdsToChildAccounts, depth); + } else { + System.out.println( + "Customer ID is likely a test account, so its customer client " + + "information cannot be retrieved"); } } } @@ -224,14 +173,12 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId) { * * @param customerClient the customer client whose info will be printed and its child accounts * will be processed if it's a manager. - * @param customerIdsToChildAccounts a map containing the account hierarchy information. The keys - * are manager account IDs, and the values are lists ofthe children for given manager - * accounts. + * @param customerIdsToChildAccounts a map containing the account hierarchy information. * @param depth the current depth we are printing from in the account hierarchy. */ private void printAccountHierarchy( CustomerClient customerClient, - Map> customerIdsToChildAccounts, + Multimap customerIdsToChildAccounts, int depth) { String leadingSpace = " "; if (depth == 0) { From 207bbffefc555ae6c535aa6a6f325a533b5dbb5d Mon Sep 17 00:00:00 2001 From: devchas Date: Thu, 9 Apr 2020 11:46:53 -0400 Subject: [PATCH 03/14] Make managerId optional and add optional loginCustomerId --- .../GetAccountHierarchy.java | 245 ++++++++++++------ .../examples/utils/ArgumentNames.java | 1 + 2 files changed, 168 insertions(+), 78 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index fcf1d5826f..0ac78d3c43 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -21,16 +21,22 @@ import com.google.ads.googleads.v3.errors.GoogleAdsError; import com.google.ads.googleads.v3.errors.GoogleAdsException; import com.google.ads.googleads.v3.resources.CustomerClient; +import com.google.ads.googleads.v3.resources.CustomerName; +import com.google.ads.googleads.v3.services.CustomerServiceClient; import com.google.ads.googleads.v3.services.GoogleAdsRow; import com.google.ads.googleads.v3.services.GoogleAdsServiceClient; import com.google.ads.googleads.v3.services.GoogleAdsServiceClient.SearchPagedResponse; +import com.google.ads.googleads.v3.services.ListAccessibleCustomersRequest; +import com.google.ads.googleads.v3.services.ListAccessibleCustomersResponse; import com.google.ads.googleads.v3.services.SearchGoogleAdsRequest; import com.google.common.base.Strings; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; /** Gets the account hierarchy of the specified manager account. */ @@ -38,17 +44,35 @@ public class GetAccountHierarchy { private static class GetAccountHierarchyParams extends CodeSampleParams { - @Parameter(names = ArgumentNames.MANAGER_ID, required = true) + @Parameter(names = ArgumentNames.MANAGER_ID) private Long managerId; + + @Parameter(names = ArgumentNames.LOGIN_CUSTOMER_ID) + private Long loginCustomerId; } public static void main(String[] args) { GetAccountHierarchyParams params = new GetAccountHierarchyParams(); if (!params.parseArguments(args)) { - // Either pass the required parameters for this example on the command line, or insert them - // into the code here. See the parameter class definition above for descriptions. - params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); + // Optional: You may pass the managerId on the command line or specify a managerId here. If + // neither are set, a null value will be passed to the run example method, and the example + // will print the hierarchies of all accessible customer IDs. + // params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); + + // Optional: You may pass the loginCustomerId on the command line or specify a loginCustomerId + // here if and only if the managerId is set. If the loginCustomerId is set neither on the + // command line nor below, a null value will be passed to the run example method, and the + // example will use each respective accessible customer ID as the loginCustomerId. + // params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); + } + + if (params.managerId != null && params.loginCustomerId == null) { + System.err.println("loginCustomerId must be provided if managerId is provided."); + return; + } else if (params.managerId == null && params.loginCustomerId != null) { + System.err.println("loginCustomerId may not be provided if managerId is not provided."); + return; } GoogleAdsClient googleAdsClient; @@ -64,7 +88,8 @@ public static void main(String[] args) { } try { - new GetAccountHierarchy().runExample(googleAdsClient, params.managerId); + new GetAccountHierarchy() + .runExample(googleAdsClient, params.managerId, params.loginCustomerId); } catch (GoogleAdsException gae) { // GoogleAdsException is the base class for most exceptions thrown by an API request. // Instances of this exception have a message and a GoogleAdsFailure that contains a @@ -80,90 +105,154 @@ public static void main(String[] args) { } } + /** + * Creates a new GoogleAdsClient instance with the specified loginCustomerId. + * + * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. + * @return GoogleAdsClient. + */ + private GoogleAdsClient createGoogleAdsClient(long loginCustomerId) { + GoogleAdsClient googleAdsClient = null; + try { + googleAdsClient = + GoogleAdsClient.newBuilder() + .fromPropertiesFile() + .setLoginCustomerId(loginCustomerId) + .build(); + } catch (FileNotFoundException fnfe) { + System.err.printf( + "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe); + return null; + } catch (IOException ioe) { + System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe); + return null; + } + return googleAdsClient; + } + /** * Runs the example. * * @param googleAdsClient the Google Ads API client. * @param managerId the root customer ID from which to begin the search. */ - private void runExample(GoogleAdsClient googleAdsClient, long managerId) { - Set managerAccountsToSearch = new HashSet<>(); - CustomerClient rootCustomerClient = null; - int depth = 0; - - // Creates the Google Ads Service client. - try (GoogleAdsServiceClient googleAdsServiceClient = - googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { - // Creates a query that retrieves all child accounts of the manager specified in search - // calls below. - String query = - "SELECT customer_client.client_customer, customer_client.level, " - + "customer_client.manager, customer_client.descriptive_name, " - + "customer_client.currency_code, customer_client.time_zone, " - + "customer_client.id " - + "FROM customer_client " - + "WHERE customer_client.level <= 1"; - - // Adds the seed customer ID to the list of IDs to be processed. - managerAccountsToSearch.add(managerId); - // Performs a breadth-first search algorithm to build a mapping of managers to their - // child accounts. - Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); - while (!managerAccountsToSearch.isEmpty()) { - long customerId = managerAccountsToSearch.iterator().next(); - managerAccountsToSearch.remove(customerId); - // Issues a search request by specifying page size. - SearchPagedResponse response = - googleAdsServiceClient.search( - SearchGoogleAdsRequest.newBuilder() - .setQuery(query) - .setCustomerId(Long.toString(customerId)) - .build()); - - // Iterates over all rows in all pages to get all customer clients under the specified - // customer's hierarchy. - for (GoogleAdsRow googleAdsRow : response.iterateAll()) { - CustomerClient customerClient = googleAdsRow.getCustomerClient(); - // The customer client making the request will be returned in the - // search result with a level of 0. - if (customerClient.getLevel().getValue() == 0) { - // Store the root customer client, which is the first encountered customer client - // that has level of 0. - if (rootCustomerClient == null) { - rootCustomerClient = customerClient; - } - // The steps below map parent and children accounts. Continue here so that managers - // accounts exclude themselves from the list of their children accounts. - continue; - } + private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long loginCustomerId) { + List seedCustomerIds = new ArrayList<>(); + if (managerId != null) { + seedCustomerIds.add(managerId); + } else { + // Issues a request for listing all accessible customers by this authenticated Google account. + try (CustomerServiceClient customerServiceClient = + googleAdsClient.getLatestVersion().createCustomerServiceClient()) { + ListAccessibleCustomersResponse accessibleCustomers = + customerServiceClient.listAccessibleCustomers( + ListAccessibleCustomersRequest.newBuilder().build()); + System.out.println( + "No manager customer ID is specified. The example will print the " + + "hierarchies of all accessible customer IDs:"); - // For all level-1 (direct child) accounts that are manager accounts, the above - // query will be run against them to create a map of managers to their - // child accounts for printing the hierarchy afterwards. - customerIdsToChildAccounts.put(customerId, customerClient); - // Checks is the child account is a manager itself so that it can later be processed - // and added to the map if it hasn't been already. - if (customerClient.getManager().getValue()) { - // A customer can be managed by multiple managers, so to prevent visiting the same - // customer multiple times, we need to check if it's already in the map. - boolean alreadyVisited = - customerIdsToChildAccounts.containsKey(customerClient.getId().getValue()); - if (!alreadyVisited && customerClient.getLevel().getValue() == 1) { - managerAccountsToSearch.add(customerClient.getId().getValue()); - } - } + for (String customerResourceName : accessibleCustomers.getResourceNamesList()) { + long customer = Long.parseLong(CustomerName.parse(customerResourceName).getCustomer()); + System.out.println(customer); + seedCustomerIds.add(customer); } } + } - if (!(rootCustomerClient == null)) { - System.out.printf( - "The hierarchy of customer ID %d is printed below.%n", - rootCustomerClient.getId().getValue()); - printAccountHierarchy(rootCustomerClient, customerIdsToChildAccounts, depth); + for (long seedCustomerId : seedCustomerIds) { + Set managerAccountsToSearch = new HashSet<>(); + CustomerClient rootCustomerClient = null; + int depth = 0; + + if (loginCustomerId != null) { + googleAdsClient = createGoogleAdsClient(loginCustomerId); } else { - System.out.println( - "Customer ID is likely a test account, so its customer client " - + "information cannot be retrieved"); + googleAdsClient = createGoogleAdsClient(seedCustomerId); + } + + if (googleAdsClient == null) { + return; + } + + // Creates the Google Ads Service client. + try (GoogleAdsServiceClient googleAdsServiceClient = + googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { + // Creates a query that retrieves all child accounts of the manager specified in search + // calls below. + String query = + "SELECT customer_client.client_customer, customer_client.level, " + + "customer_client.manager, customer_client.descriptive_name, " + + "customer_client.currency_code, customer_client.time_zone, " + + "customer_client.id " + + "FROM customer_client " + + "WHERE customer_client.level <= 1"; + + // Adds the seed customer ID to the list of IDs to be processed. + managerAccountsToSearch.add(seedCustomerId); + // Performs a breadth-first search algorithm to build a mapping of managers to their + // child accounts. + Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); + while (!managerAccountsToSearch.isEmpty()) { + long customerId = managerAccountsToSearch.iterator().next(); + managerAccountsToSearch.remove(customerId); + SearchPagedResponse response = null; + try { + // Issues a search request. + response = + googleAdsServiceClient.search( + SearchGoogleAdsRequest.newBuilder() + .setQuery(query) + .setCustomerId(Long.toString(customerId)) + .build()); + + // Iterates over all rows in all pages to get all customer clients under the specified + // customer's hierarchy. + for (GoogleAdsRow googleAdsRow : response.iterateAll()) { + CustomerClient customerClient = googleAdsRow.getCustomerClient(); + // The customer client making the request will be returned in the + // search result with a level of 0. + if (customerClient.getLevel().getValue() == 0) { + // Store the root customer client, which is the first encountered customer client + // that has level of 0. + if (rootCustomerClient == null) { + rootCustomerClient = customerClient; + } + // The steps below map parent and children accounts. Continue here so that managers + // accounts exclude themselves from the list of their children accounts. + continue; + } + + // For all level-1 (direct child) accounts that are manager accounts, the above + // query will be run against them to create a map of managers to their + // child accounts for printing the hierarchy afterwards. + customerIdsToChildAccounts.put(customerId, customerClient); + // Checks is the child account is a manager itself so that it can later be processed + // and added to the map if it hasn't been already. + if (customerClient.getManager().getValue()) { + // A customer can be managed by multiple managers, so to prevent visiting the same + // customer multiple times, we need to check if it's already in the map. + boolean alreadyVisited = + customerIdsToChildAccounts.containsKey(customerClient.getId().getValue()); + if (!alreadyVisited && customerClient.getLevel().getValue() == 1) { + managerAccountsToSearch.add(customerClient.getId().getValue()); + } + } + } + } catch (GoogleAdsException gae) { + System.out.printf("Unable to retrieve hierarchy: %s%n", gae); + } + } + + if (!(rootCustomerClient == null)) { + System.out.printf( + "The hierarchy of customer ID %d is printed below.%n", + rootCustomerClient.getId().getValue()); + printAccountHierarchy(rootCustomerClient, customerIdsToChildAccounts, depth); + } else { + System.out.println( + "Customer ID is likely a test account, so its customer client " + + "information cannot be retrieved."); + } } } } diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java index d9527f8e80..1b3d452105 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java @@ -42,6 +42,7 @@ public final class ArgumentNames { public static final String KEYWORD_TEXT = "--keywordText"; public static final String LANGUAGE_ID = "--languageId"; public static final String LOCATION_ID = "--locationId"; + public static final String LOGIN_CUSTOMER_ID = "--loginCustomerId"; public static final String RECOMMENDATION_ID = "--recommendationId"; public static final String RESTATEMENT_VALUE = "--restatementValue"; public static final String HOTEL_CENTER_ACCOUNT_ID = "--hotelCenterAccountId"; From 2dfb4191ff18a86f97aacd73f5612e5f94dc111f Mon Sep 17 00:00:00 2001 From: devchas Date: Thu, 9 Apr 2020 16:27:32 -0400 Subject: [PATCH 04/14] Address comments --- .../GetAccountHierarchy.java | 260 +++++++++++------- 1 file changed, 162 insertions(+), 98 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 0ac78d3c43..19125bbf4f 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -35,8 +35,10 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; /** Gets the account hierarchy of the specified manager account. */ @@ -109,10 +111,10 @@ public static void main(String[] args) { * Creates a new GoogleAdsClient instance with the specified loginCustomerId. * * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. - * @return GoogleAdsClient. + * @return a GoogleAdsClient instance. */ private GoogleAdsClient createGoogleAdsClient(long loginCustomerId) { - GoogleAdsClient googleAdsClient = null; + GoogleAdsClient googleAdsClient; try { googleAdsClient = GoogleAdsClient.newBuilder() @@ -135,126 +137,188 @@ private GoogleAdsClient createGoogleAdsClient(long loginCustomerId) { * * @param googleAdsClient the Google Ads API client. * @param managerId the root customer ID from which to begin the search. + * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. */ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long loginCustomerId) { List seedCustomerIds = new ArrayList<>(); if (managerId != null) { seedCustomerIds.add(managerId); } else { - // Issues a request for listing all accessible customers by this authenticated Google account. - try (CustomerServiceClient customerServiceClient = - googleAdsClient.getLatestVersion().createCustomerServiceClient()) { - ListAccessibleCustomersResponse accessibleCustomers = - customerServiceClient.listAccessibleCustomers( - ListAccessibleCustomersRequest.newBuilder().build()); - System.out.println( - "No manager customer ID is specified. The example will print the " - + "hierarchies of all accessible customer IDs:"); - - for (String customerResourceName : accessibleCustomers.getResourceNamesList()) { - long customer = Long.parseLong(CustomerName.parse(customerResourceName).getCustomer()); - System.out.println(customer); - seedCustomerIds.add(customer); - } - } + seedCustomerIds = getAccessibleCustomers(googleAdsClient); } + Map> customerClientsToHierarchies = + new HashMap<>(); + List accountsWithNoInfo = new ArrayList<>(); + // Constructs a map of account hierarchies. for (long seedCustomerId : seedCustomerIds) { - Set managerAccountsToSearch = new HashSet<>(); - CustomerClient rootCustomerClient = null; - int depth = 0; + Map> customerClientToHierarchy = + createCustomerClientToHierarchy(loginCustomerId, seedCustomerId); - if (loginCustomerId != null) { - googleAdsClient = createGoogleAdsClient(loginCustomerId); + if (customerClientToHierarchy != null) { + customerClientsToHierarchies.putAll(customerClientToHierarchy); } else { - googleAdsClient = createGoogleAdsClient(seedCustomerId); + accountsWithNoInfo.add(seedCustomerId); } + } - if (googleAdsClient == null) { - return; + // Prints the IDs of any accounts that did not produce hierarchy information. + if (!accountsWithNoInfo.isEmpty()) { + System.out.println( + "Unable to retrieve information for the following accounts which are likely either test " + + "accounts with setup issues. Please check the logs for additional details."); + for (long accountId : accountsWithNoInfo) { + System.out.println(accountId); } + System.out.println(); + } - // Creates the Google Ads Service client. - try (GoogleAdsServiceClient googleAdsServiceClient = - googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { - // Creates a query that retrieves all child accounts of the manager specified in search - // calls below. - String query = - "SELECT customer_client.client_customer, customer_client.level, " - + "customer_client.manager, customer_client.descriptive_name, " - + "customer_client.currency_code, customer_client.time_zone, " - + "customer_client.id " - + "FROM customer_client " - + "WHERE customer_client.level <= 1"; - - // Adds the seed customer ID to the list of IDs to be processed. - managerAccountsToSearch.add(seedCustomerId); - // Performs a breadth-first search algorithm to build a mapping of managers to their - // child accounts. - Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); - while (!managerAccountsToSearch.isEmpty()) { - long customerId = managerAccountsToSearch.iterator().next(); - managerAccountsToSearch.remove(customerId); - SearchPagedResponse response = null; - try { - // Issues a search request. - response = - googleAdsServiceClient.search( - SearchGoogleAdsRequest.newBuilder() - .setQuery(query) - .setCustomerId(Long.toString(customerId)) - .build()); - - // Iterates over all rows in all pages to get all customer clients under the specified - // customer's hierarchy. - for (GoogleAdsRow googleAdsRow : response.iterateAll()) { - CustomerClient customerClient = googleAdsRow.getCustomerClient(); - // The customer client making the request will be returned in the - // search result with a level of 0. - if (customerClient.getLevel().getValue() == 0) { - // Store the root customer client, which is the first encountered customer client - // that has level of 0. - if (rootCustomerClient == null) { - rootCustomerClient = customerClient; - } - // The steps below map parent and children accounts. Continue here so that managers - // accounts exclude themselves from the list of their children accounts. - continue; - } + int depth = 0; + // Prints the hierarchy information for all accounts for which there is hierarchy information + // available. + for (CustomerClient rootCustomerClient : customerClientsToHierarchies.keySet()) { + System.out.printf( + "The hierarchy of customer ID %d is printed below.%n", + rootCustomerClient.getId().getValue()); + printAccountHierarchy( + rootCustomerClient, customerClientsToHierarchies.get(rootCustomerClient), depth); + System.out.println(); + } + } + + /** + * Creates a map between a CustomerClient and each of its managers' mappings. + * + * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. + * @param seedCustomerId the ID of the customer at the root of the tree. + * @return a map between a CustomerClient and each of its managers' mappings. + */ + private Map> createCustomerClientToHierarchy( + Long loginCustomerId, long seedCustomerId) { + Set managerAccountsToSearch = new HashSet<>(); + CustomerClient rootCustomerClient = null; + + GoogleAdsClient googleAdsClient; + // Creates a GoogleAdsClient with the specified loginCustomerId. See + // https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid for more + // information. + if (loginCustomerId != null) { + googleAdsClient = createGoogleAdsClient(loginCustomerId); + } else { + googleAdsClient = createGoogleAdsClient(seedCustomerId); + } + + if (googleAdsClient == null) { + return null; + } - // For all level-1 (direct child) accounts that are manager accounts, the above - // query will be run against them to create a map of managers to their - // child accounts for printing the hierarchy afterwards. - customerIdsToChildAccounts.put(customerId, customerClient); - // Checks is the child account is a manager itself so that it can later be processed - // and added to the map if it hasn't been already. - if (customerClient.getManager().getValue()) { - // A customer can be managed by multiple managers, so to prevent visiting the same - // customer multiple times, we need to check if it's already in the map. - boolean alreadyVisited = - customerIdsToChildAccounts.containsKey(customerClient.getId().getValue()); - if (!alreadyVisited && customerClient.getLevel().getValue() == 1) { - managerAccountsToSearch.add(customerClient.getId().getValue()); - } + // Creates the Google Ads Service client. + try (GoogleAdsServiceClient googleAdsServiceClient = + googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { + // Creates a query that retrieves all child accounts of the manager specified in search + // calls below. + String query = + "SELECT customer_client.client_customer, customer_client.level, " + + "customer_client.manager, customer_client.descriptive_name, " + + "customer_client.currency_code, customer_client.time_zone, " + + "customer_client.id " + + "FROM customer_client " + + "WHERE customer_client.level <= 1"; + + // Adds the seed customer ID to the list of IDs to be processed. + managerAccountsToSearch.add(seedCustomerId); + // Performs a breadth-first search algorithm to build a mapping of managers to their + // child accounts. + Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); + while (!managerAccountsToSearch.isEmpty()) { + long customerId = managerAccountsToSearch.iterator().next(); + managerAccountsToSearch.remove(customerId); + SearchPagedResponse response = null; + try { + // Issues a search request. + response = + googleAdsServiceClient.search( + SearchGoogleAdsRequest.newBuilder() + .setQuery(query) + .setCustomerId(Long.toString(customerId)) + .build()); + + // Iterates over all rows in all pages to get all customer clients under the specified + // customer's hierarchy. + for (GoogleAdsRow googleAdsRow : response.iterateAll()) { + CustomerClient customerClient = googleAdsRow.getCustomerClient(); + + if (customerClient.getId().getValue() == seedCustomerId) { + rootCustomerClient = customerClient; + } + + // The steps below map parent and children accounts. Continue here so that managers + // accounts exclude themselves from the list of their children accounts. + if (customerClient.getId().getValue() == customerId) { + continue; + } + + // For all level-1 (direct child) accounts that are manager accounts, the above + // query will be run against them to create a map of managers to their + // child accounts for printing the hierarchy afterwards. + customerIdsToChildAccounts.put(customerId, customerClient); + // Checks is the child account is a manager itself so that it can later be processed + // and added to the map if it hasn't been already. + if (customerClient.getManager().getValue()) { + // A customer can be managed by multiple managers, so to prevent visiting the same + // customer multiple times, we need to check if it's already in the map. + boolean alreadyVisited = + customerIdsToChildAccounts.containsKey(customerClient.getId().getValue()); + if (!alreadyVisited && customerClient.getLevel().getValue() == 1) { + managerAccountsToSearch.add(customerClient.getId().getValue()); } } - } catch (GoogleAdsException gae) { - System.out.printf("Unable to retrieve hierarchy: %s%n", gae); } + } catch (GoogleAdsException gae) { + System.out.printf( + "Unable to retrieve hierarchy for customer ID %d: %s%n", + customerId, gae.getGoogleAdsFailure().getErrors(0).getMessage()); } + } - if (!(rootCustomerClient == null)) { - System.out.printf( - "The hierarchy of customer ID %d is printed below.%n", - rootCustomerClient.getId().getValue()); - printAccountHierarchy(rootCustomerClient, customerIdsToChildAccounts, depth); - } else { - System.out.println( - "Customer ID is likely a test account, so its customer client " - + "information cannot be retrieved."); + if (rootCustomerClient == null) { + return null; + } + + CustomerClient finalRootCustomerClient = rootCustomerClient; + return new HashMap>() { + { + put(finalRootCustomerClient, customerIdsToChildAccounts); } + }; + } + } + + /** + * Retrieves a list of accessible customers with the provided set up credentials. + * + * @param googleAdsClient the Google Ads API client. + * @return a list of customer IDs. + */ + private List getAccessibleCustomers(GoogleAdsClient googleAdsClient) { + List seedCustomerIds = new ArrayList<>(); + // Issues a request for listing all accessible customers by this authenticated Google account. + try (CustomerServiceClient customerServiceClient = + googleAdsClient.getLatestVersion().createCustomerServiceClient()) { + ListAccessibleCustomersResponse accessibleCustomers = + customerServiceClient.listAccessibleCustomers( + ListAccessibleCustomersRequest.newBuilder().build()); + System.out.println( + "No manager customer ID is specified. The example will print the " + + "hierarchies of all accessible customer IDs:"); + + for (String customerResourceName : accessibleCustomers.getResourceNamesList()) { + long customer = Long.parseLong(CustomerName.parse(customerResourceName).getCustomer()); + System.out.println(customer); + seedCustomerIds.add(customer); } } + return seedCustomerIds; } /** From 6e3863fc4ba3b51e7ef1d0de6c13fc1e3702ec11 Mon Sep 17 00:00:00 2001 From: devchas Date: Fri, 10 Apr 2020 12:59:22 -0400 Subject: [PATCH 05/14] Address fiboknacky comments --- .../GetAccountHierarchy.java | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 19125bbf4f..9a06ebd799 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -66,7 +66,7 @@ public static void main(String[] args) { // here if and only if the managerId is set. If the loginCustomerId is set neither on the // command line nor below, a null value will be passed to the run example method, and the // example will use each respective accessible customer ID as the loginCustomerId. - // params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); + // params.managerId = Long.parseLong("INSERT_LOGIN_CUSTOMER_ID_HERE"); } if (params.managerId != null && params.loginCustomerId == null) { @@ -107,31 +107,6 @@ public static void main(String[] args) { } } - /** - * Creates a new GoogleAdsClient instance with the specified loginCustomerId. - * - * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. - * @return a GoogleAdsClient instance. - */ - private GoogleAdsClient createGoogleAdsClient(long loginCustomerId) { - GoogleAdsClient googleAdsClient; - try { - googleAdsClient = - GoogleAdsClient.newBuilder() - .fromPropertiesFile() - .setLoginCustomerId(loginCustomerId) - .build(); - } catch (FileNotFoundException fnfe) { - System.err.printf( - "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe); - return null; - } catch (IOException ioe) { - System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe); - return null; - } - return googleAdsClient; - } - /** * Runs the example. * @@ -147,8 +122,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo seedCustomerIds = getAccessibleCustomers(googleAdsClient); } - Map> customerClientsToHierarchies = - new HashMap<>(); + Map> allHierarchies = new HashMap<>(); List accountsWithNoInfo = new ArrayList<>(); // Constructs a map of account hierarchies. for (long seedCustomerId : seedCustomerIds) { @@ -156,7 +130,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo createCustomerClientToHierarchy(loginCustomerId, seedCustomerId); if (customerClientToHierarchy != null) { - customerClientsToHierarchies.putAll(customerClientToHierarchy); + allHierarchies.putAll(customerClientToHierarchy); } else { accountsWithNoInfo.add(seedCustomerId); } @@ -176,22 +150,49 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo int depth = 0; // Prints the hierarchy information for all accounts for which there is hierarchy information // available. - for (CustomerClient rootCustomerClient : customerClientsToHierarchies.keySet()) { + for (CustomerClient rootCustomerClient : allHierarchies.keySet()) { System.out.printf( "The hierarchy of customer ID %d is printed below.%n", rootCustomerClient.getId().getValue()); - printAccountHierarchy( - rootCustomerClient, customerClientsToHierarchies.get(rootCustomerClient), depth); + printAccountHierarchy(rootCustomerClient, allHierarchies.get(rootCustomerClient), depth); System.out.println(); } } + /** + * Creates a new GoogleAdsClient instance with the specified loginCustomerId. + * + * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. + * @return a GoogleAdsClient instance. Returns null if the GoogleAdsClient cannot be created. + */ + private GoogleAdsClient createGoogleAdsClient(long loginCustomerId) { + GoogleAdsClient googleAdsClient; + try { + googleAdsClient = + GoogleAdsClient.newBuilder() + .fromPropertiesFile() + .setLoginCustomerId(loginCustomerId) + .build(); + } catch (FileNotFoundException fnfe) { + System.err.printf( + "Failed to load GoogleAdsClient configuration from file with loginCustomerId %d. " + + "Exception: %s%n", loginCustomerId, fnfe); + return null; + } catch (IOException ioe) { + System.err.printf("Failed to create GoogleAdsClient with loginCustomerId %d. Exception: %s%n", + loginCustomerId, ioe); + return null; + } + return googleAdsClient; + } + /** * Creates a map between a CustomerClient and each of its managers' mappings. * * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. * @param seedCustomerId the ID of the customer at the root of the tree. - * @return a map between a CustomerClient and each of its managers' mappings. + * @return a map between a CustomerClient and each of its managers' mappings if the account + * hierarchy can be retrieved. If the account hierarchy cannot be retrieved, returns null. */ private Map> createCustomerClientToHierarchy( Long loginCustomerId, long seedCustomerId) { @@ -208,6 +209,10 @@ private Map> createCustomerClient googleAdsClient = createGoogleAdsClient(seedCustomerId); } + // The createGoogleAdsClient method returns null if a GoogleAdsClient cannot be created. In + // that case, the account hierarchy for the given seedCustomerId will be able to be + // retrieved. This method returns null in that case to add the seedCustomerId to the list of + // customer IDs for which the account hierarchy could not be retrieved. if (googleAdsClient == null) { return null; } @@ -262,7 +267,7 @@ private Map> createCustomerClient // query will be run against them to create a map of managers to their // child accounts for printing the hierarchy afterwards. customerIdsToChildAccounts.put(customerId, customerClient); - // Checks is the child account is a manager itself so that it can later be processed + // Checks if the child account is a manager itself so that it can later be processed // and added to the map if it hasn't been already. if (customerClient.getManager().getValue()) { // A customer can be managed by multiple managers, so to prevent visiting the same @@ -281,16 +286,18 @@ private Map> createCustomerClient } } + // The rootCustomerClient will be null if the account hierarchy was unable to be retrieved + // (e.g. the account is a test account or a client account with an incomplete billing setup. + // This method returns null in these cases to add the seedCustomerId to the list of + // customer IDs for which the account hierarchy could not be retrieved. if (rootCustomerClient == null) { return null; } - CustomerClient finalRootCustomerClient = rootCustomerClient; - return new HashMap>() { - { - put(finalRootCustomerClient, customerIdsToChildAccounts); - } - }; + Map> CustomerClientToHierarchy = + new HashMap<>(); + CustomerClientToHierarchy.put(rootCustomerClient, customerIdsToChildAccounts); + return CustomerClientToHierarchy; } } From 6ef739297ae7871cee115e4bc05ce3500084b3d1 Mon Sep 17 00:00:00 2001 From: devchas Date: Mon, 13 Apr 2020 11:18:21 -0400 Subject: [PATCH 06/14] Address comments --- .../GetAccountHierarchy.java | 60 +++++++------------ 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 9a06ebd799..11b17289f5 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -41,7 +41,13 @@ import java.util.Map; import java.util.Set; -/** Gets the account hierarchy of the specified manager account. */ +/** + * Gets the account hierarchy of the specified manager account. If you don't specify manager ID, + * the example will instead print the hierarchies of all accessible customer accounts + * for your authenticated Google account. Note that if the list of accessible customers for your + * authenticated Google account includes accounts within the same hierarchy, this example will + * retrieve and print the overlapping portions of the hierarchy for each accessible customer. + */ public class GetAccountHierarchy { private static class GetAccountHierarchyParams extends CodeSampleParams { @@ -114,11 +120,13 @@ public static void main(String[] args) { * @param managerId the root customer ID from which to begin the search. * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. */ - private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long loginCustomerId) { + private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long loginCustomerId) { List seedCustomerIds = new ArrayList<>(); if (managerId != null) { + // Only gets the hierarchy for the provided manager ID if provided. seedCustomerIds.add(managerId); } else { + // Otherwise gets the account hierarchies for all accessible customers. seedCustomerIds = getAccessibleCustomers(googleAdsClient); } @@ -140,7 +148,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo if (!accountsWithNoInfo.isEmpty()) { System.out.println( "Unable to retrieve information for the following accounts which are likely either test " - + "accounts with setup issues. Please check the logs for additional details."); + + "accounts or accounts with setup issues. Please check the logs for details."); for (long accountId : accountsWithNoInfo) { System.out.println(accountId); } @@ -152,7 +160,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo // available. for (CustomerClient rootCustomerClient : allHierarchies.keySet()) { System.out.printf( - "The hierarchy of customer ID %d is printed below.%n", + "Hierarchy of customer ID %d:%n", rootCustomerClient.getId().getValue()); printAccountHierarchy(rootCustomerClient, allHierarchies.get(rootCustomerClient), depth); System.out.println(); @@ -162,28 +170,14 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo /** * Creates a new GoogleAdsClient instance with the specified loginCustomerId. * - * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. + * @param customerId the customerId used as the loginCustomerId to create the GoogleAdsClient. * @return a GoogleAdsClient instance. Returns null if the GoogleAdsClient cannot be created. */ - private GoogleAdsClient createGoogleAdsClient(long loginCustomerId) { + private GoogleAdsClient createGoogleAdsClient(long customerId) throws IOException { GoogleAdsClient googleAdsClient; - try { googleAdsClient = - GoogleAdsClient.newBuilder() - .fromPropertiesFile() - .setLoginCustomerId(loginCustomerId) - .build(); - } catch (FileNotFoundException fnfe) { - System.err.printf( - "Failed to load GoogleAdsClient configuration from file with loginCustomerId %d. " + - "Exception: %s%n", loginCustomerId, fnfe); - return null; - } catch (IOException ioe) { - System.err.printf("Failed to create GoogleAdsClient with loginCustomerId %d. Exception: %s%n", - loginCustomerId, ioe); - return null; - } - return googleAdsClient; + GoogleAdsClient.newBuilder().fromPropertiesFile().setLoginCustomerId(customerId).build(); + return googleAdsClient; } /** @@ -195,7 +189,7 @@ private GoogleAdsClient createGoogleAdsClient(long loginCustomerId) { * hierarchy can be retrieved. If the account hierarchy cannot be retrieved, returns null. */ private Map> createCustomerClientToHierarchy( - Long loginCustomerId, long seedCustomerId) { + Long loginCustomerId, long seedCustomerId) throws IOException { Set managerAccountsToSearch = new HashSet<>(); CustomerClient rootCustomerClient = null; @@ -209,14 +203,6 @@ private Map> createCustomerClient googleAdsClient = createGoogleAdsClient(seedCustomerId); } - // The createGoogleAdsClient method returns null if a GoogleAdsClient cannot be created. In - // that case, the account hierarchy for the given seedCustomerId will be able to be - // retrieved. This method returns null in that case to add the seedCustomerId to the list of - // customer IDs for which the account hierarchy could not be retrieved. - if (googleAdsClient == null) { - return null; - } - // Creates the Google Ads Service client. try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { @@ -294,10 +280,10 @@ private Map> createCustomerClient return null; } - Map> CustomerClientToHierarchy = + Map> customerClientToHierarchy = new HashMap<>(); - CustomerClientToHierarchy.put(rootCustomerClient, customerIdsToChildAccounts); - return CustomerClientToHierarchy; + customerClientToHierarchy.put(rootCustomerClient, customerIdsToChildAccounts); + return customerClientToHierarchy; } } @@ -358,10 +344,8 @@ private void printAccountHierarchy( // Recursively calls this function for all child accounts of customerClient if the current // customer is a manager account. - if (customerIdsToChildAccounts.containsKey(customerId)) { - for (CustomerClient childCustomer : customerIdsToChildAccounts.get(customerId)) { - printAccountHierarchy(childCustomer, customerIdsToChildAccounts, depth + 1); - } + for (CustomerClient childCustomer : customerIdsToChildAccounts.get(customerId)) { + printAccountHierarchy(childCustomer, customerIdsToChildAccounts, depth + 1); } } } From 816da865de71487a4ec7202b8113858b1e1e67a3 Mon Sep 17 00:00:00 2001 From: devchas Date: Mon, 13 Apr 2020 11:21:42 -0400 Subject: [PATCH 07/14] Handle unhandled exception --- .../GetAccountHierarchy.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 11b17289f5..a68028bde3 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -42,9 +42,9 @@ import java.util.Set; /** - * Gets the account hierarchy of the specified manager account. If you don't specify manager ID, - * the example will instead print the hierarchies of all accessible customer accounts - * for your authenticated Google account. Note that if the list of accessible customers for your + * Gets the account hierarchy of the specified manager account. If you don't specify manager ID, the + * example will instead print the hierarchies of all accessible customer accounts for your + * authenticated Google account. Note that if the list of accessible customers for your * authenticated Google account includes accounts within the same hierarchy, this example will * retrieve and print the overlapping portions of the hierarchy for each accessible customer. */ @@ -110,6 +110,8 @@ public static void main(String[] args) { for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) { System.err.printf(" Error %d: %s%n", i++, googleAdsError); } + } catch (IOException ioe) { + System.err.printf("Request failed. Exception: %s%n", ioe); } } @@ -120,7 +122,8 @@ public static void main(String[] args) { * @param managerId the root customer ID from which to begin the search. * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. */ - private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long loginCustomerId) { + private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long loginCustomerId) + throws IOException { List seedCustomerIds = new ArrayList<>(); if (managerId != null) { // Only gets the hierarchy for the provided manager ID if provided. @@ -159,9 +162,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long lo // Prints the hierarchy information for all accounts for which there is hierarchy information // available. for (CustomerClient rootCustomerClient : allHierarchies.keySet()) { - System.out.printf( - "Hierarchy of customer ID %d:%n", - rootCustomerClient.getId().getValue()); + System.out.printf("Hierarchy of customer ID %d:%n", rootCustomerClient.getId().getValue()); printAccountHierarchy(rootCustomerClient, allHierarchies.get(rootCustomerClient), depth); System.out.println(); } @@ -175,9 +176,9 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long lo */ private GoogleAdsClient createGoogleAdsClient(long customerId) throws IOException { GoogleAdsClient googleAdsClient; - googleAdsClient = - GoogleAdsClient.newBuilder().fromPropertiesFile().setLoginCustomerId(customerId).build(); - return googleAdsClient; + googleAdsClient = + GoogleAdsClient.newBuilder().fromPropertiesFile().setLoginCustomerId(customerId).build(); + return googleAdsClient; } /** From d7941dc4f78bf71cbdaccb78122242e80a11d4da Mon Sep 17 00:00:00 2001 From: devchas Date: Mon, 13 Apr 2020 11:42:35 -0400 Subject: [PATCH 08/14] Remove createGoogleAdsClient method --- .../GetAccountHierarchy.java | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index a68028bde3..60a201688b 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -168,19 +168,6 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long lo } } - /** - * Creates a new GoogleAdsClient instance with the specified loginCustomerId. - * - * @param customerId the customerId used as the loginCustomerId to create the GoogleAdsClient. - * @return a GoogleAdsClient instance. Returns null if the GoogleAdsClient cannot be created. - */ - private GoogleAdsClient createGoogleAdsClient(long customerId) throws IOException { - GoogleAdsClient googleAdsClient; - googleAdsClient = - GoogleAdsClient.newBuilder().fromPropertiesFile().setLoginCustomerId(customerId).build(); - return googleAdsClient; - } - /** * Creates a map between a CustomerClient and each of its managers' mappings. * @@ -194,15 +181,14 @@ private Map> createCustomerClient Set managerAccountsToSearch = new HashSet<>(); CustomerClient rootCustomerClient = null; - GoogleAdsClient googleAdsClient; // Creates a GoogleAdsClient with the specified loginCustomerId. See // https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid for more // information. - if (loginCustomerId != null) { - googleAdsClient = createGoogleAdsClient(loginCustomerId); - } else { - googleAdsClient = createGoogleAdsClient(seedCustomerId); - } + GoogleAdsClient googleAdsClient = GoogleAdsClient.newBuilder() + .fromPropertiesFile() + .setLoginCustomerId( + loginCustomerId != null ? loginCustomerId : seedCustomerId) + .build(); // Creates the Google Ads Service client. try (GoogleAdsServiceClient googleAdsServiceClient = @@ -225,7 +211,7 @@ private Map> createCustomerClient while (!managerAccountsToSearch.isEmpty()) { long customerId = managerAccountsToSearch.iterator().next(); managerAccountsToSearch.remove(customerId); - SearchPagedResponse response = null; + SearchPagedResponse response; try { // Issues a search request. response = From afe62deed05fe140b0919240a8c3dedc05dfe032 Mon Sep 17 00:00:00 2001 From: devchas Date: Wed, 15 Apr 2020 09:46:48 -0400 Subject: [PATCH 09/14] Address comments --- .../GetAccountHierarchy.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 60a201688b..7c7c74b22f 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -42,11 +42,12 @@ import java.util.Set; /** - * Gets the account hierarchy of the specified manager account. If you don't specify manager ID, the - * example will instead print the hierarchies of all accessible customer accounts for your - * authenticated Google account. Note that if the list of accessible customers for your - * authenticated Google account includes accounts within the same hierarchy, this example will - * retrieve and print the overlapping portions of the hierarchy for each accessible customer. + * Gets the account hierarchy of the specified manager account and login customer ID. If you don't + * specify manager ID or login customer ID, the example will instead print the hierarchies of all + * accessible customer accounts for your authenticated Google account. Note that if the list of + * accessible customers for your authenticated Google account includes accounts within the same + * hierarchy, this example will retrieve and print the overlapping portions of the hierarchy for + * each accessible customer. */ public class GetAccountHierarchy { @@ -121,6 +122,7 @@ public static void main(String[] args) { * @param googleAdsClient the Google Ads API client. * @param managerId the root customer ID from which to begin the search. * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. + * @throws IOException if a Google Ads Client is not successfully created. */ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long loginCustomerId) throws IOException { @@ -136,7 +138,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long lo Map> allHierarchies = new HashMap<>(); List accountsWithNoInfo = new ArrayList<>(); // Constructs a map of account hierarchies. - for (long seedCustomerId : seedCustomerIds) { + for (Long seedCustomerId : seedCustomerIds) { Map> customerClientToHierarchy = createCustomerClientToHierarchy(loginCustomerId, seedCustomerId); @@ -175,6 +177,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long lo * @param seedCustomerId the ID of the customer at the root of the tree. * @return a map between a CustomerClient and each of its managers' mappings if the account * hierarchy can be retrieved. If the account hierarchy cannot be retrieved, returns null. + * @throws IOException if a Google Ads Client is not successfully created. */ private Map> createCustomerClientToHierarchy( Long loginCustomerId, long seedCustomerId) throws IOException { @@ -184,11 +187,11 @@ private Map> createCustomerClient // Creates a GoogleAdsClient with the specified loginCustomerId. See // https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid for more // information. - GoogleAdsClient googleAdsClient = GoogleAdsClient.newBuilder() - .fromPropertiesFile() - .setLoginCustomerId( - loginCustomerId != null ? loginCustomerId : seedCustomerId) - .build(); + GoogleAdsClient googleAdsClient = + GoogleAdsClient.newBuilder() + .fromPropertiesFile() + .setLoginCustomerId(loginCustomerId != null ? loginCustomerId : seedCustomerId) + .build(); // Creates the Google Ads Service client. try (GoogleAdsServiceClient googleAdsServiceClient = @@ -293,7 +296,7 @@ private List getAccessibleCustomers(GoogleAdsClient googleAdsClient) { + "hierarchies of all accessible customer IDs:"); for (String customerResourceName : accessibleCustomers.getResourceNamesList()) { - long customer = Long.parseLong(CustomerName.parse(customerResourceName).getCustomer()); + Long customer = Long.parseLong(CustomerName.parse(customerResourceName).getCustomer()); System.out.println(customer); seedCustomerIds.add(customer); } From 44562f3ce3ac6296e09d44451aa6e241d1f59e51 Mon Sep 17 00:00:00 2001 From: devchas Date: Wed, 15 Apr 2020 09:58:01 -0400 Subject: [PATCH 10/14] Docs fix --- .../examples/accountmanagement/GetAccountHierarchy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 7c7c74b22f..734e1561c1 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -43,7 +43,7 @@ /** * Gets the account hierarchy of the specified manager account and login customer ID. If you don't - * specify manager ID or login customer ID, the example will instead print the hierarchies of all + * specify manager ID and login customer ID, the example will instead print the hierarchies of all * accessible customer accounts for your authenticated Google account. Note that if the list of * accessible customers for your authenticated Google account includes accounts within the same * hierarchy, this example will retrieve and print the overlapping portions of the hierarchy for From 4db60b8acd4869070f5b7730cb834fa300edc2c1 Mon Sep 17 00:00:00 2001 From: devchas Date: Wed, 15 Apr 2020 10:53:23 -0400 Subject: [PATCH 11/14] Address comment --- .../examples/accountmanagement/GetAccountHierarchy.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 734e1561c1..b65d3097a9 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -127,12 +127,12 @@ public static void main(String[] args) { private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long loginCustomerId) throws IOException { List seedCustomerIds = new ArrayList<>(); - if (managerId != null) { + if (managerId == null) { + // Gets the account hierarchies for all accessible customers. + seedCustomerIds = getAccessibleCustomers(googleAdsClient); + } else { // Only gets the hierarchy for the provided manager ID if provided. seedCustomerIds.add(managerId); - } else { - // Otherwise gets the account hierarchies for all accessible customers. - seedCustomerIds = getAccessibleCustomers(googleAdsClient); } Map> allHierarchies = new HashMap<>(); From fd8c96281b547cc772ea3c4b8b66998ca41e39e8 Mon Sep 17 00:00:00 2001 From: devchas Date: Wed, 15 Apr 2020 12:34:26 -0400 Subject: [PATCH 12/14] Address nbirnie comments --- .../GetAccountHierarchy.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index b65d3097a9..5c8108b50c 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -124,7 +124,7 @@ public static void main(String[] args) { * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. * @throws IOException if a Google Ads Client is not successfully created. */ - private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long loginCustomerId) + private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long loginCustomerId) throws IOException { List seedCustomerIds = new ArrayList<>(); if (managerId == null) { @@ -142,10 +142,10 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, long lo Map> customerClientToHierarchy = createCustomerClientToHierarchy(loginCustomerId, seedCustomerId); - if (customerClientToHierarchy != null) { - allHierarchies.putAll(customerClientToHierarchy); - } else { + if (customerClientToHierarchy == null) { accountsWithNoInfo.add(seedCustomerId); + } else { + allHierarchies.putAll(customerClientToHierarchy); } } @@ -190,7 +190,7 @@ private Map> createCustomerClient GoogleAdsClient googleAdsClient = GoogleAdsClient.newBuilder() .fromPropertiesFile() - .setLoginCustomerId(loginCustomerId != null ? loginCustomerId : seedCustomerId) + .setLoginCustomerId(loginCustomerId == null ? seedCustomerId : loginCustomerId) .build(); // Creates the Google Ads Service client. @@ -212,8 +212,8 @@ private Map> createCustomerClient // child accounts. Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); while (!managerAccountsToSearch.isEmpty()) { - long customerId = managerAccountsToSearch.iterator().next(); - managerAccountsToSearch.remove(customerId); + long customerIdToSearchFrom = managerAccountsToSearch.iterator().next(); + managerAccountsToSearch.remove(customerIdToSearchFrom); SearchPagedResponse response; try { // Issues a search request. @@ -221,7 +221,7 @@ private Map> createCustomerClient googleAdsServiceClient.search( SearchGoogleAdsRequest.newBuilder() .setQuery(query) - .setCustomerId(Long.toString(customerId)) + .setCustomerId(Long.toString(customerIdToSearchFrom)) .build()); // Iterates over all rows in all pages to get all customer clients under the specified @@ -229,20 +229,21 @@ private Map> createCustomerClient for (GoogleAdsRow googleAdsRow : response.iterateAll()) { CustomerClient customerClient = googleAdsRow.getCustomerClient(); + // Gets the CustomerClient object for the root customer in the tree. if (customerClient.getId().getValue() == seedCustomerId) { rootCustomerClient = customerClient; } // The steps below map parent and children accounts. Continue here so that managers // accounts exclude themselves from the list of their children accounts. - if (customerClient.getId().getValue() == customerId) { + if (customerClient.getId().getValue() == customerIdToSearchFrom) { continue; } // For all level-1 (direct child) accounts that are manager accounts, the above // query will be run against them to create a map of managers to their // child accounts for printing the hierarchy afterwards. - customerIdsToChildAccounts.put(customerId, customerClient); + customerIdsToChildAccounts.put(customerIdToSearchFrom, customerClient); // Checks if the child account is a manager itself so that it can later be processed // and added to the map if it hasn't been already. if (customerClient.getManager().getValue()) { @@ -258,7 +259,7 @@ private Map> createCustomerClient } catch (GoogleAdsException gae) { System.out.printf( "Unable to retrieve hierarchy for customer ID %d: %s%n", - customerId, gae.getGoogleAdsFailure().getErrors(0).getMessage()); + customerIdToSearchFrom, gae.getGoogleAdsFailure().getErrors(0).getMessage()); } } From aeb4d763286a600a9c592475e2e64ad0be3c45ab Mon Sep 17 00:00:00 2001 From: devchas Date: Wed, 15 Apr 2020 12:47:13 -0400 Subject: [PATCH 13/14] Change managerAccountsToSearch to LinkedList --- .../examples/accountmanagement/GetAccountHierarchy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 5c8108b50c..45850a08db 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -37,6 +37,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -181,7 +182,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo */ private Map> createCustomerClientToHierarchy( Long loginCustomerId, long seedCustomerId) throws IOException { - Set managerAccountsToSearch = new HashSet<>(); + LinkedList managerAccountsToSearch = new LinkedList<>(); CustomerClient rootCustomerClient = null; // Creates a GoogleAdsClient with the specified loginCustomerId. See @@ -212,8 +213,7 @@ private Map> createCustomerClient // child accounts. Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); while (!managerAccountsToSearch.isEmpty()) { - long customerIdToSearchFrom = managerAccountsToSearch.iterator().next(); - managerAccountsToSearch.remove(customerIdToSearchFrom); + long customerIdToSearchFrom = managerAccountsToSearch.pop(); SearchPagedResponse response; try { // Issues a search request. From ad3b2b1294c975fdea15c4ade9166bbb52f1ed11 Mon Sep 17 00:00:00 2001 From: devchas Date: Wed, 15 Apr 2020 13:36:19 -0400 Subject: [PATCH 14/14] LinkedList to queue --- .../examples/accountmanagement/GetAccountHierarchy.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java index 45850a08db..b611977328 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/accountmanagement/GetAccountHierarchy.java @@ -36,11 +36,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.Queue; /** * Gets the account hierarchy of the specified manager account and login customer ID. If you don't @@ -182,7 +181,7 @@ private void runExample(GoogleAdsClient googleAdsClient, Long managerId, Long lo */ private Map> createCustomerClientToHierarchy( Long loginCustomerId, long seedCustomerId) throws IOException { - LinkedList managerAccountsToSearch = new LinkedList<>(); + Queue managerAccountsToSearch = new LinkedList<>(); CustomerClient rootCustomerClient = null; // Creates a GoogleAdsClient with the specified loginCustomerId. See @@ -213,7 +212,7 @@ private Map> createCustomerClient // child accounts. Multimap customerIdsToChildAccounts = ArrayListMultimap.create(); while (!managerAccountsToSearch.isEmpty()) { - long customerIdToSearchFrom = managerAccountsToSearch.pop(); + long customerIdToSearchFrom = managerAccountsToSearch.poll(); SearchPagedResponse response; try { // Issues a search request.