com.seajas.search.codex.service.social.SocialProfileService.java Source code

Java tutorial

Introduction

Here is the source code for com.seajas.search.codex.service.social.SocialProfileService.java

Source

/**
 * 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());
        }
    }
}