/**
   * Gets the site links from a feed.
   *
   * @return a map of feed item ID to SiteLinkFromFeed
   */
  private static Map<Long, SiteLinkFromFeed> getSiteLinksFromFeed(
      AdWordsServices adWordsServices, AdWordsSession session, Feed feed) throws Exception {
    // Retrieve the feed's attribute mapping.
    Multimap<Long, Integer> feedMappings =
        getFeedMapping(adWordsServices, session, feed, PLACEHOLDER_SITELINKS);

    Map<Long, SiteLinkFromFeed> feedItems = Maps.newHashMap();

    for (FeedItem feedItem : getFeedItems(adWordsServices, session, feed)) {
      SiteLinkFromFeed siteLinkFromFeed = new SiteLinkFromFeed();

      for (FeedItemAttributeValue attributeValue : feedItem.getAttributeValues()) {
        // Skip this attribute if it hasn't been mapped to a field.
        if (!feedMappings.containsKey(attributeValue.getFeedAttributeId())) {
          continue;
        }

        for (Integer fieldId : feedMappings.get(attributeValue.getFeedAttributeId())) {
          switch (fieldId) {
            case PLACEHOLDER_FIELD_SITELINK_LINK_TEXT:
              siteLinkFromFeed.text = attributeValue.getStringValue();
              break;
            case PLACEHOLDER_FIELD_SITELINK_URL:
              siteLinkFromFeed.url = attributeValue.getStringValue();
              break;
            case PLACEHOLDER_FIELD_FINAL_URLS:
              siteLinkFromFeed.finalUrls = attributeValue.getStringValues();
              break;
            case PLACEHOLDER_FIELD_FINAL_MOBILE_URLS:
              siteLinkFromFeed.finalMobileUrls = attributeValue.getStringValues();
              break;
            case PLACEHOLDER_FIELD_TRACKING_URL_TEMPLATE:
              siteLinkFromFeed.trackingUrlTemplate = attributeValue.getStringValue();
              break;
            case PLACEHOLDER_FIELD_LINE_2_TEXT:
              siteLinkFromFeed.line2 = attributeValue.getStringValue();
              break;
            case PLACEHOLDER_FIELD_LINE_3_TEXT:
              siteLinkFromFeed.line3 = attributeValue.getStringValue();
              break;
            default:
              // Ignore attributes that do not map to a predefined placeholder field.
              break;
          }
        }
      }
      siteLinkFromFeed.scheduling = feedItem.getScheduling();

      feedItems.put(feedItem.getFeedItemId(), siteLinkFromFeed);
    }

    return feedItems;
  }