/**
   * Returns the list of feed item IDs that are used by a campaign through a given campaign feed.
   */
  private static Set<Long> getFeedItemIdsForCampaign(CampaignFeed campaignFeed) throws Exception {
    Set<Long> feedItemIds = Sets.newHashSet();

    FunctionOperator functionOperator = campaignFeed.getMatchingFunction().getOperator();

    if (FunctionOperator.IN.equals(functionOperator)) {
      // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
      // Extract feed items if applicable.
      feedItemIds.addAll(getFeedItemIdsFromArgument(campaignFeed.getMatchingFunction()));
    } else if (FunctionOperator.AND.equals(functionOperator)) {
      for (FunctionArgumentOperand argument : campaignFeed.getMatchingFunction().getLhsOperand()) {
        // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
        // Extract feed items if applicable.
        if (argument instanceof FunctionOperand) {
          FunctionOperand operand = (FunctionOperand) argument;
          if (FunctionOperator.IN.equals(operand.getValue().getOperator())) {
            feedItemIds.addAll(getFeedItemIdsFromArgument(operand.getValue()));
          }
        }
      }

    } else {
      // There are no other matching functions involving feed item IDs.
    }

    return feedItemIds;
  }
  /**
   * Creates the extension setting for a list of feed items.
   *
   * @param adWordsServices the AdWordsServices
   * @param session the AdWordsSession
   * @param feedItems the list of all feed items
   * @param campaignFeed the original campaign feed
   * @param feedItemIds IDs of the feed items for which extension settings should be created
   * @param platformRestrictions the platform restrictions for the new campaign extension setting
   */
  private static void createExtensionSetting(
      AdWordsServices adWordsServices,
      AdWordsSession session,
      Map<Long, SiteLinkFromFeed> feedItems,
      CampaignFeed campaignFeed,
      Set<Long> feedItemIds,
      ExtensionSettingPlatform platformRestrictions)
      throws Exception {
    // Get the CampaignExtensionSettingService.
    CampaignExtensionSettingServiceInterface campaignExtensionSettingService =
        adWordsServices.get(session, CampaignExtensionSettingServiceInterface.class);

    CampaignExtensionSetting campaignExtensionSetting = new CampaignExtensionSetting();
    campaignExtensionSetting.setCampaignId(campaignFeed.getCampaignId());
    campaignExtensionSetting.setExtensionType(FeedType.SITELINK);

    ExtensionSetting extensionSetting = new ExtensionSetting();

    List<ExtensionFeedItem> extensionFeedItems = Lists.newArrayList();

    for (Long feedItemId : feedItemIds) {
      SiteLinkFromFeed siteLinkFromFeed = feedItems.get(feedItemId);
      SitelinkFeedItem siteLinkFeedItem = new SitelinkFeedItem();
      siteLinkFeedItem.setSitelinkText(siteLinkFromFeed.text);

      if (siteLinkFromFeed.finalUrls != null && siteLinkFromFeed.finalUrls.length > 0) {
        siteLinkFeedItem.setSitelinkFinalUrls(new UrlList(siteLinkFromFeed.finalUrls));
        if (siteLinkFromFeed.finalMobileUrls != null
            && siteLinkFromFeed.finalMobileUrls.length > 0) {
          siteLinkFeedItem.setSitelinkFinalMobileUrls(
              new UrlList(siteLinkFromFeed.finalMobileUrls));
        }
        siteLinkFeedItem.setSitelinkTrackingUrlTemplate(siteLinkFromFeed.trackingUrlTemplate);
      } else {
        siteLinkFeedItem.setSitelinkUrl(siteLinkFromFeed.url);
      }

      siteLinkFeedItem.setSitelinkLine2(siteLinkFromFeed.line2);
      siteLinkFeedItem.setSitelinkLine3(siteLinkFromFeed.line3);
      siteLinkFeedItem.setScheduling(siteLinkFromFeed.scheduling);

      extensionFeedItems.add(siteLinkFeedItem);
    }

    extensionSetting.setExtensions(
        extensionFeedItems.toArray(new ExtensionFeedItem[extensionFeedItems.size()]));

    extensionSetting.setPlatformRestrictions(platformRestrictions);

    campaignExtensionSetting.setExtensionSetting(extensionSetting);

    CampaignExtensionSettingOperation operation = new CampaignExtensionSettingOperation();
    operation.setOperand(campaignExtensionSetting);
    operation.setOperator(Operator.ADD);

    campaignExtensionSettingService.mutate(new CampaignExtensionSettingOperation[] {operation});
  }
  public static void runExample(AdWordsServices adWordsServices, AdWordsSession session)
      throws Exception {
    // Get all of the feeds for the session's account.
    List<Feed> feeds = getFeeds(adWordsServices, session);

    for (Feed feed : feeds) {
      // Retrieve all the sitelinks from the current feed.
      Map<Long, SiteLinkFromFeed> feedItems = getSiteLinksFromFeed(adWordsServices, session, feed);

      // Get all the instances where a sitelink from this feed has been added to a campaign.
      List<CampaignFeed> campaignFeeds =
          getCampaignFeeds(adWordsServices, session, feed, PLACEHOLDER_SITELINKS);

      Set<Long> allFeedItemsToDelete = Sets.newHashSet();
      for (CampaignFeed campaignFeed : campaignFeeds) {
        // Retrieve the sitelinks that have been associated with this campaign.
        Set<Long> feedItemIds = getFeedItemIdsForCampaign(campaignFeed);

        ExtensionSettingPlatform platformRestrictions =
            getPlatformRestictionsForCampaign(campaignFeed);

        if (feedItemIds.isEmpty()) {
          System.out.printf(
              "Migration skipped for campaign feed with campaign ID %d "
                  + "and feed ID %d because no mapped feed item IDs were found in the "
                  + "campaign feed's matching function.%n",
              campaignFeed.getCampaignId(), campaignFeed.getFeedId());
        } else {
          // Delete the campaign feed that associates the sitelinks from the feed to the campaign.
          deleteCampaignFeed(adWordsServices, session, campaignFeed);

          // Create extension settings instead of sitelinks.
          createExtensionSetting(
              adWordsServices, session, feedItems, campaignFeed, feedItemIds, platformRestrictions);

          // Mark the sitelinks from the feed for deletion.
          allFeedItemsToDelete.addAll(feedItemIds);
        }
      }

      // Delete all the sitelinks from the feed.
      deleteOldFeedItems(adWordsServices, session, allFeedItemsToDelete, feed);
    }
  }
  /** Gets the platform restrictions for sitelinks in a campaign. */
  private static ExtensionSettingPlatform getPlatformRestictionsForCampaign(
      CampaignFeed campaignFeed) {
    String platformRestrictions = ExtensionSettingPlatform.NONE.getValue();

    if (FunctionOperator.AND.equals(campaignFeed.getMatchingFunction().getOperator())) {
      for (FunctionArgumentOperand argument : campaignFeed.getMatchingFunction().getLhsOperand()) {
        if (argument instanceof FunctionOperand) {
          FunctionOperand operand = (FunctionOperand) argument;
          if (FunctionOperator.EQUALS.equals(operand.getValue().getOperator())
              && (operand.getValue().getLhsOperand(0) instanceof RequestContextOperand)) {
            RequestContextOperand requestContextOperand =
                (RequestContextOperand) operand.getValue().getLhsOperand(0);
            if (RequestContextOperandContextType.DEVICE_PLATFORM.equals(
                requestContextOperand.getContextType())) {
              platformRestrictions =
                  ((ConstantOperand) operand.getValue().getRhsOperand(0)).getStringValue();
            }
          }
        }
      }
    }
    return ExtensionSettingPlatform.fromString(platformRestrictions.toUpperCase());
  }