/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.springsource.greenhouse.invite;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.api.Reference;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.springsource.greenhouse.account.Account;
import com.springsource.greenhouse.account.AccountRepository;
import com.springsource.greenhouse.account.ProfileReference;
import com.springsource.greenhouse.utils.Message;
/**
* UI Controller for inviting Facebook friends to join our community.
* @author Keith Donald
*/
@Controller
public class FacebookInviteController {
private final Facebook facebook;
private final UsersConnectionRepository connectionRepository;
private final AccountRepository accountRepository;
/**
* Construct the FacebookInviteController.
* The Facebook ServiceProvider is injected for obtaining the client-side proxy to Facebook's REST API.
* It is also used to lookup which of a member's Facebook friends have already joined our community.
*/
@Inject
public FacebookInviteController(Facebook facebook, UsersConnectionRepository connectionRepository, AccountRepository accountRepository) {
this.facebook = facebook;
this.connectionRepository = connectionRepository;
this.accountRepository = accountRepository;
}
/**
* Renders the Facebook friend-finder page as HTML in the web browser.
* If the member's account is connected to Facebook, adds his or her Facebook friends who are already members to the model.
* Supports distinguishing between those Facebook friends who have already joined and those who haven't.
*/
@RequestMapping(value="/invite/facebook", method=RequestMethod.GET)
public void friendFinder(Model model, Account account) {
if (facebook.isAuthorized()) {
List<ProfileReference> profileReferences = accountRepository.findProfileReferencesByIds(friendAccountIds(account.getId(), facebook));
model.addAttribute("friends", profileReferences);
} else {
model.addAttribute("friends", Collections.emptySet());
}
model.addAttribute("facebookAppId", facebookAppId);
}
/**
* Called by the Facebook multi-friend-selector form after sending invitations.
* Redirects the user back to the invite page and renders a success message.
* @param inviteIds the invitation ids assigned by Facebook, one for each invitation sent
*/
@RequestMapping(value="/invite/facebook/request-form", method=RequestMethod.POST)
public String invitationsSent(@RequestParam("ids[]") String[] inviteIds, RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttribute(Message.success("Your invitations have been sent"));
return "redirect:/invite";
}
/**
* Called by the Facebook multi-friend-selector form after choosing to cancel the sending of one or more invites.
* Redirects the user back to the main invite page.
*/
@RequestMapping(value="/invite/facebook/request-form", method=RequestMethod.GET)
public String invitationsCancelled() {
return "redirect:/invite";
}
// internal helpers
private List<Long> friendAccountIds(Long accountId, Facebook facebook) {
List<Reference> friends = facebook.friendOperations().getFriends();
if (friends.isEmpty()) {
return Collections.emptyList();
}
Set<String> providerUserIds = new HashSet<String>(friends.size());
for (Reference friend : friends) {
providerUserIds.add(friend.getId());
}
Set<String> userIds = connectionRepository.findUserIdsConnectedTo("facebook", providerUserIds);
List<Long> friendAccountIds = new ArrayList<Long>(userIds.size());
for (String localUserId : userIds) {
friendAccountIds.add(Long.valueOf(localUserId));
}
return friendAccountIds;
}
@Value("#{environment['facebook.appId']}")
private String facebookAppId;
}