Java tutorial
/** * Copyright (C) 2013 Seajas, the Netherlands. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.seajas.search.codex.service.social; import com.google.common.base.Function; import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multiset; import com.google.common.collect.Multisets; import com.seajas.search.codex.service.social.dto.HashTagDto; import com.seajas.search.codex.service.social.dto.MentionedDto; import com.seajas.search.codex.service.social.dto.ProfileRequestDto; import com.seajas.search.codex.service.social.dto.SocialProfileDto; import com.seajas.search.codex.service.social.dto.SocialProfileResponseDto; import com.seajas.search.codex.service.social.dto.TwitterProfileSummaryDto; import com.seajas.search.media.wsdl.IMediaNotification; import com.seajas.search.media.wsdl.MediaException_Exception; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.social.facebook.api.FacebookProfile; import org.springframework.social.facebook.api.Reference; import org.springframework.social.twitter.api.HashTagEntity; import org.springframework.social.twitter.api.MentionEntity; import org.springframework.social.twitter.api.Tweet; import org.springframework.social.twitter.api.TwitterProfile; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class SocialProfileService implements SocialProfileServiceInterface { private static final Logger LOG = LoggerFactory.getLogger(SocialProfileService.class); private static final String HTTP_GRAPH_FACEBOOK_PICTURE = "http://graph.facebook.com/%s/picture"; private static final int MAX_PROFILE_SUGGESTIONS_PER_PERSON = 2; @Autowired private IMediaNotification mediaService; @Autowired private SocialFacadeInterface socialFacade; @Override public SocialProfileResponseDto getSocialProfileSuggestions(final List<String> persons) { SocialProfileResponseDto responseDto = new SocialProfileResponseDto(); for (String person : persons) { boolean suggestions = true; responseDto.addFacebookProfiles(addFacebookPictures(this.searchFacebookProfiles(person, suggestions))); responseDto.addFacebookPages(addFacebookPictures(this.searchFacebookPages(person, suggestions))); responseDto.addTwitterProfiles(this.searchTwitterProfile(person, suggestions)); if (responseDto.count() >= 10) { break; } } return responseDto; } protected List<SocialProfileDto> addFacebookPictures(List<SocialProfileDto> socialProfileDtos) { if (!socialProfileDtos.isEmpty()) { LOG.info("adding facebook pictures for " + socialProfileDtos.size() + " profiles"); List<String> images = Lists.transform(socialProfileDtos, new FacebookProfilePictureFunction()); LOG.info("created " + images.size() + " facebook urls"); List<String> mediaServerImages = storeImagesOnMediaServer(images); LOG.info("stored " + mediaServerImages.size() + " images on media server"); for (int i = 0; i < socialProfileDtos.size(); i++) { SocialProfileDto profile = socialProfileDtos.get(i); profile.setProfileImageMediaUrl(mediaServerImages.get(i)); profile.setProfileImageUrl(images.get(i)); } } return socialProfileDtos; } private List<SocialProfileDto> addTwitterPictures(List<SocialProfileDto> twitterProfiles) { if (!twitterProfiles.isEmpty()) { List<String> urls = Lists.transform(twitterProfiles, new Function<SocialProfileDto, String>() { @Override public String apply(SocialProfileDto input) { return input.getProfileImageUrl(); } }); List<String> mediaUrls = this.storeImagesOnMediaServer(urls); for (int i = 0; i < twitterProfiles.size(); i++) { SocialProfileDto profile = twitterProfiles.get(i); profile.setProfileImageMediaUrl(mediaUrls.get(i)); } } return twitterProfiles; } @Override public SocialProfileResponseDto getSocialProfiles(final String person) { SocialProfileResponseDto responseDto = new SocialProfileResponseDto(); boolean suggestions = false; responseDto.setFacebookProfiles(addFacebookPictures(this.searchFacebookProfiles(person, suggestions))); responseDto.setFacebookPages(addFacebookPictures(this.searchFacebookPages(person, suggestions))); responseDto.setTwitterProfiles(this.searchTwitterProfile(person, suggestions)); return responseDto; } @Override public TwitterProfileSummaryDto getTwitterProfileSummary(final long twitterProfileId) { List<Tweet> tweets = socialFacade.getUserTimeline(twitterProfileId); SocialProfileDto socialProfileDto = null; TwitterProfile twitterProfile = socialFacade.getTwitterProfile(twitterProfileId); if (twitterProfile != null) { socialProfileDto = SocialProfileDto.translate(twitterProfile); socialProfileDto .setProfileImageMediaUrl(this.storeImageOnMediaServer(twitterProfile.getProfileImageUrl())); } Multiset<Long> mentionedCounter = HashMultiset.create(); Multiset<String> hashTagCounter = HashMultiset.create(); this.countTwitterEntities(tweets, mentionedCounter, hashTagCounter); mentionedCounter = Multisets.copyHighestCountFirst(mentionedCounter); hashTagCounter = Multisets.copyHighestCountFirst(hashTagCounter); List<MentionedDto> mentions = this.buildTwitterMentionedList(mentionedCounter); List<HashTagDto> hashTagList = Lists.newArrayList(); for (String hashTag : hashTagCounter.elementSet()) { hashTagList.add(new HashTagDto(hashTag, hashTagCounter.count(hashTag))); } return new TwitterProfileSummaryDto(socialProfileDto, hashTagList, mentions); } @Override public SocialProfileResponseDto getSocialProfiles(ProfileRequestDto requestDto) { SocialProfileResponseDto responseDto = new SocialProfileResponseDto(); if (!requestDto.getFacebookPageIds().isEmpty()) { responseDto.addFacebookPages(addFacebookPictures(getFacebookPage(requestDto.getFacebookPageIds()))); } if (!requestDto.getFacebookProfileIds().isEmpty()) { responseDto.addFacebookProfiles( addFacebookPictures(getFacebookProfile(requestDto.getFacebookProfileIds()))); } if (!requestDto.getTwitterIds().isEmpty()) { responseDto.addTwitterProfiles(addTwitterPictures(getTwitterProfile(requestDto.getTwitterIds()))); } return responseDto; } protected List<SocialProfileDto> searchFacebookProfiles(String person, boolean suggestions) { List<Reference> references = socialFacade.searchFacebookProfiles(person); LOG.debug(String.format("Found %d facebook profile references for person %s", references.size(), person)); return this.getSocialProfiles(person, references, suggestions, new Function<List<String>, List<FacebookProfile>>() { @Override public List<FacebookProfile> apply(List<String> input) { return socialFacade.getFacebookProfiles(input); } }); } protected List<SocialProfileDto> searchFacebookPages(String person, boolean suggestions) { List<Reference> references = socialFacade.searchFacebookPages(person); LOG.debug(String.format("Found %d facebook page references for person %s", references.size(), person)); return this.getSocialProfiles(person, references, suggestions, new Function<List<String>, List<FacebookProfile>>() { @Override public List<FacebookProfile> apply(List<String> input) { return socialFacade.getFacebookPages(input); } }); } protected List<SocialProfileDto> getSocialProfiles(String person, List<Reference> references, boolean suggestions, Function<List<String>, List<FacebookProfile>> lookup) { List<SocialProfileDto> dtos = Lists.newArrayList(); List<String> ids = Lists.transform(references, new FacebookReferenceToIdFunction()); List<FacebookProfile> profiles = lookup.apply(ImmutableList.copyOf(ids)); for (FacebookProfile profile : profiles) { LOG.debug(String.format("Found profile with name %s", profile.getName())); if (suggestions) { if (profile.getName().equalsIgnoreCase(person)) { dtos.add(this.getSocialProfile(profile)); } } else { dtos.add(this.getSocialProfile(profile)); } if (suggestions && dtos.size() >= MAX_PROFILE_SUGGESTIONS_PER_PERSON) { break; } } return dtos; } protected SocialProfileDto getSocialProfile(FacebookProfile facebookProfile) { SocialProfileDto dto = SocialProfileDto.translate(facebookProfile); String profileImageUrl = String.format(HTTP_GRAPH_FACEBOOK_PICTURE, dto.getId()); if (profileImageUrl != null) { dto.setProfileImageMediaUrl(this.storeImageOnMediaServer(profileImageUrl)); } return dto; } protected List<SocialProfileDto> searchTwitterProfile(String person, boolean suggestions) { List<SocialProfileDto> twitterProfileDtos = Lists.newArrayList(); List<TwitterProfile> twitterProfiles = socialFacade.searchTwitter(person); for (TwitterProfile twitterProfile : twitterProfiles) { if (suggestions && !(twitterProfile.getName().equalsIgnoreCase(person) || twitterProfile.getScreenName().equalsIgnoreCase(person))) { continue; } SocialProfileDto dto = SocialProfileDto.translate(twitterProfile); if (dto.getProfileImageUrl() != null) { dto.setProfileImageMediaUrl(this.storeImageOnMediaServer(dto.getProfileImageUrl())); } twitterProfileDtos.add(dto); if (suggestions && twitterProfileDtos.size() >= MAX_PROFILE_SUGGESTIONS_PER_PERSON) { break; } } return twitterProfileDtos; } protected List<MentionedDto> buildTwitterMentionedList(Multiset<Long> mentionedCounter) { List<MentionedDto> mentions = Lists.newArrayList(); List<Long> ids = Lists.newArrayList(mentionedCounter.elementSet()); List<TwitterProfile> twitterProfiles = socialFacade.getTwitterProfiles(ids); Map<Long, TwitterProfile> profileMap = Maps.newHashMap(); for (TwitterProfile twitterProfile : twitterProfiles) { profileMap.put(twitterProfile.getId(), twitterProfile); } List<String> profileImageUrls = Lists.newArrayList(); for (Long mentionId : mentionedCounter.elementSet()) { int count = mentionedCounter.count(mentionId); TwitterProfile profile = profileMap.get(mentionId); if (profile != null) { SocialProfileDto socialProfileDto = SocialProfileDto.translate(profile); profileImageUrls.add(profile.getProfileImageUrl()); mentions.add(new MentionedDto(socialProfileDto, count)); } } if (!profileImageUrls.isEmpty()) { List<String> mediaUrls = this.storeImagesOnMediaServer(profileImageUrls); for (int i = 0; i < mentions.size(); i++) { mentions.get(i).getSocialProfile().setProfileImageMediaUrl(mediaUrls.get(i)); } } return mentions; } protected void countTwitterEntities(List<Tweet> tweets, Multiset<Long> mentionCounter, Multiset<String> hashTagCounter) { for (Tweet tweet : tweets) { if (tweet.hasMentions()) { List<MentionEntity> mentions = tweet.getEntities().getMentions(); for (MentionEntity entity : mentions) { mentionCounter.add(entity.getId()); } } if (tweet.hasTags()) { List<HashTagEntity> hashTags = tweet.getEntities().getHashTags(); for (HashTagEntity hashTagEntity : hashTags) { hashTagCounter.add(hashTagEntity.getText()); } } } } protected String storeImageOnMediaServer(String imageUrl) { String mediaUrl = null; try { mediaUrl = mediaService.storeUrl(imageUrl, null, "image"); } catch (MediaException_Exception e) { LOG.warn("Can not store image on media service with url: " + imageUrl, e); } return mediaUrl; } protected List<String> storeImagesOnMediaServer(List<String> imageUrls) { List<String> mediaUrls = null; try { mediaUrls = mediaService.storeUrls(imageUrls, null, "image"); } catch (MediaException_Exception e) { LOG.warn("Can not store images on media service", e); } return mediaUrls; } public List<SocialProfileDto> getFacebookPage(List<String> ids) { List<FacebookProfile> pages = socialFacade.getFacebookPages(ids); return Lists.newArrayList(Lists.transform(pages, new FacebookProfileToDtoFunction())); } public List<SocialProfileDto> getFacebookProfile(List<String> ids) { List<FacebookProfile> profiles = socialFacade.getFacebookProfiles(ImmutableList.copyOf(ids)); return Lists.newArrayList(Lists.transform(profiles, new FacebookProfileToDtoFunction())); } public List<SocialProfileDto> getTwitterProfile(List<String> ids) { List<Long> twitterIds = Lists.transform(ids, new StringToLongFunction()); List<TwitterProfile> foundProfiles = socialFacade.getTwitterProfiles(twitterIds); return Lists.newArrayList(Lists.transform(foundProfiles, new TwitterProfileToDtoFunction())); } static class FacebookReferenceToIdFunction implements Function<Reference, String> { @Override public String apply(Reference input) { return input.getId(); } } static class TwitterProfileToDtoFunction implements Function<TwitterProfile, SocialProfileDto> { @Override public SocialProfileDto apply(TwitterProfile input) { return SocialProfileDto.translate(input); } } static class FacebookProfileToDtoFunction implements Function<FacebookProfile, SocialProfileDto> { @Override public SocialProfileDto apply(FacebookProfile input) { return SocialProfileDto.translate(input); } } static class StringToLongFunction implements Function<String, Long> { @Override public Long apply(String input) { return Long.valueOf(input); } } static class FacebookProfilePictureFunction implements Function<SocialProfileDto, String> { @Override public String apply(SocialProfileDto input) { return String.format(HTTP_GRAPH_FACEBOOK_PICTURE, input.getId()); } } }