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.collect.Lists; import com.google.common.primitives.Longs; import com.seajas.search.codex.model.identity.IdentityAccountToken; import com.seajas.search.codex.service.codex.CodexService; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.social.facebook.api.Facebook; import org.springframework.social.facebook.api.FacebookProfile; import org.springframework.social.facebook.api.FqlOperations; import org.springframework.social.facebook.api.FqlResult; import org.springframework.social.facebook.api.FqlResultMapper; import org.springframework.social.facebook.api.Reference; import org.springframework.social.facebook.api.impl.FacebookTemplate; import org.springframework.social.twitter.api.Tweet; import org.springframework.social.twitter.api.Twitter; import org.springframework.social.twitter.api.TwitterProfile; import org.springframework.social.twitter.api.impl.TwitterTemplate; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import javax.annotation.Resource; @Component public class SocialFacade implements SocialFacadeInterface { private static final Logger LOG = LoggerFactory.getLogger(SocialFacade.class); private static final String TWITTER_PROFILE_CACHE = "twitterProfileCache"; private static final String FACEBOOK_PROFILE_CACHE = "facebookProfileCache"; @Autowired private CodexService codexService; @Resource(name = "socialProviderKeysAndSecrets") private Map<String, List<String>> socialProviderKeysAndSecrets; @Autowired private EhCacheCacheManager cacheManager; private FacebookPageResultMapper facebookPageResultMapper = new FacebookPageResultMapper(); private FacebookProfileResultMapper facebookProfileResultMapper = new FacebookProfileResultMapper(); @Override @Cacheable("facebookProfileSearchCache") public List<Reference> searchFacebookProfiles(final String person) { return getFacebookTemplate().userOperations().search(person); } @Override @Cacheable("facebookPageSearchCache") public List<Reference> searchFacebookPages(final String person) { MultiValueMap<String, String> queryMap = new LinkedMultiValueMap<String, String>(); queryMap.add("q", person); queryMap.add("type", "page"); return getFacebookTemplate().fetchConnections("search", null, Reference.class, queryMap); } @Override @Cacheable(value = "facebookProfilesCache") public List<FacebookProfile> getFacebookProfiles(List<String> ids) { String fql = "SELECT uid, name, first_name, middle_name, last_name, sex, locale, pic_small_with_logo, pic_big_with_logo, pic_square_with_logo, pic_with_logo, username FROM user where uid in ('%s')"; return getFacebookProfiles(fql, ids, facebookProfileResultMapper); } @Override @Cacheable(value = "facebookPagesCache") public List<FacebookProfile> getFacebookPages(List<String> ids) { String fql = "SELECT page_id, name, pic_small, pic_big, pic_square, pic, username, location, about FROM page where page_id in ('%s')"; return getFacebookProfiles(fql, ids, facebookPageResultMapper); } protected List<FacebookProfile> getFacebookProfiles(String fqlQuery, List<String> ids, FqlResultMapper<FacebookProfile> resultMapper) { List<FacebookProfile> facebookProfiles = Lists.newArrayList(); List<String> copyOfIds = Lists.newArrayList(ids); // first, fetch available profiles from the cache Iterator<String> iterator = copyOfIds.iterator(); while (iterator.hasNext()) { String id = iterator.next(); Cache.ValueWrapper valueWrapper = cacheManager.getCache(FACEBOOK_PROFILE_CACHE).get(id); if (valueWrapper != null && valueWrapper.get() != null) { LOG.debug(String.format("Read profile with id %s from cache", id)); facebookProfiles.add((FacebookProfile) valueWrapper.get()); iterator.remove(); } } // secondly, if not in the cache, retrieve from twitter and store in cache String joinedIds = StringUtils.join(copyOfIds, "','"); FqlOperations fql = getFacebookTemplate().fqlOperations(); List<FacebookProfile> remainingProfiles = fql.query(String.format(fqlQuery, joinedIds), resultMapper); for (FacebookProfile profile : remainingProfiles) { LOG.debug(String.format("Write profile with id %s to cache", profile.getId())); cacheManager.getCache(FACEBOOK_PROFILE_CACHE).put(profile.getId(), profile); } facebookProfiles.addAll(remainingProfiles); return facebookProfiles; } @Override @Cacheable(value = "twitterSearchCache") public List<TwitterProfile> searchTwitter(final String person) { List<TwitterProfile> profiles = getTwitterTemplate().userOperations().searchForUsers(person); for (TwitterProfile profile : profiles) { cacheManager.getCache(TWITTER_PROFILE_CACHE).put(profile.getId(), profile); } return profiles; } @Override @Cacheable(value = TWITTER_PROFILE_CACHE) public TwitterProfile getTwitterProfile(Long twitterId) { return getTwitterTemplate().userOperations().getUserProfile(twitterId); } @Override @Cacheable(value = "twitterProfilesCache") public List<TwitterProfile> getTwitterProfiles(List<Long> searchableProfileIds) { // first, fetch available profiles from the cache List<TwitterProfile> twitterProfiles = Lists.newArrayList(); List<Long> idsCopy = Lists.newArrayList(searchableProfileIds); Iterator<Long> idIterator = idsCopy.iterator(); while (idIterator.hasNext()) { Long id = idIterator.next(); Cache.ValueWrapper valueWrapper = cacheManager.getCache(TWITTER_PROFILE_CACHE).get(id); if (valueWrapper != null && valueWrapper.get() != null) { LOG.debug(String.format("Read profile with id %d from cache", id)); twitterProfiles.add((TwitterProfile) valueWrapper.get()); idIterator.remove(); } } // secondly, if not in the cache, retrieve from twitter and store in cache long[] ids = Longs.toArray(Lists.newArrayList(idsCopy)); if (ids.length > 0) { LOG.debug("Grabbing twitter profiles with ids: " + ids); List<TwitterProfile> remainingProfiles = getTwitterTemplate().userOperations().getUsers(ids); for (TwitterProfile profile : remainingProfiles) { LOG.debug(String.format("Write profile with id %d to cache", profile.getId())); cacheManager.getCache(TWITTER_PROFILE_CACHE).put(profile.getId(), profile); } twitterProfiles.addAll(remainingProfiles); } return twitterProfiles; } @Override @Cacheable(value = "twitterUserTimelineCache") public List<Tweet> getUserTimeline(long twitterProfileId) { return getTwitterTemplate().timelineOperations().getUserTimeline(twitterProfileId, 100); } @Override public Twitter getTwitterTemplate() { IdentityAccountToken twitterToken = getToken("twitter"); Twitter twitter = null; if (twitterToken != null) { String twitterAccessToken = twitterToken.getAccessToken(); String twitterAccessSecret = twitterToken.getSecret(); List<String> keyAndSecret = socialProviderKeysAndSecrets.get("twitter"); String applicationKey = keyAndSecret.get(0); String applicationSecret = keyAndSecret.get(1); twitter = new TwitterTemplate(applicationKey, applicationSecret, twitterAccessToken, twitterAccessSecret); } else { LOG.warn("Could not retrieve valid identity account token for twitter"); } return twitter; } @Override public Facebook getFacebookTemplate() { Facebook facebook = null; IdentityAccountToken facebookToken = getToken("facebook"); if (facebookToken != null) { facebook = new FacebookTemplate(facebookToken.getAccessToken()); } else { LOG.warn("Could not retrieve valid identity account token for facebook"); } return facebook; } protected IdentityAccountToken getToken(String type) { return codexService.getNextValidTokenFromPool(type); } static class FacebookPageResultMapper implements FqlResultMapper<FacebookProfile> { @Override public FacebookProfile mapObject(FqlResult objectValues) { String id = objectValues.getString("page_id"); String username = objectValues.getString("username"); String name = objectValues.getString("name"); String firstName = objectValues.getString("first_name"); String lastName = objectValues.getString("last_name"); String gender = null; return new FacebookProfile(id, username, name, firstName, lastName, gender, null); } } static class FacebookProfileResultMapper implements FqlResultMapper<FacebookProfile> { @Override public FacebookProfile mapObject(FqlResult objectValues) { String id = objectValues.getString("uid"); String username = objectValues.getString("username"); String name = objectValues.getString("name"); String firstName = objectValues.getString("first_name"); String lastName = objectValues.getString("last_name"); String gender = objectValues.getString("sex"); return new FacebookProfile(id, username, name, firstName, lastName, gender, null); } } }