package com.androidrocks.bex.server.manager; import com.androidrocks.bex.client.json.Friend; import com.androidrocks.bex.server.persistent.BEXFriend; import com.androidrocks.bex.server.persistent.TwitFriend; import com.androidrocks.bex.server.persistent.User; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.EntityNotFoundException; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.Query; import javax.jdo.PersistenceManager; import javax.jdo.Transaction; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; public final class FriendManager { private static final Logger log = Logger.getLogger(FriendManager.class .getName()); private FriendManager() { } public static void saveBEXFriends(List<BEXFriend> friends) { for (BEXFriend friend : friends) { saveBEXFriendWithCustomKey(friend); } } public static void saveTwitFriends(List<TwitFriend> friends) { // do a batch save.. sequence save will throw an exception for (TwitFriend friend : friends) { saveTwitFriendWithCustomKey(friend); } } public static void saveBEXFriendWithCustomKey(BEXFriend friend) { PersistenceManager pm = PMF.get().getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { tx.begin(); friend.setKey(TypeFactory.createBEXFriendKeyWithPrefix(friend.getId())); pm.makePersistent(friend); log.info("#saveBEXFriendWithCustomKey: " + friend); tx.commit(); } finally { if (tx.isActive()) { tx.rollback(); } pm.close(); } } public static void saveTwitFriendWithCustomKey(TwitFriend friend) { PersistenceManager pm = PMF.get().getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { tx.begin(); friend.setKey(TypeFactory.createTwitFriendKeyWithPrefix(friend.getId())); pm.makePersistent(friend); log.info("#saveTwitFriendWithCustomKey: " + friend); tx.commit(); } finally { if (tx.isActive()) { tx.rollback(); } pm.close(); } } public static List<Friend> fetchBEXFriends() { Query query = new Query(BEXFriend.class.getSimpleName()); return TypeFactory.entitiesToJsonFriends(PMF.query (query)); } public static List<Friend> fetchFriends(Set<Key> keys){ return TypeFactory.entitiesToJsonFriends(PMF.get(keys)); } /** * Sets up BEXFriends for user * NOTE: Do not set up the TwitFriends relations, since its already set * @param user * @param twitFriends */ public static void filterFriends(User user, Map<Key, Entity> twitFriends) { Set<Key> twitFriendKeys = user.getTwitFriends(); Set<Key> userKeys = new HashSet<Key>((twitFriends.size())); for (Key friend : twitFriendKeys) { Key key = TypeFactory.createUserKey(friend.getName()); userKeys.add(key); log.info("Adding user key: " + key); } DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService(); Map<Key, Entity> userEntityMap = datastoreService.get(userKeys); log.info("Got System Users: "+userEntityMap.size()); userKeys = userEntityMap.keySet(); Set<String> userKeyNames = TypeFactory.getKeyNames(userKeys); // List<TwitFriend> twitFriends = new ArrayList<TwitFriend>(); // List<BEXFriend> bexFriends = new ArrayList<BEXFriend>(); List<Entity> bexFriends = new ArrayList<Entity>(); for (Key twitFriendKey : twitFriendKeys) { log.info("for Friend: " + twitFriendKey); // compare the key names.. only the names can match (not the entire key, as class are different) if (userKeyNames.contains(twitFriendKey.getName())) { log.info("User name matching Friend name: "+ twitFriendKey.getName()); // BEXFriend bex; Entity bex; // generate a new key for BEXFriend, since they are different from TwitFriend!! try{ bex = PMF.get(TypeFactory.createBEXFriendKey(twitFriendKey.getName())); /* bex = (BEXFriend) PMF.loadObjectById (BEXFriend.class, TypeFactory.createBEXFriendKey(twitFriendKey.getName())); */ } catch (EntityNotFoundException e){ // bex twitFriendKey might not be created yet, so create a new one // TODO: TWIT FRIEND ENTITY IS AVAILABLE, GET IT FROM twitFriends list param coming in // no need for an unnecessary data hit here Entity twit = twitFriends.get(twitFriendKey); // TwitFriend twit = (TwitFriend) PMF.loadObjectById(TwitFriend.class, twitFriendKey); // bex = TypeFactory.twitFriendToBEXFriend(twit); bex = TypeFactory.twitEntityToBEXEntity(twit); } log.info("adding as BEXFriend: " + bex); // defer the saving to batch saving later // UserManager.saveBEXFriend(user, bex); bexFriends.add(bex); } else { // NOT REQUIRED.. SINCE TWIT FRIEND RELATIONS ARE ALREADY SET log.info("User name NOT matching Friend name: "+ twitFriendKey.getName()); // TwitFriend twit = (TwitFriend) PMF.loadObjectById(TwitFriend.class, twitFriendKey); // log.info("adding as TwitFriend: " + twit); // defer the saving to batch saving later // UserManager.saveTwitFriend(user, twit); // twitFriends.add(twit); } } UserManager.saveBEXFriends(user, bexFriends); // never have to do this, coz the twit twitFriends would have been saved already, when fetching // UserManager.saveTwitFriends(user, twitFriends); log.info("#fetchTwitterFriends: BEXFriends count: " + user.getBexFriends().size()); log.info("#fetchTwitterFriends: TwitterFriends count: " + user.getTwitFriends().size()); } public static Set<Key> fetchBEXFriends(Set<String> userKeyNames) { Set<Key> keys = new HashSet<Key>(userKeyNames.size()); for (String userKeyName : userKeyNames) { keys.add(TypeFactory.createBEXFriendKey(userKeyName)); } Map<Key, Entity> entities = PMF.get(keys); return entities.keySet(); } }