package org.societies.platform.socialdata; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.comm.xmpp.interfaces.ICommManager; import org.societies.api.context.CtxException; import org.societies.api.context.model.CtxAttribute; import org.societies.api.context.model.CtxAttributeIdentifier; import org.societies.api.context.model.IndividualCtxEntity; import org.societies.api.context.model.util.SerialisationHelper; import org.societies.api.identity.IIdentity; import org.societies.api.identity.IIdentityManager; import org.societies.api.identity.INetworkNode; import org.societies.api.identity.InvalidFormatException; import org.societies.api.internal.context.broker.ICtxBroker; import org.societies.api.internal.context.model.CtxAttributeTypes; import org.societies.api.internal.sns.ISocialConnector; import org.societies.api.internal.sns.ISocialData; import org.societies.api.schema.sns.socialdata.model.SocialNetwork; import org.societies.api.sns.Checkin; import org.societies.api.sns.Event; import org.societies.api.sns.Message; import org.societies.api.sns.SocialDataState; import org.societies.platform.FacebookConn.impl.FacebookConnectorImpl; import org.societies.platform.FoursquareConnector.impl.FoursquareConnectorImpl; import org.societies.platform.TwitterConnector.impl.TwitterConnectorImpl; import org.societies.platform.sns.connecor.linkedin.LinkedinConnector; import org.societies.platform.sns.connector.googleplus.GooglePlusConnector; import org.springframework.stereotype.Service; @Service public class SocialData implements ISocialData{ private static final Logger logger = LoggerFactory.getLogger(SocialData.class); private INetworkNode cssNodeId; private IIdentity cssOwnerId; private boolean restoreState = false; // css user is modeled as individualCtxEntity private IndividualCtxEntity individualCtxEntity; private SocialDataState state = SocialDataState.INIT; /* * Platform services */ private ICtxBroker internalCtxBroker; private ICommManager commsMgr; private IIdentityManager identityMgr; //this class provides the functionality for storing sns data to context private ContextUpdater ctxUpdater; public ICtxBroker getInternalCtxBroker() { logger.info(this.getClass().getName()+": Return ctxBroker"); return internalCtxBroker; } public void setInternalCtxBroker(ICtxBroker ctxBroker) { this.internalCtxBroker = ctxBroker; logger.info(this.getClass().getName()+": Got ctxBroker"); } public ICommManager getCommsMgr() { logger.info(this.getClass().getName()+": Return commsMgr"); return commsMgr; } public void setCommsMgr(ICommManager commsMgr) { logger.info(this.getClass().getName()+": Got commsMgr"); this.commsMgr = commsMgr; this.identityMgr = this.commsMgr.getIdManager(); } HashMap<String, ISocialConnector> connectors = new HashMap<String, ISocialConnector>(); Map<String, Object> socialFriends; Map<String, Object> socialGroups; Map<String, Object> socialProfiles; Map<String, Object> socialActivities; long lastUpate ; public SocialData(){ socialFriends = new HashMap<String, Object>(); socialGroups = new HashMap<String, Object>(); socialProfiles = new HashMap<String, Object>(); socialActivities = new HashMap<String, Object>(); lastUpate = new Date().getTime(); setState(SocialDataState.INIT); } HashMap <String,CtxAttributeIdentifier> connectorsInCtxBroker = new HashMap<String, CtxAttributeIdentifier>(); private void initSocialData(){ setState(SocialDataState.INIT); logger.debug("SocialData initialization ...."); logger.debug("Inititalize Friends, Groups, Profiles, Activities data structures... "); socialFriends = new HashMap<String, Object>(); socialGroups = new HashMap<String, Object>(); socialProfiles = new HashMap<String, Object>(); socialActivities = new HashMap<String, Object>(); lastUpate = new Date().getTime(); logger.debug(" Start time:" + lastUpate); try { this.cssNodeId = identityMgr.getThisNetworkNode(); this.cssOwnerId = identityMgr.fromJid(this.cssNodeId.getBareJid()); logger.info("CSS Data >>>> CssNodeId:" + this.cssNodeId + " - CssOwnerId:" + this.cssOwnerId); } catch (InvalidFormatException e) { logger.error("Unable to read CssNode id:" + e, e); e.printStackTrace(); } logger.debug("Prepare CtxBroker to store Social Data ..."); // store SNS data to context this.ctxUpdater = new ContextUpdater(this.internalCtxBroker, this.cssOwnerId); restoreStatusBeforeShoutDown(); logger.info("SocialData Bundle started correctly"); } /** * Restore data using context */ public void restoreStatusBeforeShoutDown() { // ////////////////////////////////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////////////////////////////// // Save data into the context try { logger.debug("CtxBroker instance .... " + internalCtxBroker.toString()); individualCtxEntity = internalCtxBroker.retrieveIndividualEntity(this.cssOwnerId).get(); logger.debug("Indivudual CtxEntity: " + individualCtxEntity.getId().toString()); // Restore the connected connector Set<CtxAttribute> connectors = individualCtxEntity .getAttributes(CtxAttributeTypes.SOCIAL_NETWORK_CONNECTOR); if (connectors != null && !connectors.isEmpty()) { restoreState = true; for (CtxAttribute ctxConn : connectors) { ConnectorBean connectorBlob; try { connectorBlob = (ConnectorBean) SerialisationHelper.deserialise(ctxConn.getBinaryValue(), this .getClass().getClassLoader()); logger.info("connector bean:" + connectorBlob); HashMap<String, String> params = new HashMap<String, String>(); params.put(ISocialConnector.AUTH_TOKEN, connectorBlob.getToken()); params.put(ISocialConnector.IDENTITY, connectorBlob.getIdentity()); ISocialConnector conn =createConnector( SocialNetworkUtils.getSocialNetowkName(connectorBlob.getSnName()), params); // Add new Connector this.addSocialConnector(conn); logger.info("Restore Connector: " + conn.getID() + " for " + conn.getSocialNetwork().value()); connectorsInCtxBroker.put(conn.getID(), ctxConn.getId()); } catch (Exception e) { logger.error(e.getLocalizedMessage(), e); } updateSocialData(); } } else logger.warn("No Connector in CtxBroker!"); } catch (CtxException e) { logger.error("Error while reading from CtxBroker:" + e); e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { restoreState = false; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////// @Override public void addSocialConnector(ISocialConnector socialConnector) throws Exception { if (connectors.containsKey(socialConnector.getID())){ logger.warn("the connector id :"+socialConnector.getID() +" is already loaded"); throw new Exception("Connetor already exists"); } connectors.put(socialConnector.getID(), socialConnector); if (!connectorsInCtxBroker.containsKey(socialConnector.getID())){ if (socialConnector.getToken()!=null && !restoreState && individualCtxEntity!=null){ ConnectorBean bean = new ConnectorBean(); bean.setExipres(socialConnector.getTokenExpiration()); bean.setToken(socialConnector.getToken()); bean.setId(socialConnector.getID()); bean.setSnName(socialConnector.getConnectorName()); bean.setIdentity(individualCtxEntity.getId().toUriString()); logger.info("[ADD] Connector ID:"+socialConnector.getID()+ " for "+socialConnector.getConnectorName() + " in CtxBroker"); logger.info("connector bean:"+bean); CtxAttribute connectorCtxAttr = internalCtxBroker.createAttribute(individualCtxEntity.getId(), CtxAttributeTypes.SOCIAL_NETWORK_CONNECTOR).get(); connectorCtxAttr.setBinaryValue(SerialisationHelper.serialise(bean)); internalCtxBroker.update(connectorCtxAttr); connectorsInCtxBroker.put(socialConnector.getID(), connectorCtxAttr.getId()); logger.info("Stored into the CtxBroker with id:"+connectorCtxAttr.getId()); } else{ logger.error("Missing TOKEN in the connector bean!!!!"); } } logger.debug("Add connector "+socialConnector.getID()); } @Override public void removeSocialConnector(String connectorId) throws Exception{ logger.debug("Check if the id "+connectorId + " is associated to a connector ..."); if (connectors.containsKey(connectorId)){ removeSocialConnector(connectors.get(connectorId)); } else { logger.error("The provided id is not associated to any of the connector available."); } } @Override public void removeSocialConnector(ISocialConnector connector) throws Exception { if (connector == null) throw new Exception("Invalid Connector - IS NULL"); logger.debug("Remove " + connector.getConnectorName() + " connector..."); if (connectorsInCtxBroker.containsKey(connector.getID())) { logger.debug("Remove data from ctxBroker..."); internalCtxBroker.remove(connectorsInCtxBroker.get(connector.getID())); connectorsInCtxBroker.remove(connector.getID()); if (ctxUpdater != null){ ctxUpdater.removeConnectorData(connector); logger.debug("CtxBroker cleaned"); } else logger.warn("CtxBroker is not instanciated correctly"); } else logger.warn("ctxBroker doesn't have any connector with this ID"); logger.debug("Remove to the list of connectors (INTERNAL)"); if (connectors.containsKey(connector.getID())) { connectors.remove(connector.getID()); logger.debug("Removed succesfully"); } updateSocialData(); } @Override public List<ISocialConnector> getSocialConnectors() { Iterator<ISocialConnector>it = connectors.values().iterator(); List <ISocialConnector> list = new ArrayList<ISocialConnector>(); while (it.hasNext()){ list.add(it.next()); } return list; } @Override public List<Object> getSocialPeople() { return new ArrayList(socialFriends.values()); } @Override public List<Object> getSocialActivity() { List friends = new ArrayList(); Iterator it = socialActivities.values().iterator(); while (it.hasNext()){ Collection acts = (Collection)it.next(); friends.addAll(acts); } return friends; } @Override public List<Object> getSocialGroups() { return new ArrayList(socialGroups.values()); } @Override public List<Object> getSocialProfiles() { return new ArrayList(socialProfiles.values()); } @Override public void updateSocialData() { new PullDataFromSN(this).execute(); // setState(SocialDataState.DOWNLOADING_FROM_SN); // // socialFriends = new HashMap<String, Object>(); // socialGroups = new HashMap<String, Object>(); // socialProfiles = new HashMap<String, Object>(); // socialActivities = new HashMap<String, Object>(); // // Iterator<ISocialConnector>it = connectors.values().iterator(); // // socialActivities = new HashMap<String, Object>(); // reset old Activities // // // // while (it.hasNext()){ // // // ISocialConnector connector = it.next(); // logger.debug("Update " + connector.getConnectorName() + " data..."); // getActivities(connector); // updateProfile(connector); // updateGroups(connector); // updateFriends(connector); // // // } // // // logger.debug("Update Context Broker with Sodical data Info..."); // // store SNS data to context // try{ // if(this.ctxUpdater != null ) { // List<ISocialConnector> list = new ArrayList<ISocialConnector>(); // list.addAll(connectors.values()); // this.ctxUpdater.updateSocialData(list); // } // } catch (Exception e) { // logger.error("Context DB not updated due to "+e, e); // } // /// UPDATE ALL DATA // lastUpate = new Date().getTime(); // logger.debug("Social data completed @"+ new Date(lastUpate).toGMTString()); } void updateContextBroker(){ logger.debug("Update Context Broker with Social updates..."); try{ if(this.ctxUpdater != null ) { List<ISocialConnector> list = new ArrayList<ISocialConnector>(); list.addAll(connectors.values()); this.ctxUpdater.updateSocialData(list); } } catch (Exception e) { logger.error("Context DB not updated due to "+e, e); } /// UPDATE ALL DATA lastUpate = new Date().getTime(); logger.debug("Social data completed @"+ new Date(lastUpate).toGMTString()); if (connectors.size()==0) setState(SocialDataState.ANY_CONNECTOR); else setState(SocialDataState.WITH_SOME_SOCIAL_DATA); logger.debug("Social data State:" + state); } // private void updateGroups(ISocialConnector connector) { // GroupConverter parser = GroupConveterFactory.getPersonConverter(connector); // List<Group> groups = parser.load(connector.getUserGroups()); // Iterator<Group> it = groups.iterator(); // while (it.hasNext()){ // Group g = it.next(); // if (socialGroups.containsKey(g.getId())){ // socialGroups.remove(g.getId().getGroupId()); // // Send notification of UPDATE? // } // else { // // Send Notitication of NEW PROFILE? // } // socialGroups.put(g.getId().getGroupId(), g); // } // // } // // // private void getActivities(ISocialConnector connector) { // // ActivityConverter parser = ActivityConveterFactory.getActivityConverter(connector); // List<?> activities = parser.load(connector.getUserActivities()); // socialActivities.put(connector.getID(), activities); // } // // // private void updateFriends(ISocialConnector connector) { // // FriendsConverter parser = FriendsConveterFactory.getPersonConverter(connector); // List<Person> friends = parser.load(connector.getUserFriends()); // Iterator<Person> it = friends.iterator(); // // while (it.hasNext()){ // Person friend = it.next(); // if (socialFriends.containsKey(friend.getId())){ // socialFriends.remove(friend.getId()); // // Send notification of UPDATE? // } // else { // // Send Notitication of NEW PROFILE? // } // socialFriends.put(friend.getId(), friend); // } // } // private void updateProfile(ISocialConnector connector) { // // // logger.debug("Update "+ connector.getConnectorName() + " profile ... "); // // PersonConverter parser = PersonConverterFactory.getPersonConverter(connector); // Person profile = parser.load(connector.getUserProfile()); // // if (socialProfiles.containsKey(profile.getId())){ // socialProfiles.remove(profile.getId()); // // Send notification of UPDATE? // } // else { // // Send Notitication of NEW PROFILE? // logger.debug("Add a new Profile in the list"); // } // socialProfiles.put(profile.getId(), profile); // logger.debug("Add a new Profile in the list"); // // } @Override public long getLastUpdate() { return lastUpate; } @Override public boolean isAvailable(ISocialConnector connector) { if (connector==null) return false; return (connectors.containsKey(connector.getID())); } // @Override // public ISocialConnector createConnector(SocialNetwork socialNetwork, Map<String, String> params) { // // String name="me"; // try{ // name=this.cssOwnerId.getJid(); // if (params.containsKey(ISocialConnector.IDENTITY)) name=params.get(ISocialConnector.IDENTITY); // } // catch(Exception ex){} // // logger.info("Create a new connector with "+ socialNetwork + " name"); // switch(socialNetwork) { // case FACEBOOK: // return (ISocialConnector) new FacebookConnectorImpl(params.get(ISocialConnector.AUTH_TOKEN), name); // // case TWITTER: // return (ISocialConnector) new TwitterConnectorImpl (params.get(ISocialConnector.AUTH_TOKEN), name); // // case FOURSQUARE: // return (ISocialConnector) new FoursquareConnectorImpl(params.get(ISocialConnector.AUTH_TOKEN), name); // // case LINKEDIN: // return (ISocialConnector) new LinkedinConnector(params.get(ISocialConnector.AUTH_TOKEN), name); // // default : // return null; // } // } // public void postData(SocialNetwork snName, Map<String, ?> data) { String message = SocialNetworkUtils.genJsonPostMessage(data); logger.info("Post "+message+" to "+ snName + " SN"); List<ISocialConnector> results = getConnectorsByName(snName); Iterator<ISocialConnector> it = results.iterator(); while (it.hasNext()){ ISocialConnector conn = it.next(); logger.debug("Posting using "+conn.getID() +" connector"); conn.post(message); } } @Override public ISocialConnector createConnector( SocialNetwork socialNetwork, Map<String, String> params) { //to debug.... for(String key: params.keySet()) logger.debug(" --- " +key +" ->" + params.get(key)); String name = "me"; try { name = this.cssOwnerId.getJid(); if (params.containsKey(ISocialConnector.IDENTITY)) name = params.get(ISocialConnector.IDENTITY); } catch (Exception ex) { logger.warn("Identity not found: " + ex, ex); } switch (socialNetwork) { case FACEBOOK: logger.debug("Create FACEBOOK connector..."); return (ISocialConnector) new FacebookConnectorImpl( params.get(ISocialConnector.AUTH_TOKEN), name); case TWITTER: logger.debug("Create TWITTER connector..."); return (ISocialConnector) new TwitterConnectorImpl( params.get(ISocialConnector.AUTH_TOKEN), name); case FOURSQUARE: logger.debug("Create FOURSQUARE connector..."); return (ISocialConnector) new FoursquareConnectorImpl( params.get(ISocialConnector.AUTH_TOKEN), name); case LINKEDIN: logger.debug("Create LINKEDIN connector..."); return (ISocialConnector) new LinkedinConnector( params.get(ISocialConnector.AUTH_TOKEN), name); case GOOGLEPLUS: logger.debug("Create GOOGLEPLUS connector..."); return (ISocialConnector) new GooglePlusConnector( params.get(ISocialConnector.AUTH_TOKEN), name); default: logger.error("Hope to don't reach this part otherwise is an error..."); return null; } } public void postMessage(SocialNetwork snName, String data) { logger.info("Post a Message to " + snName + " SN"); List<ISocialConnector> results = SocialNetworkUtils .getConnectorsByName(snName, connectors.values()); Iterator<ISocialConnector> it = results.iterator(); while (it.hasNext()) { ISocialConnector conn = it.next(); conn.post(data); logger.debug("Posting using " + conn.getID() + " connector"); } } // @Override // public void postCheckin(SocialNetwork name, Checkin bean) { // // Map<String, String> params = new HashMap<String, String>(); // params.put(ISocialData.POST_DESCR, bean.getMessage()); // params.put(ISocialData.POST_LAT, "" + bean.getLatitude()); // params.put(ISocialData.POST_LAT, "" + bean.getLatitude()); // params.put(ISocialData.POST_PLACE, "" + bean.getPlaceId()); // postData(name, params); // // } // // @Override // public void postEvent(SocialNetwork name, Event bean) { // // Map<String, String> params = new HashMap<String, String>(); // params.put(ISocialData.POST_NAME, bean.getName()); // params.put(ISocialData.POST_FROM, bean.getFromDate()); // params.put(ISocialData.POST_TO, bean.getToDate()); // params.put(ISocialData.POST_PLACE, bean.getPlace()); // params.put(ISocialData.POST_DESCR, bean.getDescription()); // postData(name, params); // // } // // @Override // public void postMessage(SocialNetwork name, Message bean) { // Map<String, String> params = new HashMap<String, String>(); // params.put(ISocialData.POST_MESSAGE, bean.getData()); // // } @Override public SocialDataState getStatus() { return state; } void setState(SocialDataState newState){ logger.debug("SocialData is goint from "+state+ " to "+newState); this.state=newState; } private List<ISocialConnector> getConnectorsByName(SocialNetwork name){ Iterator <ISocialConnector> it = connectors.values().iterator(); ArrayList<ISocialConnector> results = new ArrayList<ISocialConnector>(); while (it.hasNext()){ ISocialConnector conn = it.next(); if (conn.getSocialNetwork().equals(name)){ results.add(conn); } } return results; } // New Post Methods @Override public boolean isConnected(SocialNetwork name) { for (ISocialConnector c : connectors.values()){ if (c.getSocialNetwork().equals(name)) return true; } return false; } @Override public void postCheckin(SocialNetwork name, Checkin bean) { Map<String, String> params = new HashMap<String, String>(); params.put(ISocialData.POST_DESCR, bean.getMessage()); params.put(ISocialData.POST_LAT, ""+bean.getLatitude()); params.put(ISocialData.POST_LAT, ""+bean.getLatitude()); params.put(ISocialData.POST_PLACE, ""+bean.getPlaceId()); postData(name, params); } @Override public void postEvent(SocialNetwork name, Event bean) { Map<String, String> params = new HashMap<String, String>(); params.put(ISocialData.POST_NAME, bean.getName()); params.put(ISocialData.POST_FROM, bean.getFromDate()); params.put(ISocialData.POST_TO, bean.getToDate()); params.put(ISocialData.POST_PLACE, bean.getPlace()); params.put(ISocialData.POST_DESCR, bean.getDescription()); postData(name, params); } @Override public void postMessage(SocialNetwork name, Message bean) { Map<String, String> params = new HashMap<String, String>(); params.put(ISocialData.POST_MESSAGE, bean.getData()); } }